Merge remote-tracking branch 'origin/upstream/main'
Updated to commit: f8bc783c2fb469dd86639a41cc7c7df6a8e79677
Additionally, resolved merge conflict for openthread-config-android.h
and also updated ot_version.gni to indicate new version for
soft-transition.
Also changed compilation flags to compile for THREAD_VERSION_1_1 so
that it works with current RCP firmware.
Bug: 73064
Change-Id: I4ff3f0159f0ba46c3d7012e9041fdcd92d9236a7
diff --git a/.codecov.yml b/.codecov.yml
index 2b6b883..bf74750 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -1,10 +1,6 @@
coverage:
status:
- project:
- default:
- target: auto
- threshold: 1%
- only_pulls: true
+ project: off
patch: off
ignore:
@@ -13,4 +9,4 @@
comment:
layout: "diff, flags, files"
- after_n_builds: 4
+ after_n_builds: 5
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 041a4ef..47acce8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -38,12 +38,14 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
pretty:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -58,6 +60,8 @@
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo pip3 install --system -U cmake==3.10.3
@@ -84,6 +88,8 @@
CXX: ${{ matrix.compiler_cpp }}
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -96,6 +102,8 @@
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -127,11 +135,13 @@
gcc_extract_dir: gcc-arm-none-eabi-9-2019-q4-major
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
cd /tmp
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
- sudo apt-get --no-install-recommends install -y lib32z1 ninja-build
+ sudo apt-get --no-install-recommends install -y lib32z1 ninja-build gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
wget ${{ matrix.gcc_download_url }} -O gcc-arm.tar.bz2
tar xjf gcc-arm.tar.bz2
# use the minimal required cmake version
@@ -155,6 +165,8 @@
CXX: g++-${{ matrix.gcc_ver }}
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -175,6 +187,8 @@
CXX: clang++-${{ matrix.clang_ver }}
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -198,6 +212,8 @@
LDFLAGS: -m32
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo dpkg --add-architecture i386
@@ -213,6 +229,8 @@
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -233,6 +251,8 @@
CXX: clang++
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
brew install automake ninja llvm
@@ -248,6 +268,8 @@
CXX: g++
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
brew install automake ninja
@@ -260,6 +282,8 @@
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Build
run: |
docker run --rm -v $PWD:/build/openthread openthread/android-trusty /build/openthread/script/check-android-build
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index d3f369f..a8c9a1f 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -38,7 +38,7 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
buildx:
name: buildx-${{ matrix.docker_name }}
diff --git a/tests/scripts/expect/cli-anycast.exp b/.github/workflows/makefile-check.yml
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to .github/workflows/makefile-check.yml
index 3081a6b..37e8024 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/.github/workflows/makefile-check.yml
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +26,25 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+name: Makefile Check
+on: [push, pull_request]
-set spawn_id [spawn_node 1]
+jobs:
+ cancel-previous-runs:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: rokroskar/workflow-run-cleanup-action@master
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ if: "github.ref != 'refs/heads/main'"
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+ makefile-check:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Check
+ run: |
+ script/check-core-makefiles
diff --git a/.github/workflows/otbr.yml b/.github/workflows/otbr.yml
new file mode 100644
index 0000000..7dc6195
--- /dev/null
+++ b/.github/workflows/otbr.yml
@@ -0,0 +1,187 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+name: Border Router
+
+on: [push, pull_request]
+
+jobs:
+
+ cancel-previous-runs:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: rokroskar/workflow-run-cleanup-action@master
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ if: "github.ref != 'refs/heads/main'"
+
+ backbone-router:
+ runs-on: ubuntu-20.04
+ env:
+ REFERENCE_DEVICE: 1
+ VIRTUAL_TIME: 0
+ PACKET_VERIFICATION: 1
+ THREAD_VERSION: 1.2
+ INTER_OP: 1
+ COVERAGE: 1
+ MULTIPLY: 1
+ PYTHONUNBUFFERED: 1
+ VERBOSE: 1
+ # The Border Routing and DUA feature can coexist, but current wireshark
+ # packet verification can't handle it because of the order of context ID
+ # of OMR prefix and Domain prefix is not deterministic.
+ BORDER_ROUTING: 0
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Build OTBR Docker
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ run: |
+ ./script/test build_otbr_docker
+ - name: Bootstrap
+ run: |
+ sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+ sudo apt-get --no-install-recommends install -y python3-setuptools python3-wheel ninja-build socat lcov
+ python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
+ - name: Build
+ run: |
+ ./script/test build
+ - name: Get Thread-Wireshark
+ run: |
+ ./script/test get_thread_wireshark
+ - name: Run
+ run: |
+ 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@v2
+ with:
+ name: cov-thread-1-2-backbone-docker
+ path: /tmp/coverage/
+ - uses: actions/upload-artifact@v2
+ if: ${{ failure() }}
+ with:
+ name: thread-1-2-backbone-results
+ path: |
+ *.pcap
+ *.json
+ *.log
+ - name: Generate Coverage
+ run: |
+ ./script/test generate_coverage gcc
+ - uses: actions/upload-artifact@v2
+ with:
+ name: cov-thread-1-2-backbone
+ path: tmp/coverage.info
+
+ thread-border-router:
+ runs-on: ubuntu-20.04
+ env:
+ REFERENCE_DEVICE: 1
+ VIRTUAL_TIME: 0
+ PACKET_VERIFICATION: 1
+ THREAD_VERSION: 1.2
+ INTER_OP: 1
+ COVERAGE: 1
+ MULTIPLY: 1
+ PYTHONUNBUFFERED: 1
+ VERBOSE: 1
+ BORDER_ROUTING: 1
+ steps:
+ - uses: actions/checkout@v2
+ - name: Build OTBR Docker
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ run: |
+ ./script/test build_otbr_docker
+ - name: Bootstrap
+ run: |
+ sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+ sudo apt-get --no-install-recommends install -y python3-setuptools python3-wheel ninja-build socat lcov
+ python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
+ - name: Build
+ run: |
+ ./script/test build
+ - name: Get Thread-Wireshark
+ run: |
+ ./script/test get_thread_wireshark
+ - name: Run
+ run: |
+ 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/border_router/*.py || (sudo chmod a+r *.log *.json *.pcap && false)
+ - uses: actions/upload-artifact@v2
+ with:
+ name: cov-thread-border-router-docker
+ path: /tmp/coverage/
+ - uses: actions/upload-artifact@v2
+ if: ${{ failure() }}
+ with:
+ name: thread-border-router-results
+ path: |
+ *.pcap
+ *.json
+ *.log
+ - name: Generate Coverage
+ run: |
+ ./script/test generate_coverage gcc
+ - uses: actions/upload-artifact@v2
+ with:
+ name: cov-thread-border-router
+ path: tmp/coverage.info
+
+ upload-coverage:
+ needs:
+ - backbone-router
+ - thread-border-router
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Bootstrap
+ run: |
+ sudo apt-get --no-install-recommends install -y lcov
+ - uses: actions/download-artifact@v2
+ with:
+ path: coverage/
+ - name: Upload Coverage
+ run: |
+ script/test upload_codecov
+
+ delete-coverage-artifacts:
+ needs: upload-coverage
+ if: always()
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: geekyeggo/delete-artifact@1-glob-support
+ with:
+ name: cov-*
+ useGlob: true
diff --git a/.github/workflows/otci.yml b/.github/workflows/otci.yml
new file mode 100644
index 0000000..97e78f7
--- /dev/null
+++ b/.github/workflows/otci.yml
@@ -0,0 +1,70 @@
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+name: OTCI
+
+on: [push, pull_request]
+
+jobs:
+
+ cancel-previous-runs:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: rokroskar/workflow-run-cleanup-action@master
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ if: "github.ref != 'refs/heads/main'"
+
+ cli-sim:
+ runs-on: ubuntu-20.04
+ strategy:
+ matrix:
+ virtual_time: [0, 1]
+ env:
+ REFERENCE_DEVICE: 1
+ VIRTUAL_TIME: ${{ matrix.virtual_time }}
+ REAL_DEVICE: 0
+ steps:
+ - uses: actions/checkout@v2
+ - name: Bootstrap
+ run: |
+ sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+ sudo apt-get --no-install-recommends install -y g++-multilib python3-setuptools python3-wheel
+ python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
+ - name: Build
+ run: |
+ ./bootstrap
+ make -f examples/Makefile-simulation THREAD_VERSION=1.2 DUA=1 MLR=1 BACKBONE_ROUTER=1 CSL_RECEIVER=1
+ - name: Install OTCI Python Library
+ run: |
+ (cd tools/otci && python3 setup.py install --user)
+ - name: Run
+ run: |
+ export PYTHONPATH=./tests/scripts/thread-cert/
+ export OT_CLI=./output/simulation/bin/ot-cli-ftd
+ python3 tools/otci/tests/test_otci.py
diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml
index 6c46bde..0c64cd9 100644
--- a/.github/workflows/posix.yml
+++ b/.github/workflows/posix.yml
@@ -38,8 +38,103 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
+ expects-macos:
+ runs-on: macos-10.15
+ env:
+ CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15 -DOPENTHREAD_CONFIG_MAC_SCAN_DURATION=500
+ CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15 -DOPENTHREAD_CONFIG_MAC_SCAN_DURATION=500
+ CC: clang
+ CXX: clang++
+ THREAD_VERSION: 1.1
+ steps:
+ - uses: actions/checkout@v2
+ - name: Bootstrap
+ run: |
+ brew install ninja
+ - name: Run RCP Mode
+ run: |
+ OT_OPTIONS='-DOT_READLINE=OFF -DOT_APP_NCP=OFF' OT_NODE_TYPE=rcp-cli ./script/test build expect
+ - name: Run Native IP Mode
+ run: |
+ brew install dnsmasq
+ echo 'listen-address=::1' | sudo tee $(brew --prefix)/etc/dnsmasq.conf
+ sudo brew services start dnsmasq
+ host ipv6.google.com ::1
+ OT_OPTIONS=-DOT_READLINE=OFF OT_NATIVE_IP=1 OT_NODE_TYPE=rcp-cli ./script/test clean build expect
+
+ expects-linux:
+ runs-on: ubuntu-18.04
+ env:
+ CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
+ CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
+ steps:
+ - uses: actions/checkout@v2
+ - name: Bootstrap
+ run: |
+ sudo apt-get --no-install-recommends install -y expect ninja-build lcov socat
+ - name: Run RCP Mode
+ run: |
+ ulimit -c unlimited
+ ./script/test prepare_coredump_upload
+ OT_OPTIONS='-DOT_READLINE=OFF -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED' VIRTUAL_TIME=0 OT_NODE_TYPE=rcp ./script/test build expect
+ - name: Check Crash
+ if: ${{ failure() }}
+ run: |
+ 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@v2
+ if: ${{ failure() && env.CRASHED_RCP == '1' }}
+ with:
+ name: core-expect-rcp
+ path: |
+ ./ot-core-dump/*
+ - name: Generate Coverage
+ run: |
+ ./script/test generate_coverage gcc
+ - uses: actions/upload-artifact@v2
+ with:
+ name: cov-expects-linux-1
+ path: tmp/coverage.info
+ - name: Run TUN Mode
+ run: |
+ sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
+ sudo apt-get install --no-install-recommends -y dnsmasq bind9-host ntp
+ sudo systemctl start dnsmasq ntp
+ host ipv6.google.com 127.0.0.1
+ echo 'listen-address=::1' | sudo tee /etc/dnsmasq.conf
+ echo 0 | sudo tee /proc/sys/net/ipv6/conf/all/disable_ipv6
+ sudo systemctl restart dnsmasq
+ host ipv6.google.com ::1
+ ulimit -c unlimited
+ ./script/test prepare_coredump_upload
+ OT_OPTIONS='-DOT_READLINE=OFF -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED' OT_NATIVE_IP=1 VIRTUAL_TIME=0 OT_NODE_TYPE=rcp ./script/test clean build expect
+ - name: Check Crash
+ if: ${{ failure() }}
+ run: |
+ 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@v2
+ if: ${{ failure() && env.CRASHED_TUN == '1' }}
+ with:
+ name: core-expect-posix
+ path: |
+ ./ot-core-dump/*
+ - uses: actions/upload-artifact@v2
+ if: ${{ failure() }}
+ with:
+ name: syslog-expect-posix
+ path: /var/log/syslog
+ - name: Generate Coverage
+ run: |
+ ./script/test generate_coverage gcc
+ - uses: actions/upload-artifact@v2
+ with:
+ name: cov-expects-linux-2
+ path: tmp/coverage.info
posix-cli:
runs-on: ubuntu-20.04
@@ -48,10 +143,13 @@
PYTHONUNBUFFERED: 1
READLINE: readline
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
VIRTUAL_TIME_UART: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -86,10 +184,13 @@
PYTHONUNBUFFERED: 1
READLINE: readline
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
VIRTUAL_TIME_UART: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -123,6 +224,8 @@
COVERAGE: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -148,6 +251,8 @@
COVERAGE: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -182,6 +287,8 @@
DAEMON: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -211,6 +318,7 @@
upload-coverage:
needs:
+ - expects-linux
- posix-cli
- posix-ncp
- posix-ncp-rcp-migrate
@@ -219,6 +327,8 @@
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
diff --git a/.github/workflows/simulation.yml b/.github/workflows/simulation-1.1.yml
similarity index 86%
rename from .github/workflows/simulation.yml
rename to .github/workflows/simulation-1.1.yml
index a25ad80..08958c3 100644
--- a/.github/workflows/simulation.yml
+++ b/.github/workflows/simulation-1.1.yml
@@ -26,7 +26,7 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-name: Simulation
+name: Simulation 1.1
on: [push, pull_request]
@@ -38,7 +38,7 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
distcheck:
runs-on: ubuntu-20.04
@@ -46,9 +46,12 @@
CC: clang
CXX: clang++
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -70,11 +73,14 @@
LDFLAGS: -m32
COVERAGE: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
VIRTUAL_TIME_UART: 1
MAX_NETWORK_SIZE: 999
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- uses: actions/setup-go@v1
with:
go-version: '1.14'
@@ -116,11 +122,14 @@
packet-verification:
runs-on: ubuntu-20.04
env:
- REFERENCE_DEVICE: 1
- VIRTUAL_TIME: 1
PACKET_VERIFICATION: 1
+ REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
+ VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -161,9 +170,12 @@
LDFLAGS: -m32
COVERAGE: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -200,11 +212,14 @@
LDFLAGS: -m32
COVERAGE: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
USE_MTD: 1
VIRTUAL_TIME: 1
MESSAGE_USE_HEAP: ${{ matrix.message_use_heap }}
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -227,7 +242,7 @@
./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2
with:
- name: cov-cli-mtd
+ name: cov-cli-mtd-${{ matrix.message_use_heap }}
path: tmp/coverage.info
cli-time-sync:
@@ -238,10 +253,13 @@
LDFLAGS: -m32
COVERAGE: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
TIME_SYNC: 1
VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -272,6 +290,7 @@
env:
CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
+ THREAD_VERSION: 1.1
steps:
- uses: actions/checkout@v2
- name: Bootstrap
@@ -282,87 +301,41 @@
ulimit -c unlimited
./script/test prepare_coredump_upload
OT_OPTIONS='-DOT_TIME_SYNC=ON -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED' VIRTUAL_TIME=0 ./script/test build expect
- - name: Copy Shared Libraries
+ - name: Check Crash
if: ${{ failure() }}
run: |
- ./script/test copy_so_lib
+ 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@v2
- if: ${{ failure() }}
+ if: ${{ failure() && env.CRASHED_CLI == '1' }}
with:
name: core-expect-cli
path: |
- ./build/openthread-simulation-1.1/examples/apps/cli/ot-cli-ftd
./ot-core-dump/*
- ./so-lib/*
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2
with:
- name: cov-expects-1
- path: tmp/coverage.info
- - name: Run RCP Mode
- run: |
- ulimit -c unlimited
- ./script/test prepare_coredump_upload
- OT_OPTIONS='-DOT_READLINE=OFF -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED' VIRTUAL_TIME=0 OT_NODE_TYPE=rcp ./script/test clean build expect
- - name: Generate Coverage
- run: |
- ./script/test generate_coverage gcc
- - uses: actions/upload-artifact@v2
- with:
- name: cov-expects-2
- path: tmp/coverage.info
- - name: Run TUN Mode
- run: |
- sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
- sudo apt-get install --no-install-recommends -y dnsmasq bind9-host ntp
- sudo systemctl start dnsmasq ntp
- host ipv6.google.com 127.0.0.1
- echo 'listen-address=::1' | sudo tee /etc/dnsmasq.conf
- echo 0 | sudo tee /proc/sys/net/ipv6/conf/all/disable_ipv6
- sudo systemctl restart dnsmasq
- host ipv6.google.com ::1
- ulimit -c unlimited
- ./script/test prepare_coredump_upload
- OT_OPTIONS='-DOT_READLINE=OFF -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED' OT_NATIVE_IP=1 VIRTUAL_TIME=0 OT_NODE_TYPE=rcp ./script/test clean build expect
- - name: Copy Shared Libraries
- if: ${{ failure() }}
- run: |
- ./script/test copy_so_lib
- - uses: actions/upload-artifact@v2
- if: ${{ failure() }}
- with:
- name: core-expect-posix
- path: |
- ./build/openthread-simulation-1.1/examples/apps/ncp/ot-rcp
- ./build/openthread-posix-1.1/src/posix/ot-cli
- ./ot-core-dump/*
- ./so-lib/*
- - uses: actions/upload-artifact@v2
- if: ${{ failure() }}
- with:
- name: syslog-expect-posix
- path: /var/log/syslog
- - name: Generate Coverage
- run: |
- ./script/test generate_coverage gcc
- - uses: actions/upload-artifact@v2
- with:
- name: cov-expects-3
+ name: cov-expects
path: tmp/coverage.info
external-commissioner:
runs-on: ubuntu-20.04
+ env:
+ THREAD_VERSION: 1.1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
sudo rm /etc/apt/sources.list.d/*
sudo apt-get install -y avahi-daemon avahi-utils lcov
- script/git-tool clone https://github.com/openthread/ot-commissioner.git /tmp/ot-commissioner --depth 1 --branch master
+ script/git-tool clone https://github.com/openthread/ot-commissioner.git /tmp/ot-commissioner --depth 1 --branch main
- name: Build
run: |
cd /tmp/ot-commissioner
@@ -397,9 +370,12 @@
COVERAGE: 1
MULTIPLE_INSTANCE: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y python3-setuptools python3-wheel lcov
@@ -434,9 +410,12 @@
NODE_TYPE: ncp-sim
PYTHONUNBUFFERED: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -470,11 +449,14 @@
NODE_TYPE: ncp-sim
PYTHONUNBUFFERED: 1
REFERENCE_DEVICE: 1
+ THREAD_VERSION: 1.1
VIRTUAL_TIME: 1
CC: clang
CXX: clang++
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -516,6 +498,8 @@
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
diff --git a/.github/workflows/simulation-1.2.yml b/.github/workflows/simulation-1.2.yml
index 4c9890f..3fdacde 100644
--- a/.github/workflows/simulation-1.2.yml
+++ b/.github/workflows/simulation-1.2.yml
@@ -38,7 +38,7 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
thread-1-2:
name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}
@@ -59,6 +59,8 @@
arch: ["m32", "m64"]
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -66,7 +68,6 @@
python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
- name: Build
run: |
- ./bootstrap
./script/test build
- name: Run
run: |
@@ -74,15 +75,23 @@
./script/test prepare_coredump_upload
./script/test unit
./script/test cert_suite tests/scripts/thread-cert/v1_2_*
- - name: Copy Shared Libraries
+ - name: Check Crash
if: ${{ failure() }}
run: |
- ./script/test copy_so_lib
+ CRASHED=$(./script/test check_crash | tail -1)
+ [[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
+ echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- uses: actions/upload-artifact@v2
if: ${{ failure() }}
with:
name: thread-1-2-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
path: "*.pcap"
+ - uses: actions/upload-artifact@v2
+ if: ${{ failure() && env.CRASHED == '1' }}
+ with:
+ name: core-packet-verification-thread-1-2
+ path: |
+ ./ot-core-dump/*
- name: Generate Coverage
run: |
./script/test generate_coverage "${{ matrix.compiler.gcov }}"
@@ -101,8 +110,11 @@
THREAD_VERSION: 1.2
MAC_FILTER: 1
INTER_OP: 1
+ INTER_OP_BBR: 0
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -122,10 +134,12 @@
do
./script/test cert_suite ./tests/scripts/thread-cert/v1_2_LowPower*.py
done
- - name: Copy Shared Libraries
+ - name: Check Crash
if: ${{ failure() }}
run: |
- ./script/test copy_so_lib
+ CRASHED=$(./script/test check_crash | tail -1)
+ [[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
+ echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- uses: actions/upload-artifact@v2
if: ${{ failure() }}
with:
@@ -134,14 +148,11 @@
*.pcap
*.json
- uses: actions/upload-artifact@v2
- if: ${{ failure() }}
+ if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-low-power
path: |
- ./build/openthread-simulation-1.2/examples/apps/cli/ot-cli-*
- ./build/openthread-simulation-1.1/examples/apps/cli/ot-cli-*
./ot-core-dump/*
- ./so-lib/*
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
@@ -159,6 +170,8 @@
THREAD_VERSION: 1.2
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -199,6 +212,8 @@
VIRTUAL_TIME: 0
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov socat
@@ -207,20 +222,18 @@
ulimit -c unlimited
./script/test prepare_coredump_upload
OT_OPTIONS=-DOT_READLINE=OFF OT_NODE_TYPE=rcp ./script/test build expect
- - name: Copy Shared Libraries
+ - name: Check Crash
if: ${{ failure() }}
run: |
- ./script/test copy_so_lib
+ CRASHED=$(./script/test check_crash | tail -1)
+ [[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
+ echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- uses: actions/upload-artifact@v2
- if: ${{ failure() }}
+ if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-expect-1-2
path: |
- ./build/openthread-simulation-1.2/examples/apps/cli/ot-cli-mtd
- ./build/openthread-simulation-1.2/examples/apps/ncp/ot-rcp
- ./build/openthread-posix-1.2/src/posix/ot-cli
./ot-core-dump/*
- ./so-lib/*
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
@@ -229,59 +242,62 @@
name: cov-expects
path: tmp/coverage.info
- thread-1-2-backbone:
- runs-on: ubuntu-18.04
+ thread-1-2-posix:
+ runs-on: ubuntu-20.04
env:
- REFERENCE_DEVICE: 1
- VIRTUAL_TIME: 0
- PACKET_VERIFICATION: 1
- THREAD_VERSION: 1.2
- INTER_OP: 1
COVERAGE: 1
- MULTIPLY: 1
PYTHONUNBUFFERED: 1
- VERBOSE: 1
+ READLINE: readline
+ THREAD_VERSION: 1.2
+ OT_NODE_TYPE: rcp
+ USE_MTD: 1
+ VIRTUAL_TIME: 1
+ INTER_OP: 1
steps:
- uses: actions/checkout@v2
- - name: Build OTBR Docker
- env:
- GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- run: |
- ./script/test build_otbr_docker
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
- sudo apt-get --no-install-recommends install -y python3-setuptools python3-wheel ninja-build socat lcov
+ sudo apt-get --no-install-recommends install -y libreadline6-dev g++-multilib ninja-build python3-setuptools python3-wheel llvm lcov
python3 -m pip install -r tests/scripts/thread-cert/requirements.txt
- name: Build
run: |
./script/test build
- - name: Get Thread-Wireshark
- run: |
- ./script/test get_thread_wireshark
- name: Run
run: |
- 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@v2
- with:
- name: cov-thread-1-2-backbone-docker
- path: /tmp/coverage/
+ ulimit -c unlimited
+ ./script/test prepare_coredump_upload
+ ./script/test cert tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
+ ./script/test cert tests/scripts/thread-cert/v1_2_LowPower_6_1_07_PreferringARouterOverAReed.py
+ ./script/test cert tests/scripts/thread-cert/v1_2_router_5_1_1.py
+ ./script/test cert tests/scripts/thread-cert/v1_2_test_csl_transmission.py
+ ./script/test cert tests/scripts/thread-cert/v1_2_test_enhanced_frame_pending.py
+ ./script/test cert tests/scripts/thread-cert/v1_2_test_parent_selection.py
+ - name: Check Crash
+ if: ${{ failure() }}
+ run: |
+ CRASHED=$(./script/test check_crash | tail -1)
+ [[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
+ echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- uses: actions/upload-artifact@v2
if: ${{ failure() }}
with:
- name: thread-1-2-backbone-results
+ name: thread-1-2-posix-pcaps
+ path: "*.pcap"
+ - uses: actions/upload-artifact@v2
+ if: ${{ failure() && env.CRASHED == '1' }}
+ with:
+ name: core-thread-1-2-posix
path: |
- *.pcap
- *.json
- *.log
+ ./ot-core-dump/*
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2
with:
- name: cov-thread-1-2-backbone
+ name: cov-thread-1-2-posix
path: tmp/coverage.info
upload-coverage:
@@ -290,10 +306,12 @@
- packet-verification-low-power
- packet-verification-1-1-on-1-2
- expects
- - thread-1-2-backbone
+ - thread-1-2-posix
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
index c498589..95c67cf 100644
--- a/.github/workflows/size.yml
+++ b/.github/workflows/size.yml
@@ -38,7 +38,7 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
size-report:
runs-on: ubuntu-20.04
@@ -53,6 +53,7 @@
env:
OT_BASE_BRANCH: "${{ github.base_ref }}"
SIZE_REPORT_URL: "https://openthread-size-report.glitch.me/size-report/1354027"
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
export PATH=$PATH:$HOME/.local/bin
./script/check-size
diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml
index 6646312..4536cd0 100644
--- a/.github/workflows/toranj.yml
+++ b/.github/workflows/toranj.yml
@@ -38,7 +38,7 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
toranj-ncp:
runs-on: ubuntu-18.04
@@ -47,6 +47,8 @@
TORANJ_RADIO : 15.4
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
@@ -85,6 +87,8 @@
TORANJ_RADIO : 15.4
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
@@ -223,6 +227,8 @@
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml
index 0dcf05d..37b110c 100644
--- a/.github/workflows/version.yml
+++ b/.github/workflows/version.yml
@@ -37,12 +37,14 @@
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- if: "github.ref != 'refs/heads/master'"
+ if: "github.ref != 'refs/heads/main'"
api-version:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
+ with:
+ submodules: true
- name: Check
run: |
script/check-api-version
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..c01f63e
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "third_party/Qorvo/repo"]
+ path = third_party/Qorvo/repo
+ url = https://github.com/Qorvo/qpg-openthread.git
diff --git a/Android.mk b/Android.mk
index 04ee056..3c303af 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,8 @@
LOCAL_PATH := $(call my-dir)
+ifeq ($(OPENTHREAD_ENABLE_ANDROID_MK),1)
+
OPENTHREAD_DEFAULT_VERSION := $(shell cat $(LOCAL_PATH)/.default-version)
OPENTHREAD_SOURCE_VERSION := $(shell git -C $(LOCAL_PATH) describe --always --match "[0-9].*" 2> /dev/null)
@@ -43,7 +45,6 @@
-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1 \
-DOPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE=1 \
-DOPENTHREAD_FTD=1 \
- -DOPENTHREAD_POSIX=1 \
-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1 \
$(NULL)
@@ -145,14 +146,24 @@
-pedantic-errors \
$(NULL)
+ifeq ($(ANDROID_NDK),1)
+LOCAL_SHARED_LIBRARIES := libcutils
+
+LOCAL_CFLAGS += \
+ -DOPENTHREAD_ENABLE_ANDROID_NDK=1 \
+ $(NULL)
+endif
+
LOCAL_SRC_FILES := \
src/core/api/backbone_router_api.cpp \
src/core/api/backbone_router_ftd_api.cpp \
+ src/core/api/border_agent_api.cpp \
src/core/api/border_router_api.cpp \
src/core/api/channel_manager_api.cpp \
src/core/api/channel_monitor_api.cpp \
src/core/api/child_supervision_api.cpp \
src/core/api/coap_api.cpp \
+ src/core/api/coap_secure_api.cpp \
src/core/api/commissioner_api.cpp \
src/core/api/crypto_api.cpp \
src/core/api/dataset_api.cpp \
@@ -160,6 +171,9 @@
src/core/api/dataset_updater_api.cpp \
src/core/api/diags_api.cpp \
src/core/api/dns_api.cpp \
+ src/core/api/entropy_api.cpp \
+ src/core/api/error_api.cpp \
+ src/core/api/heap_api.cpp \
src/core/api/icmp6_api.cpp \
src/core/api/instance_api.cpp \
src/core/api/ip6_api.cpp \
@@ -173,9 +187,14 @@
src/core/api/multi_radio_api.cpp \
src/core/api/netdata_api.cpp \
src/core/api/netdiag_api.cpp \
+ src/core/api/network_time_api.cpp \
+ src/core/api/ping_sender_api.cpp \
src/core/api/random_crypto_api.cpp \
src/core/api/random_noncrypto_api.cpp \
src/core/api/server_api.cpp \
+ src/core/api/sntp_api.cpp \
+ src/core/api/srp_client_api.cpp \
+ src/core/api/srp_server_api.cpp \
src/core/api/tasklet_api.cpp \
src/core/api/thread_api.cpp \
src/core/api/thread_ftd_api.cpp \
@@ -186,10 +205,14 @@
src/core/backbone_router/bbr_manager.cpp \
src/core/backbone_router/multicast_listeners_table.cpp \
src/core/backbone_router/ndproxy_table.cpp \
+ src/core/border_router/infra_if_platform.cpp \
+ src/core/border_router/router_advertisement.cpp \
+ src/core/border_router/routing_manager.cpp \
src/core/coap/coap.cpp \
src/core/coap/coap_message.cpp \
src/core/coap/coap_secure.cpp \
src/core/common/crc16.cpp \
+ src/core/common/error.cpp \
src/core/common/instance.cpp \
src/core/common/logging.cpp \
src/core/common/message.cpp \
@@ -204,6 +227,7 @@
src/core/common/trickle_timer.cpp \
src/core/crypto/aes_ccm.cpp \
src/core/crypto/aes_ecb.cpp \
+ src/core/crypto/ecdsa.cpp \
src/core/crypto/hkdf_sha256.cpp \
src/core/crypto/hmac_sha256.cpp \
src/core/crypto/mbedtls.cpp \
@@ -213,6 +237,7 @@
src/core/mac/channel_mask.cpp \
src/core/mac/data_poll_handler.cpp \
src/core/mac/data_poll_sender.cpp \
+ src/core/mac/link_raw.cpp \
src/core/mac/mac.cpp \
src/core/mac/mac_filter.cpp \
src/core/mac/mac_frame.cpp \
@@ -227,6 +252,7 @@
src/core/meshcop/dataset_local.cpp \
src/core/meshcop/dataset_manager.cpp \
src/core/meshcop/dataset_manager_ftd.cpp \
+ src/core/meshcop/dataset_updater.cpp \
src/core/meshcop/dtls.cpp \
src/core/meshcop/energy_scan_client.cpp \
src/core/meshcop/joiner.cpp \
@@ -240,7 +266,8 @@
src/core/net/dhcp6_client.cpp \
src/core/net/dhcp6_server.cpp \
src/core/net/dns_client.cpp \
- src/core/net/dns_headers.cpp \
+ src/core/net/dns_types.cpp \
+ src/core/net/dnssd_server.cpp \
src/core/net/icmp6.cpp \
src/core/net/ip6.cpp \
src/core/net/ip6_address.cpp \
@@ -248,6 +275,10 @@
src/core/net/ip6_headers.cpp \
src/core/net/ip6_mpl.cpp \
src/core/net/netif.cpp \
+ src/core/net/sntp_client.cpp \
+ src/core/net/socket.cpp \
+ src/core/net/srp_client.cpp \
+ src/core/net/srp_server.cpp \
src/core/net/udp6.cpp \
src/core/radio/radio.cpp \
src/core/radio/radio_callbacks.cpp \
@@ -281,23 +312,27 @@
src/core/thread/network_data_leader_ftd.cpp \
src/core/thread/network_data_local.cpp \
src/core/thread/network_data_notifier.cpp \
+ src/core/thread/network_data_service.cpp \
src/core/thread/network_diagnostic.cpp \
src/core/thread/panid_query_server.cpp \
src/core/thread/radio_selector.cpp \
src/core/thread/router_table.cpp \
src/core/thread/src_match_controller.cpp \
src/core/thread/thread_netif.cpp \
+ src/core/thread/time_sync_service.cpp \
src/core/thread/tmf.cpp \
src/core/thread/topology.cpp \
src/core/thread/uri_paths.cpp \
src/core/utils/channel_manager.cpp \
src/core/utils/channel_monitor.cpp \
src/core/utils/child_supervision.cpp \
- src/core/utils/dataset_updater.cpp \
+ src/core/utils/flash.cpp \
src/core/utils/heap.cpp \
src/core/utils/jam_detector.cpp \
src/core/utils/lookup_table.cpp \
+ src/core/utils/otns.cpp \
src/core/utils/parse_cmdline.cpp \
+ src/core/utils/ping_sender.cpp \
src/core/utils/slaac_address.cpp \
src/lib/hdlc/hdlc.cpp \
src/lib/platform/exit_code.c \
@@ -307,9 +342,12 @@
src/lib/url/url.cpp \
src/posix/platform/alarm.cpp \
src/posix/platform/backbone.cpp \
+ src/posix/platform/daemon.cpp \
src/posix/platform/entropy.cpp \
src/posix/platform/hdlc_interface.cpp \
+ src/posix/platform/infra_if.cpp \
src/posix/platform/logging.cpp \
+ src/posix/platform/memory.cpp \
src/posix/platform/misc.cpp \
src/posix/platform/multicast_routing.cpp \
src/posix/platform/netif.cpp \
@@ -318,7 +356,6 @@
src/posix/platform/settings.cpp \
src/posix/platform/spi_interface.cpp \
src/posix/platform/system.cpp \
- src/posix/platform/uart.cpp \
src/posix/platform/udp.cpp \
third_party/mbedtls/repo/library/aes.c \
third_party/mbedtls/repo/library/asn1parse.c \
@@ -351,9 +388,9 @@
third_party/mbedtls/repo/library/platform.c \
third_party/mbedtls/repo/library/platform_util.c \
third_party/mbedtls/repo/library/sha256.c \
- third_party/mbedtls/repo/library/ssl_cookie.c \
third_party/mbedtls/repo/library/ssl_ciphersuites.c \
third_party/mbedtls/repo/library/ssl_cli.c \
+ third_party/mbedtls/repo/library/ssl_cookie.c \
third_party/mbedtls/repo/library/ssl_srv.c \
third_party/mbedtls/repo/library/ssl_ticket.c \
third_party/mbedtls/repo/library/ssl_tls.c \
@@ -385,7 +422,6 @@
LOCAL_CFLAGS := \
$(OPENTHREAD_PUBLIC_CFLAGS) \
$(OPENTHREAD_PRIVATE_CFLAGS) \
- -DOPENTHREAD_CONFIG_UART_CLI_RAW=1 \
$(OPENTHREAD_PROJECT_CFLAGS) \
$(NULL)
@@ -399,11 +435,11 @@
src/cli/cli_coap.cpp \
src/cli/cli_coap_secure.cpp \
src/cli/cli_commissioner.cpp \
- src/cli/cli_console.cpp \
src/cli/cli_dataset.cpp \
src/cli/cli_joiner.cpp \
src/cli/cli_network_data.cpp \
- src/cli/cli_uart.cpp \
+ src/cli/cli_srp_client.cpp \
+ src/cli/cli_srp_server.cpp \
src/cli/cli_udp.cpp \
$(NULL)
@@ -414,6 +450,10 @@
LOCAL_MODULE := ot-cli
LOCAL_MODULE_TAGS := eng
+ifneq ($(ANDROID_NDK),1)
+LOCAL_SHARED_LIBRARIES := libcutils
+endif
+
LOCAL_C_INCLUDES := \
$(OPENTHREAD_PROJECT_INCLUDES) \
$(LOCAL_PATH)/include \
@@ -443,93 +483,13 @@
-lutil
LOCAL_SRC_FILES := \
+ src/posix/cli.cpp \
src/posix/main.c \
$(NULL)
LOCAL_STATIC_LIBRARIES = libopenthread-cli ot-core
include $(BUILD_EXECUTABLE)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libopenthread-ncp
-LOCAL_MODULE_TAGS := eng
-
-LOCAL_C_INCLUDES := \
- $(OPENTHREAD_PROJECT_INCLUDES) \
- $(LOCAL_PATH)/include \
- $(LOCAL_PATH)/src \
- $(LOCAL_PATH)/src/core \
- $(LOCAL_PATH)/src/ncp \
- $(LOCAL_PATH)/src/posix/platform \
- $(LOCAL_PATH)/src/posix/platform/include \
- $(LOCAL_PATH)/third_party/mbedtls \
- $(LOCAL_PATH)/third_party/mbedtls/repo/include \
- $(NULL)
-
-LOCAL_CFLAGS := \
- $(OPENTHREAD_PUBLIC_CFLAGS) \
- $(OPENTHREAD_PRIVATE_CFLAGS) \
- $(OPENTHREAD_PROJECT_CFLAGS) \
- $(NULL)
-
-LOCAL_CPPFLAGS := \
- -std=c++11 \
- -pedantic-errors \
- $(NULL)
-
-LOCAL_SRC_FILES := \
- src/lib/spinel/spinel_buffer.cpp \
- src/ncp/changed_props_set.cpp \
- src/ncp/ncp_base.cpp \
- src/ncp/ncp_base_mtd.cpp \
- src/ncp/ncp_base_ftd.cpp \
- src/ncp/ncp_base_dispatcher.cpp \
- src/ncp/ncp_uart.cpp \
- $(NULL)
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := ot-ncp
-LOCAL_MODULE_TAGS := eng
-
-LOCAL_C_INCLUDES := \
- $(OPENTHREAD_PROJECT_INCLUDES) \
- $(LOCAL_PATH)/include \
- $(LOCAL_PATH)/src \
- $(LOCAL_PATH)/src/core \
- $(LOCAL_PATH)/src/ncp \
- $(LOCAL_PATH)/src/posix/platform \
- $(LOCAL_PATH)/src/posix/platform/include \
- $(LOCAL_PATH)/third_party/mbedtls \
- $(LOCAL_PATH)/third_party/mbedtls/repo/include \
- $(NULL)
-
-LOCAL_CFLAGS := \
- $(OPENTHREAD_PUBLIC_CFLAGS) \
- $(OPENTHREAD_PRIVATE_CFLAGS) \
- -DOPENTHREAD_POSIX_APP_TYPE=OT_POSIX_APP_TYPE_NCP \
- $(OPENTHREAD_PROJECT_CFLAGS) \
- $(NULL)
-
-LOCAL_CPPFLAGS := \
- -std=c++11 \
- -pedantic-errors \
- $(NULL)
-
-LOCAL_SRC_FILES := \
- src/posix/main.c \
- $(NULL)
-
-LOCAL_LDLIBS := \
- -lrt \
- -lutil
-
-LOCAL_STATIC_LIBRARIES = libopenthread-ncp ot-core
-
-include $(BUILD_EXECUTABLE)
-
ifeq ($(USE_OTBR_DAEMON), 1)
include $(CLEAR_VARS)
@@ -564,3 +524,5 @@
ifneq ($(OPENTHREAD_PROJECT_ANDROID_MK),)
include $(OPENTHREAD_PROJECT_ANDROID_MK)
endif
+
+endif # ($(OPENTHREAD_ENABLE_ANDROID_MK),1)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b13e96a..2e7ae4a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,6 +37,7 @@
option(OT_BUILD_EXECUTABLES "Build executables" ON)
option(OT_COVERAGE "enable coverage" OFF)
set(OT_EXTERNAL_MBEDTLS "" CACHE STRING "Specify external mbedtls library")
+option(OT_MBEDTLS_THREADING "enable mbedtls threading" OFF)
add_library(ot-config INTERFACE)
@@ -57,9 +58,16 @@
include("${PROJECT_SOURCE_DIR}/etc/cmake/functions.cmake")
if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "default build type: Debug" FORCE)
+ # Check if this is a top-level CMake.
+ # If it is not, do not set the CMAKE_BUILD_TYPE because OpenThread is a part of something bigger.
+ if ("${CMAKE_PROJECT_NAME}" STREQUAL "openthread")
+ set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "default build type: Debug" FORCE)
+ endif ()
endif()
-message(STATUS "CMake build type: ${CMAKE_BUILD_TYPE}")
+
+if (CMAKE_BUILD_TYPE)
+ message(STATUS "OpenThread CMake build type: ${CMAKE_BUILD_TYPE}")
+endif ()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "(Apple)?[Cc]lang")
option(OT_COMPILE_WARNING_AS_ERROR "whether to include -Werror -pedantic-errors with gcc-compatible compilers")
@@ -91,7 +99,7 @@
"PACKAGE_VERSION=\"${OT_VERSION}\""
)
-set(OT_THREAD_VERSION "1.1" CACHE STRING "Thread version chosen by the user at configure time")
+set(OT_THREAD_VERSION "1.2" CACHE STRING "Thread version chosen by the user at configure time")
set_property(CACHE OT_THREAD_VERSION PROPERTY STRINGS "1.1" "1.2")
if(${OT_THREAD_VERSION} EQUAL "1.1")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_THREAD_VERSION=OT_THREAD_VERSION_1_1")
@@ -159,7 +167,13 @@
add_subdirectory("${PROJECT_SOURCE_DIR}/src/posix/platform")
elseif(OT_PLATFORM STREQUAL "external")
# skip in this case
-elseif(OT_PLATFORM)
+elseif(OT_PLATFORM MATCHES "^nrf*")
+ target_include_directories(ot-config INTERFACE ${PROJECT_SOURCE_DIR}/examples/platforms/nrf528xx/${OT_PLATFORM})
+ add_subdirectory("${PROJECT_SOURCE_DIR}/examples/platforms/nrf528xx")
+elseif(OT_PLATFORM MATCHES "^efr*")
+ target_include_directories(ot-config INTERFACE ${PROJECT_SOURCE_DIR}/examples/platforms/efr32/${OT_PLATFORM})
+ add_subdirectory("${PROJECT_SOURCE_DIR}/examples/platforms/efr32")
+else()
target_include_directories(ot-config INTERFACE ${PROJECT_SOURCE_DIR}/examples/platforms/${OT_PLATFORM})
add_subdirectory("${PROJECT_SOURCE_DIR}/examples/platforms/${OT_PLATFORM}")
endif()
@@ -186,7 +200,12 @@
if(OT_PLATFORM STREQUAL "simulation")
enable_testing()
- add_subdirectory(tests)
endif()
-add_custom_target(print-ot-config ALL COMMAND echo -e "$<JOIN:$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>,\"\\n\">")
+add_subdirectory(tests)
+
+add_custom_target(print-ot-config ALL
+ COMMAND ${CMAKE_COMMAND}
+ -DLIST="$<TARGET_PROPERTY:ot-config,INTERFACE_COMPILE_DEFINITIONS>"
+ -P ${PROJECT_SOURCE_DIR}/etc/cmake/print.cmake
+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6ead4f6..c33dbad 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -63,7 +63,7 @@
```bash
# Create a working branch for your new feature
-git branch --track <branch-name> origin/master
+git branch --track <branch-name> origin/main
# Checkout the branch
git checkout <branch-name>
@@ -85,16 +85,16 @@
Prior to submitting your pull request, you might want to do a few things to clean up your branch and make it as simple as possible for the original repo's maintainer to test, accept, and merge your work.
-If any commits have been made to the upstream master branch, you should rebase your development branch so that merging it will be a simple fast-forward that won't require any conflict resolution work.
+If any commits have been made to the upstream main branch, you should rebase your development branch so that merging it will be a simple fast-forward that won't require any conflict resolution work.
```bash
-# Fetch upstream master and merge with your repo's master branch
-git checkout master
-git pull upstream master
+# Fetch upstream main and merge with your repo's main branch
+git checkout main
+git pull upstream main
# If there were any new commits, rebase your development branch
git checkout <branch-name>
-git rebase master
+git rebase main
```
Now, it may be desirable to squash some of your smaller commits down into a small number of larger more cohesive commits. You can do this with an interactive rebase:
@@ -102,7 +102,7 @@
```bash
# Rebase all commits on your development branch
git checkout
-git rebase -i master
+git rebase -i main
```
This will open up a text editor where you can specify which commits to squash.
diff --git a/README.md b/README.md
index 09f3066..7b1f542 100644
--- a/README.md
+++ b/README.md
@@ -17,16 +17,16 @@
[thread]: http://threadgroup.org/technology/ourtechnology
[ot-repo]: https://github.com/openthread/openthread
[ot-logo]: doc/images/openthread_logo.png
-[ot-gh-action-build]: https://github.com/openthread/openthread/actions?query=workflow%3ABuild+branch%3Amaster+event%3Apush
-[ot-gh-action-build-svg]: https://github.com/openthread/openthread/workflows/Build/badge.svg?branch=master&event=push
-[ot-gh-action-simulation]: https://github.com/openthread/openthread/actions?query=workflow%3ASimulation+branch%3Amaster+event%3Apush
-[ot-gh-action-simulation-svg]: https://github.com/openthread/openthread/workflows/Simulation/badge.svg?branch=master&event=push
-[ot-gh-action-docker]: https://github.com/openthread/openthread/actions?query=workflow%3ADocker+branch%3Amaster+event%3Apush
-[ot-gh-action-docker-svg]: https://github.com/openthread/openthread/workflows/Docker/badge.svg?branch=master&event=push
+[ot-gh-action-build]: https://github.com/openthread/openthread/actions?query=workflow%3ABuild+branch%3Amain+event%3Apush
+[ot-gh-action-build-svg]: https://github.com/openthread/openthread/workflows/Build/badge.svg?branch=main&event=push
+[ot-gh-action-simulation]: https://github.com/openthread/openthread/actions?query=workflow%3ASimulation+branch%3Amain+event%3Apush
+[ot-gh-action-simulation-svg]: https://github.com/openthread/openthread/workflows/Simulation/badge.svg?branch=main&event=push
+[ot-gh-action-docker]: https://github.com/openthread/openthread/actions?query=workflow%3ADocker+branch%3Amain+event%3Apush
+[ot-gh-action-docker-svg]: https://github.com/openthread/openthread/workflows/Docker/badge.svg?branch=main&event=push
[ot-lgtm]: https://lgtm.com/projects/g/openthread/openthread/context:cpp
[ot-lgtm-svg]: https://img.shields.io/lgtm/grade/cpp/g/openthread/openthread.svg?logo=lgtm&logoWidth=18
[ot-codecov]: https://codecov.io/gh/openthread/openthread
-[ot-codecov-svg]: https://codecov.io/gh/openthread/openthread/branch/master/graph/badge.svg
+[ot-codecov-svg]: https://codecov.io/gh/openthread/openthread/branch/main/graph/badge.svg
# Who supports OpenThread?
@@ -51,9 +51,9 @@
# Contributing
-We would love for you to contribute to OpenThread and help make it even better than it is today! See our [Contributing Guidelines](https://github.com/openthread/openthread/blob/master/CONTRIBUTING.md) for more information.
+We would love for you to contribute to OpenThread and help make it even better than it is today! See our [Contributing Guidelines](https://github.com/openthread/openthread/blob/main/CONTRIBUTING.md) for more information.
-Contributors are required to abide by our [Code of Conduct](https://github.com/openthread/openthread/blob/master/CODE_OF_CONDUCT.md) and [Coding Conventions and Style Guide](https://github.com/openthread/openthread/blob/master/STYLE_GUIDE.md).
+Contributors are required to abide by our [Code of Conduct](https://github.com/openthread/openthread/blob/main/CODE_OF_CONDUCT.md) and [Coding Conventions and Style Guide](https://github.com/openthread/openthread/blob/main/STYLE_GUIDE.md).
# Versioning
@@ -61,7 +61,7 @@
# License
-OpenThread is released under the [BSD 3-Clause license](https://github.com/openthread/openthread/blob/master/LICENSE). See the [`LICENSE`](https://github.com/openthread/openthread/blob/master/LICENSE) file for more information.
+OpenThread is released under the [BSD 3-Clause license](https://github.com/openthread/openthread/blob/main/LICENSE). See the [`LICENSE`](https://github.com/openthread/openthread/blob/main/LICENSE) file for more information.
Please only use the OpenThread name and marks when accurately referencing this software distribution. Do not use the marks in a way that suggests you are endorsed by or otherwise affiliated with Nest, Google, or The Thread Group.
diff --git a/configure.ac b/configure.ac
index a6ed3be..8682eb0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -781,14 +781,14 @@
AC_ARG_WITH(examples,
[AS_HELP_STRING([--with-examples=TARGET],
[Build example applications for one of: simulation, cc1352, cc2538, cc2650, cc2652, efr32mg1, efr32mg12, efr32mg13, efr32mg21,
- gp712, jn5189, k32w061, kw41z, nrf52811, nrf52833, nrf52840, qpg6095, samr21 @<:@default=no@:>@.
+ gp712, jn5189, k32w061, kw41z, nrf52811, nrf52833, nrf52840, qpg6095, qpg6100, qpg7015m, samr21 @<:@default=no@:>@.
Note that building example applications also builds the associated OpenThread platform libraries
and any third_party libraries needed to support the examples.])],
[
case "${with_examples}" in
no)
;;
- simulation|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|k32w061|kw41z|nrf52811|nrf52833|nrf52840|qpg6095|samr21)
+ simulation|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|k32w061|kw41z|nrf52811|nrf52833|nrf52840|qpg6095|qpg6100|qpg7015m|samr21)
;;
*)
AC_MSG_RESULT(ERROR)
@@ -817,6 +817,8 @@
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_NRF52833], [test "${with_examples}" = "nrf52833"])
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_NRF52840], [test "${with_examples}" = "nrf52840"])
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_QPG6095], [test "${with_examples}" = "qpg6095"])
+AM_CONDITIONAL([OPENTHREAD_EXAMPLES_QPG6100], [test "${with_examples}" = "qpg6100"])
+AM_CONDITIONAL([OPENTHREAD_EXAMPLES_QPG7015M], [test "${with_examples}" = "qpg7015m"])
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_SAMR21], [test "${with_examples}" = "samr21"])
AM_COND_IF([OPENTHREAD_EXAMPLES_SIMULATION], CPPFLAGS="${CPPFLAGS} -DOPENTHREAD_EXAMPLES_SIMULATION=1", CPPFLAGS="${CPPFLAGS} -DOPENTHREAD_EXAMPLES_SIMULATION=0")
@@ -842,11 +844,11 @@
AC_ARG_WITH(platform,
[AS_HELP_STRING([--with-platform=TARGET],
[Build OpenThread platform libraries for one of: cc1352, cc2538, cc2650, cc2652,
- efr32mg1, efr32mg12, efr32mg13, efr32mg21, gp712, jn5189, kw41z, nrf52811, nrf52833, nrf52840, posix, qpg6095, samr21, simulation @<:@default=simulation@:>@.])],
+ efr32mg1, efr32mg12, efr32mg13, efr32mg21, gp712, jn5189, kw41z, nrf52811, nrf52833, nrf52840, posix, qpg6095, qpg6100, qpg7015m, samr21, simulation @<:@default=simulation@:>@.])],
[
# Make sure the given target is valid.
case "${with_platform}" in
- no|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|kw41z|nrf52811|nrf52833|nrf52840|posix|qpg6095|samr21|simulation)
+ no|cc1352|cc2538|cc2650|cc2652|efr32mg1|efr32mg12|efr32mg13|efr32mg21|gp712|jn5189|kw41z|nrf52811|nrf52833|nrf52840|posix|qpg6095|qpg6100|qpg7015m|samr21|simulation)
;;
*)
AC_MSG_RESULT(ERROR)
@@ -893,6 +895,8 @@
AM_CONDITIONAL([OPENTHREAD_PLATFORM_NRF52840], [test "${with_platform}" = "nrf52840"])
AM_CONDITIONAL([OPENTHREAD_PLATFORM_POSIX], [test "${with_platform}" = "posix"])
AM_CONDITIONAL([OPENTHREAD_PLATFORM_QPG6095], [test "${with_platform}" = "qpg6095"])
+AM_CONDITIONAL([OPENTHREAD_PLATFORM_QPG6100], [test "${with_platform}" = "qpg6100"])
+AM_CONDITIONAL([OPENTHREAD_PLATFORM_QPG7015M], [test "${with_platform}" = "qpg7015m"])
AM_CONDITIONAL([OPENTHREAD_PLATFORM_SAMR21], [test "${with_platform}" = "samr21"])
AM_CONDITIONAL([OPENTHREAD_PLATFORM_SIMULATION],[test "${with_platform}" = "simulation"])
@@ -1050,6 +1054,8 @@
examples/platforms/kw41z/Makefile
examples/platforms/nrf528xx/Makefile
examples/platforms/qpg6095/Makefile
+examples/platforms/qpg6100/Makefile
+examples/platforms/qpg7015m/Makefile
examples/platforms/samr21/Makefile
examples/platforms/simulation/Makefile
examples/platforms/utils/Makefile
diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h
index 02af682..af7348e 100644
--- a/doc/ot_api_doc.h
+++ b/doc/ot_api_doc.h
@@ -56,6 +56,8 @@
* @defgroup api-dns DNSv6
* @defgroup api-icmp6 ICMPv6
* @defgroup api-ip6 IPv6
+ * @defgroup api-srp SRP
+ * @defgroup api-ping-sender Ping Sender
* @defgroup api-udp-group UDP
*
* @{
@@ -92,6 +94,7 @@
* @defgroup api-thread-general General
* @brief This module includes functions for all Thread roles.
* @defgroup api-joiner Joiner
+ * @defgroup api-operational-dataset Operational Dataset
* @defgroup api-thread-router Router/Leader
* @brief This module includes functions for Thread Routers and Leaders.
* @defgroup api-server Server
diff --git a/doc/site/en/guides/porting/certification-and-readme.md b/doc/site/en/guides/porting/certification-and-readme.md
index 7ecb8c5..217568f 100644
--- a/doc/site/en/guides/porting/certification-and-readme.md
+++ b/doc/site/en/guides/porting/certification-and-readme.md
@@ -23,5 +23,5 @@
- Versions of libraries and toolchains used for validation of the port
See the
-[EFR32MG12 README](https://github.com/openthread/openthread/blob/master/examples/platforms/efr32/efr32mg12/README.md)
+[EFR32MG12 README](https://github.com/openthread/openthread/blob/main/examples/platforms/efr32/efr32mg12/README.md)
for an example.
diff --git a/doc/site/en/guides/porting/implement-advanced-features.md b/doc/site/en/guides/porting/implement-advanced-features.md
index 1880539..70c95c0 100644
--- a/doc/site/en/guides/porting/implement-advanced-features.md
+++ b/doc/site/en/guides/porting/implement-advanced-features.md
@@ -26,7 +26,7 @@
If the radio supports dynamically setting the Frame Pending bit in outgoing
acknowledgments to SEDs, the drivers must implement the
-[source address match](https://github.com/openthread/openthread/blob/master/include/openthread/platform/radio.h#L288)
+[source address match](https://github.com/openthread/openthread/blob/main/include/openthread/platform/radio.h#L288)
API to enable this capability. OpenThread uses this API to tell the radio which
SEDs to set the Frame Pending bit for.
@@ -55,7 +55,7 @@
> Note: This feature is optional.
mbedTLS defines several macros in the main configuration header file,
-[`mbedtls-config.h`](https://github.com/openthread/openthread/blob/master/third_party/mbedtls/mbedtls-config.h),
+[`mbedtls-config.h`](https://github.com/openthread/openthread/blob/main/third_party/mbedtls/mbedtls-config.h),
to allow users to enable alternative implementations of AES, SHA1, SHA2, and
other modules, as well as individual functions for the Elliptic curve
cryptography (ECC) over GF(p) module. See
@@ -89,7 +89,7 @@
the user-specific configuration header file for hardware acceleration.
For a complete example user-specific configuration, see the
-[`mbedtls_config_autogen.h`](https://github.com/openthread/openthread/blob/master/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h)
+[`mbedtls_config_autogen.h`](https://github.com/openthread/openthread/blob/main/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h)
file.
### AES module
diff --git a/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md b/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md
index a224bc7..147d4fd 100644
--- a/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md
+++ b/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md
@@ -36,30 +36,30 @@
API declaration:
-[`/openthread/include/openthread/platform/alarm-milli.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-milli.h)
+[`/openthread/include/openthread/platform/alarm-milli.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/alarm-milli.h)
The Alarm API provides fundamental timing and alarm services for the upper layer
timer implementation.
There are two alarm service types,
-[millisecond](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-milli.h)
-and [microsecond](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-micro.h).
+[millisecond](https://github.com/openthread/openthread/blob/main/include/openthread/platform/alarm-milli.h)
+and [microsecond](https://github.com/openthread/openthread/blob/main/include/openthread/platform/alarm-micro.h).
Millisecond is required for a new hardware platform. Microsecond is optional.
-## Step 2: UART
+## Step 2: UART
> Note: This API is optional.
API declaration:
-[`/openthread/include/openthread/platform/uart.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/uart.h)
+[`/openthread/examples/platforms/utils/uart.h`](https://github.com/openthread/openthread/blob/main/examples/platforms/utils/uart.h)
The UART API implements fundamental serial port communication via the UART
interface.
While the OpenThread
-[CLI](https://github.com/openthread/openthread/tree/master/examples/apps/cli)
-and [NCP](https://github.com/openthread/openthread/tree/master/examples/apps/ncp)
+[CLI](https://github.com/openthread/openthread/tree/main/examples/apps/cli)
+and [NCP](https://github.com/openthread/openthread/tree/main/examples/apps/ncp)
add-ons depend on the UART interface to interact with the host side, UART API
support is optional. However, even if you do not plan to use these add-ons on
your new hardware platform example, we highly recommend you add support for a
@@ -79,7 +79,7 @@
API declaration:
-[`/openthread/include/openthread/platform/radio.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/radio.h)
+[`/openthread/include/openthread/platform/radio.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/radio.h)
The Radio API defines all necessary functions called by the upper IEEE 802.15.4
MAC layer. The Radio chip must be fully compliant with the 2.4GHz IEEE
@@ -101,7 +101,7 @@
API declaration:
-[`/openthread/include/openthread/platform/misc.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/misc.h)
+[`/openthread/include/openthread/platform/misc.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/misc.h)
The Misc/Reset API provides a method to reset the software on the chip, and
query the reason for last reset.
@@ -112,7 +112,7 @@
API declaration:
-[`/openthread/include/openthread/platform/entropy.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/entropy.h)
+[`/openthread/include/openthread/platform/entropy.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/entropy.h)
The Entropy API provides a true random number generator (TRNG) for the upper
layer, which is used to maintain security assets for the entire OpenThread
@@ -142,11 +142,11 @@
API declarations:
-[`/openthread/include/openthread/platform/flash.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/flash.h)
+[`/openthread/include/openthread/platform/flash.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/flash.h)
**or**
-[`/openthread/include/openthread/platform/settings.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/settings.h)
+[`/openthread/include/openthread/platform/settings.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/settings.h)
The Non-volatile storage requirement can be satisfied by implementing one of the
two APIs listed above. The Flash API implements a flash storage driver, while
@@ -175,7 +175,7 @@
API declaration:
-[`/openthread/include/openthread/platform/logging.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/logging.h)
+[`/openthread/include/openthread/platform/logging.h`](https://github.com/openthread/openthread/blob/main/include/openthread/platform/logging.h)
The Logging API implements OpenThread's logging and debug functionality, with
multiple levels of debug output available. This API is optional if you do not
@@ -189,7 +189,7 @@
API declaration:
-[`/openthread/examples/platforms/openthread-system.h`](https://github.com/openthread/openthread/blob/master/examples/platforms/openthread-system.h)
+[`/openthread/examples/platforms/openthread-system.h`](https://github.com/openthread/openthread/blob/main/examples/platforms/openthread-system.h)
The System-specific API primarily provides initialization and deinitialization
operations for the selected hardware platform. This API is not called by the
@@ -199,6 +199,6 @@
Implementation of this API depends on your use case. If you wish to use the
generated [CLI and NCP applications](https://openthread.io/guides/build#binaries) for an [example
-platform](https://github.com/openthread/openthread/tree/master/examples/platforms),
+platform](https://github.com/openthread/openthread/tree/main/examples/platforms),
you must implement this API. Otherwise, any API can be implemented to integrate
the example platform drivers into your system/RTOS.
diff --git a/doc/site/en/guides/porting/index.md b/doc/site/en/guides/porting/index.md
index d721d75..ef97988 100644
--- a/doc/site/en/guides/porting/index.md
+++ b/doc/site/en/guides/porting/index.md
@@ -2,11 +2,11 @@
Porting the OpenThread stack to a new hardware platform consists of five steps:
-1. [Set up the build environment](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/set-up-the-build-environment.md)
-1. [Implement Platform Abstraction Layer APIs](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md)
-1. [Implement advanced features (Hardware Abstraction Layer)](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/implement-advanced-features.md)
-1. [Validate the port](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/validate-the-port.md)
-1. [Certification and README](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/certification-and-readme.md)
+1. [Set up the build environment](https://github.com/openthread/openthread/blob/main/doc/site/en/guides/porting/set-up-the-build-environment.md)
+1. [Implement Platform Abstraction Layer APIs](https://github.com/openthread/openthread/blob/main/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md)
+1. [Implement advanced features (Hardware Abstraction Layer)](https://github.com/openthread/openthread/blob/main/doc/site/en/guides/porting/implement-advanced-features.md)
+1. [Validate the port](https://github.com/openthread/openthread/blob/main/doc/site/en/guides/porting/validate-the-port.md)
+1. [Certification and README](https://github.com/openthread/openthread/blob/main/doc/site/en/guides/porting/certification-and-readme.md)
## Hardware platform requirements
diff --git a/doc/site/en/guides/porting/set-up-the-build-environment.md b/doc/site/en/guides/porting/set-up-the-build-environment.md
index 73cc493..f7a318b 100644
--- a/doc/site/en/guides/porting/set-up-the-build-environment.md
+++ b/doc/site/en/guides/porting/set-up-the-build-environment.md
@@ -20,7 +20,7 @@
conditional compilation in other Makefiles during the pre-compiling phase.
The OpenThread Autoconf script is located at:
-[`/openthread/configure.ac`](https://github.com/openthread/openthread/blob/master/configure.ac)
+[`/openthread/configure.ac`](https://github.com/openthread/openthread/blob/main/configure.ac)
### Platform example name
@@ -106,14 +106,14 @@
- `/openthread/examples/platforms/{platform-name}/Makefile.am`
- `/openthread/examples/platforms/{platform-name}/Makefile.platform.am`
-See [`/examples`](https://github.com/openthread/openthread/tree/master/examples/) for sample implementations of
+See [`/examples`](https://github.com/openthread/openthread/tree/main/examples/) for sample implementations of
these files.
The following Automake files also need to be updated with your platform
information:
-- [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.am)
-- [`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+- [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/main/examples/platforms/Makefile.am)
+- [`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/main/examples/platforms/Makefile.platform.am)
### Linker script configuration
@@ -145,7 +145,7 @@
```
Add the platform's linker script configuration to the
-[`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+[`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/main/examples/platforms/Makefile.platform.am)
utility Makefile:
```
@@ -156,7 +156,7 @@
### Subdirectory configuration
-Modify [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+Modify [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/main/examples/platforms/Makefile.platform.am)
to configure the package subdirectories for the new platform example.
Add the platform subdirectory name in the list for `make dist`, in alphabetical
@@ -214,4 +214,4 @@
> Note: Any non-original derivative code (for example, linker script or
toolchain startup code) must be contained in
-[`/openthread/third_party`](https://github.com/openthread/openthread/tree/master/third_party).
+[`/openthread/third_party`](https://github.com/openthread/openthread/tree/main/third_party).
diff --git a/etc/cmake/functions.cmake b/etc/cmake/functions.cmake
index 4cb0bef..f2ceff8 100755
--- a/etc/cmake/functions.cmake
+++ b/etc/cmake/functions.cmake
@@ -30,14 +30,18 @@
function(ot_get_platforms arg_platforms)
list(APPEND result "NO" "posix" "external")
set(platforms_dir "${PROJECT_SOURCE_DIR}/examples/platforms")
- file(GLOB platforms RELATIVE "${platforms_dir}" "${platforms_dir}/*")
+ file(GLOB platforms RELATIVE "${platforms_dir}" "${platforms_dir}/*"
+ RELATIVE "${platforms_dir}/nrf528xx" "${platforms_dir}/nrf528xx/nrf*"
+ RELATIVE "${platforms_dir}/efr32" "${platforms_dir}/efr32/efr32*")
foreach(platform IN LISTS platforms)
- if(IS_DIRECTORY "${platforms_dir}/${platform}")
+ if((IS_DIRECTORY "${platforms_dir}/${platform}") OR
+ (IS_DIRECTORY "${platforms_dir}/nrf528xx/${platform}") OR
+ (IS_DIRECTORY "${platforms_dir}/efr32/${platform}"))
list(APPEND result "${platform}")
endif()
endforeach()
- list(REMOVE_ITEM result utils)
+ list(REMOVE_ITEM result utils nrf528xx)
list(SORT result)
set(${arg_platforms} "${result}" PARENT_SCOPE)
endfunction()
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index 22f338b..f4cb897 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -72,6 +72,11 @@
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE=1")
endif()
+option(OT_BORDER_ROUTING "enable (duckhorn) border routing support")
+if(OT_BORDER_ROUTING)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1")
+endif()
+
if(NOT OT_EXTERNAL_MBEDTLS)
set(OT_MBEDTLS mbedtls)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS=1")
@@ -112,6 +117,11 @@
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE=1")
endif()
+option(OT_COAP_BLOCK "enable coap block-wise transfer (RFC7959) api support")
+if(OT_COAP_BLOCK)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE=1")
+endif()
+
option(OT_COAP_OBSERVE "enable coap observe (RFC7641) api support")
if(OT_COAP_OBSERVE)
list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE=1")
@@ -157,11 +167,21 @@
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1")
endif()
+option(OT_DNSSD_SERVER "enable DNS-SD server support")
+if(OT_DNSSD_SERVER)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1")
+endif()
+
option(OT_ECDSA "enable ECDSA support")
if(OT_ECDSA)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_ECDSA_ENABLE=1")
endif()
+option(OT_SRP_CLIENT "enable SRP client support")
+if (OT_SRP_CLIENT)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1")
+endif()
+
option(OT_DUA "enable Domain Unicast Address feature for Thread 1.2")
if(OT_DUA)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_DUA_ENABLE=1")
@@ -237,6 +257,11 @@
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1")
endif()
+option(OT_PING_SENDER "enable ping sender support" ${OT_APP_CLI})
+if(OT_PING_SENDER)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_PING_SENDER_ENABLE=1")
+endif()
+
option(OT_PLATFORM_NETIF "enable platform netif support")
if(OT_PLATFORM_NETIF)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE=1")
@@ -272,11 +297,21 @@
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE=1")
endif()
+option(OT_SRP_SERVER "enable SRP server")
+if (OT_SRP_SERVER)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_SRP_SERVER_ENABLE=1")
+endif()
+
option(OT_TIME_SYNC "enable the time synchronization service feature")
if(OT_TIME_SYNC)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_TIME_SYNC_ENABLE=1")
endif()
+option(OT_TREL "enable TREL radio link for Thread over Infrastructure feature")
+if (OT_TREL)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1")
+endif()
+
option(OT_UDP_FORWARD "enable UDP forward support")
if(OT_UDP_FORWARD)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1")
@@ -287,23 +322,6 @@
if(NOT OT_LOG_LEVEL)
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG")
endif()
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_API=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_ARP=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_BBR=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_CLI=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_COAP=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_DUA=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_ICMP=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_IP6=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_MAC=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_MEM=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_MESHCOP=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_MLE=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_MLR=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_NETDATA=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_NETDIAG=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PKT_DUMP=1")
- target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PLATFORM=1")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1")
target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1")
endif()
diff --git a/tests/scripts/expect/cli-anycast.exp b/etc/cmake/print.cmake
similarity index 71%
copy from tests/scripts/expect/cli-anycast.exp
copy to etc/cmake/print.cmake
index 3081a6b..13fcd64 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/etc/cmake/print.cmake
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +26,17 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+# Purpose of this CMake script is to support printing of properties fetched
+# using a generator expression.
+#
+# Depending on the generator in use, Ninja, Makefile, other, it is not possible
+# to always ensure proper new line on all platforms when calling echo.
+# The print.cmake handles this issue by taking a CMake list and prints each item
+# in the list on a new line.
+#
+# This script can be invoked as: `cmake -DLIST="itemA;itemB;..." -P print.cmake`
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+foreach(item ${LIST})
+ execute_process(COMMAND ${CMAKE_COMMAND} -E echo ${item})
+endforeach()
diff --git a/etc/gn/openthread.gni b/etc/gn/openthread.gni
index e692612..6774c3b 100644
--- a/etc/gn/openthread.gni
+++ b/etc/gn/openthread.gni
@@ -55,9 +55,6 @@
# Use external mbedtls. If blank, internal mbedtls will be used.
openthread_external_mbedtls = ""
- # Enable building for POSIX platforms.
- openthread_posix = current_os == "linux"
-
# Package name for OpenThread.
openthread_package_name = "OPENTHREAD"
@@ -73,7 +70,7 @@
if (openthread_enable_core_config_args) {
declare_args() {
# Thread version: 1.1, 1.2
- openthread_config_thread_version = ""
+ openthread_config_thread_version = "1.1"
# Log output: none, debug_uart, app, platform
openthread_config_log_output = ""
@@ -90,6 +87,9 @@
# Enable border router support
openthread_config_border_router_enable = false
+ # Enable border routing support
+ openthread_config_border_routing_enable = false
+
# Enable channel manager support
openthread_config_channel_manager_enable = false
@@ -126,6 +126,9 @@
# Enable DNS client support
openthread_config_dns_client_enable = false
+ # Enable DNS-SD server support
+ openthread_config_dnssd_server_enable = false
+
# Enable ECDSA support
openthread_config_ecdsa_enable = false
@@ -195,6 +198,15 @@
# Enable SNTP Client support
openthread_config_sntp_client_enable = false
+ # Enable SRP Client support
+ openthread_config_srp_client_enable = false
+
+ # Enable SRP Server support
+ openthread_config_srp_server_enable = false
+
+ # Enable ping sender support
+ openthread_config_ping_sender = false
+
# Enable the time synchronization service feature
openthread_config_time_sync_enable = false
@@ -210,8 +222,8 @@
# Enable NCP SPI support
openthread_config_ncp_spi_enable = false
- # Enable NCP UART support
- openthread_config_ncp_uart_enable = false
+ # Enable NCP HDLC support
+ openthread_config_ncp_hdlc_enable = false
# Enable builtin mbedtls management
openthread_config_enable_builtin_mbedtls_management =
diff --git a/examples/Makefile-efr32mg1 b/examples/Makefile-efr32mg1
index 4fc7590..0bb0703 100644
--- a/examples/Makefile-efr32mg1
+++ b/examples/Makefile-efr32mg1
@@ -73,15 +73,18 @@
EFR32_MBEDTLS_CPPFLAGS += -D$(MCU)
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/src
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/crypto
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/configs
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include/mbedtls
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/sl_crypto/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/CMSIS/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/Device/SiliconLabs/EFR32MG1P/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emlib/inc
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/radio/rail_lib/chip/efr32/efr32xg1x
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/silicon_labs/silabs_core/memory_manager
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include/mbedtls
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/library
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_alt/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/config
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_psa_driver/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/CMSIS/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/Device/SiliconLabs/EFR32MG1P/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emlib/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/radio/rail_lib/chip/efr32/efr32xg1x
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/silicon_labs/silabs_core/memory_manager
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/efr32/
HAL_CONF_DIR = $(CONFIG_FILE_PATH)/$(EFR32_PLATFORM)/$(BOARD_LOWERCASE)
diff --git a/examples/Makefile-efr32mg12 b/examples/Makefile-efr32mg12
index 02a8d3b..74fee97 100644
--- a/examples/Makefile-efr32mg12
+++ b/examples/Makefile-efr32mg12
@@ -43,14 +43,14 @@
PLATFORM_LOWERCASE = $(shell echo $(EFR32_PLATFORM) | tr A-Z a-z)
BOARD_LOWERCASE = $(shell echo $(BOARD) | tr A-Z a-z)
-configure_OPTIONS = \
- --enable-cli \
- --enable-ftd \
- --enable-mtd \
- --enable-ncp \
- --enable-radio-only \
- --enable-linker-map \
- --enable-builtin-mbedtls=no \
+configure_OPTIONS = \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --enable-ncp \
+ --enable-radio-only \
+ --enable-linker-map \
+ --enable-builtin-mbedtls=no \
--with-examples=$(EFR32_PLATFORM) \
MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)" \
$(NULL)
@@ -91,15 +91,18 @@
EFR32_MBEDTLS_CPPFLAGS += -D$(MCU)
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/src
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/crypto
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/configs
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include/mbedtls
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/sl_crypto/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/CMSIS/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/Device/SiliconLabs/EFR32MG12P/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emlib/inc
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/radio/rail_lib/chip/efr32/efr32xg1x
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/silicon_labs/silabs_core/memory_manager
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include/mbedtls
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/library
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_alt/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/config
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_psa_driver/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/CMSIS/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/Device/SiliconLabs/EFR32MG12P/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emlib/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/radio/rail_lib/chip/efr32/efr32xg1x
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/silicon_labs/silabs_core/memory_manager
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/efr32/
HAL_CONF_DIR = $(CONFIG_FILE_PATH)/$(EFR32_PLATFORM)/$(BOARD_LOWERCASE)
diff --git a/examples/Makefile-efr32mg13 b/examples/Makefile-efr32mg13
index 00828d9..59b9ec2 100644
--- a/examples/Makefile-efr32mg13
+++ b/examples/Makefile-efr32mg13
@@ -43,14 +43,14 @@
PLATFORM_LOWERCASE = $(shell echo $(EFR32_PLATFORM) | tr A-Z a-z)
BOARD_LOWERCASE = $(shell echo $(BOARD) | tr A-Z a-z)
-configure_OPTIONS = \
- --enable-cli \
- --enable-ftd \
- --enable-mtd \
- --enable-ncp \
- --enable-radio-only \
- --enable-linker-map \
- --enable-builtin-mbedtls=no \
+configure_OPTIONS = \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --enable-ncp \
+ --enable-radio-only \
+ --enable-linker-map \
+ --enable-builtin-mbedtls=no \
--with-examples=$(EFR32_PLATFORM) \
MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)" \
$(NULL)
@@ -76,16 +76,19 @@
EFR32_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls_config.h\"'
EFR32_MBEDTLS_CPPFLAGS += -D$(MCU)
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/src
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/efr32mg13/crypto
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/configs
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include/mbedtls
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/sl_crypto/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/CMSIS/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/Device/SiliconLabs/EFR32MG13P/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emlib/inc
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/radio/rail_lib/chip/efr32/efr32xg1x
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/silicon_labs/silabs_core/memory_manager
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/crypto
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include/mbedtls
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/library
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_alt/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/config
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_psa_driver/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/CMSIS/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/Device/SiliconLabs/EFR32MG13P/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emlib/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/radio/rail_lib/chip/efr32/efr32xg1x
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/silicon_labs/silabs_core/memory_manager
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/efr32/
HAL_CONF_DIR = $(CONFIG_FILE_PATH)/$(EFR32_PLATFORM)/$(BOARD_LOWERCASE)
diff --git a/examples/Makefile-efr32mg21 b/examples/Makefile-efr32mg21
index c2987aa..d003e33 100644
--- a/examples/Makefile-efr32mg21
+++ b/examples/Makefile-efr32mg21
@@ -43,14 +43,14 @@
PLATFORM_LOWERCASE = $(shell echo $(EFR32_PLATFORM) | tr A-Z a-z)
BOARD_LOWERCASE = $(shell echo $(BOARD) | tr A-Z a-z)
-configure_OPTIONS = \
- --enable-cli \
- --enable-ftd \
- --enable-mtd \
- --enable-ncp \
- --enable-radio-only \
- --enable-linker-map \
- --enable-builtin-mbedtls=no \
+configure_OPTIONS = \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --enable-ncp \
+ --enable-radio-only \
+ --enable-linker-map \
+ --enable-builtin-mbedtls=no \
--with-examples=$(EFR32_PLATFORM) \
MBEDTLS_CPPFLAGS="$(EFR32_MBEDTLS_CPPFLAGS)" \
$(NULL)
@@ -81,15 +81,20 @@
EFR32_MBEDTLS_CPPFLAGS += -D$(MCU)
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/src
EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/crypto
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/configs
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/include/mbedtls
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/third_party/mbedtls/sl_crypto/include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/CMSIS/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/Device/SiliconLabs/EFR32MG21/Include
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emlib/inc
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/radio/rail_lib/chip/efr32/efr32xg2x
-EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.0/util/silicon_labs/silabs_core/memory_manager
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/include/mbedtls
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/mbedtls/library
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/se_manager/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/se_manager/src
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_alt/include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/config
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_mbedtls_support/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/third_party/crypto/sl_component/sl_psa_driver/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/CMSIS/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/Device/SiliconLabs/EFR32MG21/Include
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emlib/inc
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/radio/rail_lib/chip/efr32/efr32xg2x
+EFR32_MBEDTLS_CPPFLAGS += -I$(AbsTopSourceDir)/third_party/silabs/gecko_sdk_suite/v3.1/util/silicon_labs/silabs_core/memory_manager
EFR32_MBEDTLS_CPPFLAGS += -Wno-unused-function
EFR32_MBEDTLS_CPPFLAGS += -Wno-unused-parameter
diff --git a/examples/Makefile-gp712 b/examples/Makefile-gp712
index ad08880..d14efa9 100644
--- a/examples/Makefile-gp712
+++ b/examples/Makefile-gp712
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, The OpenThread Authors.
+# Copyright (c) 2019, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -28,8 +28,10 @@
.NOTPARALLEL:
-TARGET ?= arm-bcm2708hardfp-linux-gnueabi
-PPREFIX = gp712
+TARGET ?= arm-linux-gnueabihf
+NAME = GP712
+PREFIX_UC = $(NAME)
+PREFIX_LC := $(shell echo $(PREFIX_UC) | tr A-Z a-z)
CROSS_COMPILE ?= $(TARGET)-
AR = $(CROSS_COMPILE)ar
@@ -45,63 +47,67 @@
BuildJobs ?= 9
-configure_OPTIONS = \
- --enable-cli \
- --enable-ftd \
- --enable-mtd \
- --with-examples=$(PPREFIX) \
+configure_OPTIONS = \
+ --disable-tools \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --enable-ncp \
+ --enable-cli-app \
+ --enable-radio-only \
+ --with-ncp-vendor-hook-source=no \
+ --with-ncp-bus=uart \
+ --with-examples=$(PREFIX_LC) \
$(NULL)
-DEFAULT_LOGGING ?= 1
-
ifeq ($(CLI_LOGGING),1)
configure_OPTIONS += --enable-cli-logging
endif
-GP712_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-gp712-config.h\"'
-GP712_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-gp712-config-check.h\"'
-GP712_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/gp712/
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-$(PREFIX_LC)-config.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-$(PREFIX_LC)-config-check.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/
-COMMONCFLAGS := \
- -fdata-sections \
- -ffunction-sections \
- -Os \
- -g \
- $(GP712_CONFIG_FILE_CPPFLAGS) \
- -W \
- -Wall \
+COMMONCFLAGS := \
+ -fdata-sections \
+ -ffunction-sections \
+ -Os \
+ $($(PREFIX_UC)_CONFIG_FILE_CPPFLAGS) \
+ -Wextra \
+ -Wall \
+ -Wno-psabi \
$(NULL)
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
-CPPFLAGS += \
- $(COMMONCFLAGS) \
- $(target_CPPFLAGS) \
+CPPFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CPPFLAGS) \
$(NULL)
-CFLAGS += \
- $(COMMONCFLAGS) \
- -D_BSD_SOURCE=1 \
- -D_DEFAULT_SOURCE=1 \
- $(target_CFLAGS) \
+CFLAGS += \
+ $(COMMONCFLAGS) \
+ -D_BSD_SOURCE=1 \
+ -D_DEFAULT_SOURCE=1 \
+ $(target_CFLAGS) \
$(NULL)
-CXXFLAGS += \
- $(COMMONCFLAGS) \
- $(target_CXXFLAGS) \
- -fno-exceptions \
- -fno-rtti \
+CXXFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CXXFLAGS) \
+ -fno-exceptions \
+ -fno-rtti \
$(NULL)
-LDFLAGS += \
- $(COMMONCFLAGS) \
- $(target_LDFLAGS) \
- -Wl,--gc-sections \
- -lrt \
- -lpthread \
+LDFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_LDFLAGS) \
+ -Wl,--gc-sections \
+ -Wl,-Map=$(PREFIX_LC).map \
+ -lrt \
+ -pthread \
$(NULL)
-
ECHO := @echo
MAKE := make
MKDIR_P := mkdir -p
@@ -122,15 +128,13 @@
TopResultDir = $(ResultPath)
AbsTopResultDir = $(PWD)/$(TopResultDir)
-TargetTuple = $(PPREFIX)
+TargetTuple = $(PREFIX_LC)
ifndef BuildJobs
BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
endif
JOBSFLAG := -j$(BuildJobs)
-PREFIX = $(PPREFIX)
-
#
# configure-arch <arch>
#
@@ -139,15 +143,15 @@
# arch - The architecture to configure.
#
define configure-arch
-$(ECHO) " CONFIG $(1)..."
+$(ECHO) " CONFIG $(1)"
(cd $(BuildPath)/$(1) && $(AbsTopSourceDir)/configure \
INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" \
---prefix=/$(PREFIX) \
+--prefix=/$(TargetTuple) \
--host=$(TARGET) \
--target=$(TARGET) \
---exec-prefix=/$(PREFIX) \
---program-prefix=$(PREFIX)- \
+--exec-prefix=/$(TargetTuple) \
+--program-prefix=$(TargetTuple)- \
$(configure_OPTIONS))
endef # configure-arch
diff --git a/examples/Makefile-nrf52811 b/examples/Makefile-nrf52811
index 317bd9c..6e38b30 100644
--- a/examples/Makefile-nrf52811
+++ b/examples/Makefile-nrf52811
@@ -91,14 +91,13 @@
# Otherwise, the default serial transport is UART.
#
ifndef DISABLE_TRANSPORTS
-configure_OPTIONS += --enable-ncp
configure_OPTIONS += --enable-radio-only
ifeq ($(NCP_SPI),1)
COMMONCFLAGS += -DSPIS_AS_SERIAL_TRANSPORT=1
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1
else
COMMONCFLAGS += -DUART_AS_SERIAL_TRANSPORT=1
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
configure_OPTIONS += --enable-cli
endif # NCP_SPI == 1
endif # DISABLE_TRANSPORTS
diff --git a/examples/Makefile-nrf52833 b/examples/Makefile-nrf52833
index 5f6ad35..9a5bb53 100644
--- a/examples/Makefile-nrf52833
+++ b/examples/Makefile-nrf52833
@@ -113,7 +113,7 @@
COMMONCFLAGS += -DSPIS_AS_SERIAL_TRANSPORT=1
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1
else
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
configure_OPTIONS += --enable-cli
ifeq ($(USB),1)
COMMONCFLAGS += -DUSB_CDC_AS_SERIAL_TRANSPORT=1
diff --git a/examples/Makefile-nrf52840 b/examples/Makefile-nrf52840
index e0b1576..8ea88f3 100644
--- a/examples/Makefile-nrf52840
+++ b/examples/Makefile-nrf52840
@@ -149,7 +149,7 @@
COMMONCFLAGS += -DSPIS_AS_SERIAL_TRANSPORT=1
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1
else
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
configure_OPTIONS += --enable-cli
ifeq ($(USB),1)
COMMONCFLAGS += -DUSB_CDC_AS_SERIAL_TRANSPORT=1
diff --git a/examples/Makefile-qpg6095 b/examples/Makefile-qpg6095
index 1b056ad..6354b12 100644
--- a/examples/Makefile-qpg6095
+++ b/examples/Makefile-qpg6095
@@ -27,12 +27,15 @@
#
.NOTPARALLEL:
+NAME = QPG6095
+PREFIX_UC = $(NAME)
+PREFIX_LC := $(shell echo $(PREFIX_UC) | tr A-Z a-z)
AR = arm-none-eabi-ar
-CCAS = $(CCPREFIX) arm-none-eabi-gcc
+CCAS = arm-none-eabi-gcc
CPP = arm-none-eabi-cpp
-CC = $(CCPREFIX) arm-none-eabi-gcc
-CXX = $(CCPREFIX) arm-none-eabi-g++
+CC = arm-none-eabi-gcc
+CXX = arm-none-eabi-g++
LD = arm-none-eabi-ld
STRIP = arm-none-eabi-strip
NM = arm-none-eabi-nm
@@ -42,63 +45,64 @@
BuildJobs ?= 10
GCCVersion = $(shell expr `$(CC) -dumpversion | cut -f1 -d.`)
-configure_OPTIONS = \
- --enable-cli \
- --enable-ftd \
- --enable-mtd \
- --enable-ncp \
- --enable-radio-only \
- --enable-linker-map \
- --with-examples=qpg6095 \
- MBEDTLS_CPPFLAGS="$(QPG6095_MBEDTLS_CPPFLAGS)" \
+configure_OPTIONS += \
+ --disable-tools \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --with-examples=$(PREFIX_LC) \
+ MBEDTLS_CPPFLAGS="$($(PREFIX_UC)_MBEDTLS_CPPFLAGS)" \
$(NULL)
TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
-QPG6095_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-qpg6095-config.h\"'
-QPG6095_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-qpg6095-config-check.h\"'
-QPG6095_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/qpg6095/
-QPG6095_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'
-QPG6095_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"qpg6095-mbedtls-config.h\"'
-QPG6095_MBEDTLS_CPPFLAGS += -I$(PWD)/examples/platforms/qpg6095/crypto
-QPG6095_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls
-QPG6095_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include
-QPG6095_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include/mbedtls
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-$(PREFIX_LC)-config.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-$(PREFIX_LC)-config-check.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"$(PREFIX_LC)-mbedtls-config.h\"'
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/crypto
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include/mbedtls
-COMMONCFLAGS := \
- -fdata-sections \
- -ffunction-sections \
- -Os \
- -g \
- $(QPG6095_CONFIG_FILE_CPPFLAGS) \
+COMMONCFLAGS := \
+ -fdata-sections \
+ -ffunction-sections \
+ -Os \
+ $($(PREFIX_UC)_CONFIG_FILE_CPPFLAGS) \
+ -Wall \
+ -Wextra \
$(NULL)
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
-CPPFLAGS += \
- $(COMMONCFLAGS) \
- $(target_CPPFLAGS) \
+CPPFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CPPFLAGS) \
$(NULL)
-CFLAGS += \
- $(COMMONCFLAGS) \
- $(target_CFLAGS) \
+CFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CFLAGS) \
$(NULL)
-CXXFLAGS += \
- $(COMMONCFLAGS) \
- $(target_CXXFLAGS) \
- -fno-exceptions \
- -fno-rtti \
+CXXFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CXXFLAGS) \
+ -fno-exceptions \
+ -fno-rtti \
$(NULL)
-LDFLAGS += \
- $(COMMONCFLAGS) \
- $(target_LDFLAGS) \
- -specs=nano.specs \
- -specs=nosys.specs \
- -Wl,--gc-sections \
+LDFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_LDFLAGS) \
+ -specs=nano.specs \
+ -specs=nosys.specs \
+ -Wl,--gc-sections \
+ -nostdlib \
+ -Wl,-Map=$(PREFIX_LC).map,--cref \
$(NULL)
ECHO := @echo
@@ -118,7 +122,7 @@
TopResultDir = $(ResultPath)
AbsTopResultDir = $(PWD)/$(TopResultDir)
-TargetTuple = qpg6095
+TargetTuple = $(PREFIX_LC)
ARCHS = cortex-m4
@@ -137,13 +141,13 @@
# arch - The architecture to configure.
#
define configure-arch
-$(ECHO) " CONFIG $(TargetTuple)..."
+$(ECHO) " CONFIG $(TargetTuple)"
(cd $(BuildPath)/$(TargetTuple) && $(AbsTopSourceDir)/configure \
INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" CCAS="$(CCAS)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CCASFLAGS="$(CCASFLAGS)" LDFLAGS="$(LDFLAGS)" \
--host=arm-none-eabi \
---prefix=/ \
---exec-prefix=/$(TargetTuple) \
+--prefix=/$(TargetTuple) \
+--program-prefix=$(TargetTuple)- \
$(configure_OPTIONS))
endef # configure-arch
@@ -179,8 +183,8 @@
# @FIXME: get the filenames of the targets of OBJCOPY (now they are hardcoded)
define hex-arch
$(ECHO) " HEX $(TargetTuple)"
-$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/ot-cli-mtd $(AbsTopResultDir)/$(TargetTuple)/bin/ot-cli-mtd.hex
-$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/ot-cli-ftd $(AbsTopResultDir)/$(TargetTuple)/bin/ot-cli-ftd.hex
+$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-mtd $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-mtd.hex
+$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-ftd $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-ftd.hex
endef # hex-arch
#
diff --git a/examples/Makefile-qpg6100 b/examples/Makefile-qpg6100
new file mode 100644
index 0000000..eab6ac6
--- /dev/null
+++ b/examples/Makefile-qpg6100
@@ -0,0 +1,290 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+.NOTPARALLEL:
+NAME = QPG6100
+PREFIX_UC = $(NAME)
+PREFIX_LC := $(shell echo $(PREFIX_UC) | tr A-Z a-z)
+
+AR = arm-none-eabi-ar
+CCAS = arm-none-eabi-gcc
+CPP = arm-none-eabi-cpp
+CC = arm-none-eabi-gcc
+CXX = arm-none-eabi-g++
+LD = arm-none-eabi-ld
+STRIP = arm-none-eabi-strip
+NM = arm-none-eabi-nm
+RANLIB = arm-none-eabi-ranlib
+OBJCOPY = arm-none-eabi-objcopy
+
+BuildJobs ?= 10
+GCCVersion = $(shell expr `$(CC) -dumpversion | cut -f1 -d.`)
+
+configure_OPTIONS += \
+ --disable-tools \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --with-examples=$(PREFIX_LC) \
+ MBEDTLS_CPPFLAGS="$($(PREFIX_UC)_MBEDTLS_CPPFLAGS)" \
+ $(NULL)
+
+TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
+AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
+
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-$(PREFIX_LC)-config.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-$(PREFIX_LC)-config-check.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"$(PREFIX_LC)-mbedtls-config.h\"'
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/crypto
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -DQORVO_CRYPTO_ENGINE
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include
+$(PREFIX_UC)_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo/include/mbedtls
+
+COMMONCFLAGS := \
+ -fdata-sections \
+ -ffunction-sections \
+ -Os \
+ $($(PREFIX_UC)_CONFIG_FILE_CPPFLAGS) \
+ -Wall \
+ -Wextra \
+ $(NULL)
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
+
+CPPFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CPPFLAGS) \
+ $(NULL)
+
+CFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CFLAGS) \
+ $(NULL)
+
+CXXFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CXXFLAGS) \
+ -fno-exceptions \
+ -fno-rtti \
+ $(NULL)
+
+LDFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_LDFLAGS) \
+ -specs=nano.specs \
+ -specs=nosys.specs \
+ -Wl,--gc-sections \
+ -nostdlib \
+ -Wl,-Map=$(PREFIX_LC).map,--cref \
+ $(NULL)
+
+ECHO := @echo
+MAKE := make
+MKDIR_P := mkdir -p
+LN_S := ln -s
+RM_F := rm -f
+
+INSTALL := /usr/bin/install
+INSTALLFLAGS := -p
+
+BuildPath = build
+TopBuildDir = $(BuildPath)
+AbsTopBuildDir = $(PWD)/$(TopBuildDir)
+
+ResultPath = output
+TopResultDir = $(ResultPath)
+AbsTopResultDir = $(PWD)/$(TopResultDir)
+
+TargetTuple = $(PREFIX_LC)
+
+ARCHS = cortex-m4
+
+TopTargetLibDir = $(TopResultDir)/$(TargetTuple)/lib
+
+ifndef BuildJobs
+BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
+endif
+JOBSFLAG := -j$(BuildJobs)
+
+#
+# configure-arch <arch>
+#
+# Configure OpenThread for the specified architecture.
+#
+# arch - The architecture to configure.
+#
+define configure-arch
+$(ECHO) " CONFIG $(TargetTuple)"
+(cd $(BuildPath)/$(TargetTuple) && $(AbsTopSourceDir)/configure \
+INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" CCAS="$(CCAS)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" CCASFLAGS="$(CCASFLAGS)" LDFLAGS="$(LDFLAGS)" \
+--host=arm-none-eabi \
+--prefix=/$(TargetTuple) \
+--program-prefix=$(TargetTuple)- \
+$(configure_OPTIONS))
+endef # configure-arch
+
+#
+# build-arch <arch>
+#
+# Build the OpenThread intermediate build products for the specified
+# architecture.
+#
+# arch - The architecture to build.
+#
+define build-arch
+$(ECHO) " BUILD $(TargetTuple)"
+$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \
+all
+endef # build-arch
+
+#
+# stage-arch <arch>
+#
+# Stage (install) the OpenThread final build products for the specified
+# architecture.
+#
+# arch - The architecture to stage.
+#
+define stage-arch
+$(ECHO) " STAGE $(TargetTuple)"
+$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(TargetTuple) --no-print-directory \
+DESTDIR=$(AbsTopResultDir) \
+install
+endef # stage-arch
+
+# @FIXME: get the filenames of the targets of OBJCOPY (now they are hardcoded)
+define hex-arch
+$(ECHO) " HEX $(TargetTuple)"
+$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-mtd $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-mtd.hex
+$(OBJCOPY) -O ihex $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-ftd $(AbsTopResultDir)/$(TargetTuple)/bin/$(TargetTuple)-ot-cli-ftd.hex
+endef # hex-arch
+
+#
+# ARCH_template <arch>
+#
+# Define macros, targets and rules to configure, build, and stage the
+# OpenThread for a single architecture.
+#
+# arch - The architecture to instantiate the template for.
+#
+define ARCH_template
+CONFIGURE_TARGETS += configure-$(1)
+BUILD_TARGETS += do-build-$(1)
+HEX_TARGETS += hex-$(1)
+STAGE_TARGETS += stage-$(1)
+BUILD_DIRS += $(BuildPath)/$(TargetTuple)
+DIRECTORIES += $(BuildPath)/$(TargetTuple)
+
+configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS)
+configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS)
+configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS)
+configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS)
+configure-$(1): target_CCASFLAGS=$($(1)_target_CCASFLAGS)
+
+configure-$(1): $(BuildPath)/$(TargetTuple)/config.status
+
+$(BuildPath)/$(TargetTuple)/config.status: | $(BuildPath)/$(TargetTuple)
+ $$(call configure-arch,$(1))
+
+do-build-$(1): configure-$(1)
+
+do-build-$(1):
+ +$$(call build-arch,$(1))
+
+hex-$(1): stage-$(1)
+
+hex-$(1):
+ $$(call hex-arch,$(1))
+
+$(1): hex-$(1)
+
+stage-$(1): do-build-$(1)
+
+stage-$(1): | $(TopResultDir)
+ $$(call stage-arch,$(1))
+endef # ARCH_template
+
+.DEFAULT_GOAL := all
+
+all: hex
+
+#
+# cortex-m4
+#
+
+cortex-m4_target_ABI = cortex-m4
+cortex-m4_target_CPPFLAGS = -mcpu=cortex-m4 -mthumb -ffunction-sections
+cortex-m4_target_CFLAGS = -mcpu=cortex-m4 -mthumb -ffunction-sections
+cortex-m4_target_CXXFLAGS = -mcpu=cortex-m4 -mthumb -ffunction-sections
+cortex-m4_target_LDFLAGS = -mcpu=cortex-m4 -mthumb -ffunction-sections
+
+# Instantiate an architecture-specific build template for each target
+# architecture.
+
+$(foreach arch,$(ARCHS),$(eval $(call ARCH_template,$(arch))))
+
+#
+# Common / Finalization
+#
+
+configure: $(CONFIGURE_TARGETS)
+
+build: $(BUILD_TARGETS)
+
+stage: $(STAGE_TARGETS)
+
+hex: $(HEX_TARGETS)
+
+DIRECTORIES = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS)
+
+CLEAN_DIRS = $(TopResultDir) $(BUILD_DIRS)
+
+all: hex
+
+$(DIRECTORIES):
+ $(ECHO) " MKDIR $@"
+ @$(MKDIR_P) "$@"
+
+clean:
+ $(ECHO) " CLEAN"
+ @$(RM_F) -r $(CLEAN_DIRS)
+
+help:
+ $(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following "
+ $(ECHO) "architectures: "
+ $(ECHO) ""
+ $(ECHO) " $(ARCHS)"
+ $(ECHO) ""
+ $(ECHO) "To build only a particular architecture, specify: "
+ $(ECHO) ""
+ $(ECHO) " make -f $(firstword $(MAKEFILE_LIST)) <architecture>"
+ $(ECHO) ""
diff --git a/examples/Makefile-qpg7015m b/examples/Makefile-qpg7015m
new file mode 100755
index 0000000..1ad3366
--- /dev/null
+++ b/examples/Makefile-qpg7015m
@@ -0,0 +1,277 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+.NOTPARALLEL:
+
+TARGET ?= arm-linux-gnueabihf
+NAME = QPG7015M
+PREFIX_UC = $(NAME)
+PREFIX_LC := $(shell echo $(PREFIX_UC) | tr A-Z a-z)
+CROSS_COMPILE ?= $(TARGET)-
+
+AR = $(CROSS_COMPILE)ar
+AS = $(CROSS_COMPILE)as
+CPP = $(CROSS_COMPILE)cpp
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
+LD = $(CROSS_COMPILE)ld
+STRIP = $(CROSS_COMPILE)strip
+NM = $(CROSS_COMPILE)nm
+RANLIB = $(CROSS_COMPILE)ranlib
+OBJCOPY = $(CROSS_COMPILE)objcopy
+
+BuildJobs ?= 9
+
+configure_OPTIONS = \
+ --disable-tools \
+ --enable-cli \
+ --enable-ftd \
+ --enable-mtd \
+ --enable-ncp \
+ --enable-cli-app \
+ --enable-radio-only \
+ --with-ncp-vendor-hook-source=no \
+ --with-ncp-bus=uart \
+ --with-examples=$(PREFIX_LC) \
+ $(NULL)
+
+ifeq ($(CLI_LOGGING),1)
+configure_OPTIONS += --enable-cli-logging
+endif
+
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-$(PREFIX_LC)-config.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-$(PREFIX_LC)-config-check.h\"'
+$(PREFIX_UC)_CONFIG_FILE_CPPFLAGS += -I$(PWD)/examples/platforms/$(PREFIX_LC)/
+
+COMMONCFLAGS := \
+ -fdata-sections \
+ -ffunction-sections \
+ -Os \
+ $($(PREFIX_UC)_CONFIG_FILE_CPPFLAGS) \
+ -Wextra \
+ -Wall \
+ -Wno-psabi \
+ $(NULL)
+
+include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
+
+CPPFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CPPFLAGS) \
+ $(NULL)
+
+CFLAGS += \
+ $(COMMONCFLAGS) \
+ -D_BSD_SOURCE=1 \
+ -D_DEFAULT_SOURCE=1 \
+ $(target_CFLAGS) \
+ $(NULL)
+
+CXXFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_CXXFLAGS) \
+ -fno-exceptions \
+ -fno-rtti \
+ $(NULL)
+
+LDFLAGS += \
+ $(COMMONCFLAGS) \
+ $(target_LDFLAGS) \
+ -Wl,--gc-sections \
+ -Wl,-Map=$(PREFIX_LC).map \
+ -lrt \
+ -pthread \
+ $(NULL)
+
+ECHO := @echo
+MAKE := make
+MKDIR_P := mkdir -p
+LN_S := ln -s
+RM_F := rm -f
+
+INSTALL := /usr/bin/install
+INSTALLFLAGS := -p
+
+TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
+AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
+
+BuildPath = build
+TopBuildDir = $(BuildPath)
+AbsTopBuildDir = $(PWD)/$(TopBuildDir)
+
+ResultPath = output
+TopResultDir = $(ResultPath)
+AbsTopResultDir = $(PWD)/$(TopResultDir)
+
+TargetTuple = $(PREFIX_LC)
+
+ifndef BuildJobs
+BuildJobs := $(shell getconf _NPROCESSORS_ONLN)
+endif
+JOBSFLAG := -j$(BuildJobs)
+
+#
+# configure-arch <arch>
+#
+# Configure OpenThread for the specified architecture.
+#
+# arch - The architecture to configure.
+#
+define configure-arch
+$(ECHO) " CONFIG $(1)"
+(cd $(BuildPath)/$(1) && $(AbsTopSourceDir)/configure \
+INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)" OBJC="$(OBJC)" OBJCXX="$(OBJCXX)" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" STRIP="$(STRIP)" CPPFLAGS="$(CPPFLAGS)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" \
+--prefix=/$(TargetTuple) \
+--host=$(TARGET) \
+--target=$(TARGET) \
+--exec-prefix=/$(TargetTuple) \
+--program-prefix=$(TargetTuple)- \
+$(configure_OPTIONS))
+endef # configure-arch
+
+#
+# build-arch <arch>
+#
+# Build the OpenThread intermediate build products for the specified
+# architecture.
+#
+# arch - The architecture to build.
+#
+define build-arch
+$(ECHO) " BUILD $(1)"
+$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(1) -w \
+all
+endef # build-arch
+
+#
+# stage-arch <arch>
+#
+# Stage (install) the OpenThread final build products for the specified
+# architecture.
+#
+# arch - The architecture to stage.
+#
+define stage-arch
+$(ECHO) " STAGE $(1)"
+$(MAKE) $(JOBSFLAG) -C $(BuildPath)/$(1) -w \
+DESTDIR=$(AbsTopResultDir) \
+install
+endef # stage-arch
+
+#
+# ARCH_template <arch>
+#
+# Define macros, targets and rules to configure, build, and stage the
+# OpenThread for a single architecture.
+#
+# arch - The architecture to instantiate the template for.
+#
+define ARCH_template
+CONFIGURE_TARGETS += configure-$(1)
+BUILD_TARGETS += do-build-$(1)
+STAGE_TARGETS += stage-$(1)
+BUILD_DIRS += $(BuildPath)/$(1)
+DIRECTORIES += $(BuildPath)/$(1)
+
+configure-$(1): target_CPPFLAGS=$($(1)_target_CPPFLAGS)
+configure-$(1): target_CFLAGS=$($(1)_target_CFLAGS)
+configure-$(1): target_CXXFLAGS=$($(1)_target_CXXFLAGS)
+configure-$(1): target_LDFLAGS=$($(1)_target_LDFLAGS)
+
+configure-$(1): $(BuildPath)/$(1)/config.status
+
+$(BuildPath)/$(1)/config.status: | $(BuildPath)/$(1)
+ $$(call configure-arch,$(1))
+
+do-build-$(1): configure-$(1)
+
+do-build-$(1):
+ +$$(call build-arch,$(1))
+
+stage-$(1): do-build-$(1)
+
+stage-$(1): | $(TopResultDir)
+ $$(call stage-arch,$(1))
+
+$(1): stage-$(1)
+endef # ARCH_template
+
+.DEFAULT_GOAL := all
+
+all: stage
+
+#
+# rpi_bcm2708
+#
+
+rpi_bcm2708_target_ABI = rpi_bcm2708
+rpi_bcm2708_target_CPPFLAGS = -march=armv6j -fomit-frame-pointer -fno-strict-aliasing -fno-pic -ffreestanding -mfloat-abi=hard -mfpu=vfp -pipe
+rpi_bcm2708_target_CFLAGS = -march=armv6j -fomit-frame-pointer -fno-strict-aliasing -fno-pic -ffreestanding -mfloat-abi=hard -mfpu=vfp -pipe
+rpi_bcm2708_target_CXXFLAGS = -march=armv6j -fomit-frame-pointer -fno-strict-aliasing -fno-pic -ffreestanding -mfloat-abi=hard -mfpu=vfp -pipe
+rpi_bcm2708_target_LDFLAGS = -march=armv6j -fomit-frame-pointer -fno-strict-aliasing -fno-pic -ffreestanding -mfloat-abi=hard -mfpu=vfp -pipe
+
+# Instantiate an architecture-specific build template for each target
+# architecture.
+
+$(foreach arch,$(TargetTuple),$(eval $(call ARCH_template,$(arch))))
+
+#
+# Common / Finalization
+#
+
+configure: $(CONFIGURE_TARGETS)
+
+build: $(BUILD_TARGETS)
+
+stage: $(STAGE_TARGETS)
+
+DIRECTORIES = $(TopResultDir) $(TopResultDir)/$(TargetTuple)/lib $(BUILD_DIRS)
+
+CLEAN_DIRS = $(TopResultDir) $(BUILD_DIRS)
+
+all: stage
+
+$(DIRECTORIES):
+ $(ECHO) " MKDIR $@"
+ @$(MKDIR_P) "$@"
+
+clean:
+ $(ECHO) " CLEAN"
+ @$(RM_F) -r $(CLEAN_DIRS)
+
+help:
+ $(ECHO) "Simply type 'make -f $(firstword $(MAKEFILE_LIST))' to build OpenThread for the following "
+ $(ECHO) "architectures: "
+ $(ECHO) ""
+ $(ECHO) " $(TargetTuple)"
+ $(ECHO) ""
+ $(ECHO) "To build only a particular architecture, specify: "
+ $(ECHO) ""
+ $(ECHO) " make -f $(firstword $(MAKEFILE_LIST)) <architecture>"
+ $(ECHO) ""
diff --git a/examples/Makefile-simulation b/examples/Makefile-simulation
index 755e2c6..d1d4a11 100644
--- a/examples/Makefile-simulation
+++ b/examples/Makefile-simulation
@@ -38,6 +38,7 @@
BORDER_AGENT ?= 1
BORDER_ROUTER ?= 1
COAP ?= 1
+COAP_BLOCK ?= 1
COAP_OBSERVE ?= 1
COAPS ?= 1
COMMISSIONER ?= 1
@@ -49,6 +50,7 @@
DHCP6_SERVER ?= 1
DIAGNOSTIC ?= 1
DNS_CLIENT ?= 1
+DNSSD_SERVER ?= 1
ECDSA ?= 1
IP6_FRAGM ?= 1
JAM_DETECTION ?= 1
@@ -57,9 +59,12 @@
LINK_RAW ?= 1
MAC_FILTER ?= 1
MTD_NETDIAG ?= 1
+PING_SENDER ?= 1
REFERENCE_DEVICE ?= 1
SERVICE ?= 1
SNTP_CLIENT ?= 1
+SRP_CLIENT ?= 1
+SRP_SERVER ?= 1
UDP_FORWARD ?= 1
COMMONCFLAGS := \
@@ -89,7 +94,7 @@
ifeq ($(NCP_SPI),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1
else
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
endif # NCP_SPI == 1
ifeq ($(OTNS),1)
diff --git a/examples/README.md b/examples/README.md
index 0ad87a1..f88c4b6 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -14,7 +14,6 @@
| CHANNEL_MANAGER | OT_CHANNEL_MANAGER | Enables support for channel manager. Enable this switch on devices that are supposed to request a Thread network channel change. This switch should be used only with an FTD build. |
| CHANNEL_MONITOR | OT_CHANNEL_MONITOR | Enables support for channel monitor. Enable this switch on devices that are supposed to determine the cleaner channels. |
| CHILD_SUPERVISION | OT_CHILD_SUPERVISION | Enables support for [child supervision](https://openthread.io/guides/build/features/child-supervision). Enable this switch on a parent or child node with custom OpenThread application that manages the supervision, checks timeout intervals, and verifies connectivity between parent and child. |
-| CLI_TRANSPORT | not implemented | Selects the transport of CLI. You can set this switch to UART (default) or CONSOLE. |
| COAP | OT_COAP | Enables support for the CoAP API. Enable this switch if you want to control Constrained Application Protocol communication. |
| COAP_OBSERVE | OT_COAP_OBSERVE | Enables support for CoAP Observe (RFC7641) API. |
| COAPS | OT_COAPS | Enables support for the secure CoAP API. Enable this switch if you want to control Constrained Application Protocol Secure (CoAP over DTLS) communication. |
@@ -32,6 +31,7 @@
| DEBUG_UART | not implemented | Enables the Debug UART platform feature. |
| DEBUG_UART_LOG | not implemented | Enables the log output for the debug UART. Requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART to be enabled. |
| DNS_CLIENT | OT_DNS_CLIENT | Enables support for DNS client. Enable this switch on a device that sends a DNS query for AAAA (IPv6) record. |
+| DNSSD_SERVER | OT_DNSSD_SERVER | Enables support for DNS-SD server. DNS-SD server use service information from local SRP server to resolve DNS-SD query questions. |
| DUA | OT_DUA | Enables the Domain Unicast Address feature for Thread 1.2. |
| DYNAMIC_LOG_LEVEL | not implemented | Enables the dynamic log level feature. Enable this switch if OpenThread log level is required to be set at runtime. See [Logging guide](https://openthread.io/guides/build/logs) to learn more. |
| ECDSA | OT_ECDSA | Enables support for Elliptic Curve Digital Signature Algorithm. Enable this switch if ECDSA digital signature is used by application. |
@@ -48,6 +48,7 @@
| MLR | OT_MLR | Enables Multicast Listener Registration feature for Thread 1.2. |
| MTD_NETDIAG | OT_MTD_NETDIAG | Enables the TMF network diagnostics on MTDs. |
| MULTIPLE_INSTANCE | OT_MULTIPLE_INSTANCE | Enables multiple OpenThread instances. |
+| PING_SENDER | OT_PING_SENDER | Enables support for ping sender. |
| OTNS | OT_OTNS | Enables support for [OpenThread Network Simulator](https://github.com/openthread/ot-ns). Enable this switch if you are building OpenThread for OpenThread Network Simulator. |
| PLATFORM_UDP | OT_PLATFORM_UDP | Enables platform UDP support. |
| REFERENCE_DEVICE | OT_REFERENCE_DEVICE | Enables support for Thread Test Harness reference device. Enable this switch on the reference device during certification. |
@@ -56,6 +57,9 @@
| SLAAC | OT_SLAAC | Enables support for adding auto-configured SLAAC addresses by OpenThread. This feature is enabled by default. |
| SNTP_CLIENT | OT_SNTP_CLIENT | Enables support for SNTP Client. |
| SPINEL_ENCRYPTER_LIBS | not implemented | Specifies library files (absolute paths) for implementing the NCP Spinel Encrypter. |
+| SRP_CLIENT | OT_SRP_CLIENT | Enable support for SRP client. |
+| SRP_SERVER | OT_SRP_SERVER | Enable support for SRP server. |
| THREAD_VERSION | OT_THREAD_VERSION | Enables the chosen Thread version (1.1 (default) / 1.2). For example, set to `1.2` for Thread 1.2. |
| TIME_SYNC | OT_TIME_SYNC | Enables the time synchronization service feature. **Note: Enabling this feature breaks conformance to the Thread Specification.** | |
+| TREL | OT_TREL | Enables TREL radio link for Thread over Infrastructure feature. |
| UDP_FORWARD | OT_UDP_FORWARD | Enables support for UDP forward. | Enable this switch on the Border Router device (running on the NCP design) with External Commissioning support to service Thread Commissioner packets on the NCP side. |
diff --git a/examples/apps/Makefile.am b/examples/apps/Makefile.am
index 8abfc8b..004a98f 100644
--- a/examples/apps/Makefile.am
+++ b/examples/apps/Makefile.am
@@ -47,6 +47,10 @@
if OPENTHREAD_ENABLE_NCP
SUBDIRS += ncp
+else
+if OPENTHREAD_ENABLE_RADIO_ONLY
+SUBDIRS += ncp
+endif
endif
endif
diff --git a/examples/apps/cli/Makefile.am b/examples/apps/cli/Makefile.am
index 0d3e741..f5ba445 100644
--- a/examples/apps/cli/Makefile.am
+++ b/examples/apps/cli/Makefile.am
@@ -49,6 +49,7 @@
$(NULL)
SOURCES_COMMON += \
+ cli_uart.cpp \
main.c \
$(NULL)
diff --git a/examples/apps/cli/cli_uart.cpp b/examples/apps/cli/cli_uart.cpp
new file mode 100644
index 0000000..0f3e541
--- /dev/null
+++ b/examples/apps/cli/cli_uart.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+#include "openthread-core-config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openthread-system.h>
+#include <openthread/cli.h>
+
+#include "cli/cli_config.h"
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/logging.hpp"
+#include "utils/uart.h"
+
+#if OPENTHREAD_POSIX
+#include <signal.h>
+#include <sys/types.h>
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
+ *
+ * The size of CLI UART RX buffer in bytes.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 640
+#else
+#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 512
+#endif
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_CLI_TX_BUFFER_SIZE
+ *
+ * The size of CLI message buffer in bytes.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE
+#define OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE 1024
+#endif
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+#if OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE > OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE
+#error "diag output buffer should be smaller than CLI UART tx buffer"
+#endif
+#if OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE > OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
+#error "diag command line should be smaller than CLI UART rx buffer"
+#endif
+#endif
+
+#if OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH > OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
+#error "command line should be should be smaller than CLI rx buffer"
+#endif
+
+enum
+{
+ kRxBufferSize = OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE,
+ kTxBufferSize = OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE,
+};
+
+char sRxBuffer[kRxBufferSize];
+uint16_t sRxLength;
+
+char sTxBuffer[kTxBufferSize];
+uint16_t sTxHead;
+uint16_t sTxLength;
+
+uint16_t sSendLength;
+
+#ifdef OT_CLI_UART_LOCK_HDR_FILE
+
+#include OT_CLI_UART_LOCK_HDR_FILE
+
+#else
+
+/**
+ * Macro to acquire an exclusive lock of uart cli output
+ * Default implementation does nothing
+ *
+ */
+#ifndef OT_CLI_UART_OUTPUT_LOCK
+#define OT_CLI_UART_OUTPUT_LOCK() \
+ do \
+ { \
+ } while (0)
+#endif
+
+/**
+ * Macro to release the exclusive lock of uart cli output
+ * Default implementation does nothing
+ *
+ */
+#ifndef OT_CLI_UART_OUTPUT_UNLOCK
+#define OT_CLI_UART_OUTPUT_UNLOCK() \
+ do \
+ { \
+ } while (0)
+#endif
+
+#endif // OT_CLI_UART_LOCK_HDR_FILE
+
+static int Output(const char *aBuf, uint16_t aBufLength);
+static otError ProcessCommand(void);
+
+static void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ static const char sEraseString[] = {'\b', ' ', '\b'};
+ static const char CRNL[] = {'\r', '\n'};
+ static const char sCommandPrompt[] = {'>', ' '};
+ const uint8_t * end;
+
+ end = aBuf + aBufLength;
+
+ for (; aBuf < end; aBuf++)
+ {
+ switch (*aBuf)
+ {
+ case '\r':
+ case '\n':
+ Output(CRNL, sizeof(CRNL));
+ if (sRxLength > 0)
+ {
+ sRxBuffer[sRxLength] = '\0';
+ IgnoreError(ProcessCommand());
+ }
+
+ Output(sCommandPrompt, sizeof(sCommandPrompt));
+
+ break;
+
+#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ case 0x03: // ASCII for Ctrl-C
+ kill(0, SIGINT);
+ break;
+
+ case 0x04: // ASCII for Ctrl-D
+ exit(EXIT_SUCCESS);
+ break;
+#endif
+
+ case '\b':
+ case 127:
+ if (sRxLength > 0)
+ {
+ Output(sEraseString, sizeof(sEraseString));
+ sRxBuffer[--sRxLength] = '\0';
+ }
+
+ break;
+
+ default:
+ if (sRxLength < kRxBufferSize - 1)
+ {
+ Output(reinterpret_cast<const char *>(aBuf), 1);
+ sRxBuffer[sRxLength++] = static_cast<char>(*aBuf);
+ }
+
+ break;
+ }
+ }
+}
+
+static otError ProcessCommand(void)
+{
+ otError error = OT_ERROR_NONE;
+
+ while (sRxBuffer[sRxLength - 1] == '\n' || sRxBuffer[sRxLength - 1] == '\r')
+ {
+ sRxBuffer[--sRxLength] = '\0';
+ }
+
+#if OPENTHREAD_CONFIG_LOG_OUTPUT != OPENTHREAD_CONFIG_LOG_OUTPUT_NONE
+ /*
+ * Note this is here for this reason:
+ *
+ * TEXT (command) input ... in a test automation script occurs
+ * rapidly and often without gaps between the command and the
+ * terminal CR
+ *
+ * In contrast as a human is typing there is a delay between the
+ * last character of a command and the terminal CR which executes
+ * a command.
+ *
+ * During that human induced delay a tasklet may be scheduled and
+ * the LOG becomes confusing and it is hard to determine when
+ * something happened. Which happened first? the command-CR or
+ * the tasklet.
+ *
+ * Yes, while rare it is a race condition that is hard to debug.
+ *
+ * Thus this is here to affirmatively LOG exactly when the CLI
+ * command is being executed.
+ */
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+ /* TODO: how exactly do we get the instance here? */
+#else
+ otLogInfoCli("execute command: %s", sRxBuffer);
+#endif
+#endif
+ if (sRxLength > 0)
+ {
+ otCliInputLine(sRxBuffer);
+ }
+
+ sRxLength = 0;
+
+ return error;
+}
+
+static void Send(void)
+{
+ VerifyOrExit(sSendLength == 0);
+
+ if (sTxLength > kTxBufferSize - sTxHead)
+ {
+ sSendLength = kTxBufferSize - sTxHead;
+ }
+ else
+ {
+ sSendLength = sTxLength;
+ }
+
+ if (sSendLength > 0)
+ {
+#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART
+ /* duplicate the output to the debug uart */
+ otSysDebugUart_write_bytes(reinterpret_cast<uint8_t *>(sTxBuffer + sTxHead), sSendLength);
+#endif
+ IgnoreError(otPlatUartSend(reinterpret_cast<uint8_t *>(sTxBuffer + sTxHead), sSendLength));
+ }
+
+exit:
+ return;
+}
+
+static void SendDoneTask(void)
+{
+ sTxHead = (sTxHead + sSendLength) % kTxBufferSize;
+ sTxLength -= sSendLength;
+ sSendLength = 0;
+
+ Send();
+}
+
+static int Output(const char *aBuf, uint16_t aBufLength)
+{
+ OT_CLI_UART_OUTPUT_LOCK();
+ uint16_t sent = 0;
+
+ while (aBufLength > 0)
+ {
+ uint16_t remaining = kTxBufferSize - sTxLength;
+ uint16_t tail;
+ uint16_t sendLength = aBufLength;
+
+ if (sendLength > remaining)
+ {
+ sendLength = remaining;
+ }
+
+ for (uint16_t i = 0; i < sendLength; i++)
+ {
+ tail = (sTxHead + sTxLength) % kTxBufferSize;
+ sTxBuffer[tail] = *aBuf++;
+ aBufLength--;
+ sTxLength++;
+ }
+
+ Send();
+
+ sent += sendLength;
+
+ if (aBufLength > 0)
+ {
+ // More to send, so flush what's waiting now
+ otError err = otPlatUartFlush();
+
+ if (err == OT_ERROR_NONE)
+ {
+ // Flush successful, reset the pointers
+ SendDoneTask();
+ }
+ else
+ {
+ // Flush did not succeed, so abort here.
+ break;
+ }
+ }
+ }
+
+ OT_CLI_UART_OUTPUT_UNLOCK();
+
+ return sent;
+}
+
+static int CliUartOutput(void *aContext, const char *aFormat, va_list aArguments)
+{
+ OT_UNUSED_VARIABLE(aContext);
+
+ int rval;
+
+ if (sTxLength == 0)
+ {
+ rval = vsnprintf(sTxBuffer, kTxBufferSize, aFormat, aArguments);
+ VerifyOrExit(rval > 0 && rval < kTxBufferSize, otLogWarnPlat("Failed to format CLI output `%s`", aFormat));
+ sTxHead = 0;
+ sTxLength = static_cast<uint16_t>(rval);
+ sSendLength = 0;
+ }
+ else
+ {
+ va_list retryArguments;
+ uint16_t tail = (sTxHead + sTxLength) % kTxBufferSize;
+ uint16_t remaining = (sTxHead > tail ? (sTxHead - tail) : (kTxBufferSize - tail));
+
+ va_copy(retryArguments, aArguments);
+
+ rval = vsnprintf(&sTxBuffer[tail], remaining, aFormat, aArguments);
+
+ if (rval < 0)
+ {
+ otLogWarnPlat("Failed to format CLI output `%s`", aFormat);
+ }
+ else if (rval < remaining)
+ {
+ sTxLength += rval;
+ }
+ else if (rval < kTxBufferSize)
+ {
+ while (sTxLength != 0)
+ {
+ otError error;
+
+ Send();
+
+ error = otPlatUartFlush();
+
+ if (error == OT_ERROR_NONE)
+ {
+ // Flush successful, reset the pointers
+ SendDoneTask();
+ }
+ else
+ {
+ // Flush did not succeed, so abort here.
+ otLogWarnPlat("Failed to output CLI: %s", otThreadErrorToString(error));
+ ExitNow();
+ }
+ }
+ rval = vsnprintf(sTxBuffer, kTxBufferSize, aFormat, retryArguments);
+ OT_ASSERT(rval > 0);
+ sTxLength = static_cast<uint16_t>(rval);
+ sTxHead = 0;
+ sSendLength = 0;
+ }
+ else
+ {
+ otLogWarnPlat("CLI output `%s` truncated", aFormat);
+ }
+
+ va_end(retryArguments);
+ }
+
+ Send();
+
+exit:
+ return rval;
+}
+
+void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ ReceiveTask(aBuf, aBufLength);
+}
+
+void otPlatUartSendDone(void)
+{
+ SendDoneTask();
+}
+
+extern "C" void otAppCliInit(otInstance *aInstance)
+{
+ sRxLength = 0;
+ sTxHead = 0;
+ sTxLength = 0;
+ sSendLength = 0;
+
+ IgnoreError(otPlatUartEnable());
+
+ otCliInit(aInstance, CliUartOutput, aInstance);
+}
diff --git a/examples/apps/cli/ftd.cmake b/examples/apps/cli/ftd.cmake
index 5a55455..2372153 100644
--- a/examples/apps/cli/ftd.cmake
+++ b/examples/apps/cli/ftd.cmake
@@ -27,6 +27,7 @@
#
add_executable(ot-cli-ftd
+ cli_uart.cpp
main.c
)
@@ -37,6 +38,7 @@
${OT_PLATFORM_LIB}
openthread-ftd
${OT_PLATFORM_LIB}
+ openthread-cli-ftd
${OT_MBEDTLS}
ot-config
)
diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c
index 376e04d..e03d51f 100644
--- a/examples/apps/cli/main.c
+++ b/examples/apps/cli/main.c
@@ -38,6 +38,14 @@
#include "openthread-system.h"
#include "cli/cli_config.h"
+/**
+ * This function initializes the CLI app.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+extern void otAppCliInit(otInstance *aInstance);
+
#if OPENTHREAD_EXAMPLES_SIMULATION
#include <setjmp.h>
#include <unistd.h>
@@ -51,7 +59,7 @@
#define OPENTHREAD_ENABLE_COVERAGE 0
#endif
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
return calloc(aNum, aSize);
@@ -107,9 +115,7 @@
#endif
assert(instance);
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_UART
- otCliUartInit(instance);
-#endif
+ otAppCliInit(instance);
while (!otSysPseudoResetWasRequested())
{
diff --git a/examples/apps/cli/mtd.cmake b/examples/apps/cli/mtd.cmake
index 45b8923..2d758db 100644
--- a/examples/apps/cli/mtd.cmake
+++ b/examples/apps/cli/mtd.cmake
@@ -27,6 +27,7 @@
#
add_executable(ot-cli-mtd
+ cli_uart.cpp
main.c
)
@@ -37,6 +38,7 @@
${OT_PLATFORM_LIB}
openthread-mtd
${OT_PLATFORM_LIB}
+ openthread-cli-mtd
${OT_MBEDTLS}
ot-config
)
diff --git a/examples/apps/ncp/Makefile.am b/examples/apps/ncp/Makefile.am
index 430585e..9cf17e4 100644
--- a/examples/apps/ncp/Makefile.am
+++ b/examples/apps/ncp/Makefile.am
@@ -34,6 +34,7 @@
CPPFLAGS_COMMON += \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/examples/platforms \
$(NULL)
@@ -49,6 +50,7 @@
SOURCES_COMMON += \
main.c \
+ ncp.c \
$(NULL)
LDADD_MBEDTLS = \
@@ -76,11 +78,13 @@
$(NULL)
endif # OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
+if OPENTHREAD_ENABLE_NCP
if OPENTHREAD_ENABLE_FTD
bin_PROGRAMS += \
ot-ncp-ftd \
$(NULL)
endif
+endif
ot_ncp_ftd_CPPFLAGS = \
$(CPPFLAGS_COMMON) \
@@ -110,11 +114,13 @@
$(SOURCES_COMMON) \
$(NULL)
+if OPENTHREAD_ENABLE_NCP
if OPENTHREAD_ENABLE_MTD
bin_PROGRAMS += \
ot-ncp-mtd \
$(NULL)
endif
+endif
ot_ncp_mtd_CPPFLAGS = \
$(CPPFLAGS_COMMON) \
diff --git a/examples/apps/ncp/ftd.cmake b/examples/apps/ncp/ftd.cmake
index d822b4a..f09e9db 100644
--- a/examples/apps/ncp/ftd.cmake
+++ b/examples/apps/ncp/ftd.cmake
@@ -28,6 +28,7 @@
add_executable(ot-ncp-ftd
main.c
+ ncp.c
)
target_include_directories(ot-ncp-ftd PRIVATE ${COMMON_INCLUDES})
@@ -37,6 +38,7 @@
${OT_PLATFORM_LIB}
openthread-ftd
${OT_PLATFORM_LIB}
+ openthread-ncp-ftd
${OT_MBEDTLS}
ot-config
)
diff --git a/examples/apps/ncp/main.c b/examples/apps/ncp/main.c
index 2d9c630..fa2558c 100644
--- a/examples/apps/ncp/main.c
+++ b/examples/apps/ncp/main.c
@@ -36,6 +36,14 @@
#include "openthread-system.h"
+/**
+ * This function initializes the NCP app.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+extern void otAppNcpInit(otInstance *aInstance);
+
#if OPENTHREAD_EXAMPLES_SIMULATION
#include <setjmp.h>
#include <unistd.h>
@@ -49,7 +57,7 @@
#define OPENTHREAD_ENABLE_COVERAGE 0
#endif
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
return calloc(aNum, aSize);
@@ -105,7 +113,7 @@
#endif
assert(instance);
- otNcpInit(instance);
+ otAppNcpInit(instance);
while (!otSysPseudoResetWasRequested())
{
diff --git a/examples/apps/ncp/mtd.cmake b/examples/apps/ncp/mtd.cmake
index 2cb9fad..b25eedf 100644
--- a/examples/apps/ncp/mtd.cmake
+++ b/examples/apps/ncp/mtd.cmake
@@ -28,6 +28,7 @@
add_executable(ot-ncp-mtd
main.c
+ ncp.c
)
target_include_directories(ot-ncp-mtd PRIVATE ${COMMON_INCLUDES})
@@ -37,6 +38,7 @@
${OT_PLATFORM_LIB}
openthread-mtd
${OT_PLATFORM_LIB}
+ openthread-ncp-mtd
${OT_MBEDTLS}
ot-config
)
diff --git a/examples/apps/ncp/ncp.c b/examples/apps/ncp/ncp.c
new file mode 100644
index 0000000..ee7ccf7
--- /dev/null
+++ b/examples/apps/ncp/ncp.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-core-config.h"
+
+#include <openthread/ncp.h>
+
+#include "common/code_utils.hpp"
+
+#include "ncp/ncp_config.h"
+
+#if !OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+#include "utils/uart.h"
+
+void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ otNcpHdlcReceive(aBuf, aBufLength);
+}
+
+void otPlatUartSendDone(void)
+{
+ otNcpHdlcSendDone();
+}
+#endif
+
+#if !OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
+#if !OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+static int NcpSend(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ IgnoreError(otPlatUartSend(aBuf, aBufLength));
+ return aBufLength;
+}
+#endif
+
+void otAppNcpInit(otInstance *aInstance)
+{
+#if OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+ otNcpSpiInit(aInstance);
+#else
+ IgnoreError(otPlatUartEnable());
+
+ otNcpHdlcInit(aInstance, NcpSend);
+#endif
+}
+#endif // !OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
diff --git a/examples/apps/ncp/rcp.cmake b/examples/apps/ncp/rcp.cmake
index 0298df7..923d31a 100644
--- a/examples/apps/ncp/rcp.cmake
+++ b/examples/apps/ncp/rcp.cmake
@@ -28,6 +28,7 @@
add_executable(ot-rcp
main.c
+ ncp.c
)
target_include_directories(ot-rcp PRIVATE ${COMMON_INCLUDES})
@@ -37,6 +38,7 @@
${OT_PLATFORM_LIB}
openthread-radio
${OT_PLATFORM_LIB}
+ openthread-rcp
ot-config
)
diff --git a/examples/common-switches.mk b/examples/common-switches.mk
index b1cc708..7768f66 100644
--- a/examples/common-switches.mk
+++ b/examples/common-switches.mk
@@ -32,7 +32,9 @@
BIG_ENDIAN ?= 0
BORDER_AGENT ?= 0
BORDER_ROUTER ?= 0
+BORDER_ROUTING ?= 0
COAP ?= 0
+COAP_BLOCK ?= 0
COAP_OBSERVE ?= 0
COAPS ?= 0
COMMISSIONER ?= 0
@@ -40,7 +42,6 @@
CHANNEL_MANAGER ?= 0
CHANNEL_MONITOR ?= 0
CHILD_SUPERVISION ?= 0
-CLI_TRANSPORT ?= UART
DATASET_UPDATER ?= 0
DEBUG ?= 0
DHCP6_CLIENT ?= 0
@@ -49,6 +50,7 @@
DISABLE_DOC ?= 0
DISABLE_TOOLS ?= 0
DNS_CLIENT ?= 0
+DNSSD_SERVER ?= 0
DUA ?= 0
DYNAMIC_LOG_LEVEL ?= 0
ECDSA ?= 0
@@ -68,6 +70,7 @@
MTD_NETDIAG ?= 0
MULTIPLE_INSTANCE ?= 0
OTNS ?= 0
+PING_SENDER ?= 1
PLATFORM_UDP ?= 0
REFERENCE_DEVICE ?= 0
SERVICE ?= 0
@@ -75,8 +78,11 @@
# SLAAC is enabled by default
SLAAC ?= 1
SNTP_CLIENT ?= 0
-THREAD_VERSION ?= 1.1
+SRP_CLIENT ?= 0
+SRP_SERVER ?= 0
+THREAD_VERSION ?= 1.2
TIME_SYNC ?= 0
+TREL ?= 0
UDP_FORWARD ?= 0
RCP_RESTORATION_MAX_COUNT ?= 0
@@ -97,6 +103,10 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE=1
endif
+ifeq ($(BORDER_ROUTING),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1
+endif
+
ifeq ($(COAP),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_COAP_API_ENABLE=1
endif
@@ -105,6 +115,10 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE=1
endif
+ifeq ($(COAP_BLOCK),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE=1
+endif
+
ifeq ($(COAP_OBSERVE),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE=1
endif
@@ -129,10 +143,6 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE=1
endif
-ifneq ($(CLI_TRANSPORT),)
-COMMONCFLAGS += -DOPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_$(CLI_TRANSPORT)
-endif
-
ifeq ($(CSL_RECEIVER),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE=1
endif
@@ -173,6 +183,10 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1
endif
+ifeq ($(DNSSD_SERVER),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1
+endif
+
ifeq ($(DUA),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_DUA_ENABLE=1
endif
@@ -242,6 +256,10 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1
endif
+ifeq ($(PING_SENDER),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1
+endif
+
ifeq ($(PLATFORM_UDP),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE=1
endif
@@ -263,6 +281,14 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE=1
endif
+ifeq ($(SRP_CLIENT),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1
+endif
+
+ifeq ($(SRP_SERVER),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_SRP_SERVER_ENABLE=1
+endif
+
ifeq ($(THREAD_VERSION),1.1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_THREAD_VERSION=2
else ifeq ($(THREAD_VERSION),1.2)
@@ -273,6 +299,10 @@
COMMONCFLAGS += -DOPENTHREAD_CONFIG_TIME_SYNC_ENABLE=1 -DOPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT=1
endif
+ifeq ($(TREL),1)
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE=1
+endif
+
ifeq ($(UDP_FORWARD),1)
COMMONCFLAGS += -DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1
endif
@@ -314,28 +344,5 @@
COMMONCFLAGS += -DOPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT=${RCP_RESTORATION_MAX_COUNT}
ifeq ($(FULL_LOGS),1)
-# HINT: Add more here, or comment out ones you do not need/want
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_API=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_ARP=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_BBR=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_CLI=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_COAP=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_DUA=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_ICMP=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_IP6=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_MAC=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_MEM=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_MESHCOP=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_MLE=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_MLR=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_NETDATA=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_NETDIAG=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_PKT_DUMP=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_PLATFORM=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1
-LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_PREPEND_REGION=1
+COMMONCFLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG -DOPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1 -DOPENTHREAD_CONFIG_LOG_PREPEND_REGION=1
endif
-
-CFLAGS += ${LOG_FLAGS}
-CXXFLAGS += ${LOG_FLAGS}
diff --git a/examples/platforms/Makefile.am b/examples/platforms/Makefile.am
index 750ff2e..b090fa3 100644
--- a/examples/platforms/Makefile.am
+++ b/examples/platforms/Makefile.am
@@ -42,6 +42,8 @@
nrf528xx \
simulation \
qpg6095 \
+ qpg6100 \
+ qpg7015m \
samr21 \
utils \
$(NULL)
@@ -96,7 +98,15 @@
SUBDIRS += qpg6095
endif
-if OPENTHREAD_PLATFORM_SAMR21
+if OPENTHREAD_PLATFORM_QPG6100
+SUBDIRS += qpg6100
+endif
+
+if OPENTHREAD_PLATFORM_QPG7015M
+SUBDIRS += qpg7015m
+endif
+
+if OPENTHREAD_EXAMPLES_SAMR21
SUBDIRS += samr21
endif
diff --git a/examples/platforms/Makefile.platform.am b/examples/platforms/Makefile.platform.am
index e0a1a63..085ec55 100644
--- a/examples/platforms/Makefile.platform.am
+++ b/examples/platforms/Makefile.platform.am
@@ -93,6 +93,14 @@
include $(top_srcdir)/examples/platforms/qpg6095/Makefile.platform.am
endif
+if OPENTHREAD_EXAMPLES_QPG6100
+include $(top_srcdir)/examples/platforms/qpg6100/Makefile.platform.am
+endif
+
+if OPENTHREAD_EXAMPLES_QPG7015M
+include $(top_srcdir)/examples/platforms/qpg7015m/Makefile.platform.am
+endif
+
if OPENTHREAD_EXAMPLES_SAMR21
include $(top_srcdir)/examples/platforms/samr21/Makefile.platform.am
endif # OPENTHREAD_EXAMPLES_SAMR21
diff --git a/examples/platforms/cc1352/openthread-core-cc1352-config.h b/examples/platforms/cc1352/openthread-core-cc1352-config.h
index ad73700..449ed8c 100644
--- a/examples/platforms/cc1352/openthread-core-cc1352-config.h
+++ b/examples/platforms/cc1352/openthread-core-cc1352-config.h
@@ -48,11 +48,11 @@
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
#endif /* OPENTHREAD_CORE_CC1352_CONFIG_H_ */
diff --git a/examples/platforms/cc1352/uart.c b/examples/platforms/cc1352/uart.c
index 34cd865..c4cb87f 100644
--- a/examples/platforms/cc1352/uart.c
+++ b/examples/platforms/cc1352/uart.c
@@ -41,11 +41,9 @@
#include <openthread/platform/debug_uart.h>
#include <openthread/platform/logging.h>
-#include <openthread/platform/uart.h>
#include "utils/code_utils.h"
-
-#include <utils/code_utils.h>
+#include "utils/uart.h"
#include <driverlib/ioc.h>
#include <driverlib/prcm.h>
@@ -116,7 +114,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartEnable(void)
{
@@ -138,7 +136,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartDisable(void)
{
@@ -154,7 +152,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
diff --git a/examples/platforms/cc2538/CMakeLists.txt b/examples/platforms/cc2538/CMakeLists.txt
index 341c5f1..c69d1e5 100644
--- a/examples/platforms/cc2538/CMakeLists.txt
+++ b/examples/platforms/cc2538/CMakeLists.txt
@@ -35,7 +35,7 @@
list(APPEND OT_PLATFORM_DEFINES
"OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-cc2538-config-check.h\""
- "OPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
)
set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
diff --git a/examples/platforms/cc2538/openthread-core-cc2538-config.h b/examples/platforms/cc2538/openthread-core-cc2538-config.h
index fabb6fa..1f26217 100644
--- a/examples/platforms/cc2538/openthread-core-cc2538-config.h
+++ b/examples/platforms/cc2538/openthread-core-cc2538-config.h
@@ -83,12 +83,12 @@
#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE 1
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_CC2538_USE_RADIO_RX_INTERRUPT
diff --git a/examples/platforms/cc2538/uart.c b/examples/platforms/cc2538/uart.c
index 992af65..3325c99 100644
--- a/examples/platforms/cc2538/uart.c
+++ b/examples/platforms/cc2538/uart.c
@@ -41,10 +41,10 @@
#include <openthread/platform/debug_uart.h>
#include <openthread/platform/logging.h>
-#include <openthread/platform/uart.h>
#include "platform-cc2538.h"
#include "utils/code_utils.h"
+#include "utils/uart.h"
enum
{
diff --git a/examples/platforms/cc2650/openthread-core-cc2650-config.h b/examples/platforms/cc2650/openthread-core-cc2650-config.h
index 31d2fb1..94de3b5 100644
--- a/examples/platforms/cc2650/openthread-core-cc2650-config.h
+++ b/examples/platforms/cc2650/openthread-core-cc2650-config.h
@@ -45,12 +45,12 @@
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 32
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_SETTINGS_RAM
diff --git a/examples/platforms/cc2650/uart.c b/examples/platforms/cc2650/uart.c
index d6f0483..44515fa 100644
--- a/examples/platforms/cc2650/uart.c
+++ b/examples/platforms/cc2650/uart.c
@@ -34,7 +34,8 @@
#include <driverlib/uart.h>
#include <utils/code_utils.h>
-#include <openthread/platform/uart.h>
+
+#include "utils/uart.h"
/**
* \note this will configure the uart for 115200 baud 8-N-1, no HW flow control
@@ -58,7 +59,7 @@
void UART0_intHandler(void);
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartEnable(void)
{
@@ -86,7 +87,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartDisable(void)
{
@@ -109,7 +110,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
diff --git a/examples/platforms/cc2652/openthread-core-cc2652-config.h b/examples/platforms/cc2652/openthread-core-cc2652-config.h
index 352c322..b9dccf6 100644
--- a/examples/platforms/cc2652/openthread-core-cc2652-config.h
+++ b/examples/platforms/cc2652/openthread-core-cc2652-config.h
@@ -48,11 +48,11 @@
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
#endif /* OPENTHREAD_CORE_CC2650_CONFIG_H_ */
diff --git a/examples/platforms/cc2652/uart.c b/examples/platforms/cc2652/uart.c
index b342a52..c8d951a 100644
--- a/examples/platforms/cc2652/uart.c
+++ b/examples/platforms/cc2652/uart.c
@@ -41,11 +41,9 @@
#include <openthread/platform/debug_uart.h>
#include <openthread/platform/logging.h>
-#include <openthread/platform/uart.h>
#include "utils/code_utils.h"
-
-#include <utils/code_utils.h>
+#include "utils/uart.h"
#include <driverlib/ioc.h>
#include <driverlib/prcm.h>
@@ -116,7 +114,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartEnable(void)
{
@@ -138,7 +136,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartDisable(void)
{
@@ -154,7 +152,7 @@
}
/**
- * Function documented in platform/uart.h
+ * Function documented in utils/uart.h
*/
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
diff --git a/examples/platforms/efr32/CMakeLists.txt b/examples/platforms/efr32/CMakeLists.txt
new file mode 100644
index 0000000..00bee25
--- /dev/null
+++ b/examples/platforms/efr32/CMakeLists.txt
@@ -0,0 +1,143 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+include(${PROJECT_SOURCE_DIR}/third_party/silabs/cmake/utility.cmake)
+include(${PROJECT_SOURCE_DIR}/third_party/silabs/cmake/includes.cmake)
+include(${PROJECT_SOURCE_DIR}/third_party/silabs/cmake/imported_libs.cmake)
+
+
+# ==============================================================================
+# Common sources and includes
+# ==============================================================================
+set(EFR32_COMMON_SOURCES
+ src/alarm.c
+ src/diag.c
+ src/entropy.c
+ src/fem-control.c
+ src/flash.c
+ src/ieee802154mac.h
+ src/logging.c
+ src/mbedtls_config.h
+ src/memory.c
+ src/misc.c
+ src/openthread-core-efr32-config-check.h
+ src/openthread-core-efr32-config.h
+ src/platform-band.h
+ src/platform-efr32.h
+ src/radio.c
+ src/rail_config.h
+ src/startup-gcc.c
+ src/system.c
+ src/uart.c
+)
+
+set(EFR32_INCLUDES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/${EFR32_PLATFORM}/crypto
+ ${CMAKE_CURRENT_SOURCE_DIR}/${EFR32_PLATFORM}/${BOARD_LOWERCASE}
+ ${PROJECT_SOURCE_DIR}/third_party/silabs/rail_config
+ ${SILABS_GSDK_INCLUDES}
+ ${PROJECT_SOURCE_DIR}/examples/platforms
+ ${PROJECT_SOURCE_DIR}/src/core
+)
+
+set(EFR32_CFLAGS
+ -Wno-sign-compare
+ -Wno-unused-parameter
+ -Wno-missing-field-initializers
+)
+
+# ==============================================================================
+# mbedtls
+# ==============================================================================
+if(NOT OT_EXTERNAL_MBEDTLS)
+ message(FATAL_ERROR "OT_EXTERNAL_MBEDTLS is not set. Please include the define when running cmake\n\t-DOT_EXTERNAL_MBEDTLS=silabs-mbedtls")
+else()
+ list(APPEND OT_PLATFORM_DEFINES "MBEDTLS_CONFIG_FILE=\"mbedtls_config.h\"")
+endif()
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+if(PLATFORM_LOWERCASE MATCHES "^efr32mg2\\d*")
+ list(APPEND OT_PUBLIC_INCLUDES
+ "${SILABS_GSDK_DIR}/util/third_party/crypto/sl_component/se_manager/inc"
+ "${SILABS_GSDK_DIR}/util/third_party/crypto/sl_component/se_manager/src"
+ )
+ set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+endif()
+
+# ==============================================================================
+# General variables
+# ==============================================================================
+
+# ==============================================================================
+# Filter out CFLAGS
+# ==============================================================================
+set(ignored_flags
+ "-pedantic-errors" # Needed for RAIL lib
+ "-Wshadow" # Needed for RAIL lib
+)
+
+foreach(flag IN LISTS ignored_flags)
+ string(REPLACE "${flag}" "" OT_CFLAGS "${OT_CFLAGS}")
+endforeach()
+list(APPEND EFR32_CFLAGS ${OT_CFLAGS})
+set(OT_CFLAGS ${OT_CFLAGS} PARENT_SCOPE)
+
+# Use default config file if one isn't specified
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/src/openthread-core-efr32-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\""
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-efr32-config-check.h\""
+)
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+# ==============================================================================
+# Platform targets
+# ==============================================================================
+set(EFR32_COMMON_3RD_LIBS
+ jlinkrtt
+ ${OT_MBEDTLS}
+)
+
+include(${PLATFORM_LOWERCASE}/${PLATFORM_LOWERCASE}.cmake)
+
+list(APPEND OT_PUBLIC_INCLUDES ${EFR32_INCLUDES})
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+# ==============================================================================
+# sleepy-demo
+# ==============================================================================
+option(EFR32_APP_SLEEPY_DEMO "enable sleepy-demo app" ON)
+
+if(EFR32_APP_SLEEPY_DEMO)
+ add_subdirectory(sleepy-demo)
+endif()
diff --git a/examples/platforms/efr32/Makefile.platform.am b/examples/platforms/efr32/Makefile.platform.am
index 1d53802..b1a4afb 100644
--- a/examples/platforms/efr32/Makefile.platform.am
+++ b/examples/platforms/efr32/Makefile.platform.am
@@ -55,7 +55,7 @@
LDADD_COMMON += \
$(top_builddir)/examples/platforms/efr32/libopenthread-$(PLATFORM_LOWERCASE).a \
$(top_builddir)/third_party/silabs/libsilabs-$(PLATFORM_LOWERCASE)-sdk.a \
- $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/radio/rail_lib/autogen/librail_release/$(LIBRAIL) \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/radio/rail_lib/autogen/librail_release/$(LIBRAIL) \
$(NULL)
LDFLAGS_COMMON += \
diff --git a/examples/platforms/efr32/arm-none-eabi.cmake b/examples/platforms/efr32/arm-none-eabi.cmake
new file mode 100644
index 0000000..9f2e385
--- /dev/null
+++ b/examples/platforms/efr32/arm-none-eabi.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -fdata-sections -ffunction-sections")
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=c99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/efr32/efr32_platform_defs.am b/examples/platforms/efr32/efr32_platform_defs.am
index 68d7da6..f69d240 100644
--- a/examples/platforms/efr32/efr32_platform_defs.am
+++ b/examples/platforms/efr32/efr32_platform_defs.am
@@ -30,7 +30,7 @@
# ==============================================================================
# General variables
# ==============================================================================
-SDK_SRC_DIR = $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0
+SDK_SRC_DIR = $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1
EFR32_PLATFORM = $(subst /,,$(exec_prefix))
# NOTE: This is a work-around that sets EFR32_PLATFORM to the correct platform name.
@@ -67,6 +67,8 @@
# ==============================================================================
SILABS_GSDK_CPPFLAGS = \
-I$(SDK_SRC_DIR) \
+ -I$(SDK_SRC_DIR)/hardware/board/config/$(BOARD_LOWERCASE)_brd4001a \
+ -I$(SDK_SRC_DIR)/hardware/board/config/$(BOARD_LOWERCASE) \
-I$(SDK_SRC_DIR)/hardware/kit/$(PLATFORM_UPPERCASE)_$(BOARD_UPPERCASE)/config \
-I$(SDK_SRC_DIR)/hardware/kit/common/bsp \
-I$(SDK_SRC_DIR)/hardware/kit/common/drivers \
@@ -87,7 +89,6 @@
-I$(SDK_SRC_DIR)/platform/emlib/inc \
-I$(SDK_SRC_DIR)/platform/halconfig/inc/hal-config \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32 \
- -I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32/rf/common/cortex \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/common \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/hal \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/hal/efr32 \
@@ -98,9 +99,6 @@
-I$(SDK_SRC_DIR)/platform/service/sleeptimer/config \
-I$(SDK_SRC_DIR)/platform/service/sleeptimer/inc \
-I$(SDK_SRC_DIR)/util/plugin/plugin-common/fem-control \
- -I$(SDK_SRC_DIR)/util/third_party/mbedtls/configs \
- -I$(SDK_SRC_DIR)/util/third_party/mbedtls/include \
- -I$(SDK_SRC_DIR)/util/third_party/mbedtls/sl_crypto/include \
$(NULL)
@@ -117,6 +115,8 @@
-I$(SDK_SRC_DIR)/platform/emdrv/nvm3/config/s2 \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/chip/efr32/efr32xg2x \
-I$(SDK_SRC_DIR)/platform/radio/rail_lib/plugin/pa-conversions/efr32xg21/config \
+ -I$(SDK_SRC_DIR)/util/third_party/crypto/sl_component/se_manager/inc \
+ -I$(SDK_SRC_DIR)/util/third_party/crypto/sl_component/se_manager/src \
$(NULL)
@@ -130,6 +130,7 @@
src/fem-control.c \
src/flash.c \
src/logging.c \
+ src/memory.c \
src/misc.c \
src/openthread-core-efr32-config-check.h \
src/openthread-core-efr32-config.h \
diff --git a/examples/platforms/efr32/efr32mg1/Makefile.am b/examples/platforms/efr32/efr32mg1/Makefile.am
index 873a884..fdf9e1e 100644
--- a/examples/platforms/efr32/efr32mg1/Makefile.am
+++ b/examples/platforms/efr32/efr32mg1/Makefile.am
@@ -33,7 +33,6 @@
libopenthread_efr32mg1_a_CPPFLAGS = \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-Wno-sign-compare \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
diff --git a/examples/platforms/efr32/efr32mg1/Makefile.platform.am b/examples/platforms/efr32/efr32mg1/Makefile.platform.am
index c3977f3..22912f6 100644
--- a/examples/platforms/efr32/efr32mg1/Makefile.platform.am
+++ b/examples/platforms/efr32/efr32mg1/Makefile.platform.am
@@ -31,5 +31,5 @@
#
LDADD_COMMON += \
- $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
$(NULL)
diff --git a/examples/platforms/efr32/efr32mg1/README.md b/examples/platforms/efr32/efr32mg1/README.md
index 0aa543e..2473f2c 100644
--- a/examples/platforms/efr32/efr32mg1/README.md
+++ b/examples/platforms/efr32/efr32mg1/README.md
@@ -28,8 +28,8 @@
2. Install Flex (Gecko) SDK including RAIL Library from Simplicity Studio.
- Connect EFR32MG1P Wireless Starter Kit to Simplicity Studio.
- - Find Flex SDK v3.0 in the Software Update page and click Install.
- - Flex SDK v3.0 will be installed in the path:
+ - Find Flex SDK v3.1 in the Software Update page and click Install.
+ - Flex SDK v3.1 will be installed in the path:
- Mac
- `/Applications/Simplicity\ Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite`
- Windows
@@ -66,7 +66,35 @@
$ ./bootstrap
```
-For EFR32MG1™ Mighty Gecko Wireless Starter Kit:
+For EFR32MG1™ Mighty Gecko Wireless Starter Kit, this can be done using both the CMake and autotools build systems
+
+**CMake (preferred)**
+
+```bash
+$ ./script/cmake-build efr32mg1 -DBOARD=brd4151a
+...
+-- Configuring done
+-- Generating done
+-- Build files have been written to: <path-to-openthread>/build/efr32mg1
++ [[ -n ot-rcp ]]
++ ninja ot-rcp
+[160/160] Linking CXX executable examples/apps/ncp/ot-rcp
++ cd <path-to-openthread>
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/build/efr32mg1/examples`.
+
+```bash
+# For linux
+$ find build/efr32mg1/examples -type f -executable
+build/efr32mg1/examples/apps/ncp/ot-rcp
+
+# For BSD/Darwin/mac systems
+$ find build/efr32mg1/examples -type f -perm +111
+build/efr32mg1/examples/apps/ncp/ot-rcp
+```
+
+**autotools (soon to be depracated)**
```bash
$ make -f examples/Makefile-efr32mg1 BOARD=BRD4151A
@@ -234,7 +262,7 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
## Verification
@@ -244,4 +272,4 @@
The EFR32 example has been verified with following Flex SDK/RAIL Library version:
-- Flex SDK version 3.0.x
+- Flex SDK v3.1.x
diff --git a/examples/platforms/efr32/efr32mg1/arm-none-eabi.cmake b/examples/platforms/efr32/efr32mg1/arm-none-eabi.cmake
new file mode 100644
index 0000000..9f2e385
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg1/arm-none-eabi.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -fdata-sections -ffunction-sections")
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=c99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/efr32/efr32mg1/crypto/mbedtls_config_autogen.h b/examples/platforms/efr32/efr32mg1/crypto/mbedtls_config_autogen.h
index 0104fdf..5f839fd 100644
--- a/examples/platforms/efr32/efr32mg1/crypto/mbedtls_config_autogen.h
+++ b/examples/platforms/efr32/efr32mg1/crypto/mbedtls_config_autogen.h
@@ -24,10 +24,10 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ENTROPY_ADC_C
-#define MBEDTLS_ENTROPY_RAIL_C
-#define MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_MD_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
@@ -37,14 +37,12 @@
#define MBEDTLS_ENTROPY_FORCE_SHA256
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
@@ -53,13 +51,17 @@
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
#include "config-device-acceleration.h"
+#if !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
#include "sl_malloc.h"
#define MBEDTLS_PLATFORM_FREE_MACRO sl_free
#define MBEDTLS_PLATFORM_CALLOC_MACRO sl_calloc
+#endif
+
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_C
diff --git a/examples/platforms/efr32/efr32mg1/efr32mg1.cmake b/examples/platforms/efr32/efr32mg1/efr32mg1.cmake
new file mode 100644
index 0000000..39e5da5
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg1/efr32mg1.cmake
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+# ==============================================================================
+# Verify board is supported for platform
+# ==============================================================================
+if(BOARD_LOWERCASE STREQUAL "brd4151a")
+ set(MCU "EFR32MG1P232F256GM48")
+else()
+ message(FATAL_ERROR "
+ BOARD=${BOARD} not supported.
+
+ Please provide a value for BOARD variable e.g BOARD=brd4151a.
+ Currently supported:
+ - brd4151a
+ ")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "${MCU}")
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+# ==============================================================================
+# Platform library
+# ==============================================================================
+set(OT_PLATFORM_LIB "openthread-efr32mg1")
+set(OT_PLATFORM_LIB ${OT_PLATFORM_LIB} PARENT_SCOPE)
+
+set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/efr32mg1/efr32mg1.ld")
+
+add_library(openthread-efr32mg1
+ ${EFR32_COMMON_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-efr32mg1
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-efr32mg1
+ PUBLIC
+ ${EFR32_COMMON_3RD_LIBS}
+ silabs-libnvm3_CM4_gcc
+ silabs-efr32mg1-sdk
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-efr32mg1
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-efr32mg1
+ PRIVATE
+ ${EFR32_CFLAGS}
+)
+
+target_include_directories(openthread-efr32mg1
+ PUBLIC
+ ${EFR32_INCLUDES}
+ PRIVATE
+ ${SILABS_EFR32MG1X_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
diff --git a/examples/platforms/efr32/efr32mg12/Makefile.am b/examples/platforms/efr32/efr32mg12/Makefile.am
index 73cefb5..0235236 100644
--- a/examples/platforms/efr32/efr32mg12/Makefile.am
+++ b/examples/platforms/efr32/efr32mg12/Makefile.am
@@ -33,7 +33,6 @@
libopenthread_efr32mg12_a_CPPFLAGS = \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-Wno-sign-compare \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
diff --git a/examples/platforms/efr32/efr32mg12/Makefile.platform.am b/examples/platforms/efr32/efr32mg12/Makefile.platform.am
index 3b4799a..df29d3f 100644
--- a/examples/platforms/efr32/efr32mg12/Makefile.platform.am
+++ b/examples/platforms/efr32/efr32mg12/Makefile.platform.am
@@ -31,5 +31,5 @@
#
LDADD_COMMON += \
- $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
$(NULL)
diff --git a/examples/platforms/efr32/efr32mg12/README.md b/examples/platforms/efr32/efr32mg12/README.md
index 1facf1f..713e0dc 100644
--- a/examples/platforms/efr32/efr32mg12/README.md
+++ b/examples/platforms/efr32/efr32mg12/README.md
@@ -33,8 +33,8 @@
2. Install Flex (Gecko) SDK including RAIL Library from Simplicity Studio.
- Connect EFR32MG12P Wireless Starter Kit to Simplicity Studio.
- - Find Flex SDK v3.0 in the Software Update page and click Install.
- - Flex SDK v3.0 will be installed in the path:
+ - Find Flex SDK v3.1 in the Software Update page and click Install.
+ - Flex SDK v3.1 will be installed in the path:
- Mac
- `/Applications/Simplicity\ Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite`
- Windows
@@ -71,7 +71,47 @@
$ ./bootstrap
```
-For EFR32MG12™ Mighty Gecko Wireless Starter Kit:
+For EFR32MG12™ Mighty Gecko Wireless Starter Kit, this can be done using both the CMake and autotools build systems
+
+**CMake (preferred)**
+
+```bash
+$ ./script/cmake-build efr32mg12 -DBOARD=brd4161a
+...
+-- Configuring done
+-- Generating done
+-- Build files have been written to: <path-to-openthread>/build/efr32mg12
++ [[ -n ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd ]]
++ ninja ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd
+[572/572] Linking CXX executable examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
++ cd <path-to-openthread>
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/build/efr32mg12/examples`.
+
+```bash
+# For linux
+$ find build/efr32mg12/examples -type f -executable
+build/efr32mg12/examples/apps/cli/ot-cli-mtd
+build/efr32mg12/examples/apps/cli/ot-cli-ftd
+build/efr32mg12/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg12/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg12/examples/apps/ncp/ot-rcp
+build/efr32mg12/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg12/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+
+# For BSD/Darwin/mac systems
+$ find build/efr32mg12/examples -type f -perm +111
+build/efr32mg12/examples/apps/cli/ot-cli-mtd
+build/efr32mg12/examples/apps/cli/ot-cli-ftd
+build/efr32mg12/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg12/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg12/examples/apps/ncp/ot-rcp
+build/efr32mg12/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg12/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+```
+
+**autotools (soon to be depracated)**
```bash
$ make -f examples/Makefile-efr32mg12 BOARD=BRD4161A
@@ -247,7 +287,7 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
## Verification
@@ -257,4 +297,4 @@
The EFR32 example has been verified with following Flex SDK/RAIL Library version:
-- Flex SDK version 3.0.x
+- Flex SDK v3.1.x
diff --git a/examples/platforms/efr32/efr32mg12/arm-none-eabi.cmake b/examples/platforms/efr32/efr32mg12/arm-none-eabi.cmake
new file mode 100644
index 0000000..9f2e385
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg12/arm-none-eabi.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -fdata-sections -ffunction-sections")
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=c99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h b/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h
index 42240cc..5f839fd 100644
--- a/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h
+++ b/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h
@@ -24,9 +24,10 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ENTROPY_ADC_C
-#define MBEDTLS_ENTROPY_RAIL_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_MD_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
@@ -36,14 +37,12 @@
#define MBEDTLS_ENTROPY_FORCE_SHA256
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
@@ -52,17 +51,17 @@
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
#include "config-device-acceleration.h"
-#if defined(MBEDTLS_TRNG_PRESENT)
-#define MBEDTLS_TRNG_C
-#endif
-
+#if !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
#include "sl_malloc.h"
#define MBEDTLS_PLATFORM_FREE_MACRO sl_free
#define MBEDTLS_PLATFORM_CALLOC_MACRO sl_calloc
+#endif
+
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_C
diff --git a/examples/platforms/efr32/efr32mg12/efr32mg12.cmake b/examples/platforms/efr32/efr32mg12/efr32mg12.cmake
new file mode 100644
index 0000000..ad73e5f
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg12/efr32mg12.cmake
@@ -0,0 +1,104 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+# ==============================================================================
+# Verify board is supported for platform
+# ==============================================================================
+if(BOARD_LOWERCASE STREQUAL "brd4304a")
+ set(MCU "EFR32MG12P432F1024GM48")
+elseif(BOARD_LOWERCASE STREQUAL "brd4161a")
+ set(MCU "EFR32MG12P432F1024GL125")
+elseif(BOARD_LOWERCASE STREQUAL "brd4166a")
+ set(MCU "EFR32MG12P332F1024GL125")
+elseif(BOARD_LOWERCASE STREQUAL "brd4170a")
+ set(MCU "EFR32MG12P433F1024GM68")
+else()
+ message(FATAL_ERROR "
+ BOARD=${BOARD} not supported.
+
+ Please provide a value for BOARD variable e.g BOARD=brd4161a.
+ Currently supported:
+ - brd4161a
+ - brd4166a
+ - brd4170a
+ - brd4304a
+ ")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "${MCU}")
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+# ==============================================================================
+# Platform library
+# ==============================================================================
+set(OT_PLATFORM_LIB "openthread-efr32mg12")
+set(OT_PLATFORM_LIB ${OT_PLATFORM_LIB} PARENT_SCOPE)
+
+set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/efr32mg12/efr32mg12.ld")
+
+add_library(openthread-efr32mg12
+ ${EFR32_COMMON_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-efr32mg12
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-efr32mg12
+ PUBLIC
+ ${EFR32_COMMON_3RD_LIBS}
+ silabs-libnvm3_CM4_gcc
+ silabs-efr32mg12-sdk
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-efr32mg12
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-efr32mg12
+ PRIVATE
+ ${EFR32_CFLAGS}
+)
+
+target_include_directories(openthread-efr32mg12
+ PUBLIC
+ ${EFR32_INCLUDES}
+ PRIVATE
+ ${SILABS_EFR32MG1X_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
diff --git a/examples/platforms/efr32/efr32mg13/Makefile.am b/examples/platforms/efr32/efr32mg13/Makefile.am
index b50f029..cea711d 100644
--- a/examples/platforms/efr32/efr32mg13/Makefile.am
+++ b/examples/platforms/efr32/efr32mg13/Makefile.am
@@ -33,7 +33,6 @@
libopenthread_efr32mg13_a_CPPFLAGS = \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-Wno-sign-compare \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
diff --git a/examples/platforms/efr32/efr32mg13/Makefile.platform.am b/examples/platforms/efr32/efr32mg13/Makefile.platform.am
index 47b48a4..f45ce08 100644
--- a/examples/platforms/efr32/efr32mg13/Makefile.platform.am
+++ b/examples/platforms/efr32/efr32mg13/Makefile.platform.am
@@ -31,5 +31,5 @@
#
LDADD_COMMON += \
- $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a \
$(NULL)
diff --git a/examples/platforms/efr32/efr32mg13/README.md b/examples/platforms/efr32/efr32mg13/README.md
index d38af3f..98a8c3c 100644
--- a/examples/platforms/efr32/efr32mg13/README.md
+++ b/examples/platforms/efr32/efr32mg13/README.md
@@ -32,8 +32,8 @@
2. Install Flex (Gecko) SDK including RAIL Library from Simplicity Studio.
- Connect EFR32MG13P Wireless Starter Kit to Simplicity Studio.
- - Find Flex SDK v3.0 in the Software Update page and click Install.
- - Flex SDK v3.0 will be installed in the path:
+ - Find Flex SDK v3.1 in the Software Update page and click Install.
+ - Flex SDK v3.1 will be installed in the path:
- Mac
- `/Applications/Simplicity\ Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite`
- Windows
@@ -70,7 +70,47 @@
$ ./bootstrap
```
-For EFR32MG13™ Mighty Gecko Wireless Starter Kit:
+For EFR32MG13™ Mighty Gecko Wireless Starter Kit, this can be done using both the CMake and autotools build systems
+
+**CMake (preferred)**
+
+```bash
+$ ./script/cmake-build efr32mg13 -DBOARD=brd4168a
+...
+-- Configuring done
+-- Generating done
+-- Build files have been written to: <path-to-openthread>/build/efr32mg13
++ [[ -n ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd ]]
++ ninja ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd
+[573/573] Linking CXX executable examples/apps/ncp/ot-ncp-ftd
++ cd <path-to-openthread>
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/build/efr32mg13/examples`.
+
+```bash
+# For linux
+$ find build/efr32mg13/examples -type f -executable
+build/efr32mg13/examples/apps/cli/ot-cli-mtd
+build/efr32mg13/examples/apps/cli/ot-cli-ftd
+build/efr32mg13/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg13/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg13/examples/apps/ncp/ot-rcp
+build/efr32mg13/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg13/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+
+# For BSD/Darwin/mac systems
+$ find build/efr32mg13/examples -type f -perm +111
+build/efr32mg13/examples/apps/cli/ot-cli-mtd
+build/efr32mg13/examples/apps/cli/ot-cli-ftd
+build/efr32mg13/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg13/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg13/examples/apps/ncp/ot-rcp
+build/efr32mg13/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg13/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+```
+
+**autotools (soon to be depracated)**
```bash
$ make -f examples/Makefile-efr32mg13 BOARD=BRD4168A
@@ -240,7 +280,7 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
## Verification
@@ -250,4 +290,4 @@
The EFR32 example has been verified with following Flex SDK/RAIL Library version:
-- Flex SDK version 3.0.x
+- Flex SDK v3.1.x
diff --git a/examples/platforms/efr32/efr32mg13/arm-none-eabi.cmake b/examples/platforms/efr32/efr32mg13/arm-none-eabi.cmake
new file mode 100644
index 0000000..9f2e385
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg13/arm-none-eabi.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -fdata-sections -ffunction-sections")
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=c99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/efr32/efr32mg13/crypto/mbedtls_config_autogen.h b/examples/platforms/efr32/efr32mg13/crypto/mbedtls_config_autogen.h
index c0a738c..5f839fd 100644
--- a/examples/platforms/efr32/efr32mg13/crypto/mbedtls_config_autogen.h
+++ b/examples/platforms/efr32/efr32mg13/crypto/mbedtls_config_autogen.h
@@ -24,10 +24,10 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ENTROPY_ADC_C
-#define MBEDTLS_ENTROPY_RAIL_C
-#define MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_MD_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
@@ -37,14 +37,12 @@
#define MBEDTLS_ENTROPY_FORCE_SHA256
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
@@ -53,17 +51,17 @@
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
#include "config-device-acceleration.h"
-#if defined(MBEDTLS_TRNG_PRESENT)
-#define MBEDTLS_TRNG_C
-#endif
-
+#if !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
#include "sl_malloc.h"
#define MBEDTLS_PLATFORM_FREE_MACRO sl_free
#define MBEDTLS_PLATFORM_CALLOC_MACRO sl_calloc
+#endif
+
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_C
diff --git a/examples/platforms/efr32/efr32mg13/efr32mg13.cmake b/examples/platforms/efr32/efr32mg13/efr32mg13.cmake
new file mode 100644
index 0000000..c944901
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg13/efr32mg13.cmake
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+# ==============================================================================
+# Verify board is supported for platform
+# ==============================================================================
+if(BOARD_LOWERCASE STREQUAL "brd4168a")
+ set(MCU "EFR32MG13P732F512GM48")
+else()
+ message(FATAL_ERROR "
+ BOARD=${BOARD} not supported.
+
+ Please provide a value for BOARD variable e.g BOARD=brd4168a.
+ Currently supported:
+ - brd4168a
+ ")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "${MCU}")
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+# ==============================================================================
+# Platform library
+# ==============================================================================
+set(OT_PLATFORM_LIB "openthread-efr32mg13")
+set(OT_PLATFORM_LIB ${OT_PLATFORM_LIB} PARENT_SCOPE)
+
+set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/efr32mg13/efr32mg13.ld")
+
+add_library(openthread-efr32mg13
+ ${EFR32_COMMON_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-efr32mg13
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-efr32mg13
+ PUBLIC
+ ${EFR32_COMMON_3RD_LIBS}
+ silabs-libnvm3_CM4_gcc
+ silabs-efr32mg13-sdk
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-efr32mg13
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-efr32mg13
+ PRIVATE
+ ${EFR32_CFLAGS}
+)
+
+target_include_directories(openthread-efr32mg13
+ PUBLIC
+ ${EFR32_INCLUDES}
+ PRIVATE
+ ${SILABS_EFR32MG1X_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
diff --git a/examples/platforms/efr32/efr32mg21/Makefile.am b/examples/platforms/efr32/efr32mg21/Makefile.am
index 4697d3c..3ce9a37 100644
--- a/examples/platforms/efr32/efr32mg21/Makefile.am
+++ b/examples/platforms/efr32/efr32mg21/Makefile.am
@@ -33,7 +33,6 @@
libopenthread_efr32mg21_a_CPPFLAGS = \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-Wno-sign-compare \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
diff --git a/examples/platforms/efr32/efr32mg21/Makefile.platform.am b/examples/platforms/efr32/efr32mg21/Makefile.platform.am
index f91e03a..8193b73 100644
--- a/examples/platforms/efr32/efr32mg21/Makefile.platform.am
+++ b/examples/platforms/efr32/efr32mg21/Makefile.platform.am
@@ -31,5 +31,5 @@
#
LDADD_COMMON += \
- $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.0/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v3.1/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a \
$(NULL)
diff --git a/examples/platforms/efr32/efr32mg21/README.md b/examples/platforms/efr32/efr32mg21/README.md
index b3457a2..610ca26 100644
--- a/examples/platforms/efr32/efr32mg21/README.md
+++ b/examples/platforms/efr32/efr32mg21/README.md
@@ -30,8 +30,8 @@
2. Install Flex (Gecko) SDK including RAIL Library from Simplicity Studio.
- Connect EFR32MG21 Wireless Starter Kit to Simplicity Studio.
- - Find Flex SDK v3.0 in the Software Update page and click Install.
- - Flex SDK v3.0 will be installed in the path:
+ - Find Flex SDK v3.1 in the Software Update page and click Install.
+ - Flex SDK v3.1 will be installed in the path:
- Mac
- `/Applications/Simplicity\ Studio.app/Contents/Eclipse/developer/sdks/gecko_sdk_suite`
- Windows
@@ -65,7 +65,47 @@
$ ./bootstrap
```
-For EFR32MG21™ Mighty Gecko Wireless Starter Kit:
+For EFR32MG21™ Mighty Gecko Wireless Starter Kit, this can be done using both the CMake and autotools build systems
+
+**CMake (preferred)**
+
+```bash
+$ ./script/cmake-build efr32mg21 -DBOARD=brd4180b
+...
+-- Configuring done
+-- Generating done
+-- Build files have been written to: <path-to-openthread>/build/efr32mg21
++ [[ -n ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd ]]
++ ninja ot-rcp ot-cli-ftd ot-cli-mtd ot-ncp-ftd ot-ncp-mtd sleepy-demo-ftd sleepy-demo-mtd
+[940/940] Linking CXX executable examples/apps/ncp/ot-ncp-ftd
++ cd <path-to-openthread>
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/build/efr32mg21/examples`.
+
+```bash
+# For linux
+$ find build/efr32mg21/examples -type f -executable
+build/efr32mg21/examples/apps/cli/ot-cli-mtd
+build/efr32mg21/examples/apps/cli/ot-cli-ftd
+build/efr32mg21/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg21/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg21/examples/apps/ncp/ot-rcp
+build/efr32mg21/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg21/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+
+# For BSD/Darwin/mac systems
+$ find build/efr32mg21/examples -type f -perm +111
+build/efr32mg21/examples/apps/cli/ot-cli-mtd
+build/efr32mg21/examples/apps/cli/ot-cli-ftd
+build/efr32mg21/examples/apps/ncp/ot-ncp-ftd
+build/efr32mg21/examples/apps/ncp/ot-ncp-mtd
+build/efr32mg21/examples/apps/ncp/ot-rcp
+build/efr32mg21/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/sleepy-demo-ftd
+build/efr32mg21/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/sleepy-demo-mtd
+```
+
+**autotools (soon to be depracated)**
```bash
$ make -f examples/Makefile-efr32mg21 BOARD=BRD4180A
@@ -183,7 +223,7 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
## Verification
@@ -193,4 +233,4 @@
The EFR32 example has been verified with following Flex SDK/RAIL Library version:
-- Flex SDK version 3.0.x
+- Flex SDK v3.1.x
diff --git a/examples/platforms/efr32/efr32mg21/arm-none-eabi.cmake b/examples/platforms/efr32/efr32mg21/arm-none-eabi.cmake
new file mode 100644
index 0000000..0460316
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg21/arm-none-eabi.cmake
@@ -0,0 +1,51 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m33 -mthumb -fmessage-length=0 -ffunction-sections -fdata-sections -mfpu=fpv5-sp-d16 -mfloat-abi=hard")
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=c99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/efr32/efr32mg21/crypto/mbedtls_config_autogen.h b/examples/platforms/efr32/efr32mg21/crypto/mbedtls_config_autogen.h
index 7f02e60..e55f74a 100644
--- a/examples/platforms/efr32/efr32mg21/crypto/mbedtls_config_autogen.h
+++ b/examples/platforms/efr32/efr32mg21/crypto/mbedtls_config_autogen.h
@@ -24,8 +24,9 @@
#define MBEDTLS_ECP_C
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
#define MBEDTLS_ECDSA_C
-#define MBEDTLS_ENTROPY_RAIL_C
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_MD_C
#define MBEDTLS_ECJPAKE_C
#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
@@ -35,14 +36,12 @@
#define MBEDTLS_ENTROPY_FORCE_SHA256
#define MBEDTLS_ENTROPY_MAX_SOURCES 2
#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_X509_CRT_PARSE_C
@@ -51,13 +50,18 @@
#define MBEDTLS_OID_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
+#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
#include "config-device-acceleration.h"
+#if !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC)
#include "sl_malloc.h"
#define MBEDTLS_PLATFORM_FREE_MACRO sl_free
#define MBEDTLS_PLATFORM_CALLOC_MACRO sl_calloc
+#endif
+
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_C
diff --git a/examples/platforms/efr32/efr32mg21/efr32mg21.cmake b/examples/platforms/efr32/efr32mg21/efr32mg21.cmake
new file mode 100644
index 0000000..eaaffdd
--- /dev/null
+++ b/examples/platforms/efr32/efr32mg21/efr32mg21.cmake
@@ -0,0 +1,98 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+# ==============================================================================
+# Verify board is supported for platform
+# ==============================================================================
+if(BOARD_LOWERCASE STREQUAL "brd4180a")
+ set(MCU "EFR32MG21A020F1024IM32")
+elseif(BOARD_LOWERCASE STREQUAL "brd4180b")
+ set(MCU "EFR32MG21A020F1024IM32")
+else()
+ message(FATAL_ERROR "
+ BOARD=${BOARD} not supported.
+
+ Please provide a value for BOARD variable e.g BOARD=brd4180a.
+ Currently supported:
+ - brd4180a
+ - brd4180b
+ ")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "${MCU}")
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+# ==============================================================================
+# Platform library
+# ==============================================================================
+set(OT_PLATFORM_LIB "openthread-efr32mg21")
+set(OT_PLATFORM_LIB ${OT_PLATFORM_LIB} PARENT_SCOPE)
+
+set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/efr32mg21/efr32mg21.ld")
+
+add_library(openthread-efr32mg21
+ ${EFR32_COMMON_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-efr32mg21
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-efr32mg21
+ PUBLIC
+ ${EFR32_COMMON_3RD_LIBS}
+ silabs-libnvm3_CM33_gcc
+ silabs-efr32mg21-sdk
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-efr32mg21
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-efr32mg21
+ PRIVATE
+ ${EFR32_CFLAGS}
+)
+
+target_include_directories(openthread-efr32mg21
+ PUBLIC
+ ${EFR32_INCLUDES}
+ PRIVATE
+ ${SILABS_EFR32MG2X_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
diff --git a/tests/scripts/expect/cli-anycast.exp b/examples/platforms/efr32/sleepy-demo/CMakeLists.txt
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to examples/platforms/efr32/sleepy-demo/CMakeLists.txt
index 3081a6b..b99a6b6 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/examples/platforms/efr32/sleepy-demo/CMakeLists.txt
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +26,10 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+if(OT_FTD)
+ add_subdirectory(sleepy-demo-ftd)
+endif()
-
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+if(OT_MTD)
+ add_subdirectory(sleepy-demo-mtd)
+endif()
diff --git a/tests/scripts/expect/cli-anycast.exp b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/CMakeLists.txt
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/CMakeLists.txt
index 3081a6b..f8aaf63 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/CMakeLists.txt
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +26,28 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+add_executable(sleepy-demo-ftd
+ ${PROJECT_SOURCE_DIR}/examples/apps/cli/cli_uart.cpp
+ main.c
+)
+
+target_include_directories(sleepy-demo-ftd PRIVATE ${COMMON_INCLUDES})
+
+target_link_libraries(sleepy-demo-ftd PRIVATE
+ openthread-cli-ftd
+ ${OT_PLATFORM_LIB}
+ openthread-ftd
+ ${OT_PLATFORM_LIB}
+ ${OT_MBEDTLS}
+ ot-config
+)
-set spawn_id [spawn_node 1]
+target_compile_options(sleepy-demo-ftd
+ PRIVATE
+ ${EFR32_CFLAGS}
+)
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
+install(TARGETS sleepy-demo-ftd
+ DESTINATION bin)
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
diff --git a/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/Makefile.am b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/Makefile.am
index 141968e..f7b548d 100644
--- a/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/Makefile.am
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/Makefile.am
@@ -36,14 +36,15 @@
$(NULL)
CPPFLAGS_COMMON += \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
-Wno-sign-compare \
+ -I$(top_srcdir)/examples/apps/cli \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE) \
-I$(top_srcdir)/examples/platforms/efr32/src \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/silabs/rail_config \
$(SILABS_GSDK_CPPFLAGS) \
@@ -61,6 +62,7 @@
$(NULL)
SOURCES_COMMON += \
+ ../../../../apps/cli/cli_uart.cpp \
main.c \
$(NULL)
diff --git a/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/main.c b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/main.c
index 2944a83..19560cb 100644
--- a/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/main.c
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-ftd/main.c
@@ -71,6 +71,14 @@
void applicationTick(void);
void sFtdReceiveCallback(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+/**
+ * This function initializes the CLI app.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+extern void otAppCliInit(otInstance *aInstance);
+
// Variables
static otInstance * instance;
static otUdpSocket sFtdSocket;
@@ -93,7 +101,7 @@
instance = otInstanceInitSingle();
assert(instance);
- otCliUartInit(instance);
+ otAppCliInit(instance);
otCliOutputFormat("sleepy-demo-ftd started\r\n");
setNetworkConfiguration(instance);
diff --git a/tests/scripts/expect/cli-anycast.exp b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/CMakeLists.txt
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/CMakeLists.txt
index 3081a6b..6eec209 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/CMakeLists.txt
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +26,21 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+add_executable(sleepy-demo-mtd
+ ${PROJECT_SOURCE_DIR}/examples/apps/cli/cli_uart.cpp
+ main.c
+)
+target_include_directories(sleepy-demo-mtd PRIVATE ${COMMON_INCLUDES})
-set spawn_id [spawn_node 1]
+target_link_libraries(sleepy-demo-mtd PRIVATE
+ openthread-cli-mtd
+ ${OT_PLATFORM_LIB}
+ openthread-mtd
+ ${OT_PLATFORM_LIB}
+ ${OT_MBEDTLS}
+ ot-config
+)
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+install(TARGETS sleepy-demo-mtd
+ DESTINATION bin)
diff --git a/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/Makefile.am b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/Makefile.am
index 6adedec..9d855bc 100644
--- a/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/Makefile.am
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/Makefile.am
@@ -36,14 +36,15 @@
$(NULL)
CPPFLAGS_COMMON += \
- -DNVIC_CONFIG=\"platform/base/hal/micro/cortexm3/efm32/nvic-config.h\" \
-DPLATFORM_HEADER=\"platform/base/hal/micro/cortexm3/compiler/gcc.h\" \
-Wno-sign-compare \
+ -I$(top_srcdir)/examples/apps/cli \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE)/$(BOARD_LOWERCASE) \
-I$(top_srcdir)/examples/platforms/efr32/$(PLATFORM_LOWERCASE) \
-I$(top_srcdir)/examples/platforms/efr32/src \
-I$(top_srcdir)/include \
+ -I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/silabs/rail_config \
$(SILABS_GSDK_CPPFLAGS) \
@@ -61,6 +62,7 @@
$(NULL)
SOURCES_COMMON += \
+ ../../../../apps/cli/cli_uart.cpp \
main.c \
$(NULL)
diff --git a/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/main.c b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/main.c
index 17560fe..23318f7 100644
--- a/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/main.c
+++ b/examples/platforms/efr32/sleepy-demo/sleepy-demo-mtd/main.c
@@ -76,6 +76,14 @@
void applicationTick(void);
void mtdReceiveCallback(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+/**
+ * This function initializes the CLI app.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+extern void otAppCliInit(otInstance *aInstance);
+
// Variables
static otInstance * instance;
static otUdpSocket sMtdSocket;
@@ -97,7 +105,7 @@
instance = otInstanceInitSingle();
assert(instance);
- otCliUartInit(instance);
+ otAppCliInit(instance);
otLinkSetPollPeriod(instance, SLEEPY_POLL_PERIOD_MS);
setNetworkConfiguration(instance);
@@ -211,7 +219,7 @@
config.mDeviceType = 0;
config.mNetworkData = 0;
otThreadSetLinkMode(instance, config);
- sAllowDeepSleep = true;
+ sAllowDeepSleep = false;
break;
case OT_DEVICE_ROLE_DETACHED:
diff --git a/examples/platforms/efr32/src/alarm.c b/examples/platforms/efr32/src/alarm.c
index 6caa1ef..81a0015 100644
--- a/examples/platforms/efr32/src/alarm.c
+++ b/examples/platforms/efr32/src/alarm.c
@@ -38,6 +38,7 @@
#include "openthread-system.h"
#include <openthread/config.h>
+#include <openthread/platform/alarm-micro.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include "common/logging.hpp"
@@ -145,3 +146,23 @@
}
}
}
+
+uint32_t otPlatAlarmMicroGetNow(void)
+{
+ // TODO microsecond support
+ return otPlatAlarmMilliGetNow();
+}
+
+void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
+{
+ // TODO microsecond support
+ otPlatAlarmMilliStartAt(aInstance, aT0, aDt);
+}
+
+void otPlatAlarmMicroStop(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ sl_sleeptimer_stop_timer(&sl_handle);
+ sIsRunning = false;
+}
diff --git a/examples/platforms/efr32/src/entropy.c b/examples/platforms/efr32/src/entropy.c
index 3a755e1..b9c629c 100644
--- a/examples/platforms/efr32/src/entropy.c
+++ b/examples/platforms/efr32/src/entropy.c
@@ -51,7 +51,6 @@
// Non-zero return values for mbedtls_hardware_poll() signify an error has occurred
otEXPECT_ACTION(0 == mbedtls_hardware_poll(NULL, &aOutput[outputLen], remaining, &partialLen),
error = OT_ERROR_FAILED);
- otEXPECT_ACTION(partialLen > 0, error = OT_ERROR_FAILED);
}
exit:
diff --git a/examples/platforms/efr32/src/ieee802154mac.h b/examples/platforms/efr32/src/ieee802154mac.h
new file mode 100644
index 0000000..178dfee
--- /dev/null
+++ b/examples/platforms/efr32/src/ieee802154mac.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file holds required 802.15.4 definitions
+ *
+ */
+
+#ifndef __IEEE802154IEEE802154_H__
+#define __IEEE802154IEEE802154_H__
+
+#define IEEE802154_MIN_LENGTH \
+ 4 // Technically, a version 2 packet / ACK
+ // can be 4 bytes with seq# suppression
+#define IEEE802154_MAX_LENGTH 127
+#define IEEE802154_ACK_LENGTH 5
+
+// FCF + DSN + dest PANID + dest addr + src PANID + src addr (without security header)
+#define IEEE802154_MAX_MHR_LENGTH (2 + 1 + 2 + 8 + 2 + 8)
+
+#define IEEE802154_DSN_OFFSET 2
+#define IEEE802154_FCF_OFFSET 0
+
+//------------------------------------------------------------------------
+// 802.15.4 Frame Control Field definitions for Beacon, Ack, Data, Command
+
+#define IEEE802154_FRAME_TYPE_MASK ((uint16_t)0x0007U) // Bits 0..2
+#define IEEE802154_FRAME_TYPE_BEACON ((uint16_t)0x0000U) // Beacon
+#define IEEE802154_FRAME_TYPE_DATA ((uint16_t)0x0001U) // Data
+#define IEEE802154_FRAME_TYPE_ACK ((uint16_t)0x0002U) // ACK
+#define IEEE802154_FRAME_TYPE_COMMAND ((uint16_t)0x0003U) // Command
+#define IEEE802154_FRAME_TYPE_CONTROL IEEE802154_FRAME_TYPE_COMMAND // (synonym)
+#define IEEE802154_FRAME_TYPE_RESERVED_MASK ((uint16_t)0x0004U) // Versions 0/1
+// 802.15.4E-2012 introduced MultiPurpose with different Frame Control Field
+// layout described in the MultiPurpose section below.
+#define IEEE802154_FRAME_TYPE_MULTIPURPOSE ((uint16_t)0x0005U) // MultiPurpose
+
+#define IEEE802154_FRAME_FLAG_SECURITY_ENABLED ((uint16_t)0x0008U) // Bit 3
+#define IEEE802154_FRAME_FLAG_FRAME_PENDING ((uint16_t)0x0010U) // Bit 4
+#define IEEE802154_FRAME_FLAG_ACK_REQUIRED ((uint16_t)0x0020U) // Bit 5
+#define IEEE802154_FRAME_FLAG_INTRA_PAN ((uint16_t)0x0040U) // Bit 6
+// 802.15.4-2006 renamed the Intra-Pan flag PanId-Compression
+#define IEEE802154_FRAME_FLAG_PANID_COMPRESSION IEEE802154_FRAME_FLAG_INTRA_PAN
+#define IEEE802154_FRAME_FLAG_RESERVED ((uint16_t)0x0080U) // Bit 7 reserved
+// Use the reserved flag internally to check whether frame pending bit was set in outgoing ACK
+#define IEEE802154_FRAME_PENDING_SET_IN_OUTGOING_ACK IEEE802154_FRAME_FLAG_RESERVED
+// 802.15.4E-2012 introduced these flags for Frame Version 2 frames
+// which are reserved bit positions in earlier Frame Version frames:
+#define IEEE802154_FRAME_FLAG_SEQ_SUPPRESSION ((uint16_t)0x0100U) // Bit 8
+#define IEEE802154_FRAME_FLAG_IE_LIST_PRESENT ((uint16_t)0x0200U) // Bit 9
+
+#define IEEE802154_FRAME_DESTINATION_MODE_MASK ((uint16_t)0x0C00U) // Bits 10..11
+#define IEEE802154_FRAME_DESTINATION_MODE_NONE ((uint16_t)0x0000U) // Mode 0
+#define IEEE802154_FRAME_DESTINATION_MODE_RESERVED ((uint16_t)0x0400U) // Mode 1
+#define IEEE802154_FRAME_DESTINATION_MODE_SHORT ((uint16_t)0x0800U) // Mode 2
+#define IEEE802154_FRAME_DESTINATION_MODE_LONG ((uint16_t)0x0C00U) // Mode 3
+// 802.15.4e-2012 only (not adopted into 802.15.4-2015)
+#define IEEE802154_FRAME_DESTINATION_MODE_BYTE IEEE802154_FRAME_DESTINATION_MODE_RESERVED
+
+#define IEEE802154_FRAME_VERSION_MASK ((uint16_t)0x3000U) // Bits 12..13
+#define IEEE802154_FRAME_VERSION_2003 ((uint16_t)0x0000U) // Version 0
+#define IEEE802154_FRAME_VERSION_2006 ((uint16_t)0x1000U) // Version 1
+// In 802.15.4-2015, Version 2 is just called "IEEE STD 802.15.4"
+// which can be rather confusing. It was introduced in 802.15.4E-2012.
+#define IEEE802154_FRAME_VERSION_2012 ((uint16_t)0x2000U) // Version 2
+#define IEEE802154_FRAME_VERSION_2015 ((uint16_t)0x2000U) // Version 2
+#define IEEE802154_FRAME_VERSION_RESERVED ((uint16_t)0x3000U) // Version 3
+
+#define IEEE802154_FRAME_SOURCE_MODE_MASK ((uint16_t)0xC000U) // Bits 14..15
+#define IEEE802154_FRAME_SOURCE_MODE_NONE ((uint16_t)0x0000U) // Mode 0
+#define IEEE802154_FRAME_SOURCE_MODE_RESERVED ((uint16_t)0x4000U) // Mode 1
+#define IEEE802154_FRAME_SOURCE_MODE_SHORT ((uint16_t)0x8000U) // Mode 2
+#define IEEE802154_FRAME_SOURCE_MODE_LONG ((uint16_t)0xC000U) // Mode 3
+// 802.15.4e-2012 only (not adopted into 802.15.4-2015)
+#define IEEE802154_FRAME_SOURCE_MODE_BYTE IEEE802154_FRAME_SOURCE_MODE_RESERVED
+
+//------------------------------------------------------------------------
+// 802.15.4E-2012 Frame Control Field definitions for MultiPurpose
+
+#define IEEE802154_MP_FRAME_TYPE_MASK IEEE802154_FRAME_TYPE_MASK // Bits 0..2
+#define IEEE802154_MP_FRAME_TYPE_MULTIPURPOSE IEEE802154_FRAME_TYPE_MULTIPURPOSE
+
+#define IEEE802154_MP_FRAME_FLAG_LONG_FCF ((uint16_t)0x0008U) // Bit 3
+
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_MASK ((uint16_t)0x0030U) // Bits 4..5
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_NONE ((uint16_t)0x0000U) // Mode 0
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_RESERVED ((uint16_t)0x0010U) // Mode 1
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_SHORT ((uint16_t)0x0020U) // Mode 2
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_LONG ((uint16_t)0x0030U) // Mode 3
+// 802.15.4e-2012 only (not adopted into 802.15.4-2015)
+#define IEEE802154_MP_FRAME_DESTINATION_MODE_BYTE IEEE802154_MP_FRAME_DESTINATION_MODE_RESERVED
+
+#define IEEE802154_MP_FRAME_SOURCE_MODE_MASK ((uint16_t)0x00C0U) // Bits 6..7
+#define IEEE802154_MP_FRAME_SOURCE_MODE_NONE ((uint16_t)0x0000U) // Mode 0
+#define IEEE802154_MP_FRAME_SOURCE_MODE_RESERVED ((uint16_t)0x0040U) // Mode 1
+#define IEEE802154_MP_FRAME_SOURCE_MODE_SHORT ((uint16_t)0x0080U) // Mode 2
+#define IEEE802154_MP_FRAME_SOURCE_MODE_LONG ((uint16_t)0x00C0U) // Mode 3
+// 802.15.4e-2012 only (not adopted into 802.15.4-2015)
+#define IEEE802154_MP_FRAME_SOURCE_MODE_BYTE IEEE802154_MP_FRAME_SOURCE_MODE_RESERVED
+
+#define IEEE802154_MP_FRAME_FLAG_PANID_PRESENT ((uint16_t)0x0100U) // Bit 8
+#define IEEE802154_MP_FRAME_FLAG_SECURITY_ENABLED ((uint16_t)0x0200U) // Bit 9
+#define IEEE802154_MP_FRAME_FLAG_SEQ_SUPPRESSION ((uint16_t)0x0400U) // Bit 10
+#define IEEE802154_MP_FRAME_FLAG_FRAME_PENDING ((uint16_t)0x0800U) // Bit 11
+
+#define IEEE802154_MP_FRAME_VERSION_MASK IEEE802154_FRAME_VERSION_MASK // Bits 12..13
+#define IEEE802154_MP_FRAME_VERSION_2012 ((uint16_t)0x0000U) // Zeroed out
+#define IEEE802154_MP_FRAME_VERSION_2015 ((uint16_t)0x0000U) // Zeroed out
+// All other MultiPurpose Frame Versions are reserved
+
+#define IEEE802154_MP_FRAME_FLAG_ACK_REQUIRED ((uint16_t)0x4000U) // Bit 14
+#define IEEE802154_MP_FRAME_FLAG_IE_LIST_PRESENT ((uint16_t)0x8000U) // Bit 15
+
+//------------------------------------------------------------------------
+// Information Elements fields
+
+#define IEEE802154_KEYID_MODE_0 ((uint8_t)0x0000U)
+#define IEEE802154_KEYID_MODE_0_SIZE 0
+
+#define IEEE802154_KEYID_MODE_1 ((uint8_t)0x0008U)
+#define IEEE802154_KEYID_MODE_1_SIZE 0
+
+#define IEEE802154_KEYID_MODE_2 ((uint8_t)0x0010U)
+#define IEEE802154_KEYID_MODE_2_SIZE 4
+
+#define IEEE802154_KEYID_MODE_3 ((uint8_t)0x0018U)
+#define IEEE802154_KEYID_MODE_3_SIZE 8
+
+#define IEEE802154_KEYID_MODE_MASK ((uint8_t)0x0018U)
+
+//------------------------------------------------------------------------
+// Information Elements fields
+
+// There are Header IEs and Payload IEs. Header IEs are authenticated
+// if MAC Security is enabled. Payload IEs are both authenticated and
+// encrypted if MAC security is enabled.
+
+// Header and Payload IEs have slightly different formats and different
+// contents based on the 802.15.4 spec.
+
+// Both are actually a list of IEs that continues until a termination
+// IE is seen.
+
+#define IEEE802154_FRAME_HEADER_INFO_ELEMENT_LENGTH_MASK 0x007F // bits 0-6
+#define IEEE802154_FRAME_HEADER_INFO_ELEMENT_ID_MASK 0x7F80 // bits 7-14
+#define IEEE802154_FRAME_HEADER_INFO_ELEMENT_TYPE_MASK 0x8000 // bit 15
+
+#define IEEE802154_FRAME_HEADER_INFO_ELEMENT_ID_SHIFT 7
+
+#define IEEE802154_FRAME_PAYLOAD_INFO_ELEMENT_LENGTH_MASK 0x07FF // bits 0 -10
+#define IEEE802154_FRAME_PAYLOAD_INFO_ELEMENT_GROUP_ID_MASK 0x7800 // bits 11-14
+#define IEEE802154_FRAME_PAYLOAD_INFO_ELEMENT_TYPE_MASK 0x8000 // bit 15
+
+#define IEEE802154_FRAME_PAYLOAD_INFO_ELEMENT_ID_SHIFT 11
+
+// This "type" field indicates header vs. payload IE. However there is
+// also a Header IE List terminator which would imply the IE list
+// that follows is only payload IEs.
+#define IEEE802154_FRAME_INFO_ELEMENT_TYPE_MASK 0x8000
+
+// Header Termination ID 1 is used when there are Payload IEs that follow.
+// Header Termination ID 2 is used when there are no Payload IEs and the
+// next field is the MAC payload.
+#define IEEE802154_FRAME_HEADER_TERMINATION_ID_1 0x7E
+#define IEEE802154_FRAME_HEADER_TERMINATION_ID_2 0x7F
+#define IEEE802154_FRAME_PAYLOAD_TERMINATION_ID 0x0F
+
+#endif //__IEEE802154IEEE802154_H__
diff --git a/examples/platforms/efr32/src/mbedtls_config.h b/examples/platforms/efr32/src/mbedtls_config.h
index c56ab3b..c9035a6 100644
--- a/examples/platforms/efr32/src/mbedtls_config.h
+++ b/examples/platforms/efr32/src/mbedtls_config.h
@@ -14,7 +14,11 @@
// <i> Default: 768
// <i> The size configured here determines the size of each of the two
// <i> internal I/O buffers used in mbedTLS when sending and receiving data.
-#define MBEDTLS_SSL_MAX_CONTENT_LEN 768
+#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maximum fragment length in bytes */
+#else
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maximum fragment length in bytes */
+#endif
// <q SL_MBEDTLS_SSL_MAX_FRAGMENT_LENGTH> Enable support for RFC 6066 max_fragment_length extension in SSL.
// <i> Default: 1
diff --git a/examples/platforms/efr32/src/memory.c b/examples/platforms/efr32/src/memory.c
new file mode 100644
index 0000000..1f48994
--- /dev/null
+++ b/examples/platforms/efr32/src/memory.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-core-efr32-config.h"
+#include "platform-efr32.h"
+
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#include <openthread/platform/memory.h>
+
+#include "sl_malloc.h"
+
+void *otPlatCAlloc(size_t aNum, size_t aSize)
+{
+ return sl_calloc(aNum, aSize);
+}
+
+void otPlatFree(void *aPtr)
+{
+ sl_free(aPtr);
+}
+#endif
diff --git a/examples/platforms/efr32/src/openthread-core-efr32-config.h b/examples/platforms/efr32/src/openthread-core-efr32-config.h
index d1cbde6..3608210 100644
--- a/examples/platforms/efr32/src/openthread-core-efr32-config.h
+++ b/examples/platforms/efr32/src/openthread-core-efr32-config.h
@@ -33,6 +33,9 @@
*/
#include "board_config.h"
+
+// IMPORTANT: Do not remove this include. Apps will build without error, but
+// they will not boot up properly
#include "em_msc.h"
#ifndef OPENTHREAD_CORE_EFR32_CONFIG_H_
@@ -101,7 +104,17 @@
* Define to 1 if you want to enable software transmission security logic.
*
*/
-#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 0
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE \
+ (OPENTHREAD_RADIO && (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2))
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+ *
+ * Define to 1 to enable software transmission target time logic.
+ *
+ */
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE \
+ (OPENTHREAD_RADIO && (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2))
/**
* @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE
@@ -112,6 +125,15 @@
#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ENERGY_SCAN_ENABLE 0
/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
+ *
+ * Define to 1 if you want to support microsecond timer in platform.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE \
+ (OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2))
+
+/**
* @def OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
*
* Define to 1 to enable otPlatFlash* APIs to support non-volatile storage.
@@ -122,11 +144,40 @@
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_MIN_SLEEP_DURATION_MS
+ *
+ * Minimum duration in ms below which the platform will not
+ * enter a deep sleep (EM2) mode.
+ *
+ */
+#define OPENTHREAD_CONFIG_MIN_SLEEP_DURATION_MS 5
+
+/**
+ * @def OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+ *
+ * Enable the external heap.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_EFR32_UART_TX_FLUSH_TIMEOUT_MS
+ *
+ * Maximum time to wait for a flush to complete in otPlatUartFlush().
+ *
+ * Value is in milliseconds
+ *
+ */
+#define OPENTHREAD_CONFIG_EFR32_UART_TX_FLUSH_TIMEOUT_MS 500
#endif // OPENTHREAD_CORE_EFR32_CONFIG_H_
diff --git a/examples/platforms/efr32/src/radio.c b/examples/platforms/efr32/src/radio.c
index 44e8380..a03079b 100644
--- a/examples/platforms/efr32/src/radio.c
+++ b/examples/platforms/efr32/src/radio.c
@@ -32,55 +32,87 @@
*
*/
-#include <openthread-core-config.h>
-#include <openthread/config.h>
-
#include <assert.h>
#include "openthread-system.h"
#include <openthread/config.h>
+#include <openthread/link.h>
+#include <openthread/platform/alarm-micro.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
#include "common/logging.hpp"
#include "utils/code_utils.h"
+#include "utils/mac_frame.h"
#include "utils/soft_source_match_table.h"
#include "antenna.h"
#include "board_config.h"
-#include "em_cmu.h"
#include "em_core.h"
#include "em_system.h"
-#include "hal-config.h"
+#include "ieee802154mac.h"
+#include "openthread-core-efr32-config.h"
#include "pa_conversions_efr32.h"
#include "platform-band.h"
#include "rail.h"
#include "rail_config.h"
#include "rail_ieee802154.h"
-#define IEEE802154_MIN_LENGTH (5u)
-#define IEEE802154_MAX_LENGTH (127u)
-#define IEEE802154_ACK_LENGTH (5u)
+#ifdef SL_COMPONENT_CATALOG_PRESENT
+#include "sl_component_catalog.h"
+#endif // SL_COMPONENT_CATALOG_PRESENT
-// FCF + DSN + dest PANID + dest addr + src PANID + src addr (without security header)
-#define IEEE802154_MAX_MHR_LENGTH (2u + 1u + 2u + 8u + 2u + 8u)
+#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+#include "sl_rail_util_ant_div.h"
+#include "sl_rail_util_ant_div_config.h"
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
-#define IEEE802154_FRAME_TYPE_MASK (0x07u)
-#define IEEE802154_FRAME_TYPE_ACK (0x02u)
-#define IEEE802154_FRAME_TYPE_MAC_COMMAND (0x03u)
-#define IEEE802154_ACK_REQUEST (1u << 5)
-#define IEEE802154_DSN_OFFSET (2u)
-#define IEEE802154_FCF_OFFSET (0u)
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+#include "coexistence-802154.h"
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
-#define EFR32_RECEIVE_SENSITIVITY (-100) // dBm
-#define EFR32_RSSI_AVERAGING_TIME (16u) // us
-#define EFR32_RSSI_AVERAGING_TIMEOUT (300u) // us
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+#include "sl_rail_util_ieee802154_stack_event.h"
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
-#define EFR32_SCHEDULER_SAMPLE_RSSI_PRIORITY (10u) // High priority
-#define EFR32_SCHEDULER_TX_PRIORITY (10u) // High priority
-#define EFR32_SCHEDULER_RX_PRIORITY (20u) // Low priority
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
+#include "sl_rail_util_ieee802154_phy_select.h"
+#endif // #ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
+//------------------------------------------------------------------------------
+// Enums, macros and static variables
+
+#define LOW_BYTE(n) ((uint8_t)((n)&0xFF))
+#define HIGH_BYTE(n) ((uint8_t)(LOW_BYTE((n) >> 8)))
+
+#define EFR32_RECEIVE_SENSITIVITY -100 // dBm
+#define EFR32_RSSI_AVERAGING_TIME 16 // us
+#define EFR32_RSSI_AVERAGING_TIMEOUT 300 // us
+
+// Internal flags
+#define FLAG_RADIO_INIT_DONE 0x0001
+#define FLAG_ONGOING_TX_DATA 0x0002
+#define FLAG_ONGOING_TX_ACK 0x0004
+#define FLAG_WAITING_FOR_ACK 0x0008
+#define FLAG_SYMBOL_TIMER_RUNNING 0x0010 // Not used
+#define FLAG_CURRENT_TX_USE_CSMA 0x0020
+#define FLAG_DATA_POLL_FRAME_PENDING_SET 0x0040
+#define FLAG_CALIBRATION_NEEDED 0x0080 // Not used
+#define FLAG_IDLE_PENDING 0x0100 // Not used
+
+#define TX_COMPLETE_RESULT_SUCCESS 0x00 // Not used
+#define TX_COMPLETE_RESULT_CCA_FAIL 0x01
+#define TX_COMPLETE_RESULT_OTHER_FAIL 0x02
+#define TX_COMPLETE_RESULT_NONE 0xFF // Not used
+
+#define TX_WAITING_FOR_ACK 0x00
+#define TX_NO_ACK 0x01
+
+#define ONGOING_TX_FLAGS (FLAG_ONGOING_TX_DATA | FLAG_ONGOING_TX_ACK)
+
+#define QUARTER_DBM_IN_DBM 4
+#define US_IN_MS 1000
enum
{
@@ -91,6 +123,7 @@
#endif
};
+// Energy Scan
typedef enum
{
ENERGY_SCAN_STATUS_IDLE,
@@ -104,87 +137,366 @@
ENERGY_SCAN_MODE_ASYNC
} energyScanMode;
-RAIL_Handle_t gRailHandle;
+static volatile energyScanStatus sEnergyScanStatus;
+static volatile int8_t sEnergyScanResultDbm;
+static energyScanMode sEnergyScanMode;
-static volatile bool sTransmitBusy = false;
-static bool sPromiscuous = false;
-static otRadioState sState = OT_RADIO_STATE_DISABLED;
+static bool sIsSrcMatchEnabled = false;
-enum
-{
- ACKED_WITH_FP_MATCH_LENGTH = 1 + IEEE802154_MAX_MHR_LENGTH, // PHR and MHR
- ACKED_WITH_FP_SLOTS = 32, // maximum number of Data Request packets in the RX FIFO. Length should be a power of 2.
-};
-
-typedef struct efr32AckedWithFP
-{
- uint8_t mLength;
- uint8_t mPacket[ACKED_WITH_FP_MATCH_LENGTH];
-} efr32AckedWithFP;
-static bool sIsSrcMatchEnabled = false;
-static efr32AckedWithFP sAckedWithFPFifo[ACKED_WITH_FP_SLOTS];
-static uint32_t sAckedWithFPReadIndex;
-static volatile uint32_t sAckedWithFPWriteIndex;
-
+// Receive
static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH];
+static uint8_t sReceiveAckPsdu[IEEE802154_ACK_LENGTH];
static otRadioFrame sReceiveFrame;
+static otRadioFrame sReceiveAckFrame;
static otError sReceiveError;
+// Transmit
static otRadioFrame sTransmitFrame;
static uint8_t sTransmitPsdu[IEEE802154_MAX_LENGTH];
static volatile otError sTransmitError;
+static volatile bool sTransmitBusy = false;
+static otRadioFrame * sTxFrame = NULL;
+
+// Radio
+#define CCA_THRESHOLD_UNINIT 127
+#define CCA_THRESHOLD_DEFAULT -75 // dBm - default for 2.4GHz 802.15.4
+
+static bool sPromiscuous = false;
+static otRadioState sState = OT_RADIO_STATE_DISABLED;
static efr32CommonConfig sCommonConfig;
-static efr32BandConfig sBandConfigs[EFR32_NUM_BAND_CONFIGS];
+static efr32BandConfig sBandConfig[EFR32_NUM_BAND_CONFIGS];
+static efr32BandConfig * sCurrentBandConfig = NULL;
+
+static int8_t sCcaThresholdDbm = CCA_THRESHOLD_DEFAULT;
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
static efr32RadioCounters sRailDebugCounters;
#endif
-static volatile energyScanStatus sEnergyScanStatus;
-static volatile int8_t sEnergyScanResultDbm;
-static energyScanMode sEnergyScanMode;
+// RAIL
+RAIL_Handle_t emPhyRailHandle;
+#define gRailHandle emPhyRailHandle
-#define QUARTER_DBM_IN_DBM 4
-#define US_IN_MS 1000
+static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
+ NULL, // addresses
+ {
+ // ackConfig
+ true, // ackConfig.enable
+ 672, // ackConfig.ackTimeout
+ {
+ // ackConfig.rxTransitions
+ RAIL_RF_STATE_RX, // ackConfig.rxTransitions.success
+ RAIL_RF_STATE_RX, // ackConfig.rxTransitions.error
+ },
+ {
+ // ackConfig.txTransitions
+ RAIL_RF_STATE_RX, // ackConfig.txTransitions.success
+ RAIL_RF_STATE_RX, // ackConfig.txTransitions.error
+ },
+ },
+ {
+ // timings
+ 100, // timings.idleToRx
+ 192 - 10, // timings.txToRx
+ 100, // timings.idleToTx
+ 192, // timings.rxToTx
+ 0, // timings.rxSearchTimeout
+ 0, // timings.txToRxSearchTimeout
+ },
+ RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES, // framesMask
+ false, // promiscuousMode
+ false, // isPanCoordinator
+ false, // defaultFramePendingInOutgoingAcks
+};
+
+// Misc
+static volatile uint16_t miscInternalFlags = 0;
+static bool emPendingData = false;
+
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+enum
+{
+ RHO_INACTIVE = 0,
+ RHO_EXT_ACTIVE,
+ RHO_INT_ACTIVE, // Not used
+ RHO_BOTH_ACTIVE,
+};
+
+static uint8_t rhoActive = RHO_INACTIVE;
+static bool ptaGntEventReported;
+static bool sRadioCoexEnabled = true;
+
+#if SL_OPENTHREAD_COEX_COUNTER_ENABLE
+static uint32_t sCoexCounters[SL_RAIL_UTIL_COEX_EVENT_COUNT] = {0};
+#endif // SL_OPENTHREAD_COEX_COUNTER_ENABLE
+
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+// Transmit Security
+static uint32_t sMacFrameCounter;
+static uint8_t sKeyId;
+static struct otMacKey sPrevKey;
+static struct otMacKey sCurrKey;
+static struct otMacKey sNextKey;
+
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+// IE support
+static otExtAddress sExtAddress;
+static otRadioIeInfo sTransmitIeInfo;
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+// Enhanced ACKs, CSL
+static bool sAckedWithSecEnhAck;
+static uint32_t sAckFrameCounter;
+static uint8_t sAckKeyId;
+
+static uint8_t sAckIeData[OT_ACK_IE_MAX_SIZE];
+static uint8_t sAckIeDataLength = 0;
+
+static uint32_t sCslPeriod;
+static uint32_t sCslSampleTime;
+static const uint8_t sCslIeHeader[OT_IE_HEADER_SIZE] = {CSL_IE_HEADER_BYTES_LO, CSL_IE_HEADER_BYTES_HI};
+
+static void processSecurityForEnhancedAck(uint8_t *aAckFrame)
+{
+ otRadioFrame ackFrame;
+ struct otMacKey *key = NULL;
+ uint8_t keyId;
+
+ sAckedWithSecEnhAck = false;
+ otEXPECT(aAckFrame[1] & IEEE802154_FRAME_FLAG_SECURITY_ENABLED);
+
+ memset(&ackFrame, 0, sizeof(ackFrame));
+ ackFrame.mPsdu = &aAckFrame[1];
+ ackFrame.mLength = aAckFrame[0];
+
+ keyId = otMacFrameGetKeyId(&ackFrame);
+
+ otEXPECT(otMacFrameIsKeyIdMode1(&ackFrame) && keyId != 0);
+
+ if (keyId == sKeyId)
+ {
+ key = &sCurrKey;
+ }
+ else if (keyId == sKeyId - 1)
+ {
+ key = &sPrevKey;
+ }
+ else if (keyId == sKeyId + 1)
+ {
+ key = &sNextKey;
+ }
+ else
+ {
+ otEXPECT(false);
+ }
+
+ sAckFrameCounter = sMacFrameCounter;
+ sAckKeyId = keyId;
+ sAckedWithSecEnhAck = true;
+
+ ackFrame.mInfo.mTxInfo.mAesKey = key;
+
+ otMacFrameSetKeyId(&ackFrame, keyId);
+ otMacFrameSetFrameCounter(&ackFrame, sMacFrameCounter++);
+
+ // Perform AES-CCM encryption on the frame which is going to be sent.
+ otMacFrameProcessTransmitAesCcm(&ackFrame, &sExtAddress);
+
+exit:
+ return;
+}
+
+static uint16_t getCslPhase()
+{
+ uint32_t curTime = otPlatAlarmMicroGetNow();
+ uint32_t cslPeriodInUs = sCslPeriod * OT_US_PER_TEN_SYMBOLS;
+ uint32_t diff = ((sCslSampleTime % cslPeriodInUs) - (curTime % cslPeriodInUs) + cslPeriodInUs) % cslPeriodInUs;
+
+ return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS);
+}
+
+static void updateIeData(void)
+{
+ // The CSL IE Content field:
+ // ___________________________________________________
+ // | Octets: 2 | Octets: 2 | Octets: 0/2 |
+ // |______________|______________|_____________________|
+ // | CSL Phase | CSL Period | Rendezvous time |
+ // |______________|______________|_____________________|
+ //
+ // Note: The rendezvous time is included right when sending the packet,
+ // (in txCurrentPacket), before updating the 802.15.4 header with CSL IEs.
+ // The tx frame is modified at the right offset (see mInfo.mTxInfo.mIeInfo->mTimeIeOffset)
+
+ int8_t offset = 0;
+ if (sCslPeriod > 0)
+ {
+ uint8_t *finger = sAckIeData;
+ memcpy(finger, sCslIeHeader, OT_IE_HEADER_SIZE);
+ finger += OT_IE_HEADER_SIZE;
+
+ uint16_t cslPhase = getCslPhase();
+ *finger++ = HIGH_BYTE(cslPhase);
+ *finger++ = LOW_BYTE(cslPhase);
+
+ *finger++ = HIGH_BYTE((uint16_t)sCslPeriod);
+ *finger++ = LOW_BYTE((uint16_t)sCslPeriod);
+
+ offset = finger - sAckIeData;
+ }
+
+ sAckIeDataLength = offset;
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+//------------------------------------------------------------------------------
+// Forward Declarations
static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents);
-static const RAIL_IEEE802154_Config_t sRailIeee802154Config = {
- .addresses = NULL,
- .ackConfig =
- {
- .enable = true,
- .ackTimeout = 672,
- .rxTransitions =
- {
- .success = RAIL_RF_STATE_RX,
- .error = RAIL_RF_STATE_RX,
- },
- .txTransitions =
- {
- .success = RAIL_RF_STATE_RX,
- .error = RAIL_RF_STATE_RX,
- },
- },
- .timings =
- {
- .idleToRx = 100,
- .txToRx = 192 - 10,
- .idleToTx = 100,
- .rxToTx = 192,
- .rxSearchTimeout = 0,
- .txToRxSearchTimeout = 0,
- },
- .framesMask = RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
- .promiscuousMode = false,
- .isPanCoordinator = false,
- .defaultFramePendingInOutgoingAcks = false,
-};
+static void efr32PhyStackInit(void);
-static int8_t sCcaThresholdDbm = -75; // default -75dBm energy detect threshold
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+static void efr32CoexInit(void);
+// Try to transmit the current outgoing frame subject to MAC-level PTA
+static void tryTxCurrentPacket(void);
+#else
+// Transmit the current outgoing frame.
+void txCurrentPacket(void);
+#define tryTxCurrentPacket txCurrentPacket
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
-static efr32BandConfig *sCurrentBandConfig = NULL;
+static void txFailedCallback(bool isAck, uint8_t status);
+
+static bool validatePacketDetails(RAIL_RxPacketHandle_t packetHandle,
+ RAIL_RxPacketDetails_t *pPacketDetails,
+ RAIL_RxPacketInfo_t * pPacketInfo,
+ uint16_t * packetLength);
+static bool validatePacketTimestamp(RAIL_RxPacketDetails_t *pPacketDetails, uint16_t packetLength);
+static void updateRxFrameDetails(RAIL_RxPacketDetails_t *pPacketDetails, bool framePendingSetInOutgoingAck);
+
+//------------------------------------------------------------------------------
+// Helper Functions
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+static bool phyStackEventIsEnabled(void)
+{
+ bool result = false;
+
+#if (defined(SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT) && SL_RAIL_UTIL_ANT_DIV_RX_RUNTIME_PHY_SELECT)
+ result = true;
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+ result |= (sl_rail_util_coex_is_enabled() && sRadioCoexEnabled);
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+
+ return result;
+}
+
+static RAIL_Events_t currentEventConfig = RAIL_EVENTS_NONE;
+static void updateEvents(RAIL_Events_t mask, RAIL_Events_t values)
+{
+ RAIL_Status_t status;
+ RAIL_Events_t newEventConfig = (currentEventConfig & ~mask) | (values & mask);
+ if (newEventConfig != currentEventConfig)
+ {
+ currentEventConfig = newEventConfig;
+ status = RAIL_ConfigEvents(gRailHandle, mask, values);
+ assert(status == RAIL_STATUS_NO_ERROR);
+ }
+}
+
+static sl_rail_util_ieee802154_stack_event_t handlePhyStackEvent(sl_rail_util_ieee802154_stack_event_t stackEvent,
+ uint32_t supplement)
+{
+ return (phyStackEventIsEnabled() ? sl_rail_util_ieee802154_on_event(stackEvent, supplement) : 0);
+}
+#else
+static void updateEvents(RAIL_Events_t mask, RAIL_Events_t values)
+{
+ RAIL_Status_t status;
+ status = RAIL_ConfigEvents(gRailHandle, mask, values);
+ assert(status == RAIL_STATUS_NO_ERROR);
+}
+
+#define handlePhyStackEvent(event, supplement) 0
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+// Set or clear the passed flag.
+static inline void setInternalFlag(uint16_t flag, bool val)
+{
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+ miscInternalFlags = (val ? (miscInternalFlags | flag) : (miscInternalFlags & ~flag));
+ CORE_EXIT_ATOMIC();
+}
+// Returns true if the passed flag is set, false otherwise.
+static inline bool getInternalFlag(uint16_t flag)
+{
+ return ((miscInternalFlags & flag) != 0);
+}
+
+static inline bool txWaitingForAck(void)
+{
+ return (sTransmitBusy == true && ((sTransmitFrame.mPsdu[0] & IEEE802154_FRAME_FLAG_ACK_REQUIRED) != 0));
+}
+
+static bool txIsDataRequest(void)
+{
+ uint16_t fcf = sTransmitFrame.mPsdu[IEEE802154_FCF_OFFSET] | (sTransmitFrame.mPsdu[IEEE802154_FCF_OFFSET + 1] << 8);
+
+ return (sTransmitBusy == true && (fcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_COMMAND);
+}
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+static inline bool isReceivingFrame(void)
+{
+ return (RAIL_GetRadioState(gRailHandle) & RAIL_RF_STATE_RX_ACTIVE) == RAIL_RF_STATE_RX_ACTIVE;
+}
+#endif
+
+static void radioSetIdle(void)
+{
+ if (RAIL_GetRadioState(gRailHandle) != RAIL_RF_STATE_IDLE)
+ {
+ RAIL_Idle(gRailHandle, RAIL_IDLE, true);
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_IDLED, 0U);
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_IDLED, 0U);
+ }
+ RAIL_YieldRadio(gRailHandle);
+ sState = OT_RADIO_STATE_SLEEP;
+}
+
+static otError radioSetRx(uint8_t aChannel)
+{
+ otError error = OT_ERROR_NONE;
+ RAIL_Status_t status;
+
+ RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
+ .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
+ // sliptime/transaction time is not used for bg rx
+ };
+
+ status = RAIL_StartRx(gRailHandle, aChannel, &bgRxSchedulerInfo);
+ otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
+
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_LISTEN, 0U);
+ sState = OT_RADIO_STATE_RECEIVE;
+
+ otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
+exit:
+ return error;
+}
+
+//------------------------------------------------------------------------------
+// Radio Initialization
static RAIL_Handle_t efr32RailInit(efr32CommonConfig *aCommonConfig)
{
@@ -194,29 +506,32 @@
handle = RAIL_Init(&aCommonConfig->mRailConfig, NULL);
assert(handle != NULL);
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+ status = RAIL_InitPowerManager();
+ assert(status == RAIL_STATUS_NO_ERROR);
+#endif // SL_CATALOG_POWER_MANAGER_PRESENT
+
status = RAIL_ConfigCal(handle, RAIL_CAL_ALL);
assert(status == RAIL_STATUS_NO_ERROR);
status = RAIL_IEEE802154_Init(handle, &sRailIeee802154Config);
assert(status == RAIL_STATUS_NO_ERROR);
- status = RAIL_ConfigEvents(handle, RAIL_EVENTS_ALL,
- RAIL_EVENT_RX_ACK_TIMEOUT | //
- RAIL_EVENTS_TX_COMPLETION | //
- RAIL_EVENT_RX_PACKET_RECEIVED | //
- RAIL_EVENT_RSSI_AVERAGE_DONE | //
- RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND | //
- RAIL_EVENT_CAL_NEEDED | //
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT || RADIO_CONFIG_DMP_SUPPORT
- RAIL_EVENT_CONFIG_SCHEDULED | //
- RAIL_EVENT_CONFIG_UNSCHEDULED | //
-#endif
- RAIL_EVENT_SCHEDULER_STATUS //
- );
- assert(status == RAIL_STATUS_NO_ERROR);
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ // Enhanced Frame Pending
+ // status = RAIL_IEEE802154_EnableEarlyFramePending(handle, true);
+ // assert(status == RAIL_STATUS_NO_ERROR);
- uint16_t actualLength = RAIL_SetTxFifo(handle, aCommonConfig->mRailTxFifo, 0, sizeof(aCommonConfig->mRailTxFifo));
- assert(actualLength == sizeof(aCommonConfig->mRailTxFifo));
+ // status = RAIL_IEEE802154_EnableDataFramePending(handle, true);
+ // assert(status == RAIL_STATUS_NO_ERROR);
+
+ // Enhanced ACKs (only on platforms that support it, so error checking is disabled)
+ RAIL_IEEE802154_ConfigEOptions(handle, (RAIL_IEEE802154_E_OPTION_GB868 | RAIL_IEEE802154_E_OPTION_ENH_ACK),
+ (RAIL_IEEE802154_E_OPTION_GB868 | RAIL_IEEE802154_E_OPTION_ENH_ACK));
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+ uint16_t actualLenth = RAIL_SetTxFifo(handle, aCommonConfig->mRailTxFifo, 0, sizeof(aCommonConfig->mRailTxFifo));
+ assert(actualLenth == sizeof(aCommonConfig->mRailTxFifo));
return handle;
}
@@ -237,7 +552,11 @@
else
#endif // RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
{
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
+ status = sl_rail_util_plugin_config_2p4ghz_radio(gRailHandle);
+#else
status = RAIL_IEEE802154_Config2p4GHzRadio(gRailHandle);
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
assert(status == RAIL_STATUS_NO_ERROR);
}
@@ -260,9 +579,9 @@
for (uint8_t i = 0; i < EFR32_NUM_BAND_CONFIGS; i++)
{
- if ((sBandConfigs[i].mChannelMin <= aChannel) && (aChannel <= sBandConfigs[i].mChannelMax))
+ if ((sBandConfig[i].mChannelMin <= aChannel) && (aChannel <= sBandConfig[i].mChannelMax))
{
- config = &sBandConfigs[i];
+ config = &sBandConfig[i];
break;
}
}
@@ -283,17 +602,17 @@
uint8_t index = 0;
#if RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT
- sBandConfigs[index].mChannelConfig = NULL;
- sBandConfigs[index].mChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
- sBandConfigs[index].mChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
+ sBandConfig[index].mChannelConfig = NULL;
+ sBandConfig[index].mChannelMin = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN;
+ sBandConfig[index].mChannelMax = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX;
index++;
#endif
#if RADIO_CONFIG_915MHZ_OQPSK_SUPPORT
- sBandConfigs[index].mChannelConfig = channelConfigs[0];
- sBandConfigs[index].mChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
- sBandConfigs[index].mChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
+ sBandConfig[index].mChannelConfig = channelConfigs[0]; // TO DO: channel config??
+ sBandConfig[index].mChannelMin = OT_RADIO_915MHZ_OQPSK_CHANNEL_MIN;
+ sBandConfig[index].mChannelMax = OT_RADIO_915MHZ_OQPSK_CHANNEL_MAX;
#endif
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
@@ -302,11 +621,24 @@
gRailHandle = efr32RailInit(&sCommonConfig);
assert(gRailHandle != NULL);
- efr32RailConfigLoad(&(sBandConfigs[0]));
+
+ updateEvents(RAIL_EVENTS_ALL,
+ (0 | RAIL_EVENT_RX_ACK_TIMEOUT | RAIL_EVENT_RX_PACKET_RECEIVED | RAIL_EVENTS_TXACK_COMPLETION |
+ RAIL_EVENTS_TX_COMPLETION | RAIL_EVENT_RSSI_AVERAGE_DONE | RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT || RADIO_CONFIG_DMP_SUPPORT
+ | RAIL_EVENT_CONFIG_SCHEDULED | RAIL_EVENT_CONFIG_UNSCHEDULED | RAIL_EVENT_SCHEDULER_STATUS
+#endif
+ | RAIL_EVENT_CAL_NEEDED));
+
+ efr32RailConfigLoad(&(sBandConfig[0]));
}
void efr32RadioInit(void)
{
+ if (getInternalFlag(FLAG_RADIO_INIT_DONE))
+ {
+ return;
+ }
RAIL_Status_t status;
// check if RAIL_TX_FIFO_SIZE is power of two..
@@ -316,24 +648,33 @@
assert((RAIL_TX_FIFO_SIZE >= 64) || (RAIL_TX_FIFO_SIZE <= 4096));
efr32ConfigInit(RAILCb_Generic);
+ setInternalFlag(FLAG_RADIO_INIT_DONE, true);
status = RAIL_ConfigSleep(gRailHandle, RAIL_SLEEP_CONFIG_TIMERSYNC_ENABLED);
assert(status == RAIL_STATUS_NO_ERROR);
- sReceiveFrame.mLength = 0;
- sReceiveFrame.mPsdu = sReceivePsdu;
- sTransmitFrame.mLength = 0;
- sTransmitFrame.mPsdu = sTransmitPsdu;
+ sReceiveFrame.mLength = 0;
+ sReceiveFrame.mPsdu = sReceivePsdu;
+ sReceiveAckFrame.mLength = 0;
+ sReceiveAckFrame.mPsdu = sReceiveAckPsdu;
+ sTransmitFrame.mLength = 0;
+ sTransmitFrame.mPsdu = sTransmitPsdu;
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+ sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
+#endif
+#endif
sCurrentBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL);
assert(sCurrentBandConfig != NULL);
- memset(sAckedWithFPFifo, 0, sizeof(sAckedWithFPFifo));
- sAckedWithFPWriteIndex = 0;
- sAckedWithFPReadIndex = 0;
-
efr32RadioSetTxPower(OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER);
+ assert(RAIL_ConfigRxOptions(gRailHandle, RAIL_RX_OPTION_TRACK_ABORTED_FRAMES,
+ RAIL_RX_OPTION_TRACK_ABORTED_FRAMES) == RAIL_STATUS_NO_ERROR);
+ efr32PhyStackInit();
+
sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
sTransmitError = OT_ERROR_NONE;
sTransmitBusy = false;
@@ -352,6 +693,15 @@
sCurrentBandConfig = NULL;
}
+//------------------------------------------------------------------------------
+// Energy Scan support
+
+static void energyScanComplete(int8_t scanResultDbm)
+{
+ sEnergyScanResultDbm = scanResultDbm;
+ sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
+}
+
static otError efr32StartEnergyScan(energyScanMode aMode, uint16_t aChannel, RAIL_Time_t aAveragingTimeUs)
{
RAIL_Status_t status = RAIL_STATUS_NO_ERROR;
@@ -382,9 +732,16 @@
otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
exit:
+ if (status != RAIL_STATUS_NO_ERROR)
+ {
+ energyScanComplete(OT_RADIO_RSSI_INVALID);
+ }
return error;
}
+//------------------------------------------------------------------------------
+// Stack support
+
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -418,6 +775,14 @@
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+ for (size_t i = 0; i < sizeof(*aAddress); i++)
+ {
+ sExtAddress.m8[i] = aAddress->m8[sizeof(*aAddress) - 1 - i];
+ }
+#endif
+#endif
RAIL_Status_t status;
@@ -472,18 +837,13 @@
otError otPlatRadioSleep(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
-
otError error = OT_ERROR_NONE;
otEXPECT_ACTION((sState != OT_RADIO_STATE_TRANSMIT) && (sState != OT_RADIO_STATE_DISABLED),
error = OT_ERROR_INVALID_STATE);
otLogInfoPlat("State=OT_RADIO_STATE_SLEEP", NULL);
-
- RAIL_Idle(gRailHandle, RAIL_IDLE, true);
- RAIL_YieldRadio(gRailHandle);
- sState = OT_RADIO_STATE_SLEEP;
-
+ radioSetIdle();
exit:
return error;
}
@@ -507,17 +867,11 @@
sCurrentBandConfig = config;
}
- RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
- .priority = RADIO_SCHEDULER_BACKGROUND_RX_PRIORITY,
- // sliptime/transaction time is not used for bg rx
- };
-
- status = RAIL_StartRx(gRailHandle, aChannel, &bgRxSchedulerInfo);
+ status = radioSetRx(aChannel);
otEXPECT_ACTION(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
- otLogInfoPlat("State=OT_RADIO_STATE_RECEIVE", NULL);
- sState = OT_RADIO_STATE_RECEIVE;
- sReceiveFrame.mChannel = aChannel;
+ sReceiveFrame.mChannel = aChannel;
+ sReceiveAckFrame.mChannel = aChannel;
exit:
return error;
@@ -525,29 +879,14 @@
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
{
- otError error = OT_ERROR_NONE;
- RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
- RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_DEFAULT;
- efr32BandConfig * config;
- RAIL_Status_t status;
- uint8_t frameLength;
-
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailPlatTxTriggered++;
-#endif
-
- assert(sTransmitBusy == false);
+ otError error = OT_ERROR_NONE;
+ efr32BandConfig *config;
otEXPECT_ACTION((sState != OT_RADIO_STATE_DISABLED) && (sState != OT_RADIO_STATE_TRANSMIT),
error = OT_ERROR_INVALID_STATE);
config = efr32RadioGetBandConfig(aFrame->mChannel);
otEXPECT_ACTION(config != NULL, error = OT_ERROR_INVALID_ARGS);
-
- sState = OT_RADIO_STATE_TRANSMIT;
- sTransmitError = OT_ERROR_NONE;
- sTransmitBusy = true;
-
if (sCurrentBandConfig != config)
{
RAIL_Idle(gRailHandle, RAIL_IDLE, true);
@@ -555,9 +894,115 @@
sCurrentBandConfig = config;
}
- frameLength = (uint8_t)aFrame->mLength;
+ assert(sTransmitBusy == false);
+ sState = OT_RADIO_STATE_TRANSMIT;
+ sTransmitError = OT_ERROR_NONE;
+ sTransmitBusy = true;
+ sTxFrame = aFrame;
+
+ setInternalFlag(FLAG_CURRENT_TX_USE_CSMA, aFrame->mInfo.mTxInfo.mCsmaCaEnabled);
+
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+ setInternalFlag(FLAG_ONGOING_TX_DATA, true);
+ tryTxCurrentPacket();
+ CORE_EXIT_ATOMIC();
+
+ if (sTransmitError == OT_ERROR_NONE)
+ {
+ otPlatRadioTxStarted(aInstance, aFrame);
+ }
+exit:
+ return error;
+}
+
+void txCurrentPacket(void)
+{
+ assert(getInternalFlag(FLAG_ONGOING_TX_DATA));
+ assert(sTxFrame != NULL);
+
+ RAIL_CsmaConfig_t csmaConfig = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
+ RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_DEFAULT;
+ RAIL_Status_t status;
+ uint8_t frameLength;
+ bool ackRequested;
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailPlatTxTriggered++;
+#endif
+
+ // signalling this event earlier, as this event can assert REQ (expecially for a
+ // non-CSMA transmit) giving the Coex master a little more time to grant or deny.
+ if (getInternalFlag(FLAG_CURRENT_TX_USE_CSMA))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_PENDED_PHY, (uint32_t) true);
+ }
+ else
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_PENDED_PHY, (uint32_t) false);
+ }
+
+ frameLength = (uint8_t)sTxFrame->mLength;
+
+#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ // Update IE data in the 802.15.4 header with the newest CSL period / phase
+ if (sCslPeriod > 0)
+ {
+ otMacFrameSetCslIe(sTxFrame, (uint16_t)sCslPeriod, getCslPhase());
+ }
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ bool processSecurity = false;
+#endif
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+ // Seek the time sync offset and update the rendezvous time
+ if (sTxFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
+ {
+ uint8_t *timeIe = sTxFrame->mPsdu + sTxFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
+ uint64_t time = otPlatTimeGet() + sTxFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
+
+ *timeIe = sTxFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
+
+ *(++timeIe) = (uint8_t)(time & 0xff);
+ for (uint8_t i = 1; i < sizeof(uint64_t); i++)
+ {
+ time = time >> 8;
+ *(++timeIe) = (uint8_t)(time & 0xff);
+ }
+
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ processSecurity = true;
+#endif
+ }
+#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ if (otMacFrameIsSecurityEnabled(sTxFrame) && otMacFrameIsKeyIdMode1(sTxFrame) &&
+ !sTxFrame->mInfo.mTxInfo.mIsSecurityProcessed)
+ {
+ sTxFrame->mInfo.mTxInfo.mAesKey = &sCurrKey;
+
+ if (!sTxFrame->mInfo.mTxInfo.mIsARetx)
+ {
+ otMacFrameSetKeyId(sTxFrame, sKeyId);
+ otMacFrameSetFrameCounter(sTxFrame, sMacFrameCounter++);
+ }
+
+ processSecurity = true;
+ }
+
+ if (processSecurity)
+ {
+ otMacFrameProcessTransmitAesCcm(sTxFrame, &sExtAddress);
+ }
+#endif // OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
+
RAIL_WriteTxFifo(gRailHandle, &frameLength, sizeof frameLength, true);
- RAIL_WriteTxFifo(gRailHandle, aFrame->mPsdu, frameLength - 2, false);
+ RAIL_WriteTxFifo(gRailHandle, sTxFrame->mPsdu, frameLength - 2, false);
RAIL_SchedulerInfo_t txSchedulerInfo = {
.priority = RADIO_SCHEDULER_TX_PRIORITY,
@@ -565,7 +1010,8 @@
.transactionTime = 0, // will be calculated later if DMP is used
};
- if (aFrame->mPsdu[0] & IEEE802154_ACK_REQUEST)
+ ackRequested = (sTxFrame->mPsdu[0] & IEEE802154_FRAME_FLAG_ACK_REQUIRED);
+ if (ackRequested)
{
txOptions |= RAIL_TX_OPTION_WAIT_FOR_ACK;
@@ -582,6 +1028,18 @@
#endif
}
+#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+ // Update Tx options to use currently-selected antenna.
+ // If antenna diverisity on Tx is disabled, leave both options 0
+ // so Tx antenna tracks Rx antenna.
+ if (sl_rail_util_ant_div_get_antenna_mode() != SL_RAIL_UTIL_ANT_DIV_DISABLED)
+ {
+ txOptions |= ((sl_rail_util_ant_div_get_antenna_selected() == SL_RAIL_UTIL_ANTENNA_SELECT_ANTENNA1)
+ ? RAIL_TX_OPTION_ANTENNA0
+ : RAIL_TX_OPTION_ANTENNA1);
+ }
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+
#if RADIO_CONFIG_DMP_SUPPORT
// time needed for the frame itself
// 4B preamble, 1B SFD, 1B PHR is not counted in frameLength
@@ -595,42 +1053,40 @@
}
#endif
- if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
+ if (getInternalFlag(FLAG_CURRENT_TX_USE_CSMA))
{
#if RADIO_CONFIG_DMP_SUPPORT
// time needed for CSMA/CA
txSchedulerInfo.transactionTime += RADIO_TIMING_CSMA_OVERHEAD_US;
#endif
- csmaConfig.csmaTries = aFrame->mInfo.mTxInfo.mMaxCsmaBackoffs;
+ csmaConfig.csmaTries = sTxFrame->mInfo.mTxInfo.mMaxCsmaBackoffs;
csmaConfig.ccaThreshold = sCcaThresholdDbm;
-
- status = RAIL_StartCcaCsmaTx(gRailHandle, aFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
+ status = RAIL_StartCcaCsmaTx(gRailHandle, sTxFrame->mChannel, txOptions, &csmaConfig, &txSchedulerInfo);
}
else
{
- status = RAIL_StartTx(gRailHandle, aFrame->mChannel, txOptions, &txSchedulerInfo);
+ status = RAIL_StartTx(gRailHandle, sTxFrame->mChannel, txOptions, &txSchedulerInfo);
+ if (status == RAIL_STATUS_NO_ERROR)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_STARTED, 0U);
+ }
}
-
if (status == RAIL_STATUS_NO_ERROR)
{
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
sRailDebugCounters.mRailTxStarted++;
#endif
- otPlatRadioTxStarted(aInstance, aFrame);
}
else
{
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
sRailDebugCounters.mRailTxStartFailed++;
#endif
- // Tx started at an invalid time or an invalid paramter has been passed.
- sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
- sTransmitBusy = false;
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_BLOCKED, (uint32_t)ackRequested);
+ txFailedCallback(false, TX_COMPLETE_RESULT_OTHER_FAIL);
+
otSysEventSignalPending();
}
-
-exit:
- return error;
}
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
@@ -672,7 +1128,18 @@
{
OT_UNUSED_VARIABLE(aInstance);
- return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN;
+ otRadioCaps capabilities = (OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_ENERGY_SCAN |
+ OT_RADIO_CAPS_SLEEP_TO_TX);
+
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ capabilities |= OT_RADIO_CAPS_TRANSMIT_SEC;
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+ capabilities |= OT_RADIO_CAPS_TRANSMIT_TIMING;
+#endif
+
+ return capabilities;
}
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
@@ -702,420 +1169,6 @@
sIsSrcMatchEnabled = aEnable;
}
-static bool sAckedWithFPFifoIsFull(void)
-{
- return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == otARRAY_LENGTH(sAckedWithFPFifo);
-}
-
-static bool sAckedWithFPFifoIsEmpty(void)
-{
- return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == 0;
-}
-
-static efr32AckedWithFP *sAckedWithFPFifoGetWriteSlot(void)
-{
- uint32_t idx = sAckedWithFPWriteIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
- return &sAckedWithFPFifo[idx];
-}
-
-static const efr32AckedWithFP *sAckedWithFPFifoGetReadSlot(void)
-{
- uint32_t idx = sAckedWithFPReadIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1);
- return &sAckedWithFPFifo[idx];
-}
-
-static void insertIeee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
-{
- assert(!sAckedWithFPFifoIsFull());
- efr32AckedWithFP *const slot = sAckedWithFPFifoGetWriteSlot();
-
- RAIL_RxPacketInfo_t packetInfo;
-
- RAIL_GetRxIncomingPacketInfo(aRailHandle, &packetInfo);
- assert(packetInfo.packetBytes >= 4); // PHR + FCF + DSN
-
- if (packetInfo.packetBytes > sizeof(slot->mPacket))
- {
- packetInfo.packetBytes = sizeof(slot->mPacket);
- if (packetInfo.firstPortionBytes >= sizeof(slot->mPacket))
- {
- packetInfo.firstPortionBytes = sizeof(slot->mPacket);
- packetInfo.lastPortionData = NULL;
- }
- }
- slot->mLength = packetInfo.packetBytes;
- RAIL_CopyRxPacket(slot->mPacket, &packetInfo);
-
- ++sAckedWithFPWriteIndex;
-}
-
-static bool wasAckedWithFramePending(const uint8_t *aPsdu, uint8_t aPsduLength)
-{
- bool ackedWithFramePending = false;
- uint16_t fcf = aPsdu[IEEE802154_FCF_OFFSET] | (aPsdu[IEEE802154_FCF_OFFSET + 1] << 8);
-
- otEXPECT((fcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MAC_COMMAND);
-
- while (!(ackedWithFramePending || sAckedWithFPFifoIsEmpty()))
- {
- const efr32AckedWithFP *const slot = sAckedWithFPFifoGetReadSlot();
- if ((slot->mPacket[0] == aPsduLength) && (memcmp(slot->mPacket + 1, aPsdu, slot->mLength - 1) == 0))
- {
- ackedWithFramePending = true;
- }
- ++sAckedWithFPReadIndex;
- }
-
-exit:
- return ackedWithFramePending;
-}
-
-static void processNextRxPacket(otInstance *aInstance)
-{
- RAIL_RxPacketHandle_t packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
- RAIL_RxPacketInfo_t packetInfo;
- RAIL_RxPacketDetails_t packetDetails;
- RAIL_Status_t status;
- uint16_t length;
- bool framePending = false;
-
- packetHandle = RAIL_GetRxPacketInfo(gRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST, &packetInfo);
-
- otEXPECT_ACTION(packetHandle != RAIL_RX_PACKET_HANDLE_INVALID &&
- packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS,
- packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
-
- status = RAIL_GetRxPacketDetailsAlt(gRailHandle, packetHandle, &packetDetails);
- otEXPECT(status == RAIL_STATUS_NO_ERROR);
-
- length = packetInfo.packetBytes + 1;
-
- // check the length in recv packet info structure; RAIL should take care of this.
- otEXPECT(length == packetInfo.firstPortionData[0]);
-
- // check the length validity of recv packet; RAIL should take care of this.
- otEXPECT(length >= IEEE802154_MIN_LENGTH && length <= IEEE802154_MAX_LENGTH);
-
- otLogInfoPlat("Received data:%d", length);
-
- // skip length byte
- otEXPECT(packetInfo.firstPortionBytes > 0);
- packetInfo.firstPortionData++;
- packetInfo.firstPortionBytes--;
- packetInfo.packetBytes--;
-
- // read packet
- RAIL_CopyRxPacket(sReceiveFrame.mPsdu, &packetInfo);
-
- status = RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
- if (status == RAIL_STATUS_NO_ERROR)
- {
- packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
- }
-
- sReceiveFrame.mLength = length;
-
- sReceiveFrame.mInfo.mRxInfo.mRssi = packetDetails.rssi;
- sReceiveFrame.mInfo.mRxInfo.mLqi = packetDetails.lqi;
-
- // Get the timestamp when the SFD was received
- assert(packetDetails.timeReceived.timePosition != RAIL_PACKET_TIME_INVALID);
- packetDetails.timeReceived.totalPacketBytes = length + 1;
-
- status = RAIL_GetRxTimeSyncWordEndAlt(gRailHandle, &packetDetails);
- assert(status == RAIL_STATUS_NO_ERROR);
- sReceiveFrame.mInfo.mRxInfo.mTimestamp = packetDetails.timeReceived.packetTime;
-
- if (packetDetails.isAck)
- {
- otEXPECT((length == IEEE802154_ACK_LENGTH) &&
- (sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK);
-
- sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = false;
-
- RAIL_YieldRadio(gRailHandle);
- sTransmitBusy = false;
-
- if (sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET])
- {
- sTransmitError = OT_ERROR_NONE;
- }
- else
- {
- sTransmitError = OT_ERROR_NO_ACK;
- }
- }
- else
- {
- // signal MAC layer for each received frame if promiscuous is enabled
- // otherwise only signal MAC layer for non-ACK frame
- otEXPECT(sPromiscuous || (length != IEEE802154_ACK_LENGTH));
-
- sReceiveError = OT_ERROR_NONE;
-
- // Set this flag only when the packet is really acknowledged with frame pending set.
- framePending = wasAckedWithFramePending(sReceiveFrame.mPsdu, sReceiveFrame.mLength);
- sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = framePending;
-
-#if OPENTHREAD_CONFIG_DIAG_ENABLE
-
- if (otPlatDiagModeGet())
- {
- otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
- }
- else
-#endif
- {
- otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
- otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
-#endif
- }
- if (!framePending)
- {
- RAIL_YieldRadio(gRailHandle);
- }
- }
- otSysEventSignalPending();
-
-exit:
-
- if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
- {
- RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
- }
-}
-
-static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle)
-{
- RAIL_Status_t status = RAIL_STATUS_NO_ERROR;
-
- if (sIsSrcMatchEnabled)
- {
- RAIL_IEEE802154_Address_t sourceAddress;
-
- status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
- otEXPECT(status == RAIL_STATUS_NO_ERROR);
-
- if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
- utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
- (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
- utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
- {
- status = RAIL_IEEE802154_SetFramePending(aRailHandle);
- otEXPECT(status == RAIL_STATUS_NO_ERROR);
- insertIeee802154DataRequestCommand(aRailHandle);
- }
- }
- else
- {
- status = RAIL_IEEE802154_SetFramePending(aRailHandle);
- otEXPECT(status == RAIL_STATUS_NO_ERROR);
- insertIeee802154DataRequestCommand(aRailHandle);
- }
-
-exit:
- if (status == RAIL_STATUS_INVALID_STATE)
- {
- otLogWarnPlat("Too late to modify outgoing FP");
- }
- else
- {
- assert(status == RAIL_STATUS_NO_ERROR);
- }
-}
-
-static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
-{
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
- {
- sRailDebugCounters.mRailEventConfigScheduled++;
- }
- if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
- {
- sRailDebugCounters.mRailEventConfigUnScheduled++;
- }
-#endif
- if (aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
- {
- ieee802154DataRequestCommand(aRailHandle);
- }
-
- if (aEvents & RAIL_EVENTS_TX_COMPLETION)
- {
- if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
- {
- if ((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
- {
- RAIL_YieldRadio(aRailHandle);
- sTransmitError = OT_ERROR_NONE;
- sTransmitBusy = false;
- }
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventPacketSent++;
-#endif
- }
- else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
- {
- RAIL_YieldRadio(aRailHandle);
- sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
- sTransmitBusy = false;
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventChannelBusy++;
-#endif
- }
- else
- {
- RAIL_YieldRadio(aRailHandle);
- sTransmitError = OT_ERROR_ABORT;
- sTransmitBusy = false;
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventTxAbort++;
-#endif
- }
- }
-
- if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
- {
- RAIL_YieldRadio(aRailHandle);
- sTransmitError = OT_ERROR_NO_ACK;
- sTransmitBusy = false;
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventNoAck++;
-#endif
- }
-
- if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
- {
- RAIL_HoldRxPacket(aRailHandle);
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventPacketReceived++;
-#endif
- }
-
- if (aEvents & RAIL_EVENT_CAL_NEEDED)
- {
- RAIL_Status_t status;
-
- status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
- assert(status == RAIL_STATUS_NO_ERROR);
-
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventCalNeeded++;
-#endif
- }
-
- if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
- {
- const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
- RAIL_YieldRadio(aRailHandle);
-
- sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
-
- if (energyScanResultQuarterDbm == RAIL_RSSI_INVALID)
- {
- sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
- }
- else
- {
- sEnergyScanResultDbm = energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM;
- }
-
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
-#endif
- }
- if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
- {
- RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
-
- assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
-
- if (status == RAIL_SCHEDULER_STATUS_CCA_CSMA_TX_FAIL || status == RAIL_SCHEDULER_STATUS_SINGLE_TX_FAIL ||
- status == RAIL_SCHEDULER_STATUS_SCHEDULED_TX_FAIL ||
- (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sTransmitBusy) ||
- (status == RAIL_SCHEDULER_STATUS_EVENT_INTERRUPTED && sTransmitBusy))
- {
- sTransmitError = OT_ERROR_ABORT;
- sTransmitBusy = false;
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventSchedulerStatusError++;
-#endif
- }
- else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL)
- {
- sEnergyScanStatus = ENERGY_SCAN_STATUS_COMPLETED;
- sEnergyScanResultDbm = OT_RADIO_RSSI_INVALID;
- }
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- else if (sTransmitBusy)
- {
- sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
- sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
- }
-#endif
- }
-
- otSysEventSignalPending();
-}
-
-otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
-{
- OT_UNUSED_VARIABLE(aInstance);
-
- return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
-}
-
-void efr32RadioProcess(otInstance *aInstance)
-{
- // We should process the received packet first. Adding it at the end of this function,
- // will delay the stack notification until the next call to efr32RadioProcess()
- processNextRxPacket(aInstance);
-
- if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
- {
- if (sTransmitError != OT_ERROR_NONE)
- {
- otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
- }
-
- sState = OT_RADIO_STATE_RECEIVE;
-#if OPENTHREAD_CONFIG_DIAG_ENABLE
- if (otPlatDiagModeGet())
- {
- otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
- }
- else
-#endif
- if (((sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0) || (sTransmitError != OT_ERROR_NONE))
- {
- otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
- }
- else
- {
- otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveFrame, sTransmitError);
- }
-
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
-#endif
-
- otSysEventSignalPending();
- }
- else if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
- {
- sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
- otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
- otSysEventSignalPending();
-
-#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
- sRailDebugCounters.mRailEventEnergyScanCompleted++;
-#endif
- }
-}
-
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -1123,7 +1176,6 @@
otError error = OT_ERROR_NONE;
otEXPECT_ACTION(aPower != NULL, error = OT_ERROR_INVALID_ARGS);
-
// RAIL_GetTxPowerDbm() returns power in deci-dBm (0.1dBm)
// Divide by 10 because aPower is supposed be in units dBm
*aPower = RAIL_GetTxPowerDbm(gRailHandle) / 10;
@@ -1175,6 +1227,1474 @@
return EFR32_RECEIVE_SENSITIVITY;
}
+otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ return efr32StartEnergyScan(ENERGY_SCAN_MODE_ASYNC, aScanChannel, (RAIL_Time_t)aScanDuration * US_IN_MS);
+}
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+//------------------------------------------------------------------------------
+// Radio Config: Thread 1.2 transmit security support
+
+void otPlatRadioSetMacKey(otInstance * aInstance,
+ uint8_t aKeyIdMode,
+ uint8_t aKeyId,
+ const otMacKey *aPrevKey,
+ const otMacKey *aCurrKey,
+ const otMacKey *aNextKey)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aKeyIdMode);
+
+ assert(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL);
+
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ sKeyId = aKeyId;
+ memcpy(sPrevKey.m8, aPrevKey->m8, OT_MAC_KEY_SIZE);
+ memcpy(sCurrKey.m8, aCurrKey->m8, OT_MAC_KEY_SIZE);
+ memcpy(sNextKey.m8, aNextKey->m8, OT_MAC_KEY_SIZE);
+
+ CORE_EXIT_ATOMIC();
+}
+
+void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ sMacFrameCounter = aMacFrameCounter;
+
+ CORE_EXIT_ATOMIC();
+}
+
+//------------------------------------------------------------------------------
+// Radio Config: Enhanced Acks, CSL
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, const otExtAddress *aExtAddr)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aExtAddr);
+
+ sCslPeriod = aCslPeriod;
+ updateIeData();
+
+ return OT_ERROR_NONE;
+}
+
+void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTime)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ sCslSampleTime = aCslSampleTime;
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+
+//------------------------------------------------------------------------------
+// Radio Config: Link Metrics
+
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+otError otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,
+ otLinkMetrics aLinkMetrics,
+ const otShortAddress aShortAddress,
+ const otExtAddress * aExtAddress)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ otError error = otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics);
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ if (error == OT_ERROR_NONE)
+ {
+ updateIeData();
+ }
+#endif
+
+ return error;
+}
+#endif
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
+otError otPlatRadioSetCoexEnabled(otInstance *aInstance, bool aEnabled)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ if (aEnabled && !sl_rail_util_coex_is_enabled())
+ {
+ otLogInfoPlat("Coexistence GPIO configurations not set");
+ return OT_ERROR_FAILED;
+ }
+ sRadioCoexEnabled = aEnabled;
+ return OT_ERROR_NONE;
+}
+
+bool otPlatRadioIsCoexEnabled(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return (sRadioCoexEnabled && sl_rail_util_coex_is_enabled());
+}
+
+otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ otError error = OT_ERROR_NONE;
+
+ otEXPECT_ACTION(aCoexMetrics != NULL, error = OT_ERROR_INVALID_ARGS);
+
+ memset(aCoexMetrics, 0, sizeof(otRadioCoexMetrics));
+ // TO DO:
+ // Tracking coex metrics with detailed granularity currently
+ // not implemented.
+ // memcpy(aCoexMetrics, &sCoexMetrics, sizeof(otRadioCoexMetrics));
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+//------------------------------------------------------------------------------
+// Radio implementation: Enhanced ACKs, CSL
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+static uint8_t getKeySourceLength(uint8_t keyIdMode)
+{
+ uint8_t len = 0;
+
+ switch (keyIdMode)
+ {
+ case IEEE802154_KEYID_MODE_0:
+ len = IEEE802154_KEYID_MODE_0_SIZE;
+ break;
+
+ case IEEE802154_KEYID_MODE_1:
+ len = IEEE802154_KEYID_MODE_1_SIZE;
+ break;
+
+ case IEEE802154_KEYID_MODE_2:
+ len = IEEE802154_KEYID_MODE_2_SIZE;
+ break;
+
+ case IEEE802154_KEYID_MODE_3:
+ len = IEEE802154_KEYID_MODE_3_SIZE;
+ break;
+ }
+
+ return len;
+}
+
+static bool writeIeee802154EnhancedAck(RAIL_Handle_t aRailHandle, const uint8_t *aIeData, uint8_t aIeLength)
+{
+ // This table is derived from 802.15.4-2015 Section 7.2.1.5 PAN ID
+ // Compression field and Table 7-2 for both 2003/2006 and 2015
+ // frame versions. It is indexed by 6 bits of the MacFCF:
+ // SrcAdrMode FrameVer<msbit> DstAdrMode PanIdCompression
+ // and each address' length is encoded in a nibble:
+ // 15:12 11:8 7:4 3:0
+ // SrcAdr SrcPan DstAdr DstPan
+ // Illegal combinations are indicated by 0xFFFFU.
+
+#define ADDRSIZE_DST_PAN_SHIFT 0
+#define ADDRSIZE_DST_PAN_MASK (0x0FU << ADDRSIZE_DST_PAN_SHIFT)
+#define ADDRSIZE_DST_ADR_SHIFT 4
+#define ADDRSIZE_DST_ADR_MASK (0x0FU << ADDRSIZE_DST_ADR_SHIFT)
+#define ADDRSIZE_SRC_PAN_SHIFT 8
+#define ADDRSIZE_SRC_PAN_MASK (0x0FU << ADDRSIZE_SRC_PAN_SHIFT)
+#define ADDRSIZE_SRC_ADR_SHIFT 12
+#define ADDRSIZE_SRC_ADR_MASK (0x0FU << ADDRSIZE_SRC_ADR_SHIFT)
+
+ static const uint16_t ieee802154Table7p2[64] = {
+ 0x0000U, 0x0000U, 0xFFFFU, 0xFFFFU, 0x0022U, 0x0022U, 0x0082U, 0x0082U, 0x0000U, 0x0002U, 0xFFFFU,
+ 0xFFFFU, 0x0022U, 0x0020U, 0x0082U, 0x0080U, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
+ 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU, 0x2200U,
+ 0x2200U, 0xFFFFU, 0xFFFFU, 0x2222U, 0x2022U, 0x2282U, 0x2082U, 0x2200U, 0x2000U, 0xFFFFU, 0xFFFFU,
+ 0x2222U, 0x2022U, 0x2282U, 0x2082U, 0x8200U, 0x8200U, 0xFFFFU, 0xFFFFU, 0x8222U, 0x8022U, 0x8282U,
+ 0x8082U, 0x8200U, 0x8000U, 0xFFFFU, 0xFFFFU, 0x8222U, 0x8022U, 0x8082U, 0x8080U,
+ };
+
+ // For an Enhanced ACK, we need to generate that ourselves;
+ // RAIL will generate an Immediate ACK for us, though we can
+ // tell it to go out with its FramePending bit set.
+ // An 802.15.4 packet from RAIL should look like:
+ // 1/2 | 1/2 | 0/1 | 0/2 | 0/2/8 | 0/2 | 0/2/8 | 14
+ // PHR | MacFCF | Seq# | DstPan | DstAdr | SrcPan | SrcAdr | SecHdr
+
+ // With RAIL_IEEE802154_EnableEarlyFramePending(), RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND
+ // is triggered after receiving through the SrcAdr field of the packet,
+ // not the SecHdr which hasn't been received yet.
+
+#define EARLY_FRAME_PENDING_EXPECTED_BYTES (2U + 2U + 1U + 2U + 8U + 2U + 8U)
+#define MAX_SECURED_EXPECTED_RECEIVED_BYTES (EARLY_FRAME_PENDING_EXPECTED_BYTES + 14U)
+#define FINAL_PACKET_LENGTH_WITH_IE (MAX_SECURED_EXPECTED_RECEIVED_BYTES + aIeLength)
+
+ RAIL_RxPacketInfo_t packetInfo;
+ uint8_t pkt[FINAL_PACKET_LENGTH_WITH_IE];
+
+ // TODO, in the original prototype for this code, this check was made to
+ // determine the PHY header length.
+ // When we add Sub-Ghz support, and we call RAIL_IEEE802154_ConfigGOptions,
+ // we should check for a 2-byte PHR.
+ // #if ("mac has channel pages" && IEEE802154_GB868_SUPPORTED)
+ // #define PHRLen ((emRadioChannelPageInUse == 0) ? 1 : 2)
+ // #else
+ // #define PHRLen 1
+ uint8_t PHRLen = 1;
+
+ uint8_t pktOffset = PHRLen; // No need to parse the PHR byte(s)
+ RAIL_GetRxIncomingPacketInfo(gRailHandle, &packetInfo);
+
+ // Check if packetinfo.packetBytes includes the info we want,
+ // and if not, spin-wait calling RAIL_GetRxIncomingPacketInfo()
+ // until it has arrived
+ uint32_t startMs = otPlatAlarmMilliGetNow();
+ while (packetInfo.packetBytes < MAX_SECURED_EXPECTED_RECEIVED_BYTES)
+ {
+ RAIL_GetRxIncomingPacketInfo(gRailHandle, &packetInfo);
+ if (otPlatAlarmMilliGetNow() - startMs > 100u)
+ {
+ // More than 100 ms. has elapsed.
+ break;
+ }
+ }
+
+ if (packetInfo.packetBytes < (pktOffset + 2U))
+ {
+ return false;
+ }
+
+ // Only extract what we care about
+ if (packetInfo.packetBytes > MAX_SECURED_EXPECTED_RECEIVED_BYTES)
+ {
+ packetInfo.packetBytes = MAX_SECURED_EXPECTED_RECEIVED_BYTES;
+ if (packetInfo.firstPortionBytes >= MAX_SECURED_EXPECTED_RECEIVED_BYTES)
+ {
+ packetInfo.firstPortionBytes = MAX_SECURED_EXPECTED_RECEIVED_BYTES;
+ packetInfo.lastPortionData = NULL;
+ }
+ }
+
+ RAIL_CopyRxPacket(pkt, &packetInfo);
+ uint16_t macFcf = pkt[pktOffset++];
+
+ if ((macFcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MULTIPURPOSE)
+ {
+ // Multipurpose frames have an arcane FCF structure
+ if ((macFcf & IEEE802154_MP_FRAME_FLAG_LONG_FCF) != 0U)
+ {
+ macFcf |= (pkt[pktOffset++] << 8);
+ }
+
+ // Map Multipurpose FCF to a 'normal' Version FCF as best we can.
+ macFcf =
+ (IEEE802154_FRAME_TYPE_MULTIPURPOSE |
+ ((macFcf & (IEEE802154_MP_FRAME_FLAG_SECURITY_ENABLED | IEEE802154_MP_FRAME_FLAG_IE_LIST_PRESENT)) >> 6) |
+ ((macFcf & IEEE802154_MP_FRAME_FLAG_FRAME_PENDING) >> 7) |
+ ((macFcf & IEEE802154_MP_FRAME_FLAG_ACK_REQUIRED) >> 9) |
+ ((macFcf & (IEEE802154_MP_FRAME_FLAG_PANID_PRESENT | IEEE802154_MP_FRAME_FLAG_SEQ_SUPPRESSION)) >> 2) |
+ ((macFcf & IEEE802154_MP_FRAME_DESTINATION_MODE_MASK) << 6) | IEEE802154_MP_FRAME_VERSION_2015 |
+ ((macFcf & IEEE802154_MP_FRAME_SOURCE_MODE_MASK) << 8));
+
+ // MultiPurpose's PANID_PRESENT is not equivalent to 2012/5's
+ // PANID_COMPRESSION so we map it best we can by flipping it
+ // in the following address-combination situations:
+ uint16_t addrCombo = (macFcf & (IEEE802154_FRAME_SOURCE_MODE_MASK | IEEE802154_FRAME_DESTINATION_MODE_MASK));
+ if ((addrCombo == (IEEE802154_FRAME_SOURCE_MODE_NONE | IEEE802154_FRAME_DESTINATION_MODE_NONE)) ||
+ (addrCombo == (IEEE802154_FRAME_SOURCE_MODE_SHORT | IEEE802154_FRAME_DESTINATION_MODE_SHORT)) ||
+ (addrCombo == (IEEE802154_FRAME_SOURCE_MODE_SHORT | IEEE802154_FRAME_DESTINATION_MODE_LONG)) ||
+ (addrCombo == (IEEE802154_FRAME_SOURCE_MODE_LONG | IEEE802154_FRAME_DESTINATION_MODE_SHORT)))
+ {
+ // 802.15.4-2015 PANID_COMPRESSION = MP PANID_PRESENT
+ }
+ else
+ {
+ // 802.15.4-2015 PANID_COMPRESSION = !MP PANID_PRESENT
+ macFcf ^= IEEE802154_FRAME_FLAG_PANID_COMPRESSION; // Flip it
+ }
+ }
+ else
+ {
+ macFcf |= (pkt[pktOffset++] << 8);
+ }
+
+ bool enhAck = ((macFcf & IEEE802154_FRAME_VERSION_MASK) == IEEE802154_FRAME_VERSION_2015);
+ if (!enhAck)
+ {
+ return false;
+ }
+
+ // Compress MAC FCF to index into 64-entry address-length table:
+ // SrcAdrMode FrameVer<msbit> DstAdrMode PanIdCompression
+ //
+ // Note: Use IEEE802154_FRAME_VERSION_2012 rather than _MASK so the
+ // low-order bit of the version field isn't used in deriving the index.
+ uint16_t index = (((macFcf & (IEEE802154_FRAME_SOURCE_MODE_MASK | IEEE802154_FRAME_VERSION_2012)) >> 10) |
+ ((macFcf & IEEE802154_FRAME_DESTINATION_MODE_MASK) >> 9) |
+ ((macFcf & IEEE802154_FRAME_FLAG_PANID_COMPRESSION) >> 6));
+
+ uint16_t addrSizes = ieee802154Table7p2[index];
+ // Illegal combinations mean illegal packets which we ignore
+ if (addrSizes == 0xFFFFU)
+ {
+ return false;
+ }
+
+ uint8_t seqNo =
+ ((enhAck && ((macFcf & IEEE802154_FRAME_FLAG_SEQ_SUPPRESSION) != 0U)) ? 0U : pkt[pktOffset++]); // Seq#
+
+ // Start writing the enhanced ACK -- we need to construct it since RAIL cannot.
+
+ // First extract addresses from incoming packet since we may
+ // need to reflect them in a different order in the outgoing ACK.
+ // Use byte[0] to hold each one's length.
+ uint8_t dstPan[3] = {
+ 0,
+ }; // Initialized only to eliminate false gcc warning
+ dstPan[0] = ((addrSizes & ADDRSIZE_DST_PAN_MASK) >> ADDRSIZE_DST_PAN_SHIFT);
+ if ((dstPan[0] + pktOffset) > packetInfo.packetBytes)
+ {
+ return false;
+ }
+
+ if (dstPan[0] > 0U)
+ {
+ dstPan[1] = pkt[pktOffset++];
+ dstPan[2] = pkt[pktOffset++];
+ }
+
+ uint8_t dstAdr[9];
+ dstAdr[0] = ((addrSizes & ADDRSIZE_DST_ADR_MASK) >> ADDRSIZE_DST_ADR_SHIFT);
+ if ((dstAdr[0] + pktOffset) > packetInfo.packetBytes)
+ {
+ return false;
+ }
+
+ for (uint8_t i = 1U; i <= dstAdr[0]; i++)
+ {
+ dstAdr[i] = pkt[pktOffset++];
+ }
+
+ uint8_t srcPan[3];
+ srcPan[0] = ((addrSizes & ADDRSIZE_SRC_PAN_MASK) >> ADDRSIZE_SRC_PAN_SHIFT);
+ if ((srcPan[0] + pktOffset) > packetInfo.packetBytes)
+ {
+ return false;
+ }
+
+ if (srcPan[0] > 0U)
+ {
+ srcPan[1] = pkt[pktOffset++];
+ srcPan[2] = pkt[pktOffset++];
+ }
+
+ uint8_t srcAdr[9];
+ srcAdr[0] = ((addrSizes & ADDRSIZE_SRC_ADR_MASK) >> ADDRSIZE_SRC_ADR_SHIFT);
+ if ((srcAdr[0] + pktOffset) > packetInfo.packetBytes)
+ {
+ return false;
+ }
+
+ for (uint8_t i = 1U; i <= srcAdr[0]; i++)
+ {
+ srcAdr[i] = pkt[pktOffset++];
+ }
+
+ // Once done with address fields, pick the security control (if present)
+ uint8_t securityHeader[1 + 4 + 8 + 1]; // max len: control + fc + key source + key ID
+ uint8_t securityHeaderLength = 0;
+
+ if (macFcf & IEEE802154_FRAME_FLAG_SECURITY_ENABLED)
+ {
+ uint8_t securityControl = pkt[pktOffset];
+ // Then the key ID
+ uint8_t keySourceLength = getKeySourceLength(securityControl & IEEE802154_KEYID_MODE_MASK);
+ securityHeaderLength += (sizeof(uint8_t) /* security control */
+ + sizeof(uint32_t) /* frame counter */
+ + keySourceLength + sizeof(uint8_t)); /* key ID */
+ memcpy(securityHeader, pkt + pktOffset, securityHeaderLength);
+ pktOffset += securityHeaderLength;
+ }
+
+ // Reuse packet[] buffer for outgoing Enhanced ACK.
+ // Phr1 Phr2 FcfL FcfH [Seq#] [DstPan] [DstAdr] [SrcPan] [SrcAdr]
+ // Will fill in PHR later.
+ // MAC Fcf:
+ // - Frame Type = ACK
+ // - Security Enabled, as appropriate
+ // - Frame Pending = 0 or as appropriate
+ // - ACK Request = 0
+ // - PanId compression = incoming packet's
+ // - Seq# suppression = incoming packet's
+ // - IE Present = 0 in this implementation
+ // - DstAdrMode = SrcAdrMode of incoming packet's
+ // - Frame Version = 2 (154E)
+ // - SrcAdrMode = DstAdrMode of incoming packet's (for convenience)
+ uint16_t ackFcf =
+ (IEEE802154_FRAME_TYPE_ACK | (macFcf & IEEE802154_FRAME_FLAG_PANID_COMPRESSION) |
+ (macFcf & IEEE802154_FRAME_FLAG_SEQ_SUPPRESSION) | (macFcf & IEEE802154_FRAME_FLAG_SECURITY_ENABLED) |
+ IEEE802154_FRAME_VERSION_2015 | ((macFcf & IEEE802154_FRAME_SOURCE_MODE_MASK) >> 4) |
+ ((macFcf & IEEE802154_FRAME_DESTINATION_MODE_MASK) << 4));
+
+ // Do frame-pending check now
+ if (sIsSrcMatchEnabled)
+ {
+ bool setFramePending = true;
+ if (srcAdr[0] > 0U)
+ {
+ if (srcAdr[0] == 8U)
+ {
+ setFramePending = (utilsSoftSrcMatchExtFindEntry((otExtAddress *)&srcAdr[1]) >= 0);
+ }
+ else
+ {
+ uint16_t srcAdrShort = srcAdr[1] | (srcAdr[2] << 8);
+ setFramePending = (utilsSoftSrcMatchShortFindEntry(srcAdrShort) >= 0);
+ }
+ }
+ if (setFramePending)
+ {
+ ackFcf |= IEEE802154_FRAME_FLAG_FRAME_PENDING;
+ }
+ }
+
+ pktOffset = PHRLen;
+ pkt[pktOffset++] = (uint8_t)ackFcf;
+ pkt[pktOffset++] = (uint8_t)(ackFcf >> 8);
+
+ if ((macFcf & IEEE802154_FRAME_FLAG_SEQ_SUPPRESSION) == 0U)
+ {
+ pkt[pktOffset++] = seqNo;
+ }
+
+ // Determine outgoing ACK's address field sizes
+ index = (((ackFcf & (IEEE802154_FRAME_SOURCE_MODE_MASK | IEEE802154_FRAME_VERSION_2012)) >> 10) |
+ ((ackFcf & IEEE802154_FRAME_DESTINATION_MODE_MASK) >> 9) |
+ ((ackFcf & IEEE802154_FRAME_FLAG_PANID_COMPRESSION) >> 6));
+
+ addrSizes = ieee802154Table7p2[index];
+ if (addrSizes == 0xFFFFU)
+ {
+ // Uh-oh! Enh-ACK would be malformed?! Something funky happened!
+ // Possibly a latency-induced issue.
+ return false;
+ }
+
+ // DstPan = SrcPan of incoming if avail otherwise DstPan of incoming
+ if ((addrSizes & ADDRSIZE_DST_PAN_MASK) != 0U)
+ {
+ if (srcPan[0] > 0U)
+ {
+ pkt[pktOffset++] = srcPan[1];
+ pkt[pktOffset++] = srcPan[2];
+ }
+ else if (dstPan[0] > 0U)
+ {
+ pkt[pktOffset++] = dstPan[1];
+ pkt[pktOffset++] = dstPan[2];
+ }
+ else
+ {
+ // Uh-oh! Outgoing packet needs a DstPanId but incoming had neither!
+ // Possibly a latency-induced issue.
+ return false;
+ }
+ }
+
+ // DstAdr = SrcAdr of incoming packet -- their sizes should match
+ if ((addrSizes & ADDRSIZE_DST_ADR_MASK) != 0U)
+ {
+ for (uint8_t i = 1U; i <= srcAdr[0]; i++)
+ {
+ pkt[pktOffset++] = srcAdr[i];
+ }
+ }
+
+ // SrcPan = DstPan of incoming if avail otherwise SrcPan of incoming
+ if ((addrSizes & ADDRSIZE_SRC_PAN_MASK) != 0U)
+ {
+ if (dstPan[0] > 0U)
+ {
+ pkt[pktOffset++] = dstPan[1];
+ pkt[pktOffset++] = dstPan[2];
+ }
+ else if (srcPan[0] > 0U)
+ {
+ pkt[pktOffset++] = srcPan[1];
+ pkt[pktOffset++] = srcPan[2];
+ }
+ else
+ {
+ // Uh-oh! Outgoing packet needs a SrcPanId but incoming had neither!
+ // Possibly a latency-induced issue.
+ return false;
+ }
+ }
+
+ // SrcAdr = DstAdr of incoming packet -- their sizes should match
+ if ((addrSizes & ADDRSIZE_SRC_ADR_MASK) != 0U)
+ {
+ for (uint8_t i = 1U; i <= dstAdr[0]; i++)
+ {
+ pkt[pktOffset++] = dstAdr[i];
+ }
+ }
+
+ if (ackFcf & IEEE802154_FRAME_FLAG_SECURITY_ENABLED)
+ {
+ memcpy(pkt + pktOffset, securityHeader, securityHeaderLength);
+ pktOffset += securityHeaderLength;
+ }
+
+ // Now add the IE data
+ memcpy(pkt + pktOffset, aIeData, aIeLength);
+ pktOffset += aIeLength;
+
+ // Fill in PHR now that we know Enh-ACK's length
+ if (PHRLen == 2U) // Not true till SubGhz implementation is in place
+ {
+ pkt[0] = (0x08U /*FCS=2byte*/ | 0x10U /*Whiten=enabled*/);
+ pkt[1] = (uint8_t)(__RBIT(pktOffset - 2U /*PHRLen*/ + 2U /*FCS*/) >> 24);
+ }
+ else
+ {
+ pkt[0] = (pktOffset - 1U /*PHRLen*/ + 2U /*FCS*/);
+ }
+
+ processSecurityForEnhancedAck(pkt);
+
+ return (RAIL_IEEE802154_WriteEnhAck(aRailHandle, pkt, pktOffset) == RAIL_STATUS_NO_ERROR);
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+//------------------------------------------------------------------------------
+// RAIL callbacks
+
+static void dataRequestCommandCallback(RAIL_Handle_t aRailHandle)
+{
+ // This callback occurs after the address fields of an incoming
+ // ACK-requesting CMD or DATA frame have been received and we
+ // can do a frame pending check. We must also figure out what
+ // kind of ACK is being requested -- Immediate or Enhanced.
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 && OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE)
+ // Check if we need to write an enhanced ACK.
+ if (writeIeee802154EnhancedAck(aRailHandle, sAckIeData, sAckIeDataLength))
+ {
+ return;
+ }
+#endif
+
+ // If not, RAIL will send an immediate ACK, but we need to do FP lookup.
+ RAIL_Status_t status = RAIL_STATUS_NO_ERROR;
+
+ bool framePendingSet = false;
+
+ if (sIsSrcMatchEnabled)
+ {
+ RAIL_IEEE802154_Address_t sourceAddress;
+
+ status = RAIL_IEEE802154_GetAddress(aRailHandle, &sourceAddress);
+ otEXPECT(status == RAIL_STATUS_NO_ERROR);
+
+ if ((sourceAddress.length == RAIL_IEEE802154_LongAddress &&
+ utilsSoftSrcMatchExtFindEntry((otExtAddress *)sourceAddress.longAddress) >= 0) ||
+ (sourceAddress.length == RAIL_IEEE802154_ShortAddress &&
+ utilsSoftSrcMatchShortFindEntry(sourceAddress.shortAddress) >= 0))
+ {
+ status = RAIL_IEEE802154_SetFramePending(aRailHandle);
+ otEXPECT(status == RAIL_STATUS_NO_ERROR);
+ framePendingSet = true;
+ }
+ }
+ else
+ {
+ status = RAIL_IEEE802154_SetFramePending(aRailHandle);
+ otEXPECT(status == RAIL_STATUS_NO_ERROR);
+ framePendingSet = true;
+ }
+
+ if (framePendingSet)
+ {
+ // Store whether frame pending was set in the outgoing ACK in a reserved
+ // bit of the MAC header.
+ RAIL_RxPacketInfo_t packetInfo;
+ RAIL_GetRxIncomingPacketInfo(gRailHandle, &packetInfo);
+
+ // skip length byte
+ otEXPECT(packetInfo.firstPortionBytes > 0);
+ packetInfo.firstPortionData++;
+ packetInfo.firstPortionBytes--;
+ packetInfo.packetBytes--;
+
+ uint8_t *macFcfPointer = ((packetInfo.firstPortionBytes == 0) ? (uint8_t *)packetInfo.lastPortionData
+ : (uint8_t *)packetInfo.firstPortionData);
+ *macFcfPointer |= IEEE802154_FRAME_PENDING_SET_IN_OUTGOING_ACK;
+ }
+
+exit:
+ if (status == RAIL_STATUS_INVALID_STATE)
+ {
+ otLogWarnPlat("Too late to modify outgoing FP");
+ }
+ else
+ {
+ assert(status == RAIL_STATUS_NO_ERROR);
+ }
+}
+
+static void packetReceivedCallback(RAIL_RxPacketHandle_t packetHandle)
+{
+ RAIL_RxPacketInfo_t packetInfo;
+ RAIL_RxPacketDetails_t packetDetails;
+ uint16_t length;
+ bool framePendingInAck = false;
+ bool rxCorrupted = false;
+
+ packetHandle = RAIL_GetRxPacketInfo(gRailHandle, packetHandle, &packetInfo);
+ otEXPECT_ACTION(
+ (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID && packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS),
+ rxCorrupted = true);
+
+ otEXPECT_ACTION(validatePacketDetails(packetHandle, &packetDetails, &packetInfo, &length), rxCorrupted = true);
+
+ // skip length byte
+ otEXPECT_ACTION(packetInfo.firstPortionBytes > 0, rxCorrupted = true);
+ packetInfo.firstPortionData++;
+ packetInfo.firstPortionBytes--;
+ packetInfo.packetBytes--;
+
+ uint8_t macFcf =
+ ((packetInfo.firstPortionBytes == 0) ? packetInfo.lastPortionData[0] : packetInfo.firstPortionData[0]);
+
+ if (packetDetails.isAck)
+ {
+ otEXPECT_ACTION(
+ (length == IEEE802154_ACK_LENGTH && (macFcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK),
+ rxCorrupted = true);
+
+ // read packet
+ RAIL_CopyRxPacket(sReceiveAckFrame.mPsdu, &packetInfo);
+ sReceiveAckFrame.mLength = length;
+
+ // Releasing the ACK frames here, ensures that the main thread (processNextRxPacket)
+ // is not wasting cycles, releasing the ACK frames from the Rx FIFO queue.
+ RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
+
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ENDED, (uint32_t)isReceivingFrame());
+
+ if (txWaitingForAck() &&
+ (sReceiveAckFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET]))
+ {
+ otEXPECT_ACTION(validatePacketTimestamp(&packetDetails, length), rxCorrupted = true);
+ updateRxFrameDetails(&packetDetails, false);
+
+ // Processing the ACK frame in ISR context avoids the Tx state to be messed up,
+ // in case the Rx FIFO queue gets wiped out in a DMP situation.
+ sTransmitBusy = false;
+ sTransmitError = OT_ERROR_NONE;
+ setInternalFlag(FLAG_WAITING_FOR_ACK, false);
+
+ framePendingInAck = ((macFcf & IEEE802154_FRAME_FLAG_FRAME_PENDING) != 0);
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_ACK_RECEIVED, (uint32_t)framePendingInAck);
+
+ if (txIsDataRequest() && framePendingInAck)
+ {
+ emPendingData = true;
+ }
+ }
+ // Yield the radio upon receiving an ACK as long as it is not related to
+ // a data request.
+ if (!txIsDataRequest())
+ {
+ RAIL_YieldRadio(gRailHandle);
+ }
+ }
+ else
+ {
+ otEXPECT_ACTION(sPromiscuous || (length != IEEE802154_ACK_LENGTH), rxCorrupted = true);
+
+ if (macFcf & IEEE802154_FRAME_FLAG_ACK_REQUIRED)
+ {
+ (void)handlePhyStackEvent((RAIL_IsRxAutoAckPaused(gRailHandle)
+ ? SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACK_BLOCKED
+ : SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACKING),
+ (uint32_t)isReceivingFrame());
+ setInternalFlag(FLAG_ONGOING_TX_ACK, true);
+ }
+ else
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ENDED, (uint32_t)isReceivingFrame());
+ // We received a frame that does not require an ACK as result of a data
+ // poll: we yield the radio here.
+ if (emPendingData)
+ {
+ RAIL_YieldRadio(gRailHandle);
+ emPendingData = false;
+ }
+ }
+ }
+exit:
+ if (rxCorrupted)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_CORRUPTED, (uint32_t)isReceivingFrame());
+ }
+}
+
+static void packetSentCallback(bool isAck)
+{
+ if (isAck)
+ {
+ // We successfully sent out an ACK.
+ setInternalFlag(FLAG_ONGOING_TX_ACK, false);
+ // We acked the packet we received after a poll: we can yield now.
+ if (emPendingData)
+ {
+ RAIL_YieldRadio(gRailHandle);
+ emPendingData = false;
+ }
+ }
+ else if (getInternalFlag(FLAG_ONGOING_TX_DATA))
+ {
+ setInternalFlag(FLAG_ONGOING_TX_DATA, false);
+
+ if (txWaitingForAck())
+ {
+ setInternalFlag(FLAG_WAITING_FOR_ACK, true);
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_ACK_WAITING, 0U);
+ }
+ else
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_ENDED, 0U);
+ RAIL_YieldRadio(gRailHandle);
+ sTransmitError = OT_ERROR_NONE;
+ sTransmitBusy = false;
+ }
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventPacketSent++;
+#endif
+ }
+}
+
+static void txFailedCallback(bool isAck, uint8_t status)
+{
+ if (isAck)
+ {
+ setInternalFlag(FLAG_ONGOING_TX_ACK, false);
+ }
+ else if (getInternalFlag(FLAG_ONGOING_TX_DATA))
+ {
+ if (status == TX_COMPLETE_RESULT_CCA_FAIL)
+ {
+ sTransmitError = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+ setInternalFlag(FLAG_CURRENT_TX_USE_CSMA, false);
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventChannelBusy++;
+#endif
+ }
+ else
+ {
+ sTransmitError = OT_ERROR_ABORT;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventTxAbort++;
+#endif
+ }
+ setInternalFlag(FLAG_ONGOING_TX_DATA, false);
+ RAIL_YieldRadio(gRailHandle);
+ sTransmitBusy = false;
+ }
+}
+
+static void ackTimeoutCallback(void)
+{
+ assert(txWaitingForAck());
+ assert(getInternalFlag(FLAG_WAITING_FOR_ACK));
+
+ sTransmitError = OT_ERROR_NO_ACK;
+ sTransmitBusy = false;
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventNoAck++;
+#endif
+
+#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+ // If antenna diversity is enabled toggle the selected antenna.
+ sl_rail_util_ant_div_toggle_antenna();
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+ // TO DO: Check if we have an OT function that
+ // provides the number of mac retry attempts left
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_ACK_TIMEDOUT, 0);
+
+ setInternalFlag(FLAG_WAITING_FOR_ACK, false);
+ RAIL_YieldRadio(gRailHandle);
+ emPendingData = false;
+}
+
+static void schedulerEventCallback(RAIL_Handle_t aRailHandle)
+{
+ RAIL_SchedulerStatus_t status = RAIL_GetSchedulerStatus(aRailHandle);
+ assert(status != RAIL_SCHEDULER_STATUS_INTERNAL_ERROR);
+
+ if (status == RAIL_SCHEDULER_STATUS_CCA_CSMA_TX_FAIL || status == RAIL_SCHEDULER_STATUS_SINGLE_TX_FAIL ||
+ status == RAIL_SCHEDULER_STATUS_SCHEDULED_TX_FAIL ||
+ (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sTransmitBusy) ||
+ (status == RAIL_SCHEDULER_STATUS_EVENT_INTERRUPTED && sTransmitBusy))
+ {
+ if (getInternalFlag(FLAG_ONGOING_TX_ACK))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACK_ABORTED, (uint32_t)isReceivingFrame());
+ txFailedCallback(true, 0xFF);
+ }
+ // We were in the process of TXing a data frame, treat it as a CCA_FAIL.
+ if (getInternalFlag(FLAG_ONGOING_TX_DATA))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_BLOCKED, (uint32_t)txWaitingForAck());
+ txFailedCallback(false, TX_COMPLETE_RESULT_CCA_FAIL);
+ }
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventSchedulerStatusError++;
+#endif
+ }
+ else if (status == RAIL_SCHEDULER_STATUS_AVERAGE_RSSI_FAIL ||
+ (status == RAIL_SCHEDULER_STATUS_SCHEDULE_FAIL && sEnergyScanStatus == ENERGY_SCAN_STATUS_IN_PROGRESS))
+ {
+ energyScanComplete(OT_RADIO_RSSI_INVALID);
+ }
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ else if (sTransmitBusy)
+ {
+ sRailDebugCounters.mRailEventsSchedulerStatusLastStatus = status;
+ sRailDebugCounters.mRailEventsSchedulerStatusTransmitBusy++;
+ }
+#endif
+}
+
+static void configUnscheduledCallback(void)
+{
+ // We are waiting for an ACK: we will never get the ACK we were waiting for.
+ // We want to call ackTimeoutCallback() only if the PACKET_SENT event
+ // already fired (which would clear the FLAG_ONGOING_TX_DATA flag).
+ if (getInternalFlag(FLAG_WAITING_FOR_ACK))
+ {
+ ackTimeoutCallback();
+ }
+
+ // We are about to send an ACK, which it won't happen.
+ if (getInternalFlag(FLAG_ONGOING_TX_ACK))
+ {
+ txFailedCallback(true, 0xFF);
+ }
+}
+
+static void RAILCb_Generic(RAIL_Handle_t aRailHandle, RAIL_Events_t aEvents)
+{
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ if (aEvents & (RAIL_EVENT_RX_SYNC1_DETECT | RAIL_EVENT_RX_SYNC2_DETECT))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_STARTED, (uint32_t)isReceivingFrame());
+ }
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+ if ((aEvents & RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND)
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+ && !RAIL_IsRxAutoAckPaused(aRailHandle)
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+ )
+ {
+ dataRequestCommandCallback(aRailHandle);
+ }
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ if (aEvents & RAIL_EVENT_RX_FILTER_PASSED)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACCEPTED, (uint32_t)isReceivingFrame());
+ }
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+ if (aEvents & RAIL_EVENT_TX_PACKET_SENT)
+ {
+ packetSentCallback(false);
+ }
+ else if (aEvents & RAIL_EVENT_TX_CHANNEL_BUSY)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_BLOCKED, (uint32_t)txWaitingForAck());
+ txFailedCallback(false, TX_COMPLETE_RESULT_CCA_FAIL);
+ }
+ else if (aEvents & RAIL_EVENT_TX_BLOCKED)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_BLOCKED, (uint32_t)txWaitingForAck());
+ txFailedCallback(false, TX_COMPLETE_RESULT_OTHER_FAIL);
+ }
+ else if (aEvents & (RAIL_EVENT_TX_UNDERFLOW | RAIL_EVENT_TX_ABORTED))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_ABORTED, (uint32_t)txWaitingForAck());
+ txFailedCallback(false, TX_COMPLETE_RESULT_OTHER_FAIL);
+ }
+ else
+ {
+ // Pre-completion aEvents are processed in their logical order:
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ if (aEvents & RAIL_EVENT_TX_START_CCA)
+ {
+ // We are starting RXWARM for a CCA check
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_CCA_SOON, 0U);
+ }
+ if (aEvents & RAIL_EVENT_TX_CCA_RETRY)
+ {
+ // We failed a CCA check and need to retry
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_CCA_BUSY, 0U);
+ }
+ if (aEvents & RAIL_EVENT_TX_CHANNEL_CLEAR)
+ {
+ // We're going on-air
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_STARTED, 0U);
+ }
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ }
+
+ if (aEvents & RAIL_EVENT_RX_PACKET_RECEIVED)
+ {
+ packetReceivedCallback(RAIL_HoldRxPacket(aRailHandle));
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventPacketReceived++;
+#endif
+ }
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ if (aEvents & RAIL_EVENT_RX_FRAME_ERROR)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_CORRUPTED, (uint32_t)isReceivingFrame());
+ }
+ // The following 3 events cause us to not receive a packet
+ if (aEvents & (RAIL_EVENT_RX_PACKET_ABORTED | RAIL_EVENT_RX_ADDRESS_FILTERED | RAIL_EVENT_RX_FIFO_OVERFLOW))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_FILTERED, (uint32_t)isReceivingFrame());
+ }
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+ if (aEvents & RAIL_EVENT_TXACK_PACKET_SENT)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACK_SENT, (uint32_t)isReceivingFrame());
+ packetSentCallback(true);
+ }
+ if (aEvents & (RAIL_EVENT_TXACK_ABORTED | RAIL_EVENT_TXACK_UNDERFLOW))
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACK_ABORTED, (uint32_t)isReceivingFrame());
+ txFailedCallback(true, 0xFF);
+ }
+ if (aEvents & RAIL_EVENT_TXACK_BLOCKED)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_ACK_BLOCKED, (uint32_t)isReceivingFrame());
+ txFailedCallback(true, 0xFF);
+ }
+ // Deal with ACK timeout after possible RX completion in case RAIL
+ // notifies us of the ACK and the timeout simultaneously -- we want
+ // the ACK to win over the timeout.
+ if (aEvents & RAIL_EVENT_RX_ACK_TIMEOUT)
+ {
+ if (getInternalFlag(FLAG_WAITING_FOR_ACK))
+ {
+ ackTimeoutCallback();
+ }
+ }
+
+ if (aEvents & RAIL_EVENT_CONFIG_UNSCHEDULED)
+ {
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_RX_IDLED, 0U);
+ configUnscheduledCallback();
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventConfigUnScheduled++;
+#endif
+ }
+
+ if (aEvents & RAIL_EVENT_CONFIG_SCHEDULED)
+ {
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventConfigScheduled++;
+#endif
+ }
+
+ if (aEvents & RAIL_EVENT_SCHEDULER_STATUS)
+ {
+ schedulerEventCallback(aRailHandle);
+ }
+
+ if (aEvents & RAIL_EVENT_CAL_NEEDED)
+ {
+ RAIL_Status_t status;
+
+ status = RAIL_Calibrate(aRailHandle, NULL, RAIL_CAL_ALL_PENDING);
+ // TODO: Non-RTOS DMP case fails
+#if (!defined(SL_CATALOG_BLUETOOTH_PRESENT) || defined(SL_CATALOG_KERNEL_PRESENT))
+ assert(status == RAIL_STATUS_NO_ERROR);
+#endif
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventCalNeeded++;
+#endif
+ }
+
+ if (aEvents & RAIL_EVENT_RSSI_AVERAGE_DONE)
+ {
+ const int16_t energyScanResultQuarterDbm = RAIL_GetAverageRssi(aRailHandle);
+ RAIL_YieldRadio(aRailHandle);
+
+ energyScanComplete(energyScanResultQuarterDbm == RAIL_RSSI_INVALID
+ ? OT_RADIO_RSSI_INVALID
+ : (energyScanResultQuarterDbm / QUARTER_DBM_IN_DBM));
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailPlatRadioEnergyScanDoneCbCount++;
+#endif
+ }
+
+ otSysEventSignalPending();
+}
+
+//------------------------------------------------------------------------------
+// Main thread packet handling
+
+static bool validatePacketDetails(RAIL_RxPacketHandle_t packetHandle,
+ RAIL_RxPacketDetails_t *pPacketDetails,
+ RAIL_RxPacketInfo_t * pPacketInfo,
+ uint16_t * packetLength)
+{
+ bool pktValid = true;
+
+ otEXPECT_ACTION((RAIL_GetRxPacketDetailsAlt(gRailHandle, packetHandle, pPacketDetails) == RAIL_STATUS_NO_ERROR),
+ pktValid = false);
+
+ // RAIL's packetBytes includes the 1-byte PHY header but not the 2-byte CRC
+ // We want *packetLength to match the PHY header length so we add 2 for CRC
+ // and subtract 1 for PHY header.
+ *packetLength = pPacketInfo->packetBytes + 1;
+
+ // check the length in recv packet info structure; RAIL should take care of this.
+ otEXPECT_ACTION(*packetLength == pPacketInfo->firstPortionData[0], pktValid = false);
+
+ // check the length validity of recv packet; RAIL should take care of this.
+ otEXPECT_ACTION((*packetLength >= IEEE802154_MIN_LENGTH && *packetLength <= IEEE802154_MAX_LENGTH),
+ pktValid = false);
+exit:
+ return pktValid;
+}
+
+static bool validatePacketTimestamp(RAIL_RxPacketDetails_t *pPacketDetails, uint16_t packetLength)
+{
+ bool rxTimestampValid = true;
+
+ // Get the timestamp when the SFD was received
+ otEXPECT_ACTION(pPacketDetails->timeReceived.timePosition != RAIL_PACKET_TIME_INVALID, rxTimestampValid = false);
+
+ // + 1 for the 1-byte PHY header
+ pPacketDetails->timeReceived.totalPacketBytes = packetLength + 1;
+
+ otEXPECT_ACTION((RAIL_GetRxTimeSyncWordEndAlt(gRailHandle, pPacketDetails) == RAIL_STATUS_NO_ERROR),
+ rxTimestampValid = false);
+exit:
+ return rxTimestampValid;
+}
+
+static void updateRxFrameDetails(RAIL_RxPacketDetails_t *pPacketDetails, bool framePendingSetInOutgoingAck)
+{
+ assert(pPacketDetails != NULL);
+
+ if (pPacketDetails->isAck)
+ {
+ sReceiveAckFrame.mInfo.mRxInfo.mRssi = pPacketDetails->rssi;
+ sReceiveAckFrame.mInfo.mRxInfo.mLqi = pPacketDetails->lqi;
+ sReceiveAckFrame.mInfo.mRxInfo.mTimestamp = pPacketDetails->timeReceived.packetTime;
+ }
+ else
+ {
+ sReceiveFrame.mInfo.mRxInfo.mRssi = pPacketDetails->rssi;
+ sReceiveFrame.mInfo.mRxInfo.mLqi = pPacketDetails->lqi;
+ sReceiveFrame.mInfo.mRxInfo.mTimestamp = pPacketDetails->timeReceived.packetTime;
+ // Set this flag only when the packet is really acknowledged with frame pending set.
+ sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = framePendingSetInOutgoingAck;
+ }
+}
+
+static void processNextRxPacket(otInstance *aInstance)
+{
+ RAIL_RxPacketHandle_t packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
+ RAIL_RxPacketInfo_t packetInfo;
+ RAIL_RxPacketDetails_t packetDetails;
+ RAIL_Status_t status;
+ uint16_t length;
+ bool rxProcessDone = false;
+
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ packetHandle = RAIL_GetRxPacketInfo(gRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST_COMPLETE, &packetInfo);
+ otEXPECT_ACTION(
+ (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID && packetInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS),
+ packetHandle = RAIL_RX_PACKET_HANDLE_INVALID);
+
+ otEXPECT(validatePacketDetails(packetHandle, &packetDetails, &packetInfo, &length));
+
+ // skip length byte
+ otEXPECT(packetInfo.firstPortionBytes > 0);
+ packetInfo.firstPortionData++;
+ packetInfo.firstPortionBytes--;
+ packetInfo.packetBytes--;
+
+ // As received ACK frames are already processed in packetReceivedCallback,
+ // we only need to read and process the non-ACK frames here.
+ otEXPECT(sPromiscuous || (!packetDetails.isAck && (length != IEEE802154_ACK_LENGTH)));
+
+ // read packet
+ RAIL_CopyRxPacket(sReceiveFrame.mPsdu, &packetInfo);
+ sReceiveFrame.mLength = length;
+
+ uint8_t *macFcfPointer = sReceiveFrame.mPsdu;
+
+ // Check the reserved bit in the MAC header to see whether the frame pending
+ // bit was set in the outgoing ACK
+ // Then, clear it.
+ bool framePendingSetInOutgoingAck = ((*macFcfPointer & IEEE802154_FRAME_PENDING_SET_IN_OUTGOING_ACK) != 0);
+ *macFcfPointer &= ~IEEE802154_FRAME_PENDING_SET_IN_OUTGOING_ACK;
+
+ status = RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
+ if (status == RAIL_STATUS_NO_ERROR)
+ {
+ packetHandle = RAIL_RX_PACKET_HANDLE_INVALID;
+ }
+
+ otEXPECT(validatePacketTimestamp(&packetDetails, length));
+ updateRxFrameDetails(&packetDetails, framePendingSetInOutgoingAck);
+ rxProcessDone = true;
+
+exit:
+ if (packetHandle != RAIL_RX_PACKET_HANDLE_INVALID)
+ {
+ RAIL_ReleaseRxPacket(gRailHandle, packetHandle);
+ }
+ CORE_EXIT_ATOMIC();
+
+ // signal MAC layer
+ if (rxProcessDone)
+ {
+ sReceiveError = OT_ERROR_NONE;
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+ if (otPlatDiagModeGet())
+ {
+ otPlatDiagRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
+ }
+ else
+#endif
+ {
+ otLogInfoPlat("Received %d bytes", sReceiveFrame.mLength);
+ otPlatRadioReceiveDone(aInstance, &sReceiveFrame, sReceiveError);
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailPlatRadioReceiveDoneCbCount++;
+#endif
+ }
+ otSysEventSignalPending();
+ }
+}
+
+static void processTxComplete(otInstance *aInstance)
+{
+ if (sState == OT_RADIO_STATE_TRANSMIT && sTransmitBusy == false)
+ {
+ if (sTransmitError != OT_ERROR_NONE)
+ {
+ otLogDebgPlat("Transmit failed ErrorCode=%d", sTransmitError);
+ }
+
+ sState = OT_RADIO_STATE_RECEIVE;
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+ if (otPlatDiagModeGet())
+ {
+ otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, sTransmitError);
+ }
+ else
+#endif
+ if (((sTransmitFrame.mPsdu[0] & IEEE802154_FRAME_FLAG_ACK_REQUIRED) == 0) ||
+ (sTransmitError != OT_ERROR_NONE))
+ {
+ otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, sTransmitError);
+ }
+ else
+ {
+ otPlatRadioTxDone(aInstance, &sTransmitFrame, &sReceiveAckFrame, sTransmitError);
+ }
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailPlatRadioTxDoneCbCount++;
+#endif
+ otSysEventSignalPending();
+ }
+}
+
+void efr32RadioProcess(otInstance *aInstance)
+{
+ (void)handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TICK, 0U);
+
+ // We should process the received packet first. Adding it at the end of this function,
+ // will delay the stack notification until the next call to efr32RadioProcess()
+ processNextRxPacket(aInstance);
+ processTxComplete(aInstance);
+
+ if (sEnergyScanMode == ENERGY_SCAN_MODE_ASYNC && sEnergyScanStatus == ENERGY_SCAN_STATUS_COMPLETED)
+ {
+ sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE;
+ otPlatRadioEnergyScanDone(aInstance, sEnergyScanResultDbm);
+ otSysEventSignalPending();
+
+#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+ sRailDebugCounters.mRailEventEnergyScanCompleted++;
+#endif
+ }
+}
+
+//------------------------------------------------------------------------------
+// Antenn Diveristy, Wifi coexistence and Run time PHY select support
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
+
+otError setRadioState(otRadioState state)
+{
+ otError error = OT_ERROR_NONE;
+
+ // Defer idling the radio if we have an ongoing TX task
+ otEXPECT_ACTION((!getInternalFlag(ONGOING_TX_FLAGS)), error = OT_ERROR_FAILED);
+
+ switch (state)
+ {
+ case OT_RADIO_STATE_RECEIVE:
+ otEXPECT_ACTION(radioSetRx(sReceiveFrame.mChannel) == OT_ERROR_NONE, error = OT_ERROR_FAILED);
+ break;
+ case OT_RADIO_STATE_SLEEP:
+ radioSetIdle();
+ break;
+ default:
+ error = OT_ERROR_FAILED;
+ }
+exit:
+ return error;
+}
+
+void sl_ot_update_active_radio_config(void)
+{
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ // Proceed with PHY selection only if 2.4 GHz band is used
+ otEXPECT(sBandConfig.mChannelConfig == NULL);
+
+ otRadioState currentState = sState;
+ otEXPECT(setRadioState(OT_RADIO_STATE_SLEEP) == OT_ERROR_NONE);
+ sl_rail_util_plugin_config_2p4ghz_radio(gRailHandle);
+ otEXPECT(setRadioState(currentState) == OT_ERROR_NONE);
+
+exit:
+ CORE_EXIT_ATOMIC();
+ return;
+}
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
+
+#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+void efr32AntennaConfigInit(void)
+{
+ RAIL_Status_t status;
+ sl_rail_util_ant_div_init();
+ status = sl_rail_util_ant_div_update_antenna_config();
+ assert(status == RAIL_STATUS_NO_ERROR);
+}
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+static void changeDynamicEvents(void)
+{
+ const RAIL_Events_t eventMask =
+ RAIL_EVENTS_NONE | RAIL_EVENT_RX_SYNC1_DETECT | RAIL_EVENT_RX_SYNC2_DETECT | RAIL_EVENT_RX_FRAME_ERROR |
+ RAIL_EVENT_RX_FIFO_OVERFLOW | RAIL_EVENT_RX_ADDRESS_FILTERED | RAIL_EVENT_RX_PACKET_ABORTED |
+ RAIL_EVENT_RX_FILTER_PASSED | RAIL_EVENT_TX_CHANNEL_CLEAR | RAIL_EVENT_TX_CCA_RETRY | RAIL_EVENT_TX_START_CCA;
+ RAIL_Events_t eventValues = RAIL_EVENTS_NONE;
+
+ if (phyStackEventIsEnabled())
+ {
+ eventValues |= eventMask;
+ }
+ updateEvents(eventMask, eventValues);
+}
+#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+
+static void efr32PhyStackInit(void)
+{
+#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+ efr32AntennaConfigInit();
+#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
+
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+ efr32CoexInit();
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+
+#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_STACK_EVENT_PRESENT
+ changeDynamicEvents();
+#endif
+}
+
+#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+
+static void emRadioEnableAutoAck(void)
+{
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+
+ if (getInternalFlag(FLAG_RADIO_INIT_DONE))
+ {
+ if ((rhoActive >= RHO_INT_ACTIVE) // Internal always holds ACKs
+ || ((rhoActive > RHO_INACTIVE) && ((sl_rail_util_coex_get_options() & SL_RAIL_UTIL_COEX_OPT_ACK_HOLDOFF) !=
+ SL_RAIL_UTIL_COEX_OPT_DISABLED)))
+ {
+ RAIL_PauseRxAutoAck(gRailHandle, true);
+ }
+ else
+ {
+ RAIL_PauseRxAutoAck(gRailHandle, false);
+ }
+ }
+ CORE_EXIT_ATOMIC();
+}
+
+static void emRadioEnablePta(bool enable)
+{
+ halInternalInitPta();
+
+ // When PTA is enabled, we want to negate PTA_REQ as soon as an incoming
+ // frame is aborted, e.g. due to filtering. To do that we must turn off
+ // the TRACKABFRAME feature that's normally on to benefit sniffing on PTI.
+ assert(RAIL_ConfigRxOptions(gRailHandle, RAIL_RX_OPTION_TRACK_ABORTED_FRAMES,
+ (enable ? RAIL_RX_OPTIONS_NONE : RAIL_RX_OPTION_TRACK_ABORTED_FRAMES)) ==
+ RAIL_STATUS_NO_ERROR);
+}
+
+static void efr32CoexInit(void)
+{
+ sl_rail_util_coex_options_t coexOptions = sl_rail_util_coex_get_options();
+
+#if SL_OPENTHREAD_COEX_MAC_HOLDOFF_ENABLE
+ coexOptions |= SL_RAIL_UTIL_COEX_OPT_MAC_HOLDOFF;
+#endif // SL_OPENTHREAD_COEX_MAC_HOLDOFF_ENABLE
+
+ sl_rail_util_coex_set_options(coexOptions);
+
+ emRadioEnableAutoAck(); // Might suspend AutoACK if RHO already in effect
+ emRadioEnablePta(sl_rail_util_coex_is_enabled());
+}
+
+// Managing radio transmission
+static void onPtaGrantTx(sl_rail_util_coex_req_t ptaStatus)
+{
+ // Only pay attention to first PTA Grant callback, ignore any further ones
+ if (ptaGntEventReported)
+ {
+ return;
+ }
+ ptaGntEventReported = true;
+
+ assert(ptaStatus == SL_RAIL_UTIL_COEX_REQCB_GRANTED);
+ // PTA is telling us we've gotten GRANT and should send ASAP *without* CSMA
+ setInternalFlag(FLAG_CURRENT_TX_USE_CSMA, false);
+ txCurrentPacket();
+}
+
+static void tryTxCurrentPacket(void)
+{
+ assert(getInternalFlag(FLAG_ONGOING_TX_DATA));
+
+ ptaGntEventReported = false;
+ sl_rail_util_ieee802154_stack_event_t ptaStatus =
+ handlePhyStackEvent(SL_RAIL_UTIL_IEEE802154_STACK_EVENT_TX_PENDED_MAC, (uint32_t)&onPtaGrantTx);
+ if (ptaStatus == SL_RAIL_UTIL_IEEE802154_STACK_STATUS_SUCCESS)
+ {
+ // Normal case where PTA allows us to start the (CSMA) transmit below
+ txCurrentPacket();
+ }
+ else if (ptaStatus == SL_RAIL_UTIL_IEEE802154_STACK_STATUS_CB_PENDING)
+ {
+ // onPtaGrantTx() callback will take over (and might already have)
+ }
+ else if (ptaStatus == SL_RAIL_UTIL_IEEE802154_STACK_STATUS_HOLDOFF)
+ {
+ txFailedCallback(false, TX_COMPLETE_RESULT_OTHER_FAIL);
+ }
+}
+
+// Managing CCA Threshold
+static void setCcaThreshold(void)
+{
+ if (sCcaThresholdDbm == CCA_THRESHOLD_UNINIT)
+ {
+ sCcaThresholdDbm = CCA_THRESHOLD_DEFAULT;
+ }
+ CORE_DECLARE_IRQ_STATE;
+ CORE_ENTER_ATOMIC();
+ int8_t thresholddBm = sCcaThresholdDbm;
+
+ if (getInternalFlag(FLAG_RADIO_INIT_DONE))
+ {
+ if (rhoActive > RHO_INACTIVE)
+ {
+ thresholddBm = RAIL_RSSI_INVALID_DBM;
+ }
+ assert(RAIL_SetCcaThreshold(gRailHandle, thresholddBm) == RAIL_STATUS_NO_ERROR);
+ }
+ CORE_EXIT_ATOMIC();
+}
+
+static void emRadioHoldOffInternalIsr(uint8_t active)
+{
+ if (active != rhoActive)
+ {
+ rhoActive = active; // Update rhoActive early
+ if (getInternalFlag(FLAG_RADIO_INIT_DONE))
+ {
+ setCcaThreshold();
+ emRadioEnableAutoAck();
+ }
+ }
+}
+
+// External API used by Coex Component
+void emRadioHoldOffIsr(bool active)
+{
+ emRadioHoldOffInternalIsr((uint8_t)active | (rhoActive & ~RHO_EXT_ACTIVE));
+}
+
+#if SL_OPENTHREAD_COEX_COUNTER_ENABLE
+
+void sl_rail_util_coex_counter_on_event(sl_rail_util_coex_event_t event)
+{
+ otEXPECT(event < SL_RAIL_UTIL_COEX_EVENT_COUNT);
+ sCoexCounters[event] += 1;
+exit:
+ return;
+}
+
+void efr32RadioGetCoexCounters(uint32_t (*aCoexCounters)[SL_RAIL_UTIL_COEX_EVENT_COUNT])
+{
+ memset((void *)aCoexCounters, 0, sizeof(*aCoexCounters));
+ memcpy(aCoexCounters, sCoexCounters, sizeof(*aCoexCounters));
+}
+
+void efr32RadioClearCoexCounters(void)
+{
+ memset((void *)sCoexCounters, 0, sizeof(sCoexCounters));
+}
+
+#endif // SL_OPENTHREAD_COEX_COUNTER_ENABLE
+#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
+
RAIL_AntennaConfig_t halAntennaConfig;
void initAntenna(void)
diff --git a/examples/platforms/efr32/src/system.c b/examples/platforms/efr32/src/system.c
index 9e3f57a..90fd724 100644
--- a/examples/platforms/efr32/src/system.c
+++ b/examples/platforms/efr32/src/system.c
@@ -39,7 +39,6 @@
#include <string.h>
#include "openthread-system.h"
-#include <openthread/platform/uart.h>
#include "common/logging.hpp"
@@ -55,15 +54,11 @@
#include "em_system.h"
#include "hal-config.h"
#include "hal_common.h"
+#include "platform-efr32.h"
#include "rail.h"
+#include "sl_device_init_nvic.h"
#include "sl_mpu.h"
#include "sl_sleeptimer.h"
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-#include "sl_malloc.h"
-#include "openthread/heap.h"
-#endif
-
-#include "platform-efr32.h"
#if (HAL_FEM_ENABLE)
#include "fem-control.h"
@@ -170,18 +165,8 @@
__disable_irq();
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
- otHeapSetCAllocFree(sl_calloc, sl_free);
-#endif
-#undef FIXED_EXCEPTION
-#define FIXED_EXCEPTION(vectorNumber, functionName, deviceIrqn, deviceIrqHandler)
-#define EXCEPTION(vectorNumber, functionName, deviceIrqn, deviceIrqHandler, priorityLevel, subpriority) \
- NVIC_SetPriority(deviceIrqn, NVIC_EncodePriority(PRIGROUP_POSITION - 1, priorityLevel, subpriority));
-#include NVIC_CONFIG
-#undef EXCEPTION
-
- NVIC_SetPriorityGrouping(PRIGROUP_POSITION - 1);
CHIP_Init();
+ sl_device_init_nvic();
halInitChipSpecific();
BSP_Init(BSP_INIT_BCC);
diff --git a/examples/platforms/efr32/src/uart.c b/examples/platforms/efr32/src/uart.c
index 0ba169f..638bf9e 100644
--- a/examples/platforms/efr32/src/uart.c
+++ b/examples/platforms/efr32/src/uart.c
@@ -31,18 +31,32 @@
* This file implements the OpenThread platform abstraction for UART communication.
*
*/
-
#include <stddef.h>
+#include <string.h>
#include "openthread-system.h"
-#include <openthread/platform/uart.h>
+#include <openthread-core-config.h>
#include "utils/code_utils.h"
+#include "utils/uart.h"
+#include "ecode.h"
#include "em_core.h"
+#include "sl_sleeptimer.h"
+#include "sl_status.h"
#include "uartdrv.h"
#include "hal-config.h"
+#include "platform-efr32.h"
+#include "sl_uartdrv_usart_vcom_config.h"
+
+#define HELPER1(x) USART##x##_RX_IRQn
+#define HELPER2(x) HELPER1(x)
+#define USART_IRQ HELPER2(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
+
+#define HELPER3(x) USART##x##_RX_IRQHandler
+#define HELPER4(x) HELPER3(x)
+#define USART_IRQHandler HELPER4(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
enum
{
@@ -89,9 +103,14 @@
static UARTDRV_HandleData_t sUartHandleData;
static UARTDRV_Handle_t sUartHandle = &sUartHandleData;
-static uint8_t sReceiveBuffer[2];
-static const uint8_t * sTransmitBuffer = NULL;
-static volatile uint16_t sTransmitLength = 0;
+
+// In order to reduce the probability of data loss due to disabled interrupts, we use
+// two duplicate receive buffers so we can always have one "active" receive request.
+#define RECEIVE_BUFFER_SIZE 128
+static uint8_t sReceiveBuffer1[RECEIVE_BUFFER_SIZE];
+static uint8_t sReceiveBuffer2[RECEIVE_BUFFER_SIZE];
+static uint8_t lastCount = 0;
+static volatile bool sCheckForTxComplete = false;
typedef struct ReceiveFifo_t
{
@@ -106,17 +125,21 @@
static ReceiveFifo_t sReceiveFifo;
static void processReceive(void);
+static void processTransmit(void);
static void receiveDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount)
{
+ OT_UNUSED_VARIABLE(aStatus);
+
// We can only write if incrementing mTail doesn't equal mHead
- if (sReceiveFifo.mHead != (sReceiveFifo.mTail + 1) % kReceiveFifoSize)
+ if (sReceiveFifo.mHead != (sReceiveFifo.mTail + aCount - lastCount) % kReceiveFifoSize)
{
- sReceiveFifo.mBuffer[sReceiveFifo.mTail] = aData[0];
- sReceiveFifo.mTail = (sReceiveFifo.mTail + 1) % kReceiveFifoSize;
+ memcpy(sReceiveFifo.mBuffer + sReceiveFifo.mTail, aData + lastCount, aCount - lastCount);
+ sReceiveFifo.mTail = (sReceiveFifo.mTail + aCount - lastCount) % kReceiveFifoSize;
+ lastCount = 0;
}
- UARTDRV_Receive(aHandle, aData, 1, receiveDone);
+ UARTDRV_Receive(aHandle, aData, aCount, receiveDone);
otSysEventSignalPending();
}
@@ -127,12 +150,24 @@
OT_UNUSED_VARIABLE(aData);
OT_UNUSED_VARIABLE(aCount);
- sTransmitLength = 0;
+ // This value will be used later in processTransmit() to call otPlatUartSendDone()
+ sCheckForTxComplete = true;
+
otSysEventSignalPending();
}
static void processReceive(void)
{
+ uint8_t * aData;
+ UARTDRV_Count_t aCount, remaining;
+ CORE_ATOMIC_SECTION(UARTDRV_GetReceiveStatus(sUartHandle, &aData, &aCount, &remaining);
+
+ if (aCount > lastCount) {
+ memcpy(sReceiveFifo.mBuffer + sReceiveFifo.mTail, aData + lastCount, aCount - lastCount);
+ sReceiveFifo.mTail = (sReceiveFifo.mTail + aCount - lastCount) % kReceiveFifoSize;
+ lastCount = aCount;
+ })
+
// Copy tail to prevent multiple reads
uint16_t tail = sReceiveFifo.mTail;
@@ -155,20 +190,76 @@
}
}
+static void flushTimeoutAlarmCallback(sl_sleeptimer_timer_handle_t *aHandle, void *aData)
+{
+ OT_UNUSED_VARIABLE(aHandle);
+ OT_UNUSED_VARIABLE(aData);
+ bool *flushTimedOut = (bool *)aData;
+ *flushTimedOut = true;
+}
+
otError otPlatUartFlush(void)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ otError error = OT_ERROR_NONE;
+ sl_status_t status = SL_STATUS_OK;
+ volatile bool flushTimedOut = false;
+ sl_sleeptimer_timer_handle_t flushTimer;
+
+ // Start flush timeout timer
+ status = sl_sleeptimer_start_timer_ms(&flushTimer, OPENTHREAD_CONFIG_EFR32_UART_TX_FLUSH_TIMEOUT_MS,
+ flushTimeoutAlarmCallback, NULL, 0,
+ SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG);
+ otEXPECT_ACTION(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
+
+ // Block until DMA has finished transmitting every buffer in sUartTxQueue and becomes idle
+ uint8_t transmitQueueDepth = 0;
+ bool uartFullyFlushed = false;
+ bool uartIdle = false;
+
+ do
+ {
+ // Check both peripheral status and queue depth
+ transmitQueueDepth = UARTDRV_GetTransmitDepth(sUartHandle);
+ uartIdle = UARTDRV_GetPeripheralStatus(sUartHandle) & (UARTDRV_STATUS_TXIDLE | UARTDRV_STATUS_TXC);
+ uartFullyFlushed = uartIdle && (transmitQueueDepth == 0);
+ } while (!uartFullyFlushed && !flushTimedOut);
+
+ sl_sleeptimer_stop_timer(&flushTimer);
+
+ if (flushTimedOut)
+ {
+ // Abort all transmits
+ UARTDRV_Abort(sUartHandle, uartdrvAbortTransmit);
+ }
+
+exit:
+ return error;
}
static void processTransmit(void)
{
- if (sTransmitBuffer != NULL && sTransmitLength == 0)
+ // NOTE: This check needs to be done in here and cannot be done in transmitDone because the transmit may not be
+ // fully complete when the transmitDone callback is called.
+ if (!sCheckForTxComplete)
{
- sTransmitBuffer = NULL;
+ return;
+ }
+
+ bool queueEmpty = UARTDRV_GetPeripheralStatus(sUartHandle) & (UARTDRV_STATUS_TXIDLE | UARTDRV_STATUS_TXC);
+ uint8_t transmitQueueDepth = UARTDRV_GetTransmitDepth(sUartHandle);
+
+ if (transmitQueueDepth == 0 && queueEmpty)
+ {
+ sCheckForTxComplete = false;
otPlatUartSendDone();
}
}
+void USART_IRQHandler(void)
+{
+ otSysEventSignalPending();
+}
+
otError otPlatUartEnable(void)
{
UARTDRV_InitUart_t uartInit = USART_INIT;
@@ -178,10 +269,15 @@
UARTDRV_Init(sUartHandle, &uartInit);
- for (uint8_t i = 0; i < sizeof(sReceiveBuffer); i++)
- {
- UARTDRV_Receive(sUartHandle, &sReceiveBuffer[i], sizeof(sReceiveBuffer[i]), receiveDone);
- }
+ // When one receive request is completed, the other buffer is used for a separate receive request, issued
+ // immediately.
+ UARTDRV_Receive(sUartHandle, sReceiveBuffer1, RECEIVE_BUFFER_SIZE, receiveDone);
+ UARTDRV_Receive(sUartHandle, sReceiveBuffer2, RECEIVE_BUFFER_SIZE, receiveDone);
+
+ // Enable USART0 interrupt to wake OT task when data arrives
+ NVIC_ClearPendingIRQ(USART_IRQ);
+ NVIC_EnableIRQ(USART_IRQ);
+ USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV);
return OT_ERROR_NONE;
}
@@ -193,14 +289,18 @@
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
- otError error = OT_ERROR_NONE;
+ otError error = OT_ERROR_NONE;
+ Ecode_t status = ECODE_EMDRV_UARTDRV_OK;
- otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY);
+ // Ensure that no ongoing transmits have started finishing.
+ // This prevents queued buffers from being modified before they are transmitted
+ if (sCheckForTxComplete)
+ {
+ otPlatUartFlush();
+ }
- sTransmitBuffer = aBuf;
- sTransmitLength = aBufLength;
-
- UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone);
+ status = UARTDRV_Transmit(sUartHandle, (uint8_t *)aBuf, aBufLength, transmitDone);
+ otEXPECT_ACTION(status == ECODE_EMDRV_UARTDRV_OK, error = OT_ERROR_FAILED);
exit:
return error;
diff --git a/examples/platforms/gp712/CMakeLists.txt b/examples/platforms/gp712/CMakeLists.txt
new file mode 100644
index 0000000..c4c6239
--- /dev/null
+++ b/examples/platforms/gp712/CMakeLists.txt
@@ -0,0 +1,105 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-gp712" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "openthread-core-gp712-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-gp712-config-check.h\""
+)
+
+list(APPEND OT_PLATFORM_DEFINES
+ "_BSD_SOURCE=1"
+ "_DEFAULT_SOURCE=1"
+)
+
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+if(OT_CFLAGS MATCHES "-Wno-c\\+\\+14-compat")
+ string(REPLACE "-Wno-c++14-compat" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-gp712
+ alarm.c
+ diag.c
+ entropy.c
+ flash.c
+ logging.c
+ misc.c
+ radio.c
+ system.c
+ uart-posix.c
+)
+
+set_target_properties(
+ openthread-gp712
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-gp712
+ PRIVATE
+ gp712-driver
+ ${OT_MBEDTLS}
+ ot-config
+ PUBLIC
+ -lrt
+ -pthread
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+)
+
+target_compile_definitions(openthread-gp712
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-gp712
+ PRIVATE
+ ${OT_CFLAGS}
+)
+
+target_include_directories(openthread-gp712
+ PRIVATE
+ ${OT_PUBLIC_INCLUDES}
+ ${PROJECT_SOURCE_DIR}/src/core
+ ${PROJECT_SOURCE_DIR}/examples/platforms
+)
diff --git a/examples/platforms/gp712/Makefile.am b/examples/platforms/gp712/Makefile.am
index 9009d46..706870a 100644
--- a/examples/platforms/gp712/Makefile.am
+++ b/examples/platforms/gp712/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016-2017, The OpenThread Authors.
+# Copyright (c) 2019, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,39 +32,36 @@
override CFLAGS := $(filter-out -Wcast-align,$(CFLAGS))
override CXXFLAGS := $(filter-out -Wcast-align,$(CXXFLAGS))
-lib_LIBRARIES = libopenthread-gp712.a
+lib_LIBRARIES = libopenthread-gp712.a
-libopenthread_gp712_a_CPPFLAGS = \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/examples/platforms \
- -I$(top_srcdir)/src/core \
- -lrt \
- -lpthread \
+libopenthread_gp712_a_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/core \
+ -I$(top_srcdir)/examples/platforms \
+ -I$(top_srcdir)/examples/platforms/gp712 \
+ -lrt \
+ -pthread \
$(NULL)
-PLATFORM_SOURCES = \
- alarm.c \
- alarm_qorvo.h \
- diag.c \
- entropy.c \
- flash.c \
- logging.c \
- misc.c \
- openthread-core-gp712-config.h \
- openthread-core-gp712-config-check.h \
- platform_qorvo.h \
- radio.c \
- radio_qorvo.h \
- random_qorvo.h \
- system.c \
- uart-posix.c \
- uart_qorvo.h \
+PLATFORM_SOURCES = \
+ alarm.c \
+ alarm_qorvo.h \
+ diag.c \
+ entropy.c \
+ flash.c \
+ logging.c \
+ misc.c \
+ openthread-core-gp712-config.h \
+ openthread-core-gp712-config-check.h \
+ platform_qorvo.h \
+ radio.c \
+ radio_qorvo.h \
+ random_qorvo.h \
+ system.c \
+ uart-posix.c \
+ uart_qorvo.h \
$(NULL)
-Dash = -
-libopenthread_gp712_a_LIBADD = \
- $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")
-
libopenthread_gp712_a_SOURCES = \
$(PLATFORM_SOURCES) \
$(NULL)
diff --git a/examples/platforms/gp712/Makefile.platform.am b/examples/platforms/gp712/Makefile.platform.am
index 7a979f6..d7d844f 100644
--- a/examples/platforms/gp712/Makefile.platform.am
+++ b/examples/platforms/gp712/Makefile.platform.am
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, The OpenThread Authors.
+# Copyright (c) 2019, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,5 +32,15 @@
LDADD_COMMON += \
$(top_builddir)/examples/platforms/gp712/libopenthread-gp712.a \
- $(top_srcdir)/third_party/Qorvo/gp712/libQorvoRPi.a \
$(NULL)
+if OPENTHREAD_ENABLE_FTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/gp712/lib/libQorvoGP712_ftd.a \
+ $(NULL)
+else # OPENTHREAD_ENABLE_FTD
+if OPENTHREAD_ENABLE_MTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/gp712/lib/libQorvoGP712_mtd.a \
+ $(NULL)
+endif # OPENTHREAD_ENABLE_MTD
+endif
diff --git a/examples/platforms/gp712/README.md b/examples/platforms/gp712/README.md
index f8d3aec..ceacb88 100644
--- a/examples/platforms/gp712/README.md
+++ b/examples/platforms/gp712/README.md
@@ -4,13 +4,13 @@
## Toolchain
-This example use the GNU GCC toolchain on the Raspberry Pi. To build on the Pi:
+This example uses the GNU GCC toolchain on the Raspberry Pi. To build on the Pi:
1. Download the repo to the Pi
-2. go to the subfolder in the openthread repo: third_party/nlbuild-autotools/repo/tools/packages and enter this command:
+2. go to the subfolder in the openthread repo: third_party/nlbuild-autotools/repo/ and enter this command:
```bash
-$ sudo /bin/bash build
+$ make tools
```
Note that you may need to install additional packages to make this build work, depending on your actual RPi OS version. The build process will complain if additional packages are required.
@@ -26,7 +26,21 @@
After a successful build, the `elf` files are found in `<path-to-openthread>/output/gp712/bin`.
-Building a variant which interfaces via a tcp socket is also possible. Replace the uart-posix.c with uart-socket.c in the Makefile.am from examples/platforms/gp712/Makefile.am and rebuild. Now it should be possible to open a telnet to socket 9190 of the raspberry pi from a remote PC. This also easier testing with the official Thread Test Harness.
+## Cmake build
+
+Make sure arm-linux-gnueabihf-gcc compiler installed in `$PATH`
+
+```bash
+cd <path-to-openthread>
+./script/cmake-build gp712
+```
+
+After a successful build, binary files will be generated:
+
+```
+./build/gp712/examples/apps/ncp/ot-rcp
+./build/gp712/examples/apps/cli/ot-cli-ftd
+```
##
diff --git a/examples/platforms/gp712/alarm.c b/examples/platforms/gp712/alarm.c
index d3c8c0e..a32c83b 100644
--- a/examples/platforms/gp712/alarm.c
+++ b/examples/platforms/gp712/alarm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,10 +40,6 @@
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
-void qorvoAlarmInit(void)
-{
-}
-
uint32_t otPlatAlarmMilliGetNow(void)
{
return qorvoAlarmGetTimeMs();
@@ -59,7 +55,7 @@
OT_UNUSED_VARIABLE(t0);
qorvoAlarmUnScheduleEventArg((qorvoAlarmCallback_t)qorvoAlarmFired, aInstance);
- qorvoAlarmScheduleEventArg(dt * 1000, qorvoAlarmFired, aInstance);
+ qorvoAlarmScheduleEventArg(dt, qorvoAlarmFired, aInstance);
}
void otPlatAlarmMilliStop(otInstance *aInstance)
diff --git a/examples/platforms/gp712/alarm_qorvo.h b/examples/platforms/gp712/alarm_qorvo.h
index 1073d11..c5b5036 100644
--- a/examples/platforms/gp712/alarm_qorvo.h
+++ b/examples/platforms/gp712/alarm_qorvo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/tests/scripts/expect/v1_2-rcp.exp b/examples/platforms/gp712/arm-linux-gnueabihf.cmake
old mode 100755
new mode 100644
similarity index 67%
copy from tests/scripts/expect/v1_2-rcp.exp
copy to examples/platforms/gp712/arm-linux-gnueabihf.cmake
index 776d880..c77a859
--- a/tests/scripts/expect/v1_2-rcp.exp
+++ b/examples/platforms/gp712/arm-linux-gnueabihf.cmake
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,39 +26,18 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
-spawn_node 1
+set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
+set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
+set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as)
+set(CMAKE_RANLIB arm-linux-gnueabihf-ranlib)
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "leader"
-expect "Done"
+set(COMMON_C_FLAGS "-fdata-sections -ffunction-sections")
-send "ipaddr mleid\n"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
-spawn_node 2 mtd
-
-send "panid 0xface\n"
-expect "Done"
-send "mode -\n"
-expect "Done"
-send "csl period 5000\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "child"
-expect "Done"
-send "ping $addr\n"
-expect "16 bytes from $addr: icmp_seq=1"
-
-dispose_all
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=gnu99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_ASM_FLAGS_INIT "${COMMON_C_FLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS}")
diff --git a/examples/platforms/gp712/diag.c b/examples/platforms/gp712/diag.c
index 45b933e..e79c2f2 100644
--- a/examples/platforms/gp712/diag.c
+++ b/examples/platforms/gp712/diag.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
#include <string.h>
#include <sys/time.h>
-#include <openthread/config.h>
+#include <openthread-core-config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
diff --git a/examples/platforms/gp712/entropy.c b/examples/platforms/gp712/entropy.c
index c279955..bf25db5 100644
--- a/examples/platforms/gp712/entropy.c
+++ b/examples/platforms/gp712/entropy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,53 +41,14 @@
#include "utils/code_utils.h"
-#if __SANITIZE_ADDRESS__ != 0
-
-static uint32_t sState = 1;
-
-#endif // __SANITIZE_ADDRESS__
-
void qorvoRandomInit(void)
{
-#if __SANITIZE_ADDRESS__ != 0
-
- sState = (uint32_t)time(NULL);
-
-#endif // __SANITIZE_ADDRESS__
}
-#if __SANITIZE_ADDRESS__ != 0
-
-static uint32_t randomUint32Get(void)
-{
- uint32_t mlcg, p, q;
- uint64_t tmpstate;
-
- tmpstate = (uint64_t)33614 * (uint64_t)sState;
- q = tmpstate & 0xffffffff;
- q = q >> 1;
- p = tmpstate >> 32;
- mlcg = p + q;
-
- if (mlcg & 0x80000000)
- {
- mlcg &= 0x7fffffff;
- mlcg++;
- }
-
- sState = mlcg;
-
- return mlcg;
-}
-
-#endif // __SANITIZE_ADDRESS__
-
otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
{
otError error = OT_ERROR_NONE;
-#if __SANITIZE_ADDRESS__ == 0
-
FILE * file = NULL;
size_t readLength;
@@ -106,26 +67,5 @@
fclose(file);
}
-#else // __SANITIZE_ADDRESS__
-
- /*
- * THE IMPLEMENTATION BELOW IS NOT COMPLIANT WITH THE THREAD SPECIFICATION.
- *
- * Address Sanitizer triggers test failures when reading random
- * values from /dev/urandom. The pseudo-random number generator
- * implementation below is only used to enable continuous
- * integration checks with Address Sanitizer enabled.
- */
- otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS);
-
- for (uint16_t length = 0; length < aOutputLength; length++)
- {
- aOutput[length] = (uint8_t)randomUint32Get();
- }
-
-exit:
-
-#endif // __SANITIZE_ADDRESS__
-
return error;
}
diff --git a/examples/platforms/gp712/flash.c b/examples/platforms/gp712/flash.c
index 1d94a9b..4439952 100644
--- a/examples/platforms/gp712/flash.c
+++ b/examples/platforms/gp712/flash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#include "platform_qorvo.h"
+#undef NDEBUG
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
@@ -38,7 +39,7 @@
#include <sys/stat.h>
#include <unistd.h>
-#include <openthread/config.h>
+#include <openthread-core-config.h>
#include <openthread/platform/flash.h>
static int sFlashFd = -1;
diff --git a/examples/platforms/gp712/logging.c b/examples/platforms/gp712/logging.c
index 6e8d1f7..1b15a79 100644
--- a/examples/platforms/gp712/logging.c
+++ b/examples/platforms/gp712/logging.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
#include "platform_qorvo.h"
#include <openthread-core-config.h>
-#include <openthread/config.h>
#include <ctype.h>
#include <inttypes.h>
@@ -41,16 +40,11 @@
#include <openthread/platform/logging.h>
#include <openthread/platform/toolchain.h>
+#include "uart_qorvo.h"
#include "utils/code_utils.h"
// Macro to append content to end of the log string.
-#define LOG_PRINTF(...) \
- charsWritten = snprintf(&logString[offset], sizeof(logString) - offset, __VA_ARGS__); \
- otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0); \
- offset += (unsigned int)charsWritten; \
- otEXPECT_ACTION(offset < sizeof(logString), logString[sizeof(logString) - 1] = 0)
-
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
int PlatOtLogLevelToSysLogLevel(otLogLevel aLogLevel)
@@ -88,23 +82,10 @@
OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
- OT_UNUSED_VARIABLE(aLogRegion);
-
- char logString[512];
- unsigned int offset;
- int charsWritten;
- va_list args;
-
- offset = 0;
-
+ va_list args;
va_start(args, aFormat);
- charsWritten = vsnprintf(&logString[offset], sizeof(logString) - offset, aFormat, args);
+ qorvoUartLog(aLogLevel, aLogRegion, aFormat, args);
va_end(args);
-
- otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0);
-
-exit:
- syslog(PlatOtLogLevelToSysLogLevel(aLogLevel), "%s", logString);
}
#endif
diff --git a/examples/platforms/gp712/misc.c b/examples/platforms/gp712/misc.c
index 15a297c..b332dc5 100644
--- a/examples/platforms/gp712/misc.c
+++ b/examples/platforms/gp712/misc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/examples/platforms/gp712/openthread-core-gp712-config.h b/examples/platforms/gp712/openthread-core-gp712-config.h
index e71718f..0988e6d 100644
--- a/examples/platforms/gp712/openthread-core-gp712-config.h
+++ b/examples/platforms/gp712/openthread-core-gp712-config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,4 +53,84 @@
*/
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
+ *
+ * Define to 1 if you want to enable software ACK timeout logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+ *
+ * Define to 1 if you want to enable software retransmission logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE
+ *
+ * Define to 1 if you want to enable software CSMA-CA backoff logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ *
+ * Define to 1 if you want to enable software transmission security logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+ *
+ * Define to 1 to enable software transmission target time logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DIAG_ENABLE
+ *
+ * Define as 1 to enable the diag feature.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DIAG_ENABLE
+#define OPENTHREAD_CONFIG_DIAG_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+ *
+ * Define as 1 to enable SPI NCP interface.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
+ *
+ * Define as 1 to enable UART NCP interface.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
+#endif
+
#endif // OPENTHREAD_CORE_GP712_CONFIG_H_
diff --git a/examples/platforms/gp712/platform_qorvo.h b/examples/platforms/gp712/platform_qorvo.h
index b6c7eb3..af657b8 100644
--- a/examples/platforms/gp712/platform_qorvo.h
+++ b/examples/platforms/gp712/platform_qorvo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,6 @@
#define PLATFORM_QORVO_H_
#include <openthread-core-config.h>
-#include <openthread/config.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/examples/platforms/gp712/radio.c b/examples/platforms/gp712/radio.c
index faa5c65..23fb1df 100644
--- a/examples/platforms/gp712/radio.c
+++ b/examples/platforms/gp712/radio.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -77,6 +77,11 @@
static otCachedSettings_t otCachedSettings;
+/* Upper layer relies on txpower could be set before receive, but MAC have per-channel config for it.
+ Store txpower until channel set in Receive(). */
+#define PENDING_TX_POWER_NONE (-1)
+static int8_t pendingTxPower = PENDING_TX_POWER_NONE;
+
static uint8_t sScanstate = 0;
static int8_t sLastReceivedPower = 127;
@@ -152,13 +157,12 @@
otError error = OT_ERROR_INVALID_STATE;
- if (sState == OT_RADIO_STATE_RECEIVE)
+ if (sState == OT_RADIO_STATE_RECEIVE || sState == OT_RADIO_STATE_SLEEP)
{
qorvoRadioSetRxOnWhenIdle(false);
error = OT_ERROR_NONE;
sState = OT_RADIO_STATE_SLEEP;
}
-
return error;
}
@@ -171,6 +175,11 @@
if ((sState != OT_RADIO_STATE_DISABLED) && (sScanstate == 0))
{
qorvoRadioSetCurrentChannel(aChannel);
+ if (pendingTxPower != PENDING_TX_POWER_NONE)
+ {
+ qorvoRadioSetTransmitPower(pendingTxPower);
+ pendingTxPower = PENDING_TX_POWER_NONE;
+ }
error = OT_ERROR_NONE;
}
@@ -186,8 +195,7 @@
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aPacket)
{
- otError err = OT_ERROR_NONE;
-
+ otError err = OT_ERROR_NONE;
pQorvoInstance = aInstance;
otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, err = OT_ERROR_INVALID_STATE);
@@ -226,10 +234,6 @@
sLastReceivedPower = aPacket->mInfo.mRxInfo.mRssi;
}
- // TODO Set this flag only when the packet is really acknowledged with frame pending set.
- // See https://github.com/openthread/openthread/pull/3785
- aPacket->mInfo.mRxInfo.mAckedWithFramePending = true;
-
otPlatRadioReceiveDone(pQorvoInstance, aPacket, aError);
}
@@ -334,20 +338,55 @@
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
{
- // TODO: Create a proper implementation for this driver.
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aPower);
- return OT_ERROR_NOT_IMPLEMENTED;
+ otError result;
+
+ if (aPower == NULL)
+ {
+ return OT_ERROR_INVALID_ARGS;
+ }
+
+ if ((sState == OT_RADIO_STATE_DISABLED) || (sScanstate != 0))
+ {
+ *aPower = (pendingTxPower == PENDING_TX_POWER_NONE) ? 0 : pendingTxPower;
+ return OT_ERROR_NONE;
+ }
+
+ result = qorvoRadioGetTransmitPower(aPower);
+
+ if (result == OT_ERROR_INVALID_STATE)
+ {
+ // Channel was not set, so txpower is ambigious
+ *aPower = (pendingTxPower == PENDING_TX_POWER_NONE) ? 0 : pendingTxPower;
+ return OT_ERROR_NONE;
+ }
+
+ return result;
}
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
{
- // TODO: Create a proper implementation for this driver.
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aPower);
- return OT_ERROR_NOT_IMPLEMENTED;
+ otError result;
+
+ if ((sState == OT_RADIO_STATE_DISABLED) || (sScanstate != 0))
+ {
+ pendingTxPower = aPower;
+ return OT_ERROR_NONE;
+ }
+
+ result = qorvoRadioSetTransmitPower(aPower);
+
+ if (result == OT_ERROR_INVALID_STATE)
+ {
+ // Channel was not set, so txpower is ambigious
+ pendingTxPower = aPower;
+ result = OT_ERROR_NONE;
+ }
+
+ return result;
}
otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
@@ -372,3 +411,9 @@
return GP712_RECEIVE_SENSITIVITY;
}
+
+const char *otPlatRadioGetVersionString(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return "OPENTHREAD/Qorvo/0.0";
+}
diff --git a/examples/platforms/gp712/radio_qorvo.h b/examples/platforms/gp712/radio_qorvo.h
index 0749ee1..573cf0a 100644
--- a/examples/platforms/gp712/radio_qorvo.h
+++ b/examples/platforms/gp712/radio_qorvo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#ifndef RADIO_QORVO_H_
#define RADIO_QORVO_H_
+#include <stdbool.h>
#include <stdint.h>
#include <openthread/error.h>
@@ -174,6 +175,22 @@
otError qorvoRadioClearSrcMatchExtEntry(const uint8_t *aExtAddress, uint16_t panid);
/**
+ * This function gets the transmit power for current channel
+ *
+ * @param[out] aPower The transmit power
+ *
+ */
+otError qorvoRadioGetTransmitPower(int8_t *aPower);
+
+/**
+ * This function sets the transmit power for current channel
+ *
+ * @param[in] aPower The transmit power
+ *
+ */
+otError qorvoRadioSetTransmitPower(int8_t aPower);
+
+/**
* This callback is called when the energy scan is finished.
*
* @param[in] aEnergyScanMaxRssi The amount of energy detected during the ED scan.
diff --git a/examples/platforms/gp712/random_qorvo.h b/examples/platforms/gp712/random_qorvo.h
index 8dd7eef..277019c 100644
--- a/examples/platforms/gp712/random_qorvo.h
+++ b/examples/platforms/gp712/random_qorvo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/examples/platforms/gp712/system.c b/examples/platforms/gp712/system.c
index 3126ad0..147421a 100644
--- a/examples/platforms/gp712/system.c
+++ b/examples/platforms/gp712/system.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,8 +38,9 @@
#include "stdlib.h"
#include <openthread/tasklet.h>
-#include <openthread/platform/uart.h>
+#include "alarm_qorvo.h"
+#include "platform_qorvo.h"
#include "radio_qorvo.h"
#include "random_qorvo.h"
#include "uart_qorvo.h"
@@ -52,7 +53,7 @@
int gArgumentsCount = 0;
char **gArguments = NULL;
-bool qorvoPlatGotoSleepCheck(void)
+uint8_t qorvoPlatGotoSleepCheck(void)
{
bool canGotoSleep = false;
@@ -71,7 +72,7 @@
qorvoPlatInit((qorvoPlatGotoSleepCheckCallback_t)qorvoPlatGotoSleepCheck);
platformUartInit();
- // qorvoAlarmInit();
+ qorvoAlarmInit();
qorvoRandomInit();
qorvoRadioInit();
}
diff --git a/examples/platforms/gp712/uart-posix.c b/examples/platforms/gp712/uart-posix.c
index e98c977..2b37685 100644
--- a/examples/platforms/gp712/uart-posix.c
+++ b/examples/platforms/gp712/uart-posix.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,6 +25,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+#define _XOPEN_SOURCE 500
#include "alarm_qorvo.h"
#include "platform_qorvo.h"
@@ -39,9 +40,8 @@
#include <termios.h>
#include <unistd.h>
-#include <openthread/platform/uart.h>
-
#include "utils/code_utils.h"
+#include "utils/uart.h"
#ifdef __linux__
#include <sys/prctl.h>
@@ -87,6 +87,11 @@
restore_stdin_termios();
restore_stdout_termios();
dup2(s_out_fd, STDOUT_FILENO);
+
+ qorvoPlatUnRegisterPollFunction(s_in_fd);
+ qorvoPlatUnRegisterPollFunction(s_out_fd);
+
+ otPlatUartDisable();
}
void platformUartInit(void)
@@ -95,8 +100,19 @@
s_out_fd = dup(STDOUT_FILENO);
dup2(STDERR_FILENO, STDOUT_FILENO);
+ int res = fcntl(s_in_fd, F_SETFD, fcntl(s_in_fd, F_GETFD) | FD_CLOEXEC);
+ otEXPECT_ACTION(res != -1, perror("fcntl() FD_CLOEXEC failed"));
+
+ res = fcntl(s_out_fd, F_SETFD, fcntl(s_out_fd, F_GETFD) | FD_CLOEXEC);
+ otEXPECT_ACTION(res != -1, perror("fcntl() FD_CLOEXEC failed"));
+
qorvoPlatRegisterPollFunction(s_in_fd, cbKeyPressed);
qorvoPlatRegisterPollFunction(s_out_fd, cbKeyPressed);
+
+ return;
+
+exit:
+ exit(1);
}
otError otPlatUartEnable(void)
@@ -173,14 +189,11 @@
otEXPECT_ACTION(tcsetattr(s_out_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = OT_ERROR_GENERIC);
}
+ return error;
+
exit:
-
- if (error != OT_ERROR_NONE)
- {
- close(s_in_fd);
- close(s_out_fd);
- }
-
+ close(s_in_fd);
+ close(s_out_fd);
return error;
}
@@ -203,13 +216,70 @@
s_write_buffer = aBuf;
s_write_length = aBufLength;
+ qorvoAlarmScheduleEventArg(0, platformDummy, (void *)&s_in_fd);
+
exit:
return error;
}
+void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
+{
+ if (aReadFdSet != NULL)
+ {
+ FD_SET(s_in_fd, aReadFdSet);
+
+ if (aErrorFdSet != NULL)
+ {
+ FD_SET(s_in_fd, aErrorFdSet);
+ }
+
+ if (aMaxFd != NULL && *aMaxFd < s_in_fd)
+ {
+ *aMaxFd = s_in_fd;
+ }
+ }
+
+ if ((aWriteFdSet != NULL) && (s_write_length > 0))
+ {
+ FD_SET(s_out_fd, aWriteFdSet);
+
+ if (aErrorFdSet != NULL)
+ {
+ FD_SET(s_out_fd, aErrorFdSet);
+ }
+
+ if (aMaxFd != NULL && *aMaxFd < s_out_fd)
+ {
+ *aMaxFd = s_out_fd;
+ }
+ }
+}
+
otError otPlatUartFlush(void)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ otError error = OT_ERROR_NONE;
+ ssize_t count;
+
+ otEXPECT_ACTION(s_write_buffer != NULL && s_write_length > 0, error = OT_ERROR_INVALID_STATE);
+
+ while ((count = write(s_out_fd, s_write_buffer, s_write_length)) > 0 && (s_write_length -= count) > 0)
+ {
+ s_write_buffer += count;
+ }
+
+ if (count != -1)
+ {
+ assert(s_write_length == 0);
+ s_write_buffer = NULL;
+ }
+ else
+ {
+ perror("write(UART)");
+ exit(EXIT_FAILURE);
+ }
+
+exit:
+ return error;
}
void platformUartProcess(void)
@@ -254,7 +324,6 @@
perror("read");
exit(EXIT_FAILURE);
}
-
otPlatUartReceived(s_receive_buffer, (uint16_t)rval);
}
@@ -262,19 +331,34 @@
{
rval = write(s_out_fd, s_write_buffer, s_write_length);
- if (rval <= 0)
+ if (rval >= 0)
+ {
+ s_write_buffer += (uint16_t)rval;
+ s_write_length -= (uint16_t)rval;
+
+ if (s_write_length == 0)
+ {
+ otPlatUartSendDone();
+ }
+ }
+ else if (errno != EINTR)
{
perror("write");
exit(EXIT_FAILURE);
}
-
- s_write_buffer += (uint16_t)rval;
- s_write_length -= (uint16_t)rval;
-
- if (s_write_length == 0)
- {
- otPlatUartSendDone();
- }
}
}
}
+
+/**
+ * The weak stubs functions definition.
+ */
+OT_TOOL_WEAK void otPlatUartSendDone(void)
+{
+}
+
+OT_TOOL_WEAK void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ (void)aBuf;
+ (void)aBufLength;
+}
diff --git a/examples/platforms/gp712/uart-socket.c b/examples/platforms/gp712/uart-socket.c
deleted file mode 100644
index b516581..0000000
--- a/examples/platforms/gp712/uart-socket.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (c) 2016-2017, 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 OpenThread platform abstraction for cli over ip socket communication.
- *
- */
-
-#include "alarm_qorvo.h"
-#include "platform_qorvo.h"
-#include "uart_qorvo.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include <netdb.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <pthread.h>
-
-#include <openthread/config.h>
-
-#include <common/code_utils.hpp>
-#include <openthread/platform/uart.h>
-
-#include "utils/code_utils.h"
-
-#define BUFFER_MAX_SIZE 255
-#define SOCKET_PORT 9190
-#define SOCKET_WRITE(socketInfo, buf, length) \
- sendto(socketInfo.socketId, (const char *)buf, length, 0, &socketInfo.addr, sizeof(socketInfo.addr))
-#define SOCKET_READ(socketId, buf, length) recv(socketId, buf, length, 0)
-
-typedef struct
-{
- uint32_t socketId;
- bool isValid;
- struct sockaddr addr;
- pthread_t rfReadThread;
-} PlatSocket_t;
-
-PlatSocket_t PlatSocketConnection;
-int PlatSocketPipeFd[2];
-int PlatServerSocketId;
-
-void PlatSocketRxNewConn(uint8_t id);
-void PlatSocketInit(void);
-void PlatSocketDeInit(void);
-int PlatSocketTxData(uint16_t length, uint8_t *pData, uint32_t socketId);
-
-#define PLAT_UART_MAX_CHAR 1024
-
-uint32_t PlatSocketId = 0;
-
-void PlatSocketSendInput(void *buffer)
-{
- uint8_t len = 0;
- uint8_t *buf = (uint8_t *)buffer;
- len = strlen((char *)buf);
- otPlatUartReceived((uint8_t *)buf, (uint16_t)len);
- free(buf);
- buf = 0;
- len = 0;
-}
-
-void PlatSocketRx(uint16_t length, const char *buffer, uint32_t socketId)
-{
- uint8_t *buf = 0;
- PlatSocketId = socketId;
-
- if (length > 0)
- {
- buf = malloc(length + 2);
- memcpy(buf, buffer, length);
- buf[length] = '\n';
- buf[length + 1] = 0;
- qorvoAlarmScheduleEventArg(0, PlatSocketSendInput, (void *)buf);
- }
-}
-
-void PlatSocketClose(uint32_t socketId)
-{
- OT_UNUSED_VARIABLE(socketId);
-}
-
-otError otPlatUartEnable(void)
-{
- PlatSocketInit();
- return OT_ERROR_NONE;
-}
-
-otError otPlatUartDisable(void)
-{
- PlatSocketDeInit();
- return OT_ERROR_NONE;
-}
-
-otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
-{
- otError error = OT_ERROR_NONE;
- char localbuf[PLAT_UART_MAX_CHAR];
-
- memcpy(localbuf, aBuf, aBufLength);
- localbuf[aBufLength] = 0;
- printf("%s", localbuf);
-
- if (PlatSocketId)
- {
- PlatSocketTxData(aBufLength, (uint8_t *)aBuf, PlatSocketId);
- }
-
- otPlatUartSendDone();
- return error;
-}
-
-otError otPlatUartFlush(void)
-{
- return OT_ERROR_NOT_IMPLEMENTED;
-}
-
-void platformUartInit(void)
-{
-}
-
-void platformUartProcess(void)
-{
-}
-
-int PlatSocketListenForClients()
-{
- // Setup server side socket
- int sockfd;
- struct sockaddr_in serv_addr;
- uint32_t flag = 1;
- int ret;
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- otEXPECT_ACTION(sockfd >= 0, sockfd = -1);
-
- // disable Nagle's algorithm to avoid long latency
- setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
- // allow reuse of the same address
- setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag));
- memset(&serv_addr, 0, sizeof(serv_addr));
-
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(SOCKET_PORT);
- ret = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
- otEXPECT_ACTION(ret >= 0, close(sockfd); sockfd = -1);
- ret = listen(sockfd, 10);
- otEXPECT_ACTION(ret != -1, exit(1));
-exit:
- return sockfd;
-}
-
-void PlatSocketRxSignaled(uint8_t id)
-{
- OT_UNUSED_VARIABLE(id);
-
- // Dummy callback function to flush pipe
- uint8_t readChar;
- // Remove trigger byte from pipe
- read(PlatSocketPipeFd[0], &readChar, 1);
-}
-
-void *PlatSocketReadThread(void *pClientSocket)
-{
- char buffer[BUFFER_MAX_SIZE];
- PlatSocket_t *clientSocket = ((PlatSocket_t *)pClientSocket);
-
- memset(buffer, 0, BUFFER_MAX_SIZE);
-
- while (1)
- {
- int readLen = SOCKET_READ(clientSocket->socketId, buffer, BUFFER_MAX_SIZE);
-
- if (readLen < 0)
- {
- perror("Reading socket");
- break;
- }
- else
- {
- if (readLen == 0)
- {
- break;
- }
-
- {
- uint8_t someByte = 0x12; // No functional use only using pipe to kick main thread
-
- PlatSocketRx(readLen, buffer, clientSocket->socketId);
-
- write(PlatSocketPipeFd[1], &someByte, 1); //[1] = write fd
- }
- }
- }
-
- clientSocket->isValid = 0;
- qorvoPlatUnRegisterPollFunction(clientSocket->socketId);
- close(clientSocket->socketId);
-
- PlatSocketClose(clientSocket->socketId);
-
- return NULL;
-}
-
-void PlatSocketRxNewConn(uint8_t id)
-{
- // Find first non-valid client in list - add here
- if (PlatSocketConnection.isValid == 0)
- {
- // Add new client to client list
- socklen_t len;
- len = sizeof(PlatSocketConnection.addr);
- int retval = accept(id, (struct sockaddr *)&PlatSocketConnection.addr, (socklen_t *)&len);
-
- if (retval >= 0)
- {
- int retErr;
- PlatSocketConnection.socketId = retval;
- retErr =
- pthread_create(&PlatSocketConnection.rfReadThread, NULL, PlatSocketReadThread, &PlatSocketConnection);
-
- if (retErr)
- {
- close(PlatSocketConnection.socketId);
- }
- else
- {
- PlatSocketConnection.isValid = 1;
- }
- }
- }
- else
- {
- int tempfd;
- tempfd = accept(id, (struct sockaddr *)NULL, NULL);
-
- if (tempfd >= 0)
- {
- close(tempfd);
- }
- }
-}
-
-/*****************************************************************************
- * Public Function Definitions
- *****************************************************************************/
-
-void PlatSocketInit(void)
-{
- memset(&PlatSocketConnection, 0, sizeof(PlatSocketConnection));
-
- // in case we are a server, setup listening for client
- PlatServerSocketId = PlatSocketListenForClients();
- qorvoPlatRegisterPollFunction(PlatServerSocketId, PlatSocketRxNewConn);
-
- // hack
- pipe(PlatSocketPipeFd);
- qorvoPlatRegisterPollFunction(PlatSocketPipeFd[0], PlatSocketRxSignaled);
-}
-
-void platformUartRestore(void)
-{
- PlatSocketDeInit();
-}
-
-void PlatSocketDeInit(void)
-{
- qorvoPlatUnRegisterPollFunction(PlatServerSocketId);
- close(PlatServerSocketId);
- qorvoPlatUnRegisterPollFunction(PlatSocketPipeFd[0]);
- close(PlatSocketPipeFd[0]);
- close(PlatSocketPipeFd[1]);
- close(PlatSocketConnection.socketId);
-}
-
-int PlatSocketTxData(uint16_t length, uint8_t *pData, uint32_t socketId)
-{
- int result = -1;
-
- // All sockets
- if (PlatSocketConnection.isValid)
- {
- if (PlatSocketConnection.socketId == socketId)
- {
- if (SOCKET_WRITE(PlatSocketConnection, (const char *)pData, length) < 0)
- {
- perror("TxSocket: Error Writing to client");
- close(PlatSocketConnection.socketId);
- PlatSocketConnection.isValid = 0;
- }
- else
- {
- result = 0;
- }
- }
- }
-
- return result;
-}
diff --git a/examples/platforms/gp712/uart_qorvo.h b/examples/platforms/gp712/uart_qorvo.h
index 3e348bd..ab933d0 100644
--- a/examples/platforms/gp712/uart_qorvo.h
+++ b/examples/platforms/gp712/uart_qorvo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,18 +36,7 @@
#define UART_QORVO_H_
#include <stdint.h>
-
-/**
- * This function initializes the UART driver.
- *
- */
-void qorvoUartInit(void);
-
-/**
- * This function performs UART driver processing.
- *
- */
-void qorvoUartProcess(void);
+#include <openthread/platform/logging.h>
/**
* This function enables the UART driver.
@@ -85,4 +74,15 @@
*/
void qorvoUartSendOutput(const uint8_t *aBuf, uint16_t aBufLength);
+/**
+ * Function which transmits logging via the qorvo platform.
+ *
+ * @param[in] aLogLevel The severity level of logging.
+ * @param[in] aLogRegion The code region where the logging originated from.
+ * @param[in] aFormat The format strings.
+ * @param[in] varargs The arguments for the format string.
+ *
+ */
+void qorvoUartLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...);
+
#endif // UART_QORVO_H_
diff --git a/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h b/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h
index 51f7d27..0d01e7d 100755
--- a/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h
+++ b/examples/platforms/k32w/jn5189/openthread-core-jn5189-config.h
@@ -102,12 +102,12 @@
/* TODO */
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_SETTINGS_RAM
diff --git a/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h b/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h
index c6e877b..874bc8a 100755
--- a/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h
+++ b/examples/platforms/k32w/k32w061/openthread-core-k32w061-config.h
@@ -102,12 +102,12 @@
/* TODO */
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_SETTINGS_RAM
diff --git a/examples/platforms/k32w/src/logging.c b/examples/platforms/k32w/src/logging.c
index af55c2d..39a82c7 100755
--- a/examples/platforms/k32w/src/logging.c
+++ b/examples/platforms/k32w/src/logging.c
@@ -38,7 +38,6 @@
#include <openthread/config.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/toolchain.h>
-#include <openthread/platform/uart.h>
#include "stdio.h"
#include "string.h"
diff --git a/examples/platforms/k32w/src/radio.c b/examples/platforms/k32w/src/radio.c
index 1286d54..f95df25 100755
--- a/examples/platforms/k32w/src/radio.c
+++ b/examples/platforms/k32w/src/radio.c
@@ -203,10 +203,11 @@
E_MMAC_RX_ALIGN_NORMAL | E_MMAC_RX_USE_AUTO_ACK | E_MMAC_RX_NO_MALFORMED |
E_MMAC_RX_NO_FCS_ERROR | E_MMAC_RX_ADDRESS_MATCH;
-tsRxFrameFormat sTxMacFrame; /* TX Frame */
-static tsRxFrameFormat sRxAckFrame; /* Frame used for keeping the ACK */
-static otRadioFrame sRxOtFrame; /* Used for TX/RX frame conversion */
-static uint8 sRxData[OT_RADIO_FRAME_MAX_SIZE]; /* mPsdu buffer for sRxOtFrame */
+tsRxFrameFormat sTxMacFrame; /* TX Frame */
+static tsRxFrameFormat sRxAckFrame; /* Frame used for keeping the ACK */
+static otRadioFrame sRxOtFrame; /* Used for TX/RX frame conversion */
+static uint8 sRxData[OT_RADIO_FRAME_MAX_SIZE]; /* mPsdu buffer for sRxOtFrame */
+static tsRxFrameFormat *pLastRxFrame;
static bool sRadioInitForLp = FALSE;
static bool sPromiscuousEnable = FALSE;
@@ -1277,13 +1278,13 @@
{
if ((pRxFrame = K32WGetFrame(sRxFrame, &sRxFrameIndex)) != NULL)
{
- vMMAC_SetRxFrame(pRxFrame);
- K32WRestartRx();
+ pLastRxFrame = pRxFrame;
+ vMMAC_StartMacReceive(&pRxFrame->sFrameBody, sRxOpt);
}
}
else
{
- K32WRestartRx();
+ vMMAC_StartMacReceive(&pLastRxFrame->sFrameBody, sRxOpt);
}
}
diff --git a/examples/platforms/k32w/src/system.c b/examples/platforms/k32w/src/system.c
index 979014e..9843719 100644
--- a/examples/platforms/k32w/src/system.c
+++ b/examples/platforms/k32w/src/system.c
@@ -32,9 +32,9 @@
*
*/
#include "board.h"
+#include "clock_config.h"
#include "pin_mux.h"
#include "platform-k32w.h"
-#include "openthread/platform/uart.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/examples/platforms/k32w/src/uart.c b/examples/platforms/k32w/src/uart.c
index 53ad84d..55493fa 100755
--- a/examples/platforms/k32w/src/uart.c
+++ b/examples/platforms/k32w/src/uart.c
@@ -40,7 +40,7 @@
/* Openthread general includes */
#include <utils/code_utils.h>
-#include "openthread/platform/uart.h"
+#include <utils/uart.h>
#if USE_RTOS
#include "UART_Serial_Adapter.h"
diff --git a/examples/platforms/kw41z/README.md b/examples/platforms/kw41z/README.md
index 310e84d..7597699 100644
--- a/examples/platforms/kw41z/README.md
+++ b/examples/platforms/kw41z/README.md
@@ -125,4 +125,4 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
diff --git a/examples/platforms/kw41z/openthread-core-kw41z-config.h b/examples/platforms/kw41z/openthread-core-kw41z-config.h
index 923dc03..7e24b8a 100644
--- a/examples/platforms/kw41z/openthread-core-kw41z-config.h
+++ b/examples/platforms/kw41z/openthread-core-kw41z-config.h
@@ -95,11 +95,11 @@
#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE 0
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
#endif // OPENTHREAD_CORE_KW41Z_CONFIG_H_
diff --git a/examples/platforms/kw41z/system.c b/examples/platforms/kw41z/system.c
index 8e0dc27..777bb38 100644
--- a/examples/platforms/kw41z/system.c
+++ b/examples/platforms/kw41z/system.c
@@ -38,7 +38,8 @@
#include "fsl_port.h"
#include "platform-kw41z.h"
#include <stdint.h>
-#include "openthread/platform/uart.h"
+
+#include "utils/uart.h"
otInstance *sInstance;
diff --git a/examples/platforms/kw41z/uart.c b/examples/platforms/kw41z/uart.c
index 226e04e..9b59057 100644
--- a/examples/platforms/kw41z/uart.c
+++ b/examples/platforms/kw41z/uart.c
@@ -37,7 +37,7 @@
#include <stdint.h>
#include <utils/code_utils.h>
-#include "openthread/platform/uart.h"
+#include <utils/uart.h>
#include "fsl_clock.h"
#include "fsl_lpuart.h"
diff --git a/examples/platforms/nrf528xx/CMakeLists.txt b/examples/platforms/nrf528xx/CMakeLists.txt
new file mode 100644
index 0000000..8b474e0
--- /dev/null
+++ b/examples/platforms/nrf528xx/CMakeLists.txt
@@ -0,0 +1,103 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+if(OT_NCP_SPI)
+ list(APPEND OT_PLATFORM_DEFINES "SPIS_AS_SERIAL_TRANSPORT=1")
+else()
+ option(OT_USB "enable nrf USB as serial transport support")
+ if(OT_USB)
+ list(APPEND OT_PLATFORM_DEFINES "USB_CDC_AS_SERIAL_TRANSPORT=1")
+ else()
+ list(APPEND OT_PLATFORM_DEFINES "UART_AS_SERIAL_TRANSPORT=1")
+ endif()
+endif()
+
+set(NRF_COMM_SOURCES
+ src/alarm.c
+ src/diag.c
+ src/entropy.c
+ src/fem.c
+ src/flash.c
+ src/logging.c
+ src/misc.c
+ src/radio.c
+ src/system.c
+ src/temp.c
+)
+
+set(NRF_TRANSPORT_SOURCES
+ src/transport/spi-slave.c
+ src/transport/transport.c
+ src/transport/uart.c
+ src/transport/usb-cdc-uart.c
+)
+
+set(NRF_SINGLEPHY_SOURCES
+ src/flash_nosd.c
+)
+
+set(NRF_SOFTDEVICE_SOURCES
+ src/flash_sd.c
+ src/softdevice.c
+)
+
+set(NRF_INCLUDES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ ${PROJECT_SOURCE_DIR}/examples/platforms
+ ${PROJECT_SOURCE_DIR}/src/core
+)
+
+if(OT_PLATFORM STREQUAL "nrf52811")
+ set(NRF_TRANSPORT_SOURCES
+ src/transport/spi-slave.c
+ src/transport/transport.c
+ src/transport/uart.c
+ )
+ set(NRF52811_3RD_LIBS
+ nordicsemi-nrf52811-radio-driver
+ nordicsemi-nrf52811-sdk
+ jlinkrtt
+ )
+ include(nrf52811/nrf52811.cmake)
+elseif(OT_PLATFORM STREQUAL "nrf52833")
+ set(NRF52833_3RD_LIBS
+ nordicsemi-nrf52833-radio-driver
+ nordicsemi-nrf52833-radio-driver-softdevice
+ nordicsemi-nrf52833-sdk
+ jlinkrtt
+ )
+ include(nrf52833/nrf52833.cmake)
+elseif(OT_PLATFORM STREQUAL "nrf52840")
+ set(NRF52840_3RD_LIBS
+ nordicsemi-nrf52840-radio-driver
+ nordicsemi-nrf52840-radio-driver-softdevice
+ nordicsemi-nrf52840-sdk
+ jlinkrtt
+ )
+ include(nrf52840/nrf52840.cmake)
+endif()
diff --git a/examples/platforms/nrf528xx/nrf52811/Makefile.am b/examples/platforms/nrf528xx/nrf52811/Makefile.am
index 386e152..43803ba 100644
--- a/examples/platforms/nrf528xx/nrf52811/Makefile.am
+++ b/examples/platforms/nrf528xx/nrf52811/Makefile.am
@@ -64,7 +64,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/lp_timer \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/temperature \
- -Wno-unused-parameter \
$(NULL)
# Only reference the SDK header files included in third_party/NordicSemiconductor
@@ -99,7 +98,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/nrfx/drivers/include \
-I$(top_srcdir)/third_party/NordicSemiconductor/nrfx/mdk \
-I$(top_srcdir)/third_party/NordicSemiconductor/nrfx/soc \
- -Wno-unused-parameter \
$(NULL)
endif
diff --git a/examples/platforms/nrf528xx/nrf52811/arm-none-eabi.cmake b/examples/platforms/nrf528xx/nrf52811/arm-none-eabi.cmake
new file mode 100644
index 0000000..a2e520a
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52811/arm-none-eabi.cmake
@@ -0,0 +1,56 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfloat-abi=soft -mthumb -mabi=aapcs -fdata-sections -ffunction-sections")
+
+if(COMPILER_VERSION VERSION_GREATER_EQUAL 7)
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -Wno-expansion-to-defined")
+endif()
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=gnu99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_ASM_FLAGS_INIT "${COMMON_C_FLAGS} -x assembler-with-cpp")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/nrf528xx/nrf52811/nrf52811.cmake b/examples/platforms/nrf528xx/nrf52811/nrf52811.cmake
new file mode 100644
index 0000000..ffe837e
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52811/nrf52811.cmake
@@ -0,0 +1,179 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-nrf52811" "openthread-nrf52811-transport" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/nrf52811/openthread-core-nrf52811-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52811/nrf52811.ld")
+
+set(COMM_FLAGS
+ -DDISABLE_CC310=1
+ -DCONFIG_GPIO_AS_PINRESET
+ -DNRF52811_XXAA
+ -DUSE_APP_CONFIG=1
+ -Wno-unused-parameter
+ -Wno-expansion-to-defined
+)
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-nrf52811-config-check.h\""
+)
+
+list(APPEND OT_PUBLIC_INCLUDES
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/mbedtls_plat_config"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/nrfx/mdk"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/cmsis"
+)
+
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+target_compile_definitions(ot-config INTERFACE
+ "MBEDTLS_USER_CONFIG_FILE=\"nrf52811-mbedtls-config.h\""
+)
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-nrf52811
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+add_library(openthread-nrf52811-transport
+ ${NRF_TRANSPORT_SOURCES}
+)
+
+add_library(openthread-nrf52811-sdk
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-nrf52811 openthread-nrf52811-transport openthread-nrf52811-sdk
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-nrf52811
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52811_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52811-transport
+ PUBLIC
+ ${OT_MBEDTLS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ nordicsemi-nrf52811-sdk
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52811-sdk
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52811_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-nrf52811
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52811-transport
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52811-sdk
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-nrf52811
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DRAAL_SINGLE_PHY=1
+)
+
+target_compile_options(openthread-nrf52811-transport
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+)
+
+target_compile_options(openthread-nrf52811-sdk
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DRAAL_SINGLE_PHY=1
+)
+
+target_include_directories(openthread-nrf52811
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52811
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52811-transport
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52811
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52811-sdk
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52811
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
diff --git a/examples/platforms/nrf528xx/nrf52811/platform-config.h b/examples/platforms/nrf528xx/nrf52811/platform-config.h
index e98954a..660a352 100644
--- a/examples/platforms/nrf528xx/nrf52811/platform-config.h
+++ b/examples/platforms/nrf528xx/nrf52811/platform-config.h
@@ -55,7 +55,7 @@
*
*/
#ifndef RTC_INSTANCE
-#define RTC_INSTANCE NRF_RTC0
+#define RTC_INSTANCE NRF_RTC1
#endif
/**
@@ -65,7 +65,7 @@
*
*/
#ifndef RTC_IRQ_HANDLER
-#define RTC_IRQ_HANDLER RTC0_IRQHandler
+#define RTC_IRQ_HANDLER RTC1_IRQHandler
#endif
/**
@@ -75,7 +75,7 @@
*
*/
#ifndef RTC_IRQN
-#define RTC_IRQN RTC0_IRQn
+#define RTC_IRQN RTC1_IRQn
#endif
/**
diff --git a/examples/platforms/nrf528xx/nrf52833/Makefile.am b/examples/platforms/nrf528xx/nrf52833/Makefile.am
index eb59eb5..21ee117 100644
--- a/examples/platforms/nrf528xx/nrf52833/Makefile.am
+++ b/examples/platforms/nrf528xx/nrf52833/Makefile.am
@@ -66,7 +66,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/lp_timer \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/temperature \
- -Wno-unused-parameter \
$(NULL)
# Only reference the SDK header files included in third_party/NordicSemiconductor
@@ -108,7 +107,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/nrfx/soc \
-I$(top_srcdir)/third_party/NordicSemiconductor/softdevice/s140/headers \
-I$(top_srcdir)/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52 \
- -Wno-unused-parameter \
$(NULL)
endif
@@ -144,6 +142,7 @@
SOFTDEVICE_CPPFLAGS = \
-DSOFTDEVICE_PRESENT \
-DS140 \
+ -Wno-unused-parameter \
$(NULL)
PLATFORM_SOURCES = \
diff --git a/examples/platforms/nrf528xx/nrf52833/arm-none-eabi.cmake b/examples/platforms/nrf528xx/nrf52833/arm-none-eabi.cmake
new file mode 100644
index 0000000..3147abe
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52833/arm-none-eabi.cmake
@@ -0,0 +1,56 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb -mabi=aapcs -fdata-sections -ffunction-sections")
+
+if(COMPILER_VERSION VERSION_GREATER_EQUAL 7)
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -Wno-expansion-to-defined")
+endif()
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=gnu99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_ASM_FLAGS_INIT "${COMMON_C_FLAGS} -x assembler-with-cpp")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/nrf528xx/nrf52833/nrf52833.cmake b/examples/platforms/nrf528xx/nrf52833/nrf52833.cmake
new file mode 100644
index 0000000..659559a
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52833/nrf52833.cmake
@@ -0,0 +1,220 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-nrf52833" "openthread-nrf52833-transport" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/nrf52833/openthread-core-nrf52833-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+option(OT_BOOTLOADER "OT nrf bootloader type")
+if(OT_BOOTLOADER STREQUAL "USB")
+ list(APPEND OT_PLATFORM_DEFINES "APP_USBD_NRF_DFU_TRIGGER_ENABLED=1")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52833/nrf52833_bootloader_usb.ld")
+elseif(OT_BOOTLOADER STREQUAL "UART")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52833/nrf52833_bootloader_uart.ld")
+elseif(OT_BOOTLOADER STREQUAL "BLE")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52833/nrf52833_bootloader_ble.ld")
+else()
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52833/nrf52833.ld")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-nrf52833-config-check.h\""
+)
+list(APPEND OT_PUBLIC_INCLUDES
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/mbedtls_plat_config"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/nrfx/mdk"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/cmsis"
+)
+
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+target_compile_definitions(ot-config INTERFACE
+ "MBEDTLS_USER_CONFIG_FILE=\"nrf52833-mbedtls-config.h\""
+)
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+set(COMM_FLAGS
+ -DDISABLE_CC310=1
+ -DCONFIG_GPIO_AS_PINRESET
+ -DNRF52833_XXAA
+ -DUSE_APP_CONFIG=1
+ -Wno-unused-parameter
+ -Wno-expansion-to-defined
+)
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-nrf52833
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+add_library(openthread-nrf52833-transport
+ ${NRF_TRANSPORT_SOURCES}
+)
+
+add_library(openthread-nrf52833-sdk
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+add_library(openthread-nrf52833-softdevice-sdk
+ ${NRF_COMM_SOURCES}
+ ${NRF_SOFTDEVICE_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-nrf52833 openthread-nrf52833-transport openthread-nrf52833-sdk openthread-nrf52833-softdevice-sdk
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-nrf52833
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52833_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52833-transport
+ PUBLIC
+ ${OT_MBEDTLS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ nordicsemi-nrf52833-sdk
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52833-sdk
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52833_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52833-softdevice-sdk
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52833_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-nrf52833
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52833-transport
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52833-sdk
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52833-softdevice-sdk
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-nrf52833
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+)
+
+target_compile_options(openthread-nrf52833-transport
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+)
+
+target_compile_options(openthread-nrf52833-sdk
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+)
+
+target_compile_options(openthread-nrf52833-softdevice-sdk
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DSOFTDEVICE_PRESENT
+ -DS140
+)
+
+target_include_directories(openthread-nrf52833
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52833
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52833-transport
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52833
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52833-sdk
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52833
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52833-softdevice-sdk
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52833
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
diff --git a/examples/platforms/nrf528xx/nrf52833/openthread-core-nrf52833-config.h b/examples/platforms/nrf528xx/nrf52833/openthread-core-nrf52833-config.h
index e037cd9..14e6991 100644
--- a/examples/platforms/nrf528xx/nrf52833/openthread-core-nrf52833-config.h
+++ b/examples/platforms/nrf528xx/nrf52833/openthread-core-nrf52833-config.h
@@ -221,7 +221,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS
-#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 2048
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 4000
#endif
/**
diff --git a/examples/platforms/nrf528xx/nrf52840/Makefile.am b/examples/platforms/nrf528xx/nrf52840/Makefile.am
index 6062fa4..863775b 100644
--- a/examples/platforms/nrf528xx/nrf52840/Makefile.am
+++ b/examples/platforms/nrf528xx/nrf52840/Makefile.am
@@ -66,7 +66,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/rsch/raal/softdevice \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/lp_timer \
-I$(top_srcdir)/third_party/NordicSemiconductor/drivers/radio/platform/temperature \
- -Wno-unused-parameter \
$(NULL)
# Only reference the SDK header files included in third_party/NordicSemiconductor
@@ -108,7 +107,6 @@
-I$(top_srcdir)/third_party/NordicSemiconductor/nrfx/soc \
-I$(top_srcdir)/third_party/NordicSemiconductor/softdevice/s140/headers \
-I$(top_srcdir)/third_party/NordicSemiconductor/softdevice/s140/headers/nrf52 \
- -Wno-unused-parameter \
$(NULL)
endif
@@ -145,6 +143,7 @@
SOFTDEVICE_CPPFLAGS = \
-DSOFTDEVICE_PRESENT \
-DS140 \
+ -Wno-unused-parameter \
$(NULL)
PLATFORM_SOURCES = \
@@ -154,7 +153,7 @@
libopenthread_nrf52840_a_CPPFLAGS = \
$(COMMONCPPFLAGS) \
$(SINGLEPHY_CPPFLAGS) \
- -DPLATFORM_OPENTHREAD_VANILLA \
+ -DPLATFORM_OPENTHREAD_VANILLA \
$(NULL)
libopenthread_nrf52840_a_SOURCES = \
diff --git a/examples/platforms/nrf528xx/nrf52840/README.md b/examples/platforms/nrf528xx/nrf52840/README.md
index b105709..4b8c5c8 100644
--- a/examples/platforms/nrf528xx/nrf52840/README.md
+++ b/examples/platforms/nrf528xx/nrf52840/README.md
@@ -135,11 +135,13 @@
When building an external application with OpenThread libraries and CryptoCell 310 hardware acceleration, use the following configuration:
- Crypto libraries:
- - `third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedcrypto_cc310_backend.a`
- - `third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_tls_vanilla.a`
- - `third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_x509_vanilla.a`
- - `third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_base_vanilla.a`
- - `third_party/NordicSemiconductor/libraries/nrf_security/lib/libnrf_cc310_platform_0.9.2.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedcrypto_shared.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_tls_vanilla.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_x509_vanilla.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedcrypto_cc3xx.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libnrf_cc310_platform_0.9.4.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedcrypto_oberon.a`
+ - `/third_party/NordicSemiconductor/libraries/nrf_security/lib/libmbedtls_base_vanilla.a`
- Include directories:
- `third_party/NordicSemiconductor/libraries/nrf_security/mbedtls_platform_config`
- `third_party/NordicSemiconductor/libraries/nrf_security/include`
diff --git a/examples/platforms/nrf528xx/nrf52840/arm-none-eabi.cmake b/examples/platforms/nrf528xx/nrf52840/arm-none-eabi.cmake
new file mode 100644
index 0000000..3147abe
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52840/arm-none-eabi.cmake
@@ -0,0 +1,56 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_SYSTEM_PROCESSOR ARM)
+
+set(CMAKE_C_COMPILER arm-none-eabi-gcc)
+set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
+set(CMAKE_ASM_COMPILER arm-none-eabi-as)
+set(CMAKE_RANLIB arm-none-eabi-ranlib)
+
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+set(COMMON_C_FLAGS "-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb -mabi=aapcs -fdata-sections -ffunction-sections")
+
+if(COMPILER_VERSION VERSION_GREATER_EQUAL 7)
+ set(COMMON_C_FLAGS "${COMMON_C_FLAGS} -Wno-expansion-to-defined")
+endif()
+
+set(CMAKE_C_FLAGS_INIT "${COMMON_C_FLAGS} -std=gnu99")
+set(CMAKE_CXX_FLAGS_INIT "${COMMON_C_FLAGS} -fno-exceptions -fno-rtti")
+set(CMAKE_ASM_FLAGS_INIT "${COMMON_C_FLAGS} -x assembler-with-cpp")
+set(CMAKE_EXE_LINKER_FLAGS_INIT "${COMMON_C_FLAGS} -specs=nano.specs -specs=nosys.specs")
+
+set(CMAKE_C_FLAGS_DEBUG "-Og -g")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
+set(CMAKE_ASM_FLAGS_DEBUG "-g")
+
+set(CMAKE_C_FLAGS_RELEASE "-Os")
+set(CMAKE_CXX_FLAGS_RELEASE "-Os")
+set(CMAKE_ASM_FLAGS_RELEASE "")
diff --git a/examples/platforms/nrf528xx/nrf52840/nrf52840.cmake b/examples/platforms/nrf528xx/nrf52840/nrf52840.cmake
new file mode 100644
index 0000000..fcf1a65
--- /dev/null
+++ b/examples/platforms/nrf528xx/nrf52840/nrf52840.cmake
@@ -0,0 +1,233 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-nrf52840" "openthread-nrf52840-transport" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/nrf52840/openthread-core-nrf52840-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+option(OT_BOOTLOADER "OT nrf bootloader type")
+if(OT_BOOTLOADER STREQUAL "USB")
+ list(APPEND OT_PLATFORM_DEFINES "APP_USBD_NRF_DFU_TRIGGER_ENABLED=1")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52840/nrf52840_bootloader_usb.ld")
+elseif(OT_BOOTLOADER STREQUAL "UART")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52840/nrf52840_bootloader_uart.ld")
+elseif(OT_BOOTLOADER STREQUAL "BLE")
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52840/nrf52840_bootloader_ble.ld")
+else()
+ set(LD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/nrf52840/nrf52840.ld")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-nrf52840-config-check.h\""
+)
+if(NOT OT_EXTERNAL_MBEDTLS)
+ if(OT_MBEDTLS_THREADING)
+ list(APPEND OT_PLATFORM_DEFINES "MBEDTLS_THREADING_C")
+ list(APPEND OT_PLATFORM_DEFINES "MBEDTLS_THREADING_ALT")
+ list(APPEND OT_PUBLIC_INCLUDES
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/include/software-only-threading"
+ )
+ endif()
+else()
+ list(APPEND OT_PLATFORM_DEFINES "MBEDTLS_CONFIG_FILE=\"nrf-config.h\"")
+ list(APPEND OT_PUBLIC_INCLUDES
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/include"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/config"
+ "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/nrf_cc310_plat/include"
+ )
+endif()
+
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+target_compile_definitions(ot-config INTERFACE
+ "MBEDTLS_USER_CONFIG_FILE=\"nrf52840-mbedtls-config.h\""
+)
+list(APPEND OT_PUBLIC_INCLUDES "${PROJECT_SOURCE_DIR}/third_party/NordicSemiconductor/libraries/nrf_security/mbedtls_plat_config")
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+set(COMM_FLAGS
+ -DCONFIG_GPIO_AS_PINRESET
+ -DNRF52840_XXAA
+ -DUSE_APP_CONFIG=1
+ -Wno-unused-parameter
+ -Wno-expansion-to-defined
+)
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-nrf52840
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+add_library(openthread-nrf52840-transport
+ ${NRF_TRANSPORT_SOURCES}
+)
+
+add_library(openthread-nrf52840-sdk
+ ${NRF_COMM_SOURCES}
+ ${NRF_SINGLEPHY_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+add_library(openthread-nrf52840-softdevice-sdk
+ ${NRF_COMM_SOURCES}
+ ${NRF_SOFTDEVICE_SOURCES}
+ $<TARGET_OBJECTS:openthread-platform-utils>
+)
+
+set_target_properties(openthread-nrf52840 openthread-nrf52840-transport openthread-nrf52840-sdk openthread-nrf52840-softdevice-sdk
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-nrf52840
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52840_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52840-transport
+ PUBLIC
+ ${OT_MBEDTLS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ nordicsemi-nrf52840-sdk
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52840-sdk
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52840_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_link_libraries(openthread-nrf52840-softdevice-sdk
+ PUBLIC
+ ${OT_MBEDTLS}
+ ${NRF52840_3RD_LIBS}
+ -T${LD_FILE}
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ PRIVATE
+ ot-config
+)
+
+target_compile_definitions(openthread-nrf52840
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52840-transport
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52840-sdk
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_definitions(openthread-nrf52840-softdevice-sdk
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-nrf52840
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DPLATFORM_OPENTHREAD_VANILLA
+)
+
+target_compile_options(openthread-nrf52840-transport
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DPLATFORM_OPENTHREAD_VANILLA
+)
+
+target_compile_options(openthread-nrf52840-sdk
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+)
+
+target_compile_options(openthread-nrf52840-softdevice-sdk
+ PRIVATE
+ ${OT_CFLAGS}
+ ${COMM_FLAGS}
+ -DSOFTDEVICE_PRESENT
+ -DS140
+)
+
+target_include_directories(openthread-nrf52840
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52840
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52840-transport
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52840
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52840-sdk
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52840
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
+
+target_include_directories(openthread-nrf52840-softdevice-sdk
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/nrf52840
+ ${NRF_INCLUDES}
+ ${OT_PUBLIC_INCLUDES}
+)
diff --git a/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h b/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h
index 3150c16..2ca2f20 100644
--- a/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h
+++ b/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h
@@ -221,7 +221,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS
-#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 2048
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 4000
#endif
/**
diff --git a/examples/platforms/nrf528xx/src/platform-nrf5.h b/examples/platforms/nrf528xx/src/platform-nrf5.h
index e93e757..2034a2f 100644
--- a/examples/platforms/nrf528xx/src/platform-nrf5.h
+++ b/examples/platforms/nrf528xx/src/platform-nrf5.h
@@ -199,4 +199,10 @@
int8_t nrf5GetChannelMaxTransmitPower(uint8_t aChannel);
+/**
+ * Callback function for region changed.
+ *
+ */
+void nrf5HandleRegionChanged(uint16_t aRegionCode);
+
#endif // PLATFORM_NRF5_H_
diff --git a/examples/platforms/nrf528xx/src/radio.c b/examples/platforms/nrf528xx/src/radio.c
index 71abf52..9368f56 100644
--- a/examples/platforms/nrf528xx/src/radio.c
+++ b/examples/platforms/nrf528xx/src/radio.c
@@ -45,12 +45,12 @@
#include "common/code_utils.hpp"
#include "utils/code_utils.h"
+#include "utils/link_metrics.h"
#include "utils/mac_frame.h"
#include <platform-config.h>
#include <openthread/platform/alarm-micro.h>
#include <openthread/platform/diag.h>
-#include <openthread/platform/logging.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/time.h>
@@ -108,18 +108,20 @@
static otRadioFrame sAckFrame;
static bool sAckedWithFramePending;
-static int8_t sMaxTxPowerTable[OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1];
-static int8_t sDefaultTxPower;
-static int8_t sLnaGain = 0;
+static int8_t sMaxTxPowerTable[OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1];
+static int8_t sDefaultTxPower;
+static int8_t sLnaGain = 0;
+static uint16_t sRegionCode = 0;
static uint32_t sEnergyDetectionTime;
static uint8_t sEnergyDetectionChannel;
static int8_t sEnergyDetected;
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-static uint32_t sCslPeriod;
-static uint32_t sCslSampleTime;
-static const uint8_t sCslIeHeader[OT_IE_HEADER_SIZE] = {CSL_IE_HEADER_BYTES_LO, CSL_IE_HEADER_BYTES_HI};
+static uint32_t sCslPeriod;
+static uint32_t sCslSampleTime;
+static const uint32_t sCslSampleDur = OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW * OT_US_PER_TEN_SYMBOLS;
+static const uint8_t sCslIeHeader[OT_IE_HEADER_SIZE] = {CSL_IE_HEADER_BYTES_LO, CSL_IE_HEADER_BYTES_HI};
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
typedef enum
@@ -194,6 +196,16 @@
aTo[1] = (uint8_t)(aFrom >> 8);
}
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+static void convertExtAddress(uint8_t *aTo, const otExtAddress *aFrom)
+{
+ for (uint8_t i = 0; i < sizeof(otExtAddress); i++)
+ {
+ aTo[i] = aFrom->m8[sizeof(otExtAddress) - i - 1];
+ }
+}
+#endif
+
static inline bool isPendingEventSet(RadioPendingEvents aEvent)
{
return sPendingEvents & (1UL << aEvent);
@@ -1056,14 +1068,30 @@
{
uint32_t curTime = otPlatAlarmMicroGetNow();
uint32_t cslPeriodInUs = sCslPeriod * OT_US_PER_TEN_SYMBOLS;
- uint32_t diff = (cslPeriodInUs - (curTime % cslPeriodInUs) + (sCslSampleTime % cslPeriodInUs)) % cslPeriodInUs;
-
+ uint32_t diff =
+ (cslPeriodInUs - (curTime % cslPeriodInUs) + (sCslSampleTime % cslPeriodInUs) + (sCslSampleDur / 2)) %
+ cslPeriodInUs;
return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS + 1);
}
#endif
-void nrf_802154_tx_ack_started(uint8_t *p_data)
+void nrf_802154_tx_ack_started(uint8_t *p_data, int8_t power, uint8_t lqi)
{
+ otRadioFrame ackFrame;
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ uint8_t linkMetricsDataLen = 0;
+ uint8_t linkMetricsData[OT_ENH_PROBING_IE_DATA_MAX_SIZE];
+ otMacAddress macAddress;
+#else
+ OT_UNUSED_VARIABLE(power);
+ OT_UNUSED_VARIABLE(lqi);
+#endif
+
+ OT_UNUSED_VARIABLE(ackFrame);
+
+ ackFrame.mPsdu = (uint8_t *)(p_data + 1);
+ ackFrame.mLength = p_data[0];
+
// Check if the frame pending bit is set in ACK frame.
sAckedWithFramePending = p_data[FRAME_PENDING_OFFSET] & FRAME_PENDING_BIT;
@@ -1072,13 +1100,18 @@
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
- otRadioFrame ackFrame;
- ackFrame.mPsdu = (uint8_t *)(p_data + 1);
- ackFrame.mLength = p_data[0];
otMacFrameSetCslIe(&ackFrame, sCslPeriod, getCslPhase());
}
#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ otMacFrameGetDstAddr(&ackFrame, &macAddress);
+ if ((linkMetricsDataLen = otLinkMetricsEnhAckGenData(&macAddress, lqi, power, linkMetricsData)) > 0)
+ {
+ otMacFrameSetEnhAckProbingIe(&ackFrame, linkMetricsData, linkMetricsDataLen);
+ }
+#endif
+
txAckProcessSecurity(p_data);
#endif
}
@@ -1089,6 +1122,7 @@
uint8_t aLqi,
uint32_t ack_time)
{
+ OT_UNUSED_VARIABLE(aFrame); // For ARM gcc
assert(aFrame == sTransmitPsdu);
if (aAckPsdu == NULL)
@@ -1113,6 +1147,7 @@
void nrf_802154_transmit_failed(const uint8_t *aFrame, nrf_802154_tx_error_t error)
{
+ OT_UNUSED_VARIABLE(aFrame); // For ARM gcc
assert(aFrame == sTransmitPsdu);
switch (error)
@@ -1153,7 +1188,9 @@
void nrf_802154_tx_started(const uint8_t *aFrame)
{
bool processSecurity = false;
+
assert(aFrame == sTransmitPsdu);
+ OT_UNUSED_VARIABLE(aFrame);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
@@ -1262,49 +1299,66 @@
}
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-static void updateIeData(otInstance *aInstance, const uint8_t *aShortAddr, const uint8_t *aExtAddr)
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+static void updateIeData(otInstance *aInstance, otShortAddress aShortAddr, const otExtAddress *aExtAddr)
{
+ OT_UNUSED_VARIABLE(aInstance);
+
int8_t offset = 0;
uint8_t ackIeData[OT_ACK_IE_MAX_SIZE];
+ uint8_t extAddr[OT_EXT_ADDRESS_SIZE];
+ uint8_t shortAddr[SHORT_ADDRESS_SIZE];
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ uint8_t enhAckProbingDataLen = 0;
+ otMacAddress macAddress;
+ macAddress.mType = OT_MAC_ADDRESS_TYPE_SHORT;
+ macAddress.mAddress.mShortAddress = aShortAddr;
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
memcpy(ackIeData, sCslIeHeader, OT_IE_HEADER_SIZE);
offset += OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE; // reserve space for CSL IE
}
+#endif
+
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ if ((enhAckProbingDataLen = otLinkMetricsEnhAckGetDataLen(&macAddress)) > 0)
+ {
+ offset += otMacFrameGenerateEnhAckProbingIe(ackIeData + offset, NULL, enhAckProbingDataLen);
+ }
+#endif
+
+ convertShortAddress(shortAddr, aShortAddr);
+ convertExtAddress(extAddr, aExtAddr);
if (offset > 0)
{
- nrf_802154_ack_data_set(aShortAddr, false, ackIeData, offset, NRF_802154_ACK_DATA_IE);
- nrf_802154_ack_data_set(aExtAddr, true, ackIeData, offset, NRF_802154_ACK_DATA_IE);
+ nrf_802154_ack_data_set(shortAddr, false, ackIeData, offset, NRF_802154_ACK_DATA_IE);
+ nrf_802154_ack_data_set(extAddr, true, ackIeData, offset, NRF_802154_ACK_DATA_IE);
}
else
{
- nrf_802154_ack_data_clear(aShortAddr, false, NRF_802154_ACK_DATA_IE);
- nrf_802154_ack_data_clear(aExtAddr, true, NRF_802154_ACK_DATA_IE);
+ nrf_802154_ack_data_clear(shortAddr, false, NRF_802154_ACK_DATA_IE);
+ nrf_802154_ack_data_clear(extAddr, true, NRF_802154_ACK_DATA_IE);
}
}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, const otExtAddress *aExtAddr)
{
otError error = OT_ERROR_NONE;
- uint8_t parentExtAddr[OT_EXT_ADDRESS_SIZE];
- uint8_t parentShortAddress[SHORT_ADDRESS_SIZE];
- const uint8_t *shortAddress;
+ otShortAddress shortAddress;
sCslPeriod = aCslPeriod;
- for (uint32_t i = 0; i < sizeof(parentExtAddr); i++)
- {
- parentExtAddr[i] = aExtAddr->m8[sizeof(parentExtAddr) - i - 1];
- }
+ shortAddress = nrf_802154_pib_short_address_get()[1]
+ << 8; // Don't need the other byte because this is parent's short address
+ shortAddress &= 0xfc00;
- shortAddress = nrf_802154_pib_short_address_get();
- memcpy(parentShortAddress, shortAddress, SHORT_ADDRESS_SIZE);
- parentShortAddress[0] &= 0xfc;
-
- updateIeData(aInstance, parentShortAddress, parentExtAddr);
+ updateIeData(aInstance, shortAddress, aExtAddr);
return error;
}
@@ -1324,8 +1378,17 @@
const otExtAddress * aExtAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aLinkMetrics);
+ OT_UNUSED_VARIABLE(aShortAddress);
+ OT_UNUSED_VARIABLE(aExtAddress);
- return OT_ERROR_NOT_IMPLEMENTED;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics));
+ updateIeData(aInstance, aShortAddress, aExtAddress);
+
+exit:
+ return error;
}
#endif
@@ -1362,3 +1425,29 @@
return power;
}
+
+otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ sRegionCode = aRegionCode;
+ nrf5HandleRegionChanged(aRegionCode);
+ return OT_ERROR_NONE;
+}
+
+otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aRegionCode != NULL, error = OT_ERROR_INVALID_ARGS);
+
+ *aRegionCode = sRegionCode;
+exit:
+ return error;
+}
+
+OT_TOOL_WEAK void nrf5HandleRegionChanged(uint16_t aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aRegionCode);
+}
diff --git a/examples/platforms/nrf528xx/src/transport/transport.c b/examples/platforms/nrf528xx/src/transport/transport.c
index 2ffe205..074be88 100644
--- a/examples/platforms/nrf528xx/src/transport/transport.c
+++ b/examples/platforms/nrf528xx/src/transport/transport.c
@@ -40,6 +40,8 @@
void nrf5TransportInit(bool aPseudoReset)
{
+ OT_UNUSED_VARIABLE(aPseudoReset);
+
#if ((UART_AS_SERIAL_TRANSPORT == 1) || (USB_CDC_AS_SERIAL_TRANSPORT == 1))
if (!aPseudoReset)
{
@@ -52,13 +54,14 @@
#endif
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
- OT_UNUSED_VARIABLE(aPseudoReset);
nrf5SpiSlaveInit();
#endif
}
void nrf5TransportDeinit(bool aPseudoReset)
{
+ OT_UNUSED_VARIABLE(aPseudoReset);
+
#if ((UART_AS_SERIAL_TRANSPORT == 1) || (USB_CDC_AS_SERIAL_TRANSPORT == 1))
if (!aPseudoReset)
{
@@ -67,7 +70,6 @@
#endif
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
- OT_UNUSED_VARIABLE(aPseudoReset);
nrf5SpiSlaveDeinit();
#endif
}
diff --git a/examples/platforms/nrf528xx/src/transport/uart.c b/examples/platforms/nrf528xx/src/transport/uart.c
index 8fc18fb..7c1c607 100644
--- a/examples/platforms/nrf528xx/src/transport/uart.c
+++ b/examples/platforms/nrf528xx/src/transport/uart.c
@@ -39,8 +39,8 @@
#include <stdint.h>
#include <utils/code_utils.h>
+#include <utils/uart.h>
#include <openthread/platform/toolchain.h>
-#include <openthread/platform/uart.h>
#include "openthread-system.h"
diff --git a/examples/platforms/nrf528xx/src/transport/usb-cdc-uart.c b/examples/platforms/nrf528xx/src/transport/usb-cdc-uart.c
index ec3a006..a05c41a 100644
--- a/examples/platforms/nrf528xx/src/transport/usb-cdc-uart.c
+++ b/examples/platforms/nrf528xx/src/transport/usb-cdc-uart.c
@@ -46,10 +46,10 @@
#include <common/logging.hpp>
#include <openthread-system.h>
#include <utils/code_utils.h>
+#include <utils/uart.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/diag.h>
#include <openthread/platform/misc.h>
-#include <openthread/platform/uart.h>
#include "platform-nrf5-transport.h"
diff --git a/examples/platforms/qpg6095/CMakeLists.txt b/examples/platforms/qpg6095/CMakeLists.txt
index b59202a..36c8622 100644
--- a/examples/platforms/qpg6095/CMakeLists.txt
+++ b/examples/platforms/qpg6095/CMakeLists.txt
@@ -80,9 +80,10 @@
${OT_MBEDTLS}
ot-config
PUBLIC
- -T${CMAKE_CURRENT_SOURCE_DIR}/qpg6095.ld
+ -T${PROJECT_SOURCE_DIR}/third_party/Qorvo/repo/qpg6095/ld/qpg6095.ld
+ -nostdlib
-Wl,--gc-sections
- -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map,--cref
)
target_compile_definitions(openthread-qpg6095
diff --git a/examples/platforms/qpg6095/Makefile.am b/examples/platforms/qpg6095/Makefile.am
index b9122d4..1778da6 100644
--- a/examples/platforms/qpg6095/Makefile.am
+++ b/examples/platforms/qpg6095/Makefile.am
@@ -32,45 +32,49 @@
override CFLAGS := $(filter-out -Wcast-align,$(CFLAGS))
override CXXFLAGS := $(filter-out -Wcast-align,$(CXXFLAGS))
-lib_LIBRARIES = libopenthread-qpg6095.a
+lib_LIBRARIES = libopenthread-qpg6095.a
-libopenthread_qpg6095_a_CPPFLAGS = \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/examples/platforms \
- -I$(top_srcdir)/examples/platforms/utils \
- -I$(top_srcdir)/src/core \
- -lrt \
- -lpthread \
+libopenthread_qpg6095_a_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/core \
+ -I$(top_srcdir)/examples/platforms \
+ -I$(top_srcdir)/examples/platforms/utils \
+ -I$(top_srcdir)/examples/platforms/qpg6095 \
+ -lrt \
+ -lpthread \
$(NULL)
-CLEANFILES =
-
-libopenthread_qpg6095_a_SOURCES = \
- alarm.c \
- alarm_qorvo.h \
- diag.c \
- entropy.c \
- logging.c \
- misc.c \
- misc_qorvo.h \
- openthread-core-qpg6095-config.h \
- openthread-core-qpg6095-config-check.h \
- platform.c \
- platform_qorvo.h \
- radio.c \
- radio_qorvo.h \
- random_qorvo.h \
- settings.cpp \
- settings_qorvo.h \
- uart.c \
- uart_qorvo.h \
+PLATFORM_SOURCES = \
+ alarm.c \
+ alarm_qorvo.h \
+ diag.c \
+ entropy.c \
+ logging.c \
+ misc.c \
+ misc_qorvo.h \
+ openthread-core-qpg6095-config.h \
+ openthread-core-qpg6095-config-check.h \
+ platform.c \
+ platform_qorvo.h \
+ radio.c \
+ radio_qorvo.h \
+ random_qorvo.h \
+ settings.cpp \
+ settings_qorvo.h \
+ uart.c \
+ uart_qorvo.h \
$(NULL)
-libopenthread_qpg6095_a_LIBADD = \
- $(top_builddir)/examples/platforms/utils/libopenthread_platform_utils_a-settings_ram.o
+libopenthread_qpg6095_a_SOURCES = \
+ $(PLATFORM_SOURCES) \
+ $(NULL)
+
+Dash = -
+libopenthread_qpg6095_a_LIBADD = \
+ $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")
if OPENTHREAD_BUILD_COVERAGE
-CLEANFILES += $(wildcard *.gcda *.gcno)
+CLEANFILES = $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/examples/platforms/qpg6095/Makefile.platform.am b/examples/platforms/qpg6095/Makefile.platform.am
index 0184c9e..5a433f1 100644
--- a/examples/platforms/qpg6095/Makefile.platform.am
+++ b/examples/platforms/qpg6095/Makefile.platform.am
@@ -30,12 +30,20 @@
# qpg6095 platform-specific Makefile
#
-LDADD_COMMON += \
- $(top_builddir)/examples/platforms/qpg6095/libopenthread-qpg6095.a \
- $(top_srcdir)/third_party/Qorvo/qpg6095/libQorvoQPG6095.a \
+LDADD_COMMON += \
+ $(top_builddir)/examples/platforms/qpg6095/libopenthread-qpg6095.a \
$(NULL)
-
-LDFLAGS_COMMON += \
- -T $(top_srcdir)/examples/platforms/qpg6095/qpg6095.ld \
+if OPENTHREAD_ENABLE_FTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg6095/lib/libQorvoQPG6095_ftd.a \
$(NULL)
-
+else # OPENTHREAD_ENABLE_FTD
+if OPENTHREAD_ENABLE_MTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg6095/lib/libQorvoQPG6095_mtd.a \
+ $(NULL)
+endif # OPENTHREAD_ENABLE_MTD
+endif
+LDFLAGS_COMMON += \
+ -T $(top_srcdir)/third_party/Qorvo/repo/qpg6095/ld/qpg6095.ld \
+ $(NULL)
diff --git a/examples/platforms/qpg6095/arm-none-eabi.cmake b/examples/platforms/qpg6095/arm-none-eabi.cmake
index de1ed14..fc54b18 100644
--- a/examples/platforms/qpg6095/arm-none-eabi.cmake
+++ b/examples/platforms/qpg6095/arm-none-eabi.cmake
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
diff --git a/examples/platforms/qpg6095/crypto/qpg6095-mbedtls-config.h b/examples/platforms/qpg6095/crypto/qpg6095-mbedtls-config.h
index 95c23b8..f04c0c0 100644
--- a/examples/platforms/qpg6095/crypto/qpg6095-mbedtls-config.h
+++ b/examples/platforms/qpg6095/crypto/qpg6095-mbedtls-config.h
@@ -25,3 +25,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
+
+#ifndef QGP6095_MBEDTLS_CONFIG_H
+#define QGP6095_MBEDTLS_CONFIG_H
+/* enable this to speed up crypto calculations by using a ram patch for bignum.c */
+#define MBEDTLS_BIGNUM_RAMPATCH 0
+
+/* enable this in case the QPG6095 runs too slow for the crypto calculations */
+#define MBEDTLS_SLOW_CPU 1
+#define MBEDTLS_COMPUTATION_UNTILL_SEQ_NR 6
+
+#include "mbedtls/check_config.h"
+
+#endif // QGP6095_MBEDTLS_CONFIG_H
diff --git a/examples/platforms/qpg6095/diag.c b/examples/platforms/qpg6095/diag.c
index 27f541d..e79c2f2 100644
--- a/examples/platforms/qpg6095/diag.c
+++ b/examples/platforms/qpg6095/diag.c
@@ -26,16 +26,17 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "platform_qorvo.h"
-
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
-#include <openthread/config.h>
+#include <openthread-core-config.h>
+#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/radio.h>
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+
/**
* Diagnostics mode variables.
*
@@ -73,3 +74,5 @@
{
OT_UNUSED_VARIABLE(aInstance);
}
+
+#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
diff --git a/examples/platforms/qpg6095/entropy.c b/examples/platforms/qpg6095/entropy.c
index 39936d0..e7a989d 100644
--- a/examples/platforms/qpg6095/entropy.c
+++ b/examples/platforms/qpg6095/entropy.c
@@ -39,26 +39,11 @@
#include <common/code_utils.hpp>
#include <openthread/platform/radio.h>
-#define GP_COMPONENT_ID GP_COMPONENT_ID_APP
-
-// uint8_t pseudoRandom = 0x34;
-
-void qorvoRandomInit(void)
-{
- // pseudoRandom += (uint8_t) (seed&0xFF);
-}
-
otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
{
otError error = OT_ERROR_NONE;
assert(aOutputLength < 256);
- // uint8_t i;
qorvoRandomGet((uint8_t *)aOutput, (uint8_t)aOutputLength);
- // for(i=0; i<aOutputLength; i++)
- // {
- // aOutput[i] = pseudoRandom;
- // pseudoRandom = (pseudoRandom * 97 + 1)%256;
- // }
return error;
}
diff --git a/examples/platforms/qpg6095/logging.c b/examples/platforms/qpg6095/logging.c
index de5ab3f..b703ecb 100644
--- a/examples/platforms/qpg6095/logging.c
+++ b/examples/platforms/qpg6095/logging.c
@@ -39,8 +39,6 @@
#include "uart_qorvo.h"
#include "utils/code_utils.h"
-// Macro to append content to end of the log string.
-
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
diff --git a/examples/platforms/qpg6095/openthread-core-qpg6095-config.h b/examples/platforms/qpg6095/openthread-core-qpg6095-config.h
index 03720ce..e6e644b 100644
--- a/examples/platforms/qpg6095/openthread-core-qpg6095-config.h
+++ b/examples/platforms/qpg6095/openthread-core-qpg6095-config.h
@@ -50,12 +50,4 @@
*/
#define OPENTHREAD_CONFIG_PLATFORM_INFO "QPG6095"
-/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
- *
- * Define to 1 to enable NCP UART support.
- *
- */
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
-
#endif // OPENTHREAD_CORE_QPG6095_CONFIG_H_
diff --git a/examples/platforms/qpg6095/platform.c b/examples/platforms/qpg6095/platform.c
index 6ea68aa..53aafb2 100644
--- a/examples/platforms/qpg6095/platform.c
+++ b/examples/platforms/qpg6095/platform.c
@@ -38,14 +38,17 @@
#include "random_qorvo.h"
#include "uart_qorvo.h"
#include <openthread/tasklet.h>
-#include <openthread/platform/uart.h>
#include "stdio.h"
#include "stdlib.h"
static otInstance *localInstance = NULL;
-bool qorvoPlatGotoSleepCheck(void)
+#ifdef QORVO_USE_ROM
+extern void flash_jump_gpJumpTables_GetRomVersion(void);
+#endif // QORVO_USE_ROM
+
+uint8_t qorvoPlatGotoSleepCheck(void)
{
if (localInstance)
{
@@ -61,7 +64,11 @@
{
OT_UNUSED_VARIABLE(argc);
OT_UNUSED_VARIABLE(argv);
+#ifdef QORVO_USE_ROM
+ flash_jump_gpJumpTables_GetRomVersion();
+#endif // QORVO_USE_ROM
qorvoPlatInit((qorvoPlatGotoSleepCheckCallback_t)qorvoPlatGotoSleepCheck);
+ qorvoUartInit();
qorvoAlarmInit();
qorvoRandomInit();
qorvoRadioInit();
diff --git a/examples/platforms/qpg6095/platform_qorvo.h b/examples/platforms/qpg6095/platform_qorvo.h
index 1afb173..85eb380 100644
--- a/examples/platforms/qpg6095/platform_qorvo.h
+++ b/examples/platforms/qpg6095/platform_qorvo.h
@@ -38,7 +38,7 @@
#include <stdbool.h>
#include <stdint.h>
-typedef bool (*qorvoPlatGotoSleepCheckCallback_t)(void);
+typedef uint8_t (*qorvoPlatGotoSleepCheckCallback_t)(void);
/**
* This function initializes the platform.
diff --git a/examples/platforms/qpg6095/qpg6095.ld b/examples/platforms/qpg6095/qpg6095.ld
deleted file mode 100644
index aa61a2d..0000000
--- a/examples/platforms/qpg6095/qpg6095.ld
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-/* Memory Spaces Definitions */
-MEMORY
-{
- SYSRAM (rxw) : ORIGIN = 0x20008000, LENGTH = 0x8000
- UCRAM (rxw) : ORIGIN = 0x20010000, LENGTH = 0x8000
- FLASH (rx) : ORIGIN = 0x04000000, LENGTH = 0x80000
-}
-
-SECTIONS
-{
- flash_end = 0x4000000 + 0x80000;
- .vpp 0x0400001C : { LONG(_ivt >> 8); } > FLASH
- .mw 0x04000020 : { LONG(0x693A5C81); } > FLASH
- rts_start_offset = 0x200;
- rts_start_address = ORIGIN(FLASH) + rts_start_offset;
- .rt rts_start_address : {. = ALIGN(4); *(.rt_flash); } > FLASH
- .isr_vector : ALIGN(0x800) { _ivt = .; KEEP(*(.isr_vector)); } > FLASH
-
- __exidx_start = .;
- .text : { . = ALIGN(4); *(.text) *(.text.*); } > FLASH
- .rodata : { . = ALIGN(4); *(.rodata) *(.rodata.*); } > FLASH
- __exidx_end = .;
-
- _slower_retain = ORIGIN(SYSRAM) ; /* Start retained memory in sleep */
-
- /* Fixed sections */
- .mw_crc 0x20008000 : { . += 0x4; } > SYSRAM
- .crc 0x20008004 : { . += 0x4; } > SYSRAM
- .ret_hw 0x20008008 : { . += 0x138; } > SYSRAM
- .ret_sw 0x20008140 : { . += 0x80; } > SYSRAM
-
- /* Windowed sections */
- .ram_regmap : { . += 0x140; } > SYSRAM
- .events : { . += 0x10 ; } > SYSRAM
- .pbm_options : { . += 0x400 ; } > SYSRAM
-
- .lower_ram_retain_gpmicro_accessible (NOLOAD) : { . = ALIGN(4); *(.lower_ram_retain_gpmicro_accessible) *(.lower_ram_retain_gpmicro_accessible.*); } > SYSRAM
- .lower_ram_retain (NOLOAD) : { . = ALIGN(4); *(.lower_ram_retain) *(.lower_ram_retain.*); } > SYSRAM
-
- .bss : { . = ALIGN(4); *(.bss) *(COMMON);} > SYSRAM
-
- _elower_retain = . ; /* End memory to be retained */
- .lower_ram_noretain (NOLOAD) : { . = ALIGN(4); *(.lower_ram_noretain) *(.lower_ram_noretain.*); } > SYSRAM
- _elower_ram = . ;
-
- . = ORIGIN(UCRAM);
-
- PROVIDE(_shigher_retain = .);
- .higher_ram_retain (NOLOAD) : { . = ALIGN(4); *(.higher_ram_retain) *(.higher_ram_retain.*); } > UCRAM
- PROVIDE(_ehigher_retain = .);
- .higher_ram_noretain (NOLOAD) : { . = ALIGN(4); *(.higher_ram_noretain) *(.higher_ram_noretain.*); } > UCRAM
- .data : { . = ALIGN(4); *(.data) *(.data.*); } > UCRAM AT > FLASH
- .bss_uc : { . = ALIGN(4); *(.bss.*) ;} > UCRAM
- _ehigher_ram = . ;
-
- /* remove the debugging information from the standard libraries */
- /DISCARD/ : {
- libc.a ( * )
- libm.a ( * )
- libgcc.a ( * )
- }
-
- .gpNvm flash_end - 0x4000:
- {
- gpNvm_Start = . ;
- . = 0x4000 ;
- gpNvm_End = . ;
- } > FLASH
-
- _etext = ADDR(.text) + SIZEOF(.text);
- _sidata = LOADADDR(.data);
- _sdata = ADDR(.data);
- _edata = ADDR(.data) + ALIGN(SIZEOF(.data), 4);
- _ldata = _edata - _sdata;
- _sbss = ADDR(.bss);
- _ebss = ADDR(.bss) + ALIGN(SIZEOF(.bss), 4);
- _lbss = _ebss - _sbss;
- /* use UCRAM for stack */
- _sstack = _ehigher_ram;
- _estack = ORIGIN(UCRAM) + LENGTH(UCRAM);
- _sbss_uc = ADDR(.bss_uc);
- _ebss_uc = ADDR(.bss_uc) + ALIGN(SIZEOF(.bss_uc), 4);
- _lbss_uc = _ebss_uc - _sbss_uc;
-
- __configured_stack_size = 0x1200;
- __stack_size = _estack - _sstack;
- ASSERT(__stack_size >= __configured_stack_size, "STACK too small")
-
- _elower_ram = ADDR(.lower_ram_retain) + ALIGN(SIZEOF(.lower_ram_retain), 4);
- __lowerram_retain_size = _elower_retain - _slower_retain;
-
- __higherram_retain_size = SIZEOF(.higher_ram_retain);
-
- sw_retention_begin = ADDR(.ret_sw);
- sw_retention_end = ADDR(.ret_sw) + SIZEOF(.ret_sw);
- ram_regmap_begin = ADDR(.ram_regmap);
- events_begin = ADDR(.events);
- pbm_options_begin = ADDR(.pbm_options);
-
- total_nr_of_events_as_an_address = SIZEOF(.events) / 16;
-}
-
-ENTRY(reset_handler)
-
diff --git a/examples/platforms/qpg6095/radio.c b/examples/platforms/qpg6095/radio.c
index 2376214..873588a 100644
--- a/examples/platforms/qpg6095/radio.c
+++ b/examples/platforms/qpg6095/radio.c
@@ -32,14 +32,15 @@
*
*/
-#include "radio_qorvo.h"
-
#include <string.h>
-#include <common/logging.hpp>
#include <openthread/platform/diag.h>
#include <openthread/platform/radio.h>
+#include "utils/code_utils.h"
+
+#include "radio_qorvo.h"
+
enum
{
QPG6095_RECEIVE_SENSITIVITY = -100, // dBm
@@ -67,42 +68,34 @@
extern otRadioFrame sTransmitFrame;
static otRadioState sState;
-// static bool sIsReceiverEnabled = false;
-static otInstance *pQorvoInstance;
+static otInstance * pQorvoInstance;
typedef struct otCachedSettings_s
{
uint16_t panid;
} otCachedSettings_t;
+
static otCachedSettings_t otCachedSettings;
-static uint8_t scanstate = 0;
+/* Upper layer relies on txpower could be set before receive, but MAC have per-channel config for it.
+ Store txpower until channel set in Receive(). */
+#define PENDING_TX_POWER_NONE (-1)
+static int8_t pendingTxPower = PENDING_TX_POWER_NONE;
-/*****************************************************************************
- * Static Function Prototypes
- *****************************************************************************/
-
-/*****************************************************************************
- * Static Data Definitions
- *****************************************************************************/
-
-/*****************************************************************************
- * Static Function Definitions
- *****************************************************************************/
-
-/*****************************************************************************
- * Public Function Definitions
- *****************************************************************************/
+static uint8_t sScanstate = 0;
+static int8_t sLastReceivedPower = 127;
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
{
OT_UNUSED_VARIABLE(aInstance);
+
qorvoRadioGetIeeeEui64(aIeeeEui64);
}
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid)
{
OT_UNUSED_VARIABLE(aInstance);
+
qorvoRadioSetPanId(panid);
otCachedSettings.panid = panid;
}
@@ -110,19 +103,22 @@
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *address)
{
OT_UNUSED_VARIABLE(aInstance);
+
qorvoRadioSetExtendedAddress(address->m8);
}
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t address)
{
OT_UNUSED_VARIABLE(aInstance);
+
qorvoRadioSetShortAddress(address);
}
bool otPlatRadioIsEnabled(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
- return (sState != OT_RADIO_STATE_DISABLED) ? true : false;
+
+ return (sState != OT_RADIO_STATE_DISABLED);
}
otError otPlatRadioEnable(otInstance *aInstance)
@@ -141,40 +137,52 @@
otError otPlatRadioDisable(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
- if (otPlatRadioIsEnabled(aInstance))
+
+ otEXPECT(otPlatRadioIsEnabled(aInstance));
+
+ if (sState == OT_RADIO_STATE_RECEIVE)
{
- if (sState == OT_RADIO_STATE_RECEIVE)
- {
- qorvoRadioSetRxOnWhenIdle(false);
- }
- sState = OT_RADIO_STATE_DISABLED;
+ qorvoRadioSetRxOnWhenIdle(false);
}
+ sState = OT_RADIO_STATE_DISABLED;
+
+exit:
return OT_ERROR_NONE;
}
otError otPlatRadioSleep(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
- if (sState == OT_RADIO_STATE_RECEIVE)
+
+ otError error = OT_ERROR_INVALID_STATE;
+
+ if (sState == OT_RADIO_STATE_RECEIVE || sState == OT_RADIO_STATE_SLEEP)
{
qorvoRadioSetRxOnWhenIdle(false);
+ error = OT_ERROR_NONE;
sState = OT_RADIO_STATE_SLEEP;
}
-
- return OT_ERROR_NONE;
+ return error;
}
otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
{
- otError error = OT_ERROR_INVALID_STATE;
+ otError error = OT_ERROR_INVALID_STATE;
+
pQorvoInstance = aInstance;
- if ((sState != OT_RADIO_STATE_DISABLED) && (scanstate == 0))
+ if ((sState != OT_RADIO_STATE_DISABLED) && (sScanstate == 0))
{
qorvoRadioSetCurrentChannel(aChannel);
+ if (pendingTxPower != PENDING_TX_POWER_NONE)
+ {
+ qorvoRadioSetTransmitPower(pendingTxPower);
+ pendingTxPower = PENDING_TX_POWER_NONE;
+ }
error = OT_ERROR_NONE;
}
+
if (sState == OT_RADIO_STATE_SLEEP)
{
qorvoRadioSetRxOnWhenIdle(true);
@@ -187,14 +195,16 @@
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aPacket)
{
+ otError err = OT_ERROR_NONE;
+
pQorvoInstance = aInstance;
- if (sState == OT_RADIO_STATE_DISABLED)
- {
- return OT_ERROR_INVALID_STATE;
- }
+ otEXPECT_ACTION(sState != OT_RADIO_STATE_DISABLED, err = OT_ERROR_INVALID_STATE);
- return qorvoRadioTransmit(aPacket);
+ err = qorvoRadioTransmit(aPacket);
+
+exit:
+ return err;
}
void cbQorvoRadioTransmitDone(otRadioFrame *aPacket, bool aFramePending, otError aError)
@@ -220,9 +230,10 @@
void cbQorvoRadioReceiveDone(otRadioFrame *aPacket, otError aError)
{
- // TODO Set this flag only when the packet is really acknowledged with frame pending set.
- // See https://github.com/openthread/openthread/pull/3785
- aPacket->mInfo.mRxInfo.mAckedWithFramePending = true;
+ if (aError == OT_ERROR_NONE)
+ {
+ sLastReceivedPower = aPacket->mInfo.mRxInfo.mRssi;
+ }
otPlatRadioReceiveDone(pQorvoInstance, aPacket, aError);
}
@@ -230,24 +241,28 @@
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
return &sTransmitFrame;
}
int8_t otPlatRadioGetRssi(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
- return 0;
+
+ return sLastReceivedPower;
}
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_TRANSMIT_RETRIES;
}
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
return false;
}
@@ -260,36 +275,42 @@
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
{
OT_UNUSED_VARIABLE(aInstance);
+
qorvoRadioEnableSrcMatch(aEnable);
}
otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+
return qorvoRadioAddSrcMatchShortEntry(aShortAddress, otCachedSettings.panid);
}
otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+
return qorvoRadioAddSrcMatchExtEntry(aExtAddress->m8, otCachedSettings.panid);
}
otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, uint16_t aShortAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+
return qorvoRadioClearSrcMatchShortEntry(aShortAddress, otCachedSettings.panid);
}
otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
{
OT_UNUSED_VARIABLE(aInstance);
+
return qorvoRadioClearSrcMatchExtEntry(aExtAddress->m8, otCachedSettings.panid);
}
void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
/* clear both short and extended addresses here */
qorvoRadioClearSrcMatchEntries();
}
@@ -297,6 +318,7 @@
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
/* not implemented */
/* assumes clearing of short and extended entries is done simultaniously by the openthread stack */
}
@@ -304,36 +326,75 @@
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
{
OT_UNUSED_VARIABLE(aInstance);
- scanstate = 1;
+
+ sScanstate = 1;
return qorvoRadioEnergyScan(aScanChannel, aScanDuration);
}
void cbQorvoRadioEnergyScanDone(int8_t aEnergyScanMaxRssi)
{
- scanstate = 0;
+ sScanstate = 0;
otPlatRadioEnergyScanDone(pQorvoInstance, aEnergyScanMaxRssi);
}
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
{
- // TODO: Create a proper implementation for this driver.
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aPower);
- return OT_ERROR_NOT_IMPLEMENTED;
+
+ otError result;
+
+ if (aPower == NULL)
+ {
+ return OT_ERROR_INVALID_ARGS;
+ }
+
+ if ((sState == OT_RADIO_STATE_DISABLED) || (sScanstate != 0))
+ {
+ *aPower = (pendingTxPower == PENDING_TX_POWER_NONE) ? 0 : pendingTxPower;
+ return OT_ERROR_NONE;
+ }
+
+ result = qorvoRadioGetTransmitPower(aPower);
+
+ if (result == OT_ERROR_INVALID_STATE)
+ {
+ // Channel was not set, so txpower is ambigious
+ *aPower = (pendingTxPower == PENDING_TX_POWER_NONE) ? 0 : pendingTxPower;
+ return OT_ERROR_NONE;
+ }
+
+ return result;
}
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
{
- // TODO: Create a proper implementation for this driver.
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aPower);
- return OT_ERROR_NOT_IMPLEMENTED;
+
+ otError result;
+
+ if ((sState == OT_RADIO_STATE_DISABLED) || (sScanstate != 0))
+ {
+ pendingTxPower = aPower;
+ return OT_ERROR_NONE;
+ }
+
+ result = qorvoRadioSetTransmitPower(aPower);
+
+ if (result == OT_ERROR_INVALID_STATE)
+ {
+ // Channel was not set, so txpower is ambigious
+ pendingTxPower = aPower;
+ result = OT_ERROR_NONE;
+ }
+
+ return result;
}
otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aThreshold);
+
return OT_ERROR_NOT_IMPLEMENTED;
}
@@ -341,11 +402,19 @@
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aThreshold);
+
return OT_ERROR_NOT_IMPLEMENTED;
}
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+
return QPG6095_RECEIVE_SENSITIVITY;
}
+
+const char *otPlatRadioGetVersionString(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return "OPENTHREAD/Qorvo/0.0";
+}
diff --git a/examples/platforms/qpg6095/radio_qorvo.h b/examples/platforms/qpg6095/radio_qorvo.h
index 678a096..573cf0a 100644
--- a/examples/platforms/qpg6095/radio_qorvo.h
+++ b/examples/platforms/qpg6095/radio_qorvo.h
@@ -37,6 +37,8 @@
#include <stdbool.h>
#include <stdint.h>
+
+#include <openthread/error.h>
#include <openthread/platform/radio.h>
/**
@@ -173,6 +175,22 @@
otError qorvoRadioClearSrcMatchExtEntry(const uint8_t *aExtAddress, uint16_t panid);
/**
+ * This function gets the transmit power for current channel
+ *
+ * @param[out] aPower The transmit power
+ *
+ */
+otError qorvoRadioGetTransmitPower(int8_t *aPower);
+
+/**
+ * This function sets the transmit power for current channel
+ *
+ * @param[in] aPower The transmit power
+ *
+ */
+otError qorvoRadioSetTransmitPower(int8_t aPower);
+
+/**
* This callback is called when the energy scan is finished.
*
* @param[in] aEnergyScanMaxRssi The amount of energy detected during the ED scan.
diff --git a/examples/platforms/qpg6095/settings.cpp b/examples/platforms/qpg6095/settings.cpp
index a6e4e44..6dff98d 100644
--- a/examples/platforms/qpg6095/settings.cpp
+++ b/examples/platforms/qpg6095/settings.cpp
@@ -38,6 +38,7 @@
#include "openthread/platform/settings.h"
#include <utils/code_utils.h>
+#include <utils/settings.h>
#include "settings_qorvo.h"
diff --git a/examples/platforms/qpg6095/uart.c b/examples/platforms/qpg6095/uart.c
index c5336a2..5f3d1aa 100644
--- a/examples/platforms/qpg6095/uart.c
+++ b/examples/platforms/qpg6095/uart.c
@@ -41,7 +41,8 @@
#define HAVE__BOOL 1
#include <common/code_utils.hpp>
-#include <openthread/platform/uart.h>
+
+#include "utils/uart.h"
otError otPlatUartEnable(void)
{
@@ -78,3 +79,13 @@
{
otPlatUartSendDone();
}
+
+OT_TOOL_WEAK void otPlatUartSendDone(void)
+{
+}
+
+OT_TOOL_WEAK void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ OT_UNUSED_VARIABLE(aBuf);
+ OT_UNUSED_VARIABLE(aBufLength);
+}
diff --git a/examples/platforms/qpg6095/uart_qorvo.h b/examples/platforms/qpg6095/uart_qorvo.h
index 7803648..c827741 100644
--- a/examples/platforms/qpg6095/uart_qorvo.h
+++ b/examples/platforms/qpg6095/uart_qorvo.h
@@ -40,12 +40,6 @@
#include <openthread/platform/logging.h>
/**
- * This function performs UART driver processing.
- *
- */
-void qorvoUartProcess(void);
-
-/**
* This function enables the UART driver.
*
*/
diff --git a/examples/platforms/qpg6100/CMakeLists.txt b/examples/platforms/qpg6100/CMakeLists.txt
new file mode 100644
index 0000000..efa778b
--- /dev/null
+++ b/examples/platforms/qpg6100/CMakeLists.txt
@@ -0,0 +1,104 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-qpg6100" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "openthread-core-qpg6100-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-qpg6100-config-check.h\""
+)
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+target_compile_definitions(ot-config INTERFACE "MBEDTLS_USER_CONFIG_FILE=\"qpg6100-mbedtls-config.h\"")
+
+list(APPEND OT_PUBLIC_INCLUDES
+ "${CMAKE_CURRENT_SOURCE_DIR}/crypto"
+)
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+if(OT_CFLAGS MATCHES "-Wno-c\\+\\+14-compat")
+ string(REPLACE "-Wno-c++14-compat" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-qpg6100
+ alarm.c
+ diag.c
+ entropy.c
+ logging.c
+ misc.c
+ platform.c
+ radio.c
+ settings.cpp
+ uart.c
+)
+
+set_target_properties(
+ openthread-qpg6100
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-qpg6100
+ PRIVATE
+ qpg6100-driver
+ ${OT_MBEDTLS}
+ ot-config
+ PUBLIC
+ -T${PROJECT_SOURCE_DIR}/third_party/Qorvo/repo/qpg6100/ld/qpg6100.ld
+ -nostdlib
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map,--cref
+)
+
+target_compile_definitions(openthread-qpg6100
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-qpg6100
+ PRIVATE
+ ${OT_CFLAGS}
+)
+
+target_include_directories(openthread-qpg6100
+ PRIVATE
+ ${OT_PUBLIC_INCLUDES}
+ ${PROJECT_SOURCE_DIR}/src/core
+ ${PROJECT_SOURCE_DIR}/examples/platforms
+)
diff --git a/examples/platforms/qpg6100/Makefile.am b/examples/platforms/qpg6100/Makefile.am
new file mode 100644
index 0000000..8e98877
--- /dev/null
+++ b/examples/platforms/qpg6100/Makefile.am
@@ -0,0 +1,80 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
+
+# Do not enable -Wcast-align for this platform
+override CFLAGS := $(filter-out -Wcast-align,$(CFLAGS))
+override CXXFLAGS := $(filter-out -Wcast-align,$(CXXFLAGS))
+
+lib_LIBRARIES = libopenthread-qpg6100.a
+
+libopenthread_qpg6100_a_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/core \
+ -I$(top_srcdir)/examples/platforms \
+ -I$(top_srcdir)/examples/platforms/utils \
+ -I$(top_srcdir)/examples/platforms/qpg6100 \
+ -lrt \
+ -lpthread \
+ $(NULL)
+
+PLATFORM_SOURCES = \
+ alarm.c \
+ alarm_qorvo.h \
+ diag.c \
+ entropy.c \
+ logging.c \
+ misc.c \
+ misc_qorvo.h \
+ openthread-core-qpg6100-config.h \
+ openthread-core-qpg6100-config-check.h \
+ platform.c \
+ platform_qorvo.h \
+ radio.c \
+ radio_qorvo.h \
+ random_qorvo.h \
+ settings.cpp \
+ settings_qorvo.h \
+ uart.c \
+ uart_qorvo.h \
+ $(NULL)
+
+libopenthread_qpg6100_a_SOURCES = \
+ $(PLATFORM_SOURCES) \
+ $(NULL)
+
+Dash = -
+libopenthread_qpg6100_a_LIBADD = \
+ $(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")
+
+if OPENTHREAD_BUILD_COVERAGE
+CLEANFILES = $(wildcard *.gcda *.gcno)
+endif # OPENTHREAD_BUILD_COVERAGE
+
+include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/examples/platforms/qpg6100/Makefile.platform.am b/examples/platforms/qpg6100/Makefile.platform.am
new file mode 100644
index 0000000..559980f
--- /dev/null
+++ b/examples/platforms/qpg6100/Makefile.platform.am
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+#
+# qpg6100 platform-specific Makefile
+#
+
+LDADD_COMMON += \
+ $(top_builddir)/examples/platforms/qpg6100/libopenthread-qpg6100.a \
+ $(NULL)
+if OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg6100/lib/libmbedtls_alt.a \
+ $(NULL)
+endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
+if OPENTHREAD_ENABLE_FTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg6100/lib/libQorvoQPG6100_ftd.a \
+ $(NULL)
+else # OPENTHREAD_ENABLE_FTD
+if OPENTHREAD_ENABLE_MTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg6100/lib/libQorvoQPG6100_mtd.a \
+ $(NULL)
+endif # OPENTHREAD_ENABLE_MTD
+endif
+LDFLAGS_COMMON += \
+ -T $(top_srcdir)/third_party/Qorvo/repo/qpg6100/ld/qpg6100.ld \
+ $(NULL)
diff --git a/examples/platforms/qpg6100/alarm.c b/examples/platforms/qpg6100/alarm.c
new file mode 120000
index 0000000..b6f42ba
--- /dev/null
+++ b/examples/platforms/qpg6100/alarm.c
@@ -0,0 +1 @@
+../qpg6095/alarm.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/alarm_qorvo.h b/examples/platforms/qpg6100/alarm_qorvo.h
new file mode 120000
index 0000000..c9bb615
--- /dev/null
+++ b/examples/platforms/qpg6100/alarm_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/alarm_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/arm-none-eabi.cmake b/examples/platforms/qpg6100/arm-none-eabi.cmake
new file mode 120000
index 0000000..de6f304
--- /dev/null
+++ b/examples/platforms/qpg6100/arm-none-eabi.cmake
@@ -0,0 +1 @@
+../qpg6095/arm-none-eabi.cmake
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/crypto/aes_alt.h b/examples/platforms/qpg6100/crypto/aes_alt.h
new file mode 100644
index 0000000..f67cf47
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/aes_alt.h
@@ -0,0 +1,230 @@
+/**
+ * \file aes_alt.h
+ *
+ * \brief AES block cipher
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_AES_ALT_H
+#define MBEDTLS_AES_ALT_H
+
+#if defined(MBEDTLS_AES_ALT)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief AES context structure
+ *
+ * \note buf is able to hold 32 extra bytes, which can be used:
+ * - for alignment purposes if VIA padlock is used, and/or
+ * - to simplify key expansion in the 256-bit case by
+ * generating an extra round key
+ */
+typedef struct
+{
+ uint32_t buf[68]; /*!< unaligned data */
+ unsigned char key[32]; /*!< internal copy of the key */
+ unsigned int keysize; /*!< size in bytes of the key */
+} mbedtls_aes_context;
+
+/**
+ * \brief Initialize AES context
+ *
+ * \param ctx AES context to be initialized
+ */
+void mbedtls_aes_init(mbedtls_aes_context *ctx);
+
+/**
+ * \brief Clear AES context
+ *
+ * \param ctx AES context to be cleared
+ */
+void mbedtls_aes_free(mbedtls_aes_context *ctx);
+
+/**
+ * \brief AES key schedule (encryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key encryption key
+ * \param keybits must be 128, 192 or 256
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits);
+
+/**
+ * \brief AES key schedule (decryption)
+ *
+ * \param ctx AES context to be initialized
+ * \param key decryption key
+ * \param keybits must be 128, 192 or 256
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
+ */
+int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits);
+
+/**
+ * \brief AES-ECB block encryption/decryption
+ *
+ * \param ctx AES context
+ * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param input 16-byte input block
+ * \param output 16-byte output block
+ *
+ * \return 0 if successful
+ */
+int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]);
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+/**
+ * \brief AES-CBC buffer encryption/decryption
+ * Length should be a multiple of the block
+ * size (16 bytes)
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx AES context
+ * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
+ */
+int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char * output);
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+/**
+ * \brief AES-CFB128 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx AES context
+ * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param length length of the input data
+ * \param iv_off offset in IV (updated after use)
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx,
+ int mode,
+ size_t length,
+ size_t * iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char * output);
+
+/**
+ * \brief AES-CFB8 buffer encryption/decryption.
+ *
+ * Note: Due to the nature of CFB you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \note Upon exit, the content of the IV is updated so that you can
+ * call the function same function again on the following
+ * block(s) of data and get the same result as if it was
+ * encrypted in one call. This allows a "streaming" usage.
+ * If on the other hand you need to retain the contents of the
+ * IV, you should either save it manually or use the cipher
+ * module instead.
+ *
+ * \param ctx AES context
+ * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
+ * \param length length of the input data
+ * \param iv initialization vector (updated after use)
+ * \param input buffer holding the input data
+ * \param output buffer holding the output data
+ *
+ * \return 0 if successful
+ */
+int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx,
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char * output);
+#endif /*MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+/**
+ * \brief AES-CTR buffer encryption/decryption
+ *
+ * Warning: You have to keep the maximum use of your counter in mind!
+ *
+ * Note: Due to the nature of CTR you should use the same key schedule for
+ * both encryption and decryption. So a context initialized with
+ * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+ *
+ * \param ctx AES context
+ * \param length The length of the data
+ * \param nc_off The offset in the current stream_block (for resuming
+ * within current cipher stream). The offset pointer to
+ * should be 0 at the start of a stream.
+ * \param nonce_counter The 128-bit nonce and counter.
+ * \param stream_block The saved stream-block for resuming. Is overwritten
+ * by the function.
+ * \param input The input data stream
+ * \param output The output data stream
+ *
+ * \return 0 if successful
+ */
+int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,
+ size_t length,
+ size_t * nc_off,
+ unsigned char nonce_counter[16],
+ unsigned char stream_block[16],
+ const unsigned char *input,
+ unsigned char * output);
+#endif /* MBEDTLS_CIPHER_MODE_CTR */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_AES_ALT */
+
+#endif /* aes_alt.h */
diff --git a/examples/platforms/qpg6100/crypto/ccm_alt.h b/examples/platforms/qpg6100/crypto/ccm_alt.h
new file mode 100644
index 0000000..9bd9b9b
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/ccm_alt.h
@@ -0,0 +1,163 @@
+/**
+ * \file ccm_alt.h
+ *
+ * \brief CCM combines Counter mode encryption with CBC-MAC authentication
+ * for 128-bit block ciphers.
+ *
+ * Input to CCM includes the following elements:
+ * <ul><li>Payload - data that is both authenticated and encrypted.</li>
+ * <li>Associated data (Adata) - data that is authenticated but not
+ * encrypted, For example, a header.</li>
+ * <li>Nonce - A unique value that is assigned to the payload and the
+ * associated data.</li></ul>
+ *
+ */
+/*
+ * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of Mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CCM_ALT_H
+#define MBEDTLS_CCM_ALT_H
+
+#if defined(MBEDTLS_CCM_ALT)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#ifndef MBEDTLS_AES_MAX_KEY_SIZE
+#define MBEDTLS_AES_MAX_KEY_SIZE 32
+#endif
+
+/**
+ * \brief The CCM context-type definition. The CCM context is passed
+ * to the APIs called.
+ */
+typedef struct
+{
+ uint8_t key[MBEDTLS_AES_MAX_KEY_SIZE];
+ int keysize;
+} mbedtls_ccm_context;
+
+/**
+ * \brief This function initializes the specified CCM context,
+ * to make references valid, and prepare the context
+ * for mbedtls_ccm_setkey() or mbedtls_ccm_free().
+ *
+ * \param ctx The CCM context to initialize.
+ */
+void mbedtls_ccm_init(mbedtls_ccm_context *ctx);
+
+/**
+ * \brief This function initializes the CCM context set in the
+ * \p ctx parameter and sets the encryption key.
+ *
+ * \param ctx The CCM context to initialize.
+ * \param cipher The 128-bit block cipher to use.
+ * \param key The encryption key.
+ * \param keybits The key size in bits. This must be acceptable by the cipher.
+ *
+ * \return \c 0 on success, or a cipher-specific error code.
+ */
+int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
+ mbedtls_cipher_id_t cipher,
+ const unsigned char *key,
+ unsigned int keybits);
+
+/**
+ * \brief This function releases and clears the specified CCM context
+ * and underlying cipher sub-context.
+ *
+ * \param ctx The CCM context to clear.
+ */
+void mbedtls_ccm_free(mbedtls_ccm_context *ctx);
+
+/**
+ * \brief This function encrypts a buffer using CCM.
+ *
+ * \param ctx The CCM context to use for encryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector (nonce).
+ * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * Must be less than 2^16 - 2^8.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * Must be at least \p length Bytes wide.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag to generate in Bytes:
+ * 4, 6, 8, 10, 14 or 16.
+ *
+ * \note The tag is written to a separate buffer. To concatenate
+ * the \p tag with the \p output, as done in <em>RFC-3610:
+ * Counter with CBC-MAC (CCM)</em>, use
+ * \p tag = \p output + \p length, and make sure that the
+ * output buffer is at least \p length + \p tag_len wide.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char * output,
+ unsigned char * tag,
+ size_t tag_len);
+
+/**
+ * \brief This function performs a CCM authenticated decryption of a
+ * buffer.
+ *
+ * \param ctx The CCM context to use for decryption.
+ * \param length The length of the input data in Bytes.
+ * \param iv Initialization vector.
+ * \param iv_len The length of the IV in Bytes: 7, 8, 9, 10, 11, 12, or 13.
+ * \param add The additional data field.
+ * \param add_len The length of additional data in Bytes.
+ * \param input The buffer holding the input data.
+ * \param output The buffer holding the output data.
+ * \param tag The buffer holding the tag.
+ * \param tag_len The length of the tag in Bytes.
+ *
+ * \return 0 if successful and authenticated, or
+ * #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
+ */
+int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx,
+ size_t length,
+ const unsigned char *iv,
+ size_t iv_len,
+ const unsigned char *add,
+ size_t add_len,
+ const unsigned char *input,
+ unsigned char * output,
+ const unsigned char *tag,
+ size_t tag_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CCM_ALT */
+
+#endif /* MBEDTLS_CCM_ALT_H */
diff --git a/examples/platforms/qpg6100/crypto/ecjpake_alt.h b/examples/platforms/qpg6100/crypto/ecjpake_alt.h
new file mode 100644
index 0000000..b1660b9
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/ecjpake_alt.h
@@ -0,0 +1,233 @@
+/**
+ * \file ecjpake_alt.h
+ *
+ * \brief Elliptic curve J-PAKE
+ */
+/*
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef MBEDTLS_ECJPAKE_ALT_H
+#define MBEDTLS_ECJPAKE_ALT_H
+
+#if defined(MBEDTLS_ECJPAKE_ALT)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MBEDTLS_ECJPAKE_ALT // QORVO
+/**
+ * Roles in the EC J-PAKE exchange
+ */
+typedef enum
+{
+ MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */
+ MBEDTLS_ECJPAKE_SERVER, /**< Server */
+} mbedtls_ecjpake_role;
+#endif // MBEDTLS_ECJPAKE_ALT // QORVO
+
+#ifndef MBEDTLS_ECJPAKE_MAX_BYTES
+
+/** The maximum size in bytes for a ECJPAKE number or coordinate.
+ *
+ * Default size works for P256 as MbedTLS and the Thread standard officially
+ * only support P256. To support larger curves, chose MBEDTLS_ECP_MAX_BYTES.
+ */
+#define MBEDTLS_ECJPAKE_MAX_BYTES (256 / 8)
+#endif
+
+/**
+ * EC J-PAKE context structure.
+ *
+ * J-PAKE is a symmetric protocol, except for the identifiers used in
+ * Zero-Knowledge Proofs, and the serialization of the second message
+ * (KeyExchange) as defined by the Thread spec.
+ *
+ * In order to benefit from this symmetry, we choose a different naming
+ * convetion from the Thread v1.0 spec. Correspondance is indicated in the
+ * description as a pair C: client name, S: server name
+ */
+typedef struct
+{
+ mbedtls_ecp_group grp; /**< Elliptic curve */
+ mbedtls_ecjpake_role role; /**< Are we client or server? */
+ int point_format; /**< Format for point export */
+
+ mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */
+ mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */
+ mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */
+ mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */
+ mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */
+
+ mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */
+ mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */
+
+ mbedtls_mpi s; /**< Pre-shared secret (passphrase) */
+
+ const struct sx_ecc_curve_t *curve; /**< Elliptic curve for HW offload */
+ int hashalg; /**< Hash algorithm for HW offload */
+} mbedtls_ecjpake_context;
+
+#ifndef MBEDTLS_ECJPAKE_ALT // QORVO
+/**
+ * \brief Initialize a context
+ * (just makes it ready for setup() or free()).
+ *
+ * \param ctx context to initialize
+ */
+void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx);
+
+/**
+ * \brief Set up a context for use
+ *
+ * \note Currently the only values for hash/curve allowed by the
+ * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1.
+ *
+ * \param ctx context to set up
+ * \param role Our role: client or server
+ * \param hash hash function to use (MBEDTLS_MD_XXX)
+ * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX)
+ * \param secret pre-shared secret (passphrase)
+ * \param len length of the shared secret
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
+ mbedtls_ecjpake_role role,
+ mbedtls_md_type_t hash,
+ mbedtls_ecp_group_id curve,
+ const unsigned char * secret,
+ size_t len);
+
+/**
+ * \brief Check if a context is ready for use
+ *
+ * \param ctx Context to check
+ *
+ * \return 0 if the context is ready for use,
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
+ */
+int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx);
+
+/**
+ * \brief Generate and write the first round message
+ * (TLS: contents of the Client/ServerHello extension,
+ * excluding extension type and length bytes)
+ *
+ * \param ctx Context to use
+ * \param buf Buffer to write the contents to
+ * \param len Buffer size
+ * \param olen Will be updated with the number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
+ unsigned char * buf,
+ size_t len,
+ size_t * olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Read and process the first round message
+ * (TLS: contents of the Client/ServerHello extension,
+ * excluding extension type and length bytes)
+ *
+ * \param ctx Context to use
+ * \param buf Pointer to extension contents
+ * \param len Extension length
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len);
+
+/**
+ * \brief Generate and write the second round message
+ * (TLS: contents of the Client/ServerKeyExchange)
+ *
+ * \param ctx Context to use
+ * \param buf Buffer to write the contents to
+ * \param len Buffer size
+ * \param olen Will be updated with the number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
+ unsigned char * buf,
+ size_t len,
+ size_t * olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Read and process the second round message
+ * (TLS: contents of the Client/ServerKeyExchange)
+ *
+ * \param ctx Context to use
+ * \param buf Pointer to the message
+ * \param len Message length
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len);
+
+/**
+ * \brief Derive the shared secret
+ * (TLS: Pre-Master Secret)
+ *
+ * \param ctx Context to use
+ * \param buf Buffer to write the contents to
+ * \param len Buffer size
+ * \param olen Will be updated with the number of bytes written
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successfull,
+ * a negative error code otherwise
+ */
+int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
+ unsigned char * buf,
+ size_t len,
+ size_t * olen,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Free a context's content
+ *
+ * \param ctx context to free
+ */
+void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx);
+#endif // MBEDTLS_ECJPAKE_ALT // QORVO
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_ECJPAKE_ALT */
+
+#endif /* ecjpake.h */
diff --git a/examples/platforms/qpg6100/crypto/ecp_alt.h b/examples/platforms/qpg6100/crypto/ecp_alt.h
new file mode 100644
index 0000000..afd208c
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/ecp_alt.h
@@ -0,0 +1,657 @@
+/**
+ * \file ecp_alt.h
+ *
+ * \brief Elliptic curves over GF(p)
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/* Adapted for hardware acceleration by CryptoSoc
+ * Copyright (c) 2018 Barco Silex
+ * Copyright (c) 2018 François Beerten
+ */
+
+#ifndef MBEDTLS_ECP_ALT_H
+#define MBEDTLS_ECP_ALT_H
+
+/*
+ * default mbed TLS elliptic curve arithmetic implementation
+ *
+ * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an
+ * alternative implementation for the whole module and it will replace this
+ * one.)
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MBEDTLS_ECP_ALT // QORVO
+/**
+ * Domain parameters (curve, subgroup and generator) identifiers.
+ *
+ * Only curves over prime fields are supported.
+ *
+ * \warning This library does not support validation of arbitrary domain
+ * parameters. Therefore, only well-known domain parameters from trusted
+ * sources should be used. See mbedtls_ecp_group_load().
+ */
+typedef enum
+{
+ MBEDTLS_ECP_DP_NONE = 0,
+ MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */
+ MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */
+ MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */
+ MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */
+ MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */
+ MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */
+ MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */
+ MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */
+ MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */
+ MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */
+ MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
+ MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
+} mbedtls_ecp_group_id;
+
+/**
+ * Number of supported curves (plus one for NONE).
+ *
+ * (Montgomery curves excluded for now.)
+ */
+#define MBEDTLS_ECP_DP_MAX 12
+
+/**
+ * Curve information for use by other modules
+ */
+typedef struct
+{
+ mbedtls_ecp_group_id grp_id; /*!< Internal identifier */
+ uint16_t tls_id; /*!< TLS NamedCurve identifier */
+ uint16_t bit_size; /*!< Curve size in bits */
+ const char * name; /*!< Human-friendly name */
+} mbedtls_ecp_curve_info;
+
+/**
+ * \brief ECP point structure (jacobian coordinates)
+ *
+ * \note All functions expect and return points satisfying
+ * the following condition: Z == 0 or Z == 1. (Other
+ * values of Z are used by internal functions only.)
+ * The point is zero, or "at infinity", if Z == 0.
+ * Otherwise, X and Y are its standard (affine) coordinates.
+ */
+typedef struct
+{
+ mbedtls_mpi X; /*!< the point's X coordinate */
+ mbedtls_mpi Y; /*!< the point's Y coordinate */
+ mbedtls_mpi Z; /*!< the point's Z coordinate */
+} mbedtls_ecp_point;
+#endif // MBEDTLS_ECP_ALT // QORVO
+
+/**
+ * \brief ECP group structure
+ *
+ * We consider two types of curves equations:
+ * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492)
+ * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft)
+ * In both cases, a generator G for a prime-order subgroup is fixed. In the
+ * short weierstrass, this subgroup is actually the whole curve, and its
+ * cardinal is denoted by N.
+ *
+ * In the case of Short Weierstrass curves, our code requires that N is an odd
+ * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.)
+ *
+ * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
+ * the quantity actually used in the formulas. Also, nbits is not the size of N
+ * but the required size for private keys.
+ *
+ * If modp is NULL, reduction modulo P is done using a generic algorithm.
+ * Otherwise, it must point to a function that takes an mbedtls_mpi in the range
+ * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more
+ * than pbits, so that the integer may be efficiently brought in the 0..P-1
+ * range by a few additions or substractions. It must return 0 on success and
+ * non-zero on failure.
+ */
+typedef struct
+{
+ mbedtls_ecp_group_id id; /*!< internal group identifier */
+ mbedtls_mpi P; /*!< prime modulus of the base field */
+ mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4. for pkparse only. */
+ mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused. for pkparse only. */
+ mbedtls_ecp_point G; /*!< generator of the (sub)group used */
+ mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */
+ size_t pbits; /*!< number of bits in P */
+ size_t nbits; /*!< number of bits in 1. P, or 2. private keys */
+ unsigned int h; /*!< internal: 1 if the constants are static */
+ int (*modp)(mbedtls_mpi *); /*!< Internally unused. NULL to build some tests. */
+ mbedtls_ecp_point *T; /*!< Internally unused. Needed to build benchmark. */
+ size_t T_size; /*!< Internally unused. Needed to build benchmark. */
+} mbedtls_ecp_group;
+
+#ifndef MBEDTLS_ECP_ALT // QORVO
+/**
+ * \brief ECP key pair structure
+ *
+ * A generic key pair that could be used for ECDSA, fixed ECDH, etc.
+ *
+ * \note Members purposefully in the same order as struc mbedtls_ecdsa_context.
+ */
+typedef struct
+{
+ mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
+ mbedtls_mpi d; /*!< our secret value */
+ mbedtls_ecp_point Q; /*!< our public value */
+} mbedtls_ecp_keypair;
+#endif // MBEDTLS_ECP_ALT // QORVO
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDTLS_ECP_MAX_BITS)
+/**
+ * Maximum size of the groups (that is, of N and P)
+ */
+#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
+#endif
+
+#define MBEDTLS_ECP_MAX_BYTES ((MBEDTLS_ECP_MAX_BITS + 7) / 8)
+#define MBEDTLS_ECP_MAX_PT_LEN (2 * MBEDTLS_ECP_MAX_BYTES + 1)
+
+#if defined(MBEDTLS_ECP_WINDOW_SIZE)
+#error "MBEDTLS_ECP_WINDOW_SIZE not applicable for HW accel"
+#endif /* MBEDTLS_ECP_WINDOW_SIZE */
+
+#if defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
+#error "MBEDTLS_ECP_FIXED_POINT_OPTIM not applicable for HW accel"
+#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
+
+/* \} name SECTION: Module settings */
+
+/*
+ * Point formats, from RFC 4492's enum ECPointFormat
+ */
+#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */
+#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */
+
+/*
+ * Some other constants from RFC 4492
+ */
+#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */
+
+#ifndef MBEDTLS_ECP_ALT // QORVO
+/**
+ * \brief Get the list of supported curves in order of preferrence
+ * (full information)
+ *
+ * \return A statically allocated array, the last entry is 0.
+ */
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void);
+
+/**
+ * \brief Get the list of supported curves in order of preferrence
+ * (grp_id only)
+ *
+ * \return A statically allocated array,
+ * terminated with MBEDTLS_ECP_DP_NONE.
+ */
+const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void);
+
+/**
+ * \brief Get curve information from an internal group identifier
+ *
+ * \param grp_id A MBEDTLS_ECP_DP_XXX value
+ *
+ * \return The associated curve information or NULL
+ */
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id);
+
+/**
+ * \brief Get curve information from a TLS NamedCurve value
+ *
+ * \param tls_id A MBEDTLS_ECP_DP_XXX value
+ *
+ * \return The associated curve information or NULL
+ */
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id);
+
+/**
+ * \brief Get curve information from a human-readable name
+ *
+ * \param name The name
+ *
+ * \return The associated curve information or NULL
+ */
+const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name);
+
+/**
+ * \brief Initialize a point (as zero)
+ */
+void mbedtls_ecp_point_init(mbedtls_ecp_point *pt);
+
+/**
+ * \brief Initialize a group (to something meaningless)
+ */
+void mbedtls_ecp_group_init(mbedtls_ecp_group *grp);
+
+/**
+ * \brief Initialize a key pair (as an invalid one)
+ */
+void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key);
+
+/**
+ * \brief Free the components of a point
+ */
+void mbedtls_ecp_point_free(mbedtls_ecp_point *pt);
+
+/**
+ * \brief Free the components of an ECP group
+ */
+void mbedtls_ecp_group_free(mbedtls_ecp_group *grp);
+
+/**
+ * \brief Free the components of a key pair
+ */
+void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key);
+
+/**
+ * \brief Copy the contents of point Q into P
+ *
+ * \param P Destination point
+ * \param Q Source point
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q);
+
+/**
+ * \brief Copy the contents of a group object
+ *
+ * \param dst Destination group
+ * \param src Source group
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src);
+
+/**
+ * \brief Set a point to zero
+ *
+ * \param pt Destination point
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt);
+
+/**
+ * \brief Tell if a point is zero
+ *
+ * \param pt Point to test
+ *
+ * \return 1 if point is zero, 0 otherwise
+ */
+int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt);
+
+/**
+ * \brief Compare two points
+ *
+ * \note This assumes the points are normalized. Otherwise,
+ * they may compare as "not equal" even if they are.
+ *
+ * \param P First point to compare
+ * \param Q Second point to compare
+ *
+ * \return 0 if the points are equal,
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
+ */
+int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q);
+
+/**
+ * \brief Import a non-zero point from two ASCII strings
+ *
+ * \param P Destination point
+ * \param radix Input numeric base
+ * \param x First affine coordinate as a null-terminated string
+ * \param y Second affine coordinate as a null-terminated string
+ *
+ * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
+ */
+int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y);
+
+/**
+ * \brief Export a point into unsigned binary data
+ *
+ * \param grp Group to which the point should belong
+ * \param P Point to export
+ * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro
+ * \param olen Length of the actual output
+ * \param buf Output buffer
+ * \param buflen Length of the output buffer
+ *
+ * \return 0 if successful,
+ * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+ * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *P,
+ int format,
+ size_t * olen,
+ unsigned char * buf,
+ size_t buflen);
+
+/**
+ * \brief Import a point from unsigned binary data
+ *
+ * \param grp Group to which the point should belong
+ * \param P Point to import
+ * \param buf Input buffer
+ * \param ilen Actual length of input
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
+ * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ * is not implemented.
+ *
+ * \note This function does NOT check that the point actually
+ * belongs to the given group, see mbedtls_ecp_check_pubkey() for
+ * that.
+ */
+int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point * P,
+ const unsigned char * buf,
+ size_t ilen);
+
+/**
+ * \brief Import a point from a TLS ECPoint record
+ *
+ * \param grp ECP group used
+ * \param pt Destination point
+ * \param buf $(Start of input buffer)
+ * \param len Buffer length
+ *
+ * \note buf is updated to point right after the ECPoint on exit
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_XXX if initialization failed
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
+ */
+int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp,
+ mbedtls_ecp_point * pt,
+ const unsigned char ** buf,
+ size_t len);
+
+/**
+ * \brief Export a point as a TLS ECPoint record
+ *
+ * \param grp ECP group used
+ * \param pt Point to export
+ * \param format Export format
+ * \param olen length of data written
+ * \param buf Buffer to write to
+ * \param blen Buffer length
+ *
+ * \return 0 if successful,
+ * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+ * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *pt,
+ int format,
+ size_t * olen,
+ unsigned char * buf,
+ size_t blen);
+
+/**
+ * \brief Set a group using well-known domain parameters
+ *
+ * \param grp Destination group
+ * \param id Index in the list of well-known domain parameters
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_XXX if initialization failed
+ * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups
+ *
+ * \note Index should be a value of RFC 4492's enum NamedCurve,
+ * usually in the form of a MBEDTLS_ECP_DP_XXX macro.
+ */
+int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id);
+
+/**
+ * \brief Set a group from a TLS ECParameters record
+ *
+ * \param grp Destination group
+ * \param buf &(Start of input buffer)
+ * \param len Buffer length
+ *
+ * \note buf is updated to point right after ECParameters on exit
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_MPI_XXX if initialization failed
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
+ */
+int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len);
+
+/**
+ * \brief Write the TLS ECParameters record for a group
+ *
+ * \param grp ECP group used
+ * \param olen Number of bytes actually written
+ * \param buf Buffer to write to
+ * \param blen Buffer length
+ *
+ * \return 0 if successful,
+ * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+ */
+int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen);
+
+/**
+ * \brief Multiplication by an integer: R = m * P
+ * (Not thread-safe to use same group in multiple threads)
+ *
+ * \note In order to prevent timing attacks, this function
+ * executes the exact same sequence of (base field)
+ * operations for any valid m. It avoids any if-branch or
+ * array index depending on the value of m.
+ *
+ * \note If f_rng is not NULL, it is used to randomize intermediate
+ * results in order to prevent potential timing attacks
+ * targeting these results. It is recommended to always
+ * provide a non-NULL f_rng (the overhead is negligible).
+ *
+ * \param grp ECP group
+ * \param R Destination point
+ * \param m Integer by which to multiply
+ * \param P Point to multiply
+ * \param f_rng RNG function (see notes)
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey
+ * or P is not a valid pubkey,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_ecp_mul(mbedtls_ecp_group * grp,
+ mbedtls_ecp_point * R,
+ const mbedtls_mpi * m,
+ const mbedtls_ecp_point *P,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Multiplication and addition of two points by integers:
+ * R = m * P + n * Q
+ * (Not thread-safe to use same group in multiple threads)
+ *
+ * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee
+ * a constant execution flow and timing.
+ *
+ * \param grp ECP group
+ * \param R Destination point
+ * \param m Integer by which to multiply P
+ * \param P Point to multiply by m
+ * \param n Integer by which to multiply Q
+ * \param Q Point to be multiplied by n
+ *
+ * \return 0 if successful,
+ * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey
+ * or P or Q is not a valid pubkey,
+ * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
+ */
+int mbedtls_ecp_muladd(mbedtls_ecp_group * grp,
+ mbedtls_ecp_point * R,
+ const mbedtls_mpi * m,
+ const mbedtls_ecp_point *P,
+ const mbedtls_mpi * n,
+ const mbedtls_ecp_point *Q);
+
+/**
+ * \brief Check that a point is a valid public key on this curve
+ *
+ * \param grp Curve/group the point should belong to
+ * \param pt Point to check
+ *
+ * \return 0 if point is a valid public key,
+ * MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
+ *
+ * \note This function only checks the point is non-zero, has valid
+ * coordinates and lies on the curve, but not that it is
+ * indeed a multiple of G. This is additional check is more
+ * expensive, isn't required by standards, and shouldn't be
+ * necessary if the group used has a small cofactor. In
+ * particular, it is useless for the NIST groups which all
+ * have a cofactor of 1.
+ *
+ * \note Uses bare components rather than an mbedtls_ecp_keypair structure
+ * in order to ease use with other structures such as
+ * mbedtls_ecdh_context of mbedtls_ecdsa_context.
+ */
+int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt);
+
+/**
+ * \brief Check that an mbedtls_mpi is a valid private key for this curve
+ *
+ * \param grp Group used
+ * \param d Integer to check
+ *
+ * \return 0 if point is a valid private key,
+ * MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
+ *
+ * \note Uses bare components rather than an mbedtls_ecp_keypair structure
+ * in order to ease use with other structures such as
+ * mbedtls_ecdh_context of mbedtls_ecdsa_context.
+ */
+int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d);
+
+/**
+ * \brief Generate a keypair with configurable base point
+ *
+ * \param grp ECP group
+ * \param G Chosen base point
+ * \param d Destination MPI (secret part)
+ * \param Q Destination point (public part)
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
+ *
+ * \note Uses bare components rather than an mbedtls_ecp_keypair structure
+ * in order to ease use with other structures such as
+ * mbedtls_ecdh_context of mbedtls_ecdsa_context.
+ */
+int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group * grp,
+ const mbedtls_ecp_point *G,
+ mbedtls_mpi * d,
+ mbedtls_ecp_point * Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Generate a keypair
+ *
+ * \param grp ECP group
+ * \param d Destination MPI (secret part)
+ * \param Q Destination point (public part)
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
+ *
+ * \note Uses bare components rather than an mbedtls_ecp_keypair structure
+ * in order to ease use with other structures such as
+ * mbedtls_ecdh_context of mbedtls_ecdsa_context.
+ */
+int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp,
+ mbedtls_mpi * d,
+ mbedtls_ecp_point *Q,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Generate a keypair
+ *
+ * \param grp_id ECP group identifier
+ * \param key Destination keypair
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
+ */
+int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id,
+ mbedtls_ecp_keypair *key,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng);
+
+/**
+ * \brief Check a public-private key pair
+ *
+ * \param pub Keypair structure holding a public key
+ * \param prv Keypair structure holding a private (plus public) key
+ *
+ * \return 0 if successful (keys are valid and match), or
+ * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or
+ * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code.
+ */
+int mbedtls_ecp_check_pub_priv(const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv);
+#endif // MBEDTLS_ECP_ALT // QORVO
+
+#if defined(MBEDTLS_SELF_TEST)
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if a test failed
+ */
+int mbedtls_ecp_self_test(int verbose);
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ecp_alt.h */
diff --git a/examples/platforms/qpg6100/crypto/qpg6100-mbedtls-config.h b/examples/platforms/qpg6100/crypto/qpg6100-mbedtls-config.h
new file mode 100644
index 0000000..9830b8c
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/qpg6100-mbedtls-config.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, 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 QGP6100_MBEDTLS_CONFIG_H
+#define QGP6100_MBEDTLS_CONFIG_H
+
+#ifdef QORVO_CRYPTO_ENGINE
+
+#undef MBEDTLS_ECP_WINDOW_SIZE
+#undef MBEDTLS_ECP_FIXED_POINT_OPTIM
+
+#define MBEDTLS_AES_ALT
+#define MBEDTLS_CCM_ALT
+#define MBEDTLS_ECP_ALT
+#define MBEDTLS_ECJPAKE_ALT
+#define MBEDTLS_SHA256_ALT
+
+#else
+
+#define MBEDTLS_SLOW_CPU 1
+#define MBEDTLS_COMPUTATION_UNTILL_SEQ_NR 6
+
+#endif // QORVO_CRYPTO_ENGINE
+
+#include "mbedtls/check_config.h"
+
+#endif // QGP6100_MBEDTLS_CONFIG_H
diff --git a/examples/platforms/qpg6100/crypto/sha256_alt.h b/examples/platforms/qpg6100/crypto/sha256_alt.h
new file mode 100644
index 0000000..5d051e3
--- /dev/null
+++ b/examples/platforms/qpg6100/crypto/sha256_alt.h
@@ -0,0 +1,194 @@
+/**
+ * \file mbedtls_sha256.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef MBEDTLS_SHA256_ALT_H
+#define MBEDTLS_SHA256_ALT_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+ int is224; /*!< 0 => SHA-256, else SHA-224 */
+} mbedtls_sha256_context;
+
+/**
+ * \brief This function initializes a SHA-256 context.
+ *
+ * \param ctx The SHA-256 context to initialize.
+ */
+void mbedtls_sha256_init(mbedtls_sha256_context *ctx);
+
+/**
+ * \brief This function clears a SHA-256 context.
+ *
+ * \param ctx The SHA-256 context to clear.
+ */
+void mbedtls_sha256_free(mbedtls_sha256_context *ctx);
+
+/**
+ * \brief This function clones the state of a SHA-256 context.
+ *
+ * \param dst The destination context.
+ * \param src The context to clone.
+ */
+void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src);
+
+/**
+ * \brief This function starts a SHA-224 or SHA-256 checksum
+ * calculation.
+ *
+ * \param ctx The context to initialize.
+ * \param is224 Determines which function to use.
+ * <ul><li>0: Use SHA-256.</li>
+ * <li>1: Use SHA-224.</li></ul>
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224);
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-256 checksum calculation.
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen);
+
+/**
+ * \brief This function finishes the SHA-256 operation, and writes
+ * the result to the output buffer.
+ *
+ * \param ctx The SHA-256 context.
+ * \param output The SHA-224 or SHA-256 checksum result.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, unsigned char output[32]);
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-256 computation. This function is for
+ * internal use only.
+ *
+ * \param ctx The SHA-256 context.
+ * \param data The buffer holding one block of data.
+ *
+ * \return \c 0 on success.
+ */
+int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]);
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+/**
+ * \brief This function starts a SHA-256 checksum calculation.
+ *
+ * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context to initialize.
+ * \param is224 Determines which function to use.
+ * <ul><li>0: Use SHA-256.</li>
+ * <li>1: Use SHA-224.</li></ul>
+ */
+MBEDTLS_DEPRECATED static inline void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
+{
+ mbedtls_sha256_starts_ret(ctx, is224);
+}
+
+/**
+ * \brief This function feeds an input buffer into an ongoing
+ * SHA-256 checksum calculation.
+ *
+ * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context to initialize.
+ * \param input The buffer holding the data.
+ * \param ilen The length of the input data.
+ */
+MBEDTLS_DEPRECATED static inline void mbedtls_sha256_update(mbedtls_sha256_context *ctx,
+ const unsigned char * input,
+ size_t ilen)
+{
+ mbedtls_sha256_update_ret(ctx, input, ilen);
+}
+
+/**
+ * \brief This function finishes the SHA-256 operation, and writes
+ * the result to the output buffer.
+ *
+ * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context.
+ * \param output The SHA-224or SHA-256 checksum result.
+ */
+MBEDTLS_DEPRECATED static inline void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char output[32])
+{
+ mbedtls_sha256_finish_ret(ctx, output);
+}
+
+/**
+ * \brief This function processes a single data block within
+ * the ongoing SHA-256 computation. This function is for
+ * internal use only.
+ *
+ * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0.
+ *
+ * \param ctx The SHA-256 context.
+ * \param data The buffer holding one block of data.
+ */
+MBEDTLS_DEPRECATED static inline void mbedtls_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
+{
+ mbedtls_internal_sha256_process(ctx, data);
+}
+
+#undef MBEDTLS_DEPRECATED
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/examples/platforms/qpg6100/diag.c b/examples/platforms/qpg6100/diag.c
new file mode 120000
index 0000000..5e48d47
--- /dev/null
+++ b/examples/platforms/qpg6100/diag.c
@@ -0,0 +1 @@
+../qpg6095/diag.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/entropy.c b/examples/platforms/qpg6100/entropy.c
new file mode 120000
index 0000000..7a6cd5a
--- /dev/null
+++ b/examples/platforms/qpg6100/entropy.c
@@ -0,0 +1 @@
+../qpg6095/entropy.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/logging.c b/examples/platforms/qpg6100/logging.c
new file mode 120000
index 0000000..57dabcc
--- /dev/null
+++ b/examples/platforms/qpg6100/logging.c
@@ -0,0 +1 @@
+../qpg6095/logging.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/misc.c b/examples/platforms/qpg6100/misc.c
new file mode 120000
index 0000000..cba8d92
--- /dev/null
+++ b/examples/platforms/qpg6100/misc.c
@@ -0,0 +1 @@
+../qpg6095/misc.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/misc_qorvo.h b/examples/platforms/qpg6100/misc_qorvo.h
new file mode 120000
index 0000000..460e055
--- /dev/null
+++ b/examples/platforms/qpg6100/misc_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/misc_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/openthread-core-qpg6100-config-check.h b/examples/platforms/qpg6100/openthread-core-qpg6100-config-check.h
new file mode 100644
index 0000000..0ec3b40
--- /dev/null
+++ b/examples/platforms/qpg6100/openthread-core-qpg6100-config-check.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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_CORE_QPG6100_CONFIG_CHECK_H_
+#define OPENTHREAD_CORE_QPG6100_CONFIG_CHECK_H_
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+#error "Platform qpg6100 doesn't support configuration option: OPENTHREAD_CONFIG_TIME_SYNC_ENABLE"
+#endif
+
+#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+#error "Platform qpg6100 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
+#endif
+
+#endif /* OPENTHREAD_CORE_QPG6100_CONFIG_CHECK_H_ */
diff --git a/examples/platforms/qpg6100/openthread-core-qpg6100-config.h b/examples/platforms/qpg6100/openthread-core-qpg6100-config.h
new file mode 100644
index 0000000..be3b33b
--- /dev/null
+++ b/examples/platforms/qpg6100/openthread-core-qpg6100-config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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 qpg6100 compile-time configuration constants for OpenThread.
+ */
+
+#ifndef OPENTHREAD_CORE_QPG6100_CONFIG_H_
+#define OPENTHREAD_CORE_QPG6100_CONFIG_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_LEGACY_TRANSMIT_DONE
+ *
+ * Define to 1 if you want use legacy transmit done.
+ *
+ */
+#define OPENTHREAD_CONFIG_LEGACY_TRANSMIT_DONE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_INFO
+ *
+ * The platform-specific string to insert into the OpenThread version string.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_INFO "QPG6100"
+
+#endif // OPENTHREAD_CORE_QPG6100_CONFIG_H_
diff --git a/examples/platforms/qpg6100/platform.c b/examples/platforms/qpg6100/platform.c
new file mode 120000
index 0000000..e8cd210
--- /dev/null
+++ b/examples/platforms/qpg6100/platform.c
@@ -0,0 +1 @@
+../qpg6095/platform.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/platform_qorvo.h b/examples/platforms/qpg6100/platform_qorvo.h
new file mode 120000
index 0000000..965c015
--- /dev/null
+++ b/examples/platforms/qpg6100/platform_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/platform_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/radio.c b/examples/platforms/qpg6100/radio.c
new file mode 120000
index 0000000..211d358
--- /dev/null
+++ b/examples/platforms/qpg6100/radio.c
@@ -0,0 +1 @@
+../qpg6095/radio.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/radio_qorvo.h b/examples/platforms/qpg6100/radio_qorvo.h
new file mode 120000
index 0000000..8af682a
--- /dev/null
+++ b/examples/platforms/qpg6100/radio_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/radio_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/random_qorvo.h b/examples/platforms/qpg6100/random_qorvo.h
new file mode 120000
index 0000000..92af247
--- /dev/null
+++ b/examples/platforms/qpg6100/random_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/random_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/settings.cpp b/examples/platforms/qpg6100/settings.cpp
new file mode 120000
index 0000000..1d0596d
--- /dev/null
+++ b/examples/platforms/qpg6100/settings.cpp
@@ -0,0 +1 @@
+../qpg6095/settings.cpp
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/settings_qorvo.h b/examples/platforms/qpg6100/settings_qorvo.h
new file mode 120000
index 0000000..0b689fc
--- /dev/null
+++ b/examples/platforms/qpg6100/settings_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/settings_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/uart.c b/examples/platforms/qpg6100/uart.c
new file mode 120000
index 0000000..dd4e551
--- /dev/null
+++ b/examples/platforms/qpg6100/uart.c
@@ -0,0 +1 @@
+../qpg6095/uart.c
\ No newline at end of file
diff --git a/examples/platforms/qpg6100/uart_qorvo.h b/examples/platforms/qpg6100/uart_qorvo.h
new file mode 120000
index 0000000..cad2bfd
--- /dev/null
+++ b/examples/platforms/qpg6100/uart_qorvo.h
@@ -0,0 +1 @@
+../qpg6095/uart_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/CMakeLists.txt b/examples/platforms/qpg7015m/CMakeLists.txt
new file mode 100644
index 0000000..1f2b9f2
--- /dev/null
+++ b/examples/platforms/qpg7015m/CMakeLists.txt
@@ -0,0 +1,105 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(OT_PLATFORM_LIB "openthread-qpg7015m" PARENT_SCOPE)
+
+if(NOT OT_CONFIG)
+ set(OT_CONFIG "openthread-core-qpg7015m-config.h")
+ set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES
+ "OPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE=\"openthread-core-qpg7015m-config-check.h\""
+)
+
+list(APPEND OT_PLATFORM_DEFINES
+ "_BSD_SOURCE=1"
+ "_DEFAULT_SOURCE=1"
+)
+
+set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
+
+set(OT_PUBLIC_INCLUDES ${OT_PUBLIC_INCLUDES} PARENT_SCOPE)
+
+if(OT_CFLAGS MATCHES "-pedantic-errors")
+ string(REPLACE "-pedantic-errors" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+if(OT_CFLAGS MATCHES "-Wno-c\\+\\+14-compat")
+ string(REPLACE "-Wno-c++14-compat" "" OT_CFLAGS "${OT_CFLAGS}")
+endif()
+
+list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
+
+add_library(openthread-qpg7015m
+ alarm.c
+ diag.c
+ entropy.c
+ flash.c
+ logging.c
+ misc.c
+ radio.c
+ system.c
+ uart-posix.c
+)
+
+set_target_properties(
+ openthread-qpg7015m
+ PROPERTIES
+ C_STANDARD 99
+ CXX_STANDARD 11
+)
+
+target_link_libraries(openthread-qpg7015m
+ PRIVATE
+ qpg7015m-driver
+ ${OT_MBEDTLS}
+ ot-config
+ PUBLIC
+ -lrt
+ -pthread
+ -Wl,--gc-sections
+ -Wl,-Map=$<TARGET_PROPERTY:NAME>.map
+)
+
+target_compile_definitions(openthread-qpg7015m
+ PUBLIC
+ ${OT_PLATFORM_DEFINES}
+)
+
+target_compile_options(openthread-qpg7015m
+ PRIVATE
+ ${OT_CFLAGS}
+)
+
+target_include_directories(openthread-qpg7015m
+ PRIVATE
+ ${OT_PUBLIC_INCLUDES}
+ ${PROJECT_SOURCE_DIR}/src/core
+ ${PROJECT_SOURCE_DIR}/examples/platforms
+)
diff --git a/examples/platforms/qpg7015m/Makefile.am b/examples/platforms/qpg7015m/Makefile.am
new file mode 100755
index 0000000..11c0a6b
--- /dev/null
+++ b/examples/platforms/qpg7015m/Makefile.am
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
+
+# Do not enable -Wcast-align for this platform
+override CFLAGS := $(filter-out -Wcast-align,$(CFLAGS))
+override CXXFLAGS := $(filter-out -Wcast-align,$(CXXFLAGS))
+
+lib_LIBRARIES = libopenthread-qpg7015m.a
+
+libopenthread_qpg7015m_a_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/core \
+ -I$(top_srcdir)/examples/platforms \
+ -I$(top_srcdir)/examples/platforms/qpg7015m \
+ -lrt \
+ -pthread \
+ $(NULL)
+
+PLATFORM_SOURCES = \
+ alarm.c \
+ alarm_qorvo.h \
+ diag.c \
+ entropy.c \
+ flash.c \
+ logging.c \
+ misc.c \
+ openthread-core-qpg7015m-config.h \
+ openthread-core-qpg7015m-config-check.h \
+ platform_qorvo.h \
+ radio.c \
+ radio_qorvo.h \
+ random_qorvo.h \
+ system.c \
+ uart-posix.c \
+ uart_qorvo.h \
+ $(NULL)
+
+libopenthread_qpg7015m_a_SOURCES = \
+ $(PLATFORM_SOURCES) \
+ $(NULL)
+
+if OPENTHREAD_BUILD_COVERAGE
+CLEANFILES = $(wildcard *.gcda *.gcno)
+endif # OPENTHREAD_BUILD_COVERAGE
+
+include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/tests/scripts/expect/v1_2-rcp.exp b/examples/platforms/qpg7015m/Makefile.platform.am
similarity index 67%
copy from tests/scripts/expect/v1_2-rcp.exp
copy to examples/platforms/qpg7015m/Makefile.platform.am
index 776d880..0b62f4b 100755
--- a/tests/scripts/expect/v1_2-rcp.exp
+++ b/examples/platforms/qpg7015m/Makefile.platform.am
@@ -1,6 +1,5 @@
-#!/usr/bin/expect -f
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2019, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,39 +26,21 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+#
+# qpg7015m platform-specific Makefile
+#
-spawn_node 1
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "leader"
-expect "Done"
-
-send "ipaddr mleid\n"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
-
-spawn_node 2 mtd
-
-send "panid 0xface\n"
-expect "Done"
-send "mode -\n"
-expect "Done"
-send "csl period 5000\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "child"
-expect "Done"
-send "ping $addr\n"
-expect "16 bytes from $addr: icmp_seq=1"
-
-dispose_all
+LDADD_COMMON += \
+ $(top_builddir)/examples/platforms/qpg7015m/libopenthread-qpg7015m.a \
+ $(NULL)
+if OPENTHREAD_ENABLE_FTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg7015m/lib/libQorvoQPG7015M_ftd.a \
+ $(NULL)
+else # OPENTHREAD_ENABLE_FTD
+if OPENTHREAD_ENABLE_MTD
+LDADD_COMMON += \
+ $(top_srcdir)/third_party/Qorvo/repo/qpg7015m/lib/libQorvoQPG7015M_mtd.a \
+ $(NULL)
+endif # OPENTHREAD_ENABLE_MTD
+endif
diff --git a/examples/platforms/qpg7015m/README.md b/examples/platforms/qpg7015m/README.md
new file mode 100644
index 0000000..d9ac217
--- /dev/null
+++ b/examples/platforms/qpg7015m/README.md
@@ -0,0 +1,87 @@
+# OpenThread on Qorvo qpg7015m Example
+
+This directory contains example platform drivers for Qorvo qpg7015m on RPi.
+
+## Toolchain
+
+This example uses the GNU GCC toolchain on the Raspberry Pi. To build on the Pi:
+
+1. Download the repo to the Pi
+2. go to the subfolder in the openthread repo: third_party/nlbuild-autotools/repo/tools/packages and enter this command:
+
+```bash
+$ sudo /bin/bash build
+```
+
+Note that you may need to install additional packages to make this build work, depending on your actual RPi OS version. The build process will complain if additional packages are required.
+
+## Build Examples
+
+```bash
+$ cd <path-to-openthread>
+$ ./script/bootstrap
+$ ./bootstrap
+$ REFERENCE_DEVICE=1 CLI_LOGGING=1 COMMISSIONER=1 JOINER=1 DHCP6_CLIENT=1 DHCP6_SERVER=1 BORDER_ROUTER=1 make -f examples/Makefile-qpg7015m
+```
+
+After a successful build, the `elf` files are found in `<path-to-openthread>/output/qpg7015m/bin`.
+
+Building a variant which interfaces via a tcp socket is also possible. Replace the uart-posix.c with uart-socket.c in the Makefile.am from examples/platforms/qpg7015m/Makefile.am and rebuild. Now it should be possible to open a telnet to socket 9190 of the raspberry pi from a remote PC. This also easier testing with the official Thread Test Harness.
+
+## Cmake build
+
+Make sure arm-linux-gnueabihf-gcc compiler installed in `$PATH`
+
+```bash
+cd <path-to-openthread>
+./script/cmake-build qpg7015m
+```
+
+After a successful build, binary files will be generated:
+
+```
+./build/qpg7015m/examples/apps/ncp/ot-rcp
+./build/qpg7015m/examples/apps/cli/ot-cli-ftd
+```
+
+##
+
+## Interact
+
+1. Spawn the process:
+
+```bash
+$ cd <path-to-openthread>/output/qpg7015m/bin
+$ ./qpg7015m-ot-cli-ftd
+```
+
+2. Type `help` for list of commands.
+
+```bash
+> help
+help
+channel
+childtimeout
+contextreusedelay
+extaddr
+extpanid
+ipaddr
+keysequence
+leaderweight
+masterkey
+mode
+netdata register
+networkidtimeout
+networkname
+panid
+ping
+prefix
+releaserouterid
+rloc16
+route
+routerupgradethreshold
+scan
+start
+state
+stop
+```
diff --git a/examples/platforms/qpg7015m/alarm.c b/examples/platforms/qpg7015m/alarm.c
new file mode 120000
index 0000000..55ac139
--- /dev/null
+++ b/examples/platforms/qpg7015m/alarm.c
@@ -0,0 +1 @@
+../gp712/alarm.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/alarm_qorvo.h b/examples/platforms/qpg7015m/alarm_qorvo.h
new file mode 120000
index 0000000..5cbe463
--- /dev/null
+++ b/examples/platforms/qpg7015m/alarm_qorvo.h
@@ -0,0 +1 @@
+../gp712/alarm_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/arm-linux-gnueabihf.cmake b/examples/platforms/qpg7015m/arm-linux-gnueabihf.cmake
new file mode 120000
index 0000000..18b8c9f
--- /dev/null
+++ b/examples/platforms/qpg7015m/arm-linux-gnueabihf.cmake
@@ -0,0 +1 @@
+../gp712/arm-linux-gnueabihf.cmake
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/diag.c b/examples/platforms/qpg7015m/diag.c
new file mode 120000
index 0000000..909d4a2
--- /dev/null
+++ b/examples/platforms/qpg7015m/diag.c
@@ -0,0 +1 @@
+../gp712/diag.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/entropy.c b/examples/platforms/qpg7015m/entropy.c
new file mode 120000
index 0000000..88ca2c0
--- /dev/null
+++ b/examples/platforms/qpg7015m/entropy.c
@@ -0,0 +1 @@
+../gp712/entropy.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/flash.c b/examples/platforms/qpg7015m/flash.c
new file mode 120000
index 0000000..daa0f37
--- /dev/null
+++ b/examples/platforms/qpg7015m/flash.c
@@ -0,0 +1 @@
+../gp712/flash.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/logging.c b/examples/platforms/qpg7015m/logging.c
new file mode 120000
index 0000000..bcd76a0
--- /dev/null
+++ b/examples/platforms/qpg7015m/logging.c
@@ -0,0 +1 @@
+../gp712/logging.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/misc.c b/examples/platforms/qpg7015m/misc.c
new file mode 120000
index 0000000..cf10dfa
--- /dev/null
+++ b/examples/platforms/qpg7015m/misc.c
@@ -0,0 +1 @@
+../gp712/misc.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/openthread-core-qpg7015m-config-check.h b/examples/platforms/qpg7015m/openthread-core-qpg7015m-config-check.h
new file mode 100644
index 0000000..c249326
--- /dev/null
+++ b/examples/platforms/qpg7015m/openthread-core-qpg7015m-config-check.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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_CORE_QPG7015M_CONFIG_CHECK_H_
+#define OPENTHREAD_CORE_QPG7015M_CONFIG_CHECK_H_
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+#error "Platform qpg7015m doesn't support configuration option: OPENTHREAD_CONFIG_TIME_SYNC_ENABLE"
+#endif
+
+#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
+#error "Platform qpg7015m doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
+#endif
+
+#endif /* OPENTHREAD_CORE_QPG7015M_CONFIG_CHECK_H_ */
diff --git a/examples/platforms/qpg7015m/openthread-core-qpg7015m-config.h b/examples/platforms/qpg7015m/openthread-core-qpg7015m-config.h
new file mode 100755
index 0000000..74c466d
--- /dev/null
+++ b/examples/platforms/qpg7015m/openthread-core-qpg7015m-config.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, 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 qpg7015m compile-time configuration constants for OpenThread.
+ */
+
+#ifndef OPENTHREAD_CORE_QPG7015M_CONFIG_H_
+#define OPENTHREAD_CORE_QPG7015M_CONFIG_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_INFO
+ *
+ * The platform-specific string to insert into the OpenThread version string.
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_INFO "QPG7015M"
+
+/**
+ * @def OPENTHREAD_CONFIG_PLATFORM_INFO
+ *
+ * Define to 1 to enable otPlatFlash* APIs to support non-volatile storage.
+ *
+ * When defined to 1, the platform MUST implement the otPlatFlash* APIs
+ * instead of the otPlatSettings*
+ *
+ */
+#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
+ *
+ * Define to 1 if you want to enable software ACK timeout logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+ *
+ * Define to 1 if you want to enable software retransmission logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RETRANSMIT_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE
+ *
+ * Define to 1 if you want to enable software CSMA-CA backoff logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+ *
+ * Define to 1 if you want to enable software transmission security logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+ *
+ * Define to 1 to enable software transmission target time logic.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DIAG_ENABLE
+ *
+ * Define as 1 to enable the diag feature.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DIAG_ENABLE
+#define OPENTHREAD_CONFIG_DIAG_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+ *
+ * Define as 1 to enable SPI NCP interface.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
+ *
+ * Define as 1 to enable UART NCP interface.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
+#endif
+
+#endif // OPENTHREAD_CORE_QPG7015M_CONFIG_H_
diff --git a/examples/platforms/qpg7015m/platform_qorvo.h b/examples/platforms/qpg7015m/platform_qorvo.h
new file mode 120000
index 0000000..d8fa024
--- /dev/null
+++ b/examples/platforms/qpg7015m/platform_qorvo.h
@@ -0,0 +1 @@
+../gp712/platform_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/radio.c b/examples/platforms/qpg7015m/radio.c
new file mode 120000
index 0000000..0f26eb0
--- /dev/null
+++ b/examples/platforms/qpg7015m/radio.c
@@ -0,0 +1 @@
+../gp712/radio.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/radio_qorvo.h b/examples/platforms/qpg7015m/radio_qorvo.h
new file mode 120000
index 0000000..4fb8f67
--- /dev/null
+++ b/examples/platforms/qpg7015m/radio_qorvo.h
@@ -0,0 +1 @@
+../gp712/radio_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/random_qorvo.h b/examples/platforms/qpg7015m/random_qorvo.h
new file mode 120000
index 0000000..2cfcf18
--- /dev/null
+++ b/examples/platforms/qpg7015m/random_qorvo.h
@@ -0,0 +1 @@
+../gp712/random_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/system.c b/examples/platforms/qpg7015m/system.c
new file mode 120000
index 0000000..3f7a267
--- /dev/null
+++ b/examples/platforms/qpg7015m/system.c
@@ -0,0 +1 @@
+../gp712/system.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/uart-posix.c b/examples/platforms/qpg7015m/uart-posix.c
new file mode 120000
index 0000000..05e781a
--- /dev/null
+++ b/examples/platforms/qpg7015m/uart-posix.c
@@ -0,0 +1 @@
+../gp712/uart-posix.c
\ No newline at end of file
diff --git a/examples/platforms/qpg7015m/uart_qorvo.h b/examples/platforms/qpg7015m/uart_qorvo.h
new file mode 120000
index 0000000..b58c124
--- /dev/null
+++ b/examples/platforms/qpg7015m/uart_qorvo.h
@@ -0,0 +1 @@
+../gp712/uart_qorvo.h
\ No newline at end of file
diff --git a/examples/platforms/samr21/README.md b/examples/platforms/samr21/README.md
index e5b9dfe..5e5a35a 100644
--- a/examples/platforms/samr21/README.md
+++ b/examples/platforms/samr21/README.md
@@ -195,7 +195,7 @@
For a list of all available commands, visit [OpenThread CLI Reference README.md][cli].
-[cli]: https://github.com/openthread/openthread/blob/master/src/cli/README.md
+[cli]: https://github.com/openthread/openthread/blob/main/src/cli/README.md
## Other boards
diff --git a/examples/platforms/samr21/openthread-core-samr21-config.h b/examples/platforms/samr21/openthread-core-samr21-config.h
index 0397a42..54b22a9 100644
--- a/examples/platforms/samr21/openthread-core-samr21-config.h
+++ b/examples/platforms/samr21/openthread-core-samr21-config.h
@@ -75,11 +75,11 @@
#define OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER 5
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
#endif // OPENTHREAD_CORE_SAMR21_CONFIG_H_
diff --git a/examples/platforms/samr21/uart.c b/examples/platforms/samr21/uart.c
index 8f8aa1e..6a5ebc6 100644
--- a/examples/platforms/samr21/uart.c
+++ b/examples/platforms/samr21/uart.c
@@ -34,7 +34,7 @@
#include "asf.h"
-#include <openthread/platform/uart.h>
+#include "utils/uart.h"
enum
{
diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt
index 9352fba..fb670f4 100644
--- a/examples/platforms/simulation/CMakeLists.txt
+++ b/examples/platforms/simulation/CMakeLists.txt
@@ -52,8 +52,7 @@
"_BSD_SOURCE=1"
"_DEFAULT_SOURCE=1"
"OPENTHREAD_EXAMPLES_SIMULATION=1"
- "OPENTHREAD_POSIX=1"
- "OPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
)
set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c
index 51182eb..a92841e 100644
--- a/examples/platforms/simulation/radio.c
+++ b/examples/platforms/simulation/radio.c
@@ -117,6 +117,7 @@
static int8_t sTxPower = 0;
static int8_t sCcaEdThresh = -74;
static int8_t sLnaGain = 0;
+static uint16_t sRegionCode = 0;
enum
{
@@ -678,7 +679,7 @@
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (sCslPeriod > 0)
+ if (sCslPeriod > 0 && !sTransmitFrame.mInfo.mTxInfo.mIsARetx)
{
otMacFrameSetCslIe(&sTransmitFrame, (uint16_t)sCslPeriod, getCslPhase());
}
@@ -1236,3 +1237,23 @@
return otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics);
}
#endif
+
+otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ sRegionCode = aRegionCode;
+ return OT_ERROR_NONE;
+}
+
+otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aRegionCode != NULL, error = OT_ERROR_INVALID_ARGS);
+
+ *aRegionCode = sRegionCode;
+exit:
+ return error;
+}
diff --git a/examples/platforms/simulation/spi-stubs.c b/examples/platforms/simulation/spi-stubs.c
index 7c0dd62..585bca7 100644
--- a/examples/platforms/simulation/spi-stubs.c
+++ b/examples/platforms/simulation/spi-stubs.c
@@ -33,7 +33,6 @@
#include <openthread/config.h>
#include <openthread/platform/spi-slave.h>
-#include <openthread/platform/uart.h>
#if OPENTHREAD_CONFIG_NCP_SPI_ENABLE
diff --git a/examples/platforms/simulation/trel.c b/examples/platforms/simulation/trel.c
index a77a1c3..8e53962 100644
--- a/examples/platforms/simulation/trel.c
+++ b/examples/platforms/simulation/trel.c
@@ -46,35 +46,64 @@
#define TREL_MAX_PENDING_TX 5
-typedef struct PendingTx
+OT_TOOL_PACKED_BEGIN
+struct PacketHeader
{
- uint8_t mPacketBuffer[TREL_MAX_PACKET_SIZE];
- uint16_t mPacketLength;
+ otIp6Address mSrcIp6Address;
otIp6Address mDestIp6Address;
-} PendingTx;
+ uint16_t mPort;
+} OT_TOOL_PACKED_END;
-static uint8_t sNumPendingTx = 0;
-static PendingTx sPendingTx[TREL_MAX_PENDING_TX];
+typedef struct PacketHeader PacketHeader;
-static int sTxFd = -1;
-static int sRxFd = -1;
-static uint16_t sPortOffset = 0;
-static bool sEnabled = true;
+OT_TOOL_PACKED_BEGIN
+struct Packet
+{
+ PacketHeader mHeader;
+ uint8_t mPayload[TREL_MAX_PACKET_SIZE];
+ uint16_t mLength; // Total packet length including the header.
+} OT_TOOL_PACKED_END;
+
+typedef struct Packet Packet;
+
+static uint8_t sNumPendingTx = 0;
+static Packet sPendingTx[TREL_MAX_PENDING_TX];
+
+static int sTxFd = -1;
+static int sRxFd = -1;
+static uint16_t sPortOffset = 0;
+static bool sEnabled = true;
+static otIp6Address sUnicastAddress;
+static otIp6Address sMulticastAddress;
+static uint16_t sUdpPort;
#if DEBUG_LOG
-static void dumpBuffer(const uint8_t *aBuffer, uint16_t aLength)
+static void dumpBuffer(const void *aBuffer, uint16_t aLength)
{
+ const uint8_t *buffer = (const uint8_t *)aBuffer;
fprintf(stderr, "[ (len:%d) ", aLength);
while (aLength--)
{
- fprintf(stderr, "%02x ", *aBuffer++);
+ fprintf(stderr, "%02x ", *buffer++);
}
fprintf(stderr, "]");
}
+
+static const char *ip6AddrToString(const void *aAddress)
+{
+ static char string[INET6_ADDRSTRLEN];
+
+ return inet_ntop(AF_INET6, aAddress, string, sizeof(string));
+}
#endif
+static bool ip6AddrsAreEqual(const otIp6Address *aFirst, const otIp6Address *aSecond)
+{
+ return (memcmp(aFirst, aSecond, sizeof(otIp6Address)) == 0);
+}
+
static void initFds(void)
{
int fd;
@@ -148,7 +177,7 @@
}
}
-void sendPendingTxPackets(void)
+static void sendPendingTxPackets(void)
{
ssize_t rval;
struct sockaddr_in sockaddr;
@@ -163,12 +192,11 @@
{
#if DEBUG_LOG
fprintf(stderr, "\n[trel-udp] Sending packet (num:%d)", i);
- dumpBuffer(sPendingTx[i].mPacketBuffer, sPendingTx[i].mPacketLength);
+ dumpBuffer(&sPendingTx[i], sPendingTx[i].mLength);
fprintf(stderr, "\n");
#endif
- rval = sendto(sTxFd, sPendingTx[i].mPacketBuffer, sPendingTx[i].mPacketLength, 0, (struct sockaddr *)&sockaddr,
- sizeof(sockaddr));
+ rval = sendto(sTxFd, &sPendingTx[i], sPendingTx[i].mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (rval < 0)
{
@@ -183,23 +211,41 @@
//---------------------------------------------------------------------------------------------------------------------
// otPlatTrel
-void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aPort)
+void otPlatTrelUdp6Init(otInstance *aInstance, const otIp6Address *aUnicastAddress, uint16_t aUdpPort)
{
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aUnicastAddress);
- OT_UNUSED_VARIABLE(aPort);
+
+ sUnicastAddress = *aUnicastAddress;
+ sUdpPort = aUdpPort;
+
+#if DEBUG_LOG
+ fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6Init(aUnicastAddress:%s, aUdpPort:%d)\n",
+ ip6AddrToString(aUnicastAddress), aUdpPort);
+#endif
}
void otPlatTrelUdp6UpdateAddress(otInstance *aInstance, const otIp6Address *aUnicastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aUnicastAddress);
+
+ sUnicastAddress = *aUnicastAddress;
+
+#if DEBUG_LOG
+ fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6UpdateAddress(aUnicastAddress:%s)\n",
+ ip6AddrToString(aUnicastAddress));
+#endif
}
void otPlatTrelUdp6SubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aMulticastAddress)
{
OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aMulticastAddress);
+
+ sMulticastAddress = *aMulticastAddress;
+
+#if DEBUG_LOG
+ fprintf(stderr, "\n[trel-udp6] otPlatTrelUdp6SubscribeMulticastAddress(aMulticastAddress:%s)\n",
+ ip6AddrToString(aMulticastAddress));
+#endif
}
otError otPlatTrelUdp6SendTo(otInstance * aInstance,
@@ -208,16 +254,20 @@
const otIp6Address *aDestAddress)
{
otError error = OT_ERROR_NONE;
+ Packet *packet;
OT_UNUSED_VARIABLE(aInstance);
otEXPECT(sEnabled);
otEXPECT_ACTION(sNumPendingTx < TREL_MAX_PENDING_TX, error = OT_ERROR_ABORT);
+ otEXPECT_ACTION(aLength <= TREL_MAX_PACKET_SIZE, error = OT_ERROR_ABORT);
- memcpy(sPendingTx[sNumPendingTx].mPacketBuffer, aBuffer, aLength);
- sPendingTx[sNumPendingTx].mPacketLength = aLength;
- memcpy(&sPendingTx[sNumPendingTx].mDestIp6Address, aDestAddress, sizeof(otIp6Address));
- sNumPendingTx++;
+ packet = &sPendingTx[sNumPendingTx++];
+ packet->mHeader.mSrcIp6Address = sUnicastAddress;
+ packet->mHeader.mDestIp6Address = *aDestAddress;
+ packet->mHeader.mPort = sUdpPort;
+ packet->mLength = aLength + sizeof(PacketHeader);
+ memcpy(packet->mPayload, aBuffer, aLength);
exit:
return error;
@@ -306,11 +356,10 @@
if (FD_ISSET(sRxFd, aReadFdSet))
{
- uint8_t rxPacketBuffer[TREL_MAX_PACKET_SIZE];
- uint16_t rxPacketLength;
- ssize_t rval;
+ Packet rxPacket;
+ ssize_t rval;
- rval = recvfrom(sRxFd, (char *)rxPacketBuffer, sizeof(rxPacketBuffer), 0, NULL, NULL);
+ rval = recvfrom(sRxFd, (char *)&rxPacket, sizeof(rxPacket) - sizeof(rxPacket.mLength), 0, NULL, NULL);
if (rval < 0)
{
@@ -318,16 +367,21 @@
exit(EXIT_FAILURE);
}
- rxPacketLength = (uint16_t)(rval);
+ rxPacket.mLength = (uint16_t)(rval);
#if DEBUG_LOG
fprintf(stderr, "\n[trel-udp6] recvdPacket()");
- dumpBuffer(rxPacketBuffer, rxPacketLength);
+ fprintf(stderr, " src:%s", ip6AddrToString(&rxPacket.mHeader.mSrcIp6Address));
+ fprintf(stderr, " dst:%s", ip6AddrToString(&rxPacket.mHeader.mDestIp6Address));
+ fprintf(stderr, " port:%u ", rxPacket.mHeader.mPort);
+ dumpBuffer(&rxPacket, rxPacket.mLength);
fprintf(stderr, "\n");
#endif
- if (sEnabled)
+ if (sEnabled && (rxPacket.mHeader.mPort == sUdpPort) &&
+ (ip6AddrsAreEqual(&rxPacket.mHeader.mDestIp6Address, &sUnicastAddress) ||
+ ip6AddrsAreEqual(&rxPacket.mHeader.mDestIp6Address, &sMulticastAddress)))
{
- otPlatTrelUdp6HandleReceived(aInstance, rxPacketBuffer, rxPacketLength);
+ otPlatTrelUdp6HandleReceived(aInstance, rxPacket.mPayload, rxPacket.mLength - sizeof(PacketHeader));
}
}
}
diff --git a/examples/platforms/simulation/uart.c b/examples/platforms/simulation/uart.c
index 777bbed..3bbcfac 100644
--- a/examples/platforms/simulation/uart.c
+++ b/examples/platforms/simulation/uart.c
@@ -39,9 +39,9 @@
#include <unistd.h>
#include <openthread/platform/debug_uart.h>
-#include <openthread/platform/uart.h>
#include "utils/code_utils.h"
+#include "utils/uart.h"
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
diff --git a/examples/platforms/simulation/virtual_time/platform-sim.c b/examples/platforms/simulation/virtual_time/platform-sim.c
index dfe7599..819a460 100644
--- a/examples/platforms/simulation/virtual_time/platform-sim.c
+++ b/examples/platforms/simulation/virtual_time/platform-sim.c
@@ -48,7 +48,8 @@
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
-#include <openthread/platform/uart.h>
+
+#include "utils/uart.h"
uint32_t gNodeId = 1;
@@ -168,7 +169,7 @@
otError otPlatUartFlush(void)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return OT_ERROR_NONE;
}
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
diff --git a/examples/platforms/utils/Makefile.am b/examples/platforms/utils/Makefile.am
index a8cf2e4..53cd3db 100644
--- a/examples/platforms/utils/Makefile.am
+++ b/examples/platforms/utils/Makefile.am
@@ -29,19 +29,32 @@
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
lib_LIBRARIES = libopenthread-platform-utils.a
+noinst_LTLIBRARIES = libutils-link-metrics.la
-libopenthread_platform_utils_a_CPPFLAGS = \
+COMMON_FLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/jlink/SEGGER_RTT_V640/RTT \
$(NULL)
+libutils_link_metrics_la_CPPFLAGS = \
+ $(COMMON_FLAGS) \
+ -fno-threadsafe-statics \
+ $(NULL)
+
+libutils_link_metrics_la_SOURCES = \
+ link_metrics.cpp \
+ link_metrics.h \
+ $(NULL)
+
+libopenthread_platform_utils_a_CPPFLAGS = \
+ $(COMMON_FLAGS) \
+ $(NULL)
+
libopenthread_platform_utils_a_SOURCES = \
code_utils.h \
debug_uart.c \
- link_metrics.cpp \
- link_metrics.h \
logging_rtt.c \
logging_rtt.h \
mac_frame.cpp \
@@ -51,6 +64,11 @@
settings_ram.c \
soft_source_match_table.c \
soft_source_match_table.h \
+ uart.h \
+ $(NULL)
+
+libopenthread_platform_utils_a_LIBADD = \
+ libutils-link-metrics.la \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/examples/platforms/utils/link_metrics.cpp b/examples/platforms/utils/link_metrics.cpp
index f73f131..883ed59 100644
--- a/examples/platforms/utils/link_metrics.cpp
+++ b/examples/platforms/utils/link_metrics.cpp
@@ -114,6 +114,18 @@
}
/**
+ * This method gets the length of Link Metrics Data.
+ *
+ * @returns The number of bytes for the data.
+ *
+ */
+ uint8_t GetEnhAckDataLen() const
+ {
+ return static_cast<uint8_t>(mLinkMetrics.mLqi) + static_cast<uint8_t>(mLinkMetrics.mLinkMargin) +
+ static_cast<uint8_t>(mLinkMetrics.mRssi);
+ }
+
+ /**
* This method gets the metrics configured for the Enhanced-ACK Based Probing.
*
* @returns The metrics configured.
@@ -236,4 +248,16 @@
exit:
return bytes;
}
+
+uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress)
+{
+ uint8_t len = 0;
+ LinkMetricsDataInfo *dataInfo = GetLinkMetricsInfoByMacAddress(aMacAddress);
+
+ VerifyOrExit(dataInfo != nullptr);
+ len = dataInfo->GetEnhAckDataLen();
+
+exit:
+ return len;
+}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
diff --git a/examples/platforms/utils/link_metrics.h b/examples/platforms/utils/link_metrics.h
index 1582b87..099d64b 100644
--- a/examples/platforms/utils/link_metrics.h
+++ b/examples/platforms/utils/link_metrics.h
@@ -97,6 +97,16 @@
*/
uint8_t otLinkMetricsEnhAckGenData(const otMacAddress *aMacAddress, uint8_t aLqi, int8_t aRssi, uint8_t *aData);
+/**
+ * This method returns the data length of Enhanced-ACK Based Probing for a specific Initiator.
+ *
+ * @param[in] aMacAddress The Mac address of the Initiator.
+ *
+ * @returns The size of data. `0` if it's not configured for the Initiator.
+ *
+ */
+uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp
index 24c0dea..eab1398 100644
--- a/examples/platforms/utils/mac_frame.cpp
+++ b/examples/platforms/utils/mac_frame.cpp
@@ -91,6 +91,26 @@
return static_cast<const Mac::Frame *>(aFrame)->GetAckRequest();
}
+static void GetOtMacAddress(const Mac::Address &aInAddress, otMacAddress *aOutAddress)
+{
+ switch (aInAddress.GetType())
+ {
+ case Mac::Address::kTypeNone:
+ aOutAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
+ break;
+
+ case Mac::Address::kTypeShort:
+ aOutAddress->mType = OT_MAC_ADDRESS_TYPE_SHORT;
+ aOutAddress->mAddress.mShortAddress = aInAddress.GetShort();
+ break;
+
+ case Mac::Address::kTypeExtended:
+ aOutAddress->mType = OT_MAC_ADDRESS_TYPE_EXTENDED;
+ aOutAddress->mAddress.mExtAddress = aInAddress.GetExtended();
+ break;
+ }
+}
+
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
{
otError error;
@@ -99,22 +119,21 @@
error = static_cast<const Mac::Frame *>(aFrame)->GetSrcAddr(address);
SuccessOrExit(error);
- switch (address.GetType())
- {
- case Mac::Address::kTypeNone:
- aMacAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
- break;
+ GetOtMacAddress(address, aMacAddress);
- case Mac::Address::kTypeShort:
- aMacAddress->mType = OT_MAC_ADDRESS_TYPE_SHORT;
- aMacAddress->mAddress.mShortAddress = address.GetShort();
- break;
+exit:
+ return error;
+}
- case Mac::Address::kTypeExtended:
- aMacAddress->mType = OT_MAC_ADDRESS_TYPE_EXTENDED;
- aMacAddress->mAddress.mExtAddress = address.GetExtended();
- break;
- }
+otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
+{
+ otError error;
+ Mac::Address address;
+
+ error = static_cast<const Mac::Frame *>(aFrame)->GetDstAddr(address);
+ SuccessOrExit(error);
+
+ GetOtMacAddress(address, aMacAddress);
exit:
return error;
@@ -211,7 +230,7 @@
{
assert(aDest != nullptr);
- reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::Frame::kHeaderIeCsl);
+ reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::CslIe::kHeaderIeId);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(sizeof(Mac::CslIe));
return sizeof(Mac::HeaderIe) + sizeof(Mac::CslIe);
@@ -225,7 +244,7 @@
assert(aDest != nullptr);
- reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::Frame::kHeaderIeVendor);
+ reinterpret_cast<Mac::HeaderIe *>(aDest)->SetId(Mac::ThreadIe::kHeaderIeId);
reinterpret_cast<Mac::HeaderIe *>(aDest)->SetLength(len);
aDest += sizeof(Mac::HeaderIe);
diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h
index 5aef724..1d6c39a 100644
--- a/examples/platforms/utils/mac_frame.h
+++ b/examples/platforms/utils/mac_frame.h
@@ -154,6 +154,18 @@
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
/**
+ * Get destination MAC address.
+ *
+ * @param[in] aFrame A pointer to the frame.
+ * @param[out] aMacAddress A pointer to MAC address.
+ *
+ * @retval OT_ERROR_NONE Successfully got the destination MAC address.
+ * @retval OT_ERROR_PARSE Failed to parse the destination MAC address.
+ *
+ */
+otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
+
+/**
* Get the sequence of @p aFrame.
*
* @param[in] aFrame A pointer to the frame.
diff --git a/include/openthread/platform/uart.h b/examples/platforms/utils/uart.h
similarity index 100%
rename from include/openthread/platform/uart.h
rename to examples/platforms/utils/uart.h
diff --git a/include/Makefile.am b/include/Makefile.am
index e5554d3..427133e 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -43,15 +43,17 @@
openthread/channel_monitor.h \
openthread/child_supervision.h \
openthread/cli.h \
- openthread/coap_secure.h \
openthread/coap.h \
+ openthread/coap_secure.h \
openthread/commissioner.h \
+ openthread/config.h \
openthread/crypto.h \
openthread/dataset.h \
openthread/dataset_ftd.h \
openthread/dataset_updater.h \
openthread/diag.h \
openthread/dns.h \
+ openthread/dns_client.h \
openthread/entropy.h \
openthread/error.h \
openthread/heap.h \
@@ -70,10 +72,13 @@
openthread/netdata.h \
openthread/netdiag.h \
openthread/network_time.h \
+ openthread/ping_sender.h \
openthread/random_crypto.h \
openthread/random_noncrypto.h \
openthread/server.h \
openthread/sntp.h \
+ openthread/srp_client.h \
+ openthread/srp_server.h \
openthread/tasklet.h \
openthread/thread.h \
openthread/thread_ftd.h \
@@ -86,22 +91,23 @@
ot_platform_headers = \
openthread/platform/alarm-micro.h \
openthread/platform/alarm-milli.h \
+ openthread/platform/debug_uart.h \
openthread/platform/diag.h \
- openthread/platform/flash.h \
openthread/platform/entropy.h \
- openthread/platform/memory.h \
- openthread/platform/misc.h \
+ openthread/platform/flash.h \
+ openthread/platform/infra_if.h \
openthread/platform/logging.h \
+ openthread/platform/memory.h \
+ openthread/platform/messagepool.h \
+ openthread/platform/misc.h \
openthread/platform/otns.h \
openthread/platform/radio.h \
- openthread/platform/time.h \
- openthread/platform/uart.h \
- openthread/platform/udp.h \
- openthread/platform/spi-slave.h \
openthread/platform/settings.h \
- openthread/platform/messagepool.h \
+ openthread/platform/spi-slave.h \
+ openthread/platform/time.h \
openthread/platform/toolchain.h \
openthread/platform/trel-udp6.h \
+ openthread/platform/udp.h \
$(NULL)
ot_platformdir = $(includedir)/openthread/platform
diff --git a/include/openthread-config-android.h b/include/openthread-config-android.h
index 40e6d9b..0783033 100644
--- a/include/openthread-config-android.h
+++ b/include/openthread-config-android.h
@@ -26,6 +26,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef OPENTHREAD_CONFIG_ANDROID_VERSION_HEADER_ENABLE
+#include <openthread-config-android-version.h>
+#endif
+
/* Define to 1 to enable the border agent feature. */
#define OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE 1
@@ -53,8 +57,8 @@
/* Define to 1 if you want to use legacy network support */
#define OPENTHREAD_CONFIG_LEGACY_ENABLE 0
-/* Define to 1 to enable the NCP UART interface. */
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 0
+/* Define to 1 to enable the NCP HDLC interface. */
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 0
/* Define to 1 to enable posix platform. */
#define OPENTHREAD_PLATFORM_POSIX 0
diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn
index 47b6b73..767f670 100644
--- a/include/openthread/BUILD.gn
+++ b/include/openthread/BUILD.gn
@@ -67,12 +67,14 @@
"coap.h",
"coap_secure.h",
"commissioner.h",
+ "config.h",
"crypto.h",
"dataset.h",
"dataset_ftd.h",
"dataset_updater.h",
"diag.h",
"dns.h",
+ "dns_client.h",
"entropy.h",
"error.h",
"heap.h",
@@ -82,6 +84,7 @@
"jam_detection.h",
"joiner.h",
"link.h",
+ "link_metrics.h",
"link_raw.h",
"logging.h",
"message.h",
@@ -90,12 +93,14 @@
"netdata.h",
"netdiag.h",
"network_time.h",
+ "ping_sender.h",
"platform/alarm-micro.h",
"platform/alarm-milli.h",
"platform/debug_uart.h",
"platform/diag.h",
"platform/entropy.h",
"platform/flash.h",
+ "platform/infra_if.h",
"platform/logging.h",
"platform/memory.h",
"platform/messagepool.h",
@@ -107,12 +112,13 @@
"platform/time.h",
"platform/toolchain.h",
"platform/trel-udp6.h",
- "platform/uart.h",
"platform/udp.h",
"random_crypto.h",
"random_noncrypto.h",
"server.h",
"sntp.h",
+ "srp_client.h",
+ "srp_server.h",
"tasklet.h",
"thread.h",
"thread_ftd.h",
diff --git a/include/openthread/border_router.h b/include/openthread/border_router.h
index e5e413d..c1e4891 100644
--- a/include/openthread/border_router.h
+++ b/include/openthread/border_router.h
@@ -53,6 +53,45 @@
*/
/**
+ * This method initializes the Border Routing Manager on given infrastructure interface.
+ *
+ * @note This method MUST be called before any other otBorderRouting* APIs.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aInfraIfIndex The infrastructure interface index.
+ * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure
+ * interface is running.
+ * @param[in] aInfraIfLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure
+ * interface. NULL if the IPv6 link-local address is missing.
+ *
+ * @retval OT_ERROR_NONE Successfully started the Border Routing Manager on given infrastructure.
+ * @retval OT_ERROR_INVALID_STATE The Border Routing Manager has already been initialized.
+ * @retval OT_ERROR_INVALID_ARGS The index or the IPv6 link-local address of the infra interface is not valid.
+ * @retval OT_ERROR_FAILED Internal failure. Usually due to failure in generating random prefixes.
+ *
+ * @sa otPlatInfraIfStateChanged.
+ *
+ */
+otError otBorderRoutingInit(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ bool aInfraIfIsRunning,
+ const otIp6Address *aInfraIfLinkLocalAddress);
+
+/**
+ * This method enables/disables the Border Routing Manager.
+ *
+ * @note The Border Routing Manager is disabled by default.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnabled A boolean to enable/disable the routing manager.
+ *
+ * @retval OT_ERROR_INVALID_STATE The Border Routing Manager is not initialized yet.
+ * @retval OT_ERROR_NONE Successfully enabled/disabled the Border Routing Manager.
+ *
+ */
+otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
* This method provides a full or stable copy of the local Thread Network Data.
*
* @param[in] aInstance A pointer to an OpenThread instance.
diff --git a/include/openthread/cli.h b/include/openthread/cli.h
index 5a8f54c..56c9868 100644
--- a/include/openthread/cli.h
+++ b/include/openthread/cli.h
@@ -74,37 +74,28 @@
* @param[in] aBufLength A length of the output data stored in the buffer.
* @param[out] aContext A user context pointer.
*
- * @returns Number of bytes processed by the callback.
+ * @returns Number of bytes written by the callback.
*
*/
-typedef int (*otCliConsoleOutputCallback)(const char *aBuf, uint16_t aBufLength, void *aContext);
+typedef int (*otCliOutputCallback)(void *aContext, const char *aFormat, va_list aArguments);
/**
- * Initialize the CLI CONSOLE module.
+ * Initialize the CLI module.
*
* @param[in] aInstance The OpenThread instance structure.
- * @param[in] aCallback A callback method called to process console output.
+ * @param[in] aCallback A callback method called to process CLI output.
* @param[in] aContext A user context pointer.
*
*/
-void otCliConsoleInit(otInstance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext);
+void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
/**
* This method is called to feed in a console input line.
*
- * @param[in] aBuf A pointer to a buffer with an input.
- * @param[in] aBufLength A length of the input data stored in the buffer.
+ * @param[in] aBuf A pointer to a null-terminated string.
*
*/
-void otCliConsoleInputLine(char *aBuf, uint16_t aBufLength);
-
-/**
- * Initialize the CLI UART module.
- *
- * @param[in] aInstance The OpenThread instance structure.
- *
- */
-void otCliUartInit(otInstance *aInstance);
+void otCliInputLine(char *aBuf);
/**
* Set a user command table.
@@ -135,15 +126,6 @@
void otCliOutputFormat(const char *aFmt, ...);
/**
- * Write string to the CLI console
- *
- * @param[in] aString A pointer to the string, which may not be null-terminated.
- * @param[in] aLength Number of bytes.
- *
- */
-void otCliOutput(const char *aString, uint16_t aLength);
-
-/**
* Write error code to the CLI console
*
* If the @p aError is `OT_ERROR_PENDING` nothing will be outputted.
diff --git a/include/openthread/coap.h b/include/openthread/coap.h
index 5089df8..2a2df22 100644
--- a/include/openthread/coap.h
+++ b/include/openthread/coap.h
@@ -144,26 +144,13 @@
OT_COAP_OPTION_LOCATION_QUERY = 20, ///< Location-Query
OT_COAP_OPTION_BLOCK2 = 23, ///< Block2 (RFC7959)
OT_COAP_OPTION_BLOCK1 = 27, ///< Block1 (RFC7959)
+ OT_COAP_OPTION_SIZE2 = 28, ///< Size2 (RFC7959)
OT_COAP_OPTION_PROXY_URI = 35, ///< Proxy-Uri
OT_COAP_OPTION_PROXY_SCHEME = 39, ///< Proxy-Scheme
OT_COAP_OPTION_SIZE1 = 60, ///< Size1
} otCoapOptionType;
/**
- * CoAP Block Size Exponents
- */
-typedef enum otCoapBlockSize
-{
- OT_COAP_BLOCK_SIZE_16 = 0,
- OT_COAP_BLOCK_SIZE_32 = 1,
- OT_COAP_BLOCK_SIZE_64 = 2,
- OT_COAP_BLOCK_SIZE_128 = 3,
- OT_COAP_BLOCK_SIZE_256 = 4,
- OT_COAP_BLOCK_SIZE_512 = 5,
- OT_COAP_BLOCK_SIZE_1024 = 6,
-} otCoapBlockSize;
-
-/**
* This structure represents a CoAP option.
*
*/
@@ -328,6 +315,20 @@
} otCoapOptionContentFormat;
/**
+ * CoAP Block Size Exponents
+ */
+typedef enum otCoapBlockSzx
+{
+ OT_COAP_OPTION_BLOCK_SZX_16 = 0,
+ OT_COAP_OPTION_BLOCK_SZX_32 = 1,
+ OT_COAP_OPTION_BLOCK_SZX_64 = 2,
+ OT_COAP_OPTION_BLOCK_SZX_128 = 3,
+ OT_COAP_OPTION_BLOCK_SZX_256 = 4,
+ OT_COAP_OPTION_BLOCK_SZX_512 = 5,
+ OT_COAP_OPTION_BLOCK_SZX_1024 = 6
+} otCoapBlockSzx;
+
+/**
* This function pointer is called when a CoAP response is received or on the request timeout.
*
* @param[in] aContext A pointer to application-specific context.
@@ -356,6 +357,58 @@
typedef void (*otCoapRequestHandler)(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
/**
+ * This function pointer is called when a CoAP message with an block-wise transfer option is received.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * @param[in] aContext A pointer to application-specific context.
+ * @param[in] aBlock A pointer to the block segment.
+ * @param[in] aPosition The position of @p aBlock in a sequence in bytes.
+ * @param[in] aBlockLength The length of the block segment in bytes.
+ * @param[in] aMore Flag if more block segments are following.
+ * @param[in] aTotalLength The total length in bytes of the transfered information (indicated by a Size1 or Size2
+ * option).
+ *
+ * @retval OT_ERROR_NONE Block segment was stored successfully.
+ * @retval OT_ERROR_NO_BUFS No more memory to store blocks.
+ * @retval OT_ERROR_NO_FRAME_RECEIVED Block segment missing.
+ *
+ */
+typedef otError (*otCoapBlockwiseReceiveHook)(void * aContext,
+ const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength);
+
+/**
+ * This function pointer is called before the next block in a block-wise transfer is sent.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * @param[in] aContext A pointer to application-specific context.
+ * @param[inout] aBlock A pointer to where the block segment can be written to.
+ * @param[in] aPosition The position in a sequence from which to obtain the block segment.
+ * @param[inout] aBlockLength On entry, the maximum block segment length in bytes.
+ * @param[out] aMore A pointer to the flag if more block segments will follow.
+ *
+ * @warning By changing the value of aBlockLength, the block size of the whole exchange is
+ * renegotiated. It is recommended to do this after the first block has been received as
+ * later changes could cause problems with other CoAP implementations.
+ *
+ * @retval OT_ERROR_NONE No error occurred.
+ * @retval OT_ERROR_INVALID_ARGS Block at @p aPosition does not exist.
+ *
+ */
+typedef otError (*otCoapBlockwiseTransmitHook)(void * aContext,
+ uint8_t * aBlock,
+ uint32_t aPosition,
+ uint16_t *aBlockLength,
+ bool * aMore);
+
+/**
* This structure represents a CoAP resource.
*
*/
@@ -368,6 +421,30 @@
} otCoapResource;
/**
+ * This structure represents a CoAP resource with block-wise transfer.
+ *
+ */
+typedef struct otCoapBlockwiseResource
+{
+ const char * mUriPath; ///< The URI Path string
+ otCoapRequestHandler mHandler; ///< The callback for handling a received request
+
+ /** The callback for handling incoming block-wise transfer.
+ * This callback is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ * configuration is enabled.
+ */
+ otCoapBlockwiseReceiveHook mReceiveHook;
+
+ /** The callback for handling outgoing block-wise transfer.
+ * This callback is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ * configuration is enabled.
+ */
+ otCoapBlockwiseTransmitHook mTransmitHook;
+ void * mContext; ///< Application-specific context
+ struct otCoapBlockwiseResource *mNext; ///< The next CoAP resource in the list
+} otCoapBlockwiseResource;
+
+/**
* This structure represents the CoAP transmission parameters.
*
* @note mAckTimeout * ((2 ** (mMaxRetransmit + 1)) - 1) * (mAckRandomFactorNumerator / mAckRandomFactorDenominator)
@@ -539,7 +616,7 @@
* @returns The actual size exponent value.
*
*/
-uint16_t otCoapBlockSizeFromExponent(otCoapBlockSize aSize);
+uint16_t otCoapBlockSizeFromExponent(otCoapBlockSzx aSize);
/**
* This function appends a Block2 option
@@ -554,7 +631,7 @@
* @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
*
*/
-otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSize aSize);
+otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize);
/**
* This function appends a Block1 option
@@ -569,7 +646,7 @@
* @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
*
*/
-otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSize aSize);
+otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize);
/**
* This function appends a Proxy-Uri option.
@@ -805,6 +882,73 @@
const otCoapTxParameters *aTxParameters);
/**
+ * This function sends a CoAP request block-wise with custom transmission parameters.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If the response is expected to be block-wise, a respective hook function should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the message to send.
+ * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
+ * @param[in] aHandler A function pointer that shall be called on response reception or timeout.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ * @param[in] aTxParameters A pointer to transmission parameters for this request. Use NULL for defaults.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
+ *
+ * @retval OT_ERROR_NONE Successfully sent CoAP message.
+ * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
+ *
+ */
+otError otCoapSendRequestBlockWiseWithParameters(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ otCoapResponseHandler aHandler,
+ void * aContext,
+ const otCoapTxParameters * aTxParameters,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook);
+
+/**
+ * This function sends a CoAP request block-wise.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If the response is expected to be block-wise, a respective hook function should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the message to send.
+ * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
+ * @param[in] aHandler A function pointer that shall be called on response reception or timeout.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
+ *
+ * @retval OT_ERROR_NONE Successfully sent CoAP message.
+ * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
+ *
+ */
+static inline otError otCoapSendRequestBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ otCoapResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
+{
+ // NOLINTNEXTLINE(modernize-use-nullptr)
+ return otCoapSendRequestBlockWiseWithParameters(aInstance, aMessage, aMessageInfo, aHandler, aContext, NULL,
+ aTransmitHook, aReceiveHook);
+}
+
+/**
* This function sends a CoAP request.
*
* If a response for a request is expected, respective function and context information should be provided.
@@ -871,6 +1015,24 @@
void otCoapRemoveResource(otInstance *aInstance, otCoapResource *aResource);
/**
+ * This function adds a block-wise resource to the CoAP server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aResource A pointer to the resource.
+ *
+ */
+void otCoapAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
+
+/**
+ * This function removes a block-wise resource from the CoAP server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aResource A pointer to the resource.
+ *
+ */
+void otCoapRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
+
+/**
* This function sets the default handler for unhandled CoAP requests.
*
* @param[in] aInstance A pointer to an OpenThread instance.
@@ -898,6 +1060,56 @@
const otCoapTxParameters *aTxParameters);
/**
+ * This function sends a CoAP response block-wise from the server with custom transmission parameters.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the CoAP response to send.
+ * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
+ * @param[in] aTxParameters A pointer to transmission parameters for this response. Use NULL for defaults.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ *
+ * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
+ *
+ */
+otError otCoapSendResponseBlockWiseWithParameters(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ const otCoapTxParameters * aTxParameters,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook);
+
+/**
+ * This function sends a CoAP response block-wise from the server.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the CoAP response to send.
+ * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ *
+ * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
+ *
+ */
+static inline otError otCoapSendResponseBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook)
+{
+ // NOLINTNEXTLINE(modernize-use-nullptr)
+ return otCoapSendResponseBlockWiseWithParameters(aInstance, aMessage, aMessageInfo, NULL, aContext, aTransmitHook);
+}
+
+/**
* This function sends a CoAP response from the server.
*
* @param[in] aInstance A pointer to an OpenThread instance.
diff --git a/include/openthread/coap_secure.h b/include/openthread/coap_secure.h
index 11caec5..ee17716 100644
--- a/include/openthread/coap_secure.h
+++ b/include/openthread/coap_secure.h
@@ -230,6 +230,35 @@
bool otCoapSecureIsConnectionActive(otInstance *aInstance);
/**
+ * This method sends a CoAP request block-wise over secure DTLS connection.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A reference to the message to send.
+ * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aTransmitHook A function pointer that is called on Block1 response reception.
+ * @param[in] aReceiveHook A function pointer that is called on Block2 response reception.
+ *
+ * @retval OT_ERROR_NONE Successfully sent CoAP message.
+ * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
+ * @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized.
+ *
+ */
+otError otCoapSecureSendRequestBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ otCoapResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook);
+
+/**
* This method sends a CoAP request over secure DTLS connection.
*
* If a response for a request is expected, respective function and context information should be provided.
@@ -270,6 +299,24 @@
void otCoapSecureRemoveResource(otInstance *aInstance, otCoapResource *aResource);
/**
+ * This function adds a block-wise resource to the CoAP Secure server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aResource A pointer to the resource.
+ *
+ */
+void otCoapSecureAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
+
+/**
+ * This function removes a block-wise resource from the CoAP Secure server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aResource A pointer to the resource.
+ *
+ */
+void otCoapSecureRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource);
+
+/**
* This function sets the default handler for unhandled CoAP Secure requests.
*
* @param[in] aInstance A pointer to an OpenThread instance.
@@ -293,6 +340,28 @@
void * aContext);
/**
+ * This function sends a CoAP response block-wise from the CoAP Secure server.
+ *
+ * This function is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration
+ * is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMessage A pointer to the CoAP response to send.
+ * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage.
+ * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
+ * @param[in] aTransmitHook A function pointer that is called on Block1 request reception.
+ *
+ * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
+ *
+ */
+otError otCoapSecureSendResponseBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook);
+
+/**
* This function sends a CoAP response from the CoAP Secure server.
*
* @param[in] aInstance A pointer to an OpenThread instance.
diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h
index 04d805d..8ec38d2 100644
--- a/include/openthread/dataset.h
+++ b/include/openthread/dataset.h
@@ -44,7 +44,7 @@
#endif
/**
- * @addtogroup api-thread-general
+ * @addtogroup api-operational-dataset
*
* @{
*
diff --git a/include/openthread/dataset_ftd.h b/include/openthread/dataset_ftd.h
index 4e28aae..f1ae621 100644
--- a/include/openthread/dataset_ftd.h
+++ b/include/openthread/dataset_ftd.h
@@ -43,7 +43,7 @@
#endif
/**
- * @addtogroup api-thread-general
+ * @addtogroup api-operational-dataset
*
* @{
*
diff --git a/include/openthread/dataset_updater.h b/include/openthread/dataset_updater.h
index 5706863..627ddb3 100644
--- a/include/openthread/dataset_updater.h
+++ b/include/openthread/dataset_updater.h
@@ -43,7 +43,7 @@
#endif
/**
- * @addtogroup api-dataset-updater
+ * @addtogroup api-operational-dataset
*
* @brief
* This module includes functions for Dataset Updater.
@@ -80,7 +80,6 @@
* @param[in] aDataset A pointer to the Dataset containing the fields to change.
* @param[in] aCallback A callback to indicate when Dataset update request finishes.
* @param[in] aContext An arbitrary context passed to callback.
- * @param[in] aRetryWaitInterval The wait time after sending Pending dataset before retrying (interval in ms).
*
* @retval OT_ERROR_NONE Dataset update started successfully (@p aCallback will be invoked on completion).
* @retval OT_ERROR_INVALID_STATE Device is disabled (MLE is disabled).
@@ -92,8 +91,7 @@
otError otDatasetUpdaterRequestUpdate(otInstance * aInstance,
const otOperationalDataset *aDataset,
otDatasetUpdaterCallback aCallback,
- void * aContext,
- uint32_t aReryWaitInterval);
+ void * aContext);
/**
* This function cancels an ongoing (if any) Operational Dataset update request.
diff --git a/include/openthread/dns.h b/include/openthread/dns.h
index a964781..f34322b 100644
--- a/include/openthread/dns.h
+++ b/include/openthread/dns.h
@@ -29,14 +29,15 @@
/**
* @file
* @brief
- * This file defines the top-level dns functions for the OpenThread library.
+ * This file defines the top-level DNS functions for the OpenThread library.
*/
#ifndef OPENTHREAD_DNS_H_
#define OPENTHREAD_DNS_H_
-#include <openthread/ip6.h>
-#include <openthread/message.h>
+#include <stdint.h>
+
+#include <openthread/error.h>
#ifdef __cplusplus
extern "C" {
@@ -52,60 +53,92 @@
*
*/
-#define OT_DNS_MAX_HOSTNAME_LENGTH 62 ///< Maximum allowed hostname length (maximum label size - 1 for compression).
+#define OT_DNS_MAX_NAME_SIZE 255 ///< Maximum name string size (includes null char at the end of string).
-#define OT_DNS_DEFAULT_SERVER_IP "2001:4860:4860::8888" ///< Defines default DNS Server address - Google DNS.
-#define OT_DNS_DEFAULT_SERVER_PORT 53 ///< Defines default DNS Server port.
+#define OT_DNS_MAX_LABEL_SIZE 64 ///< Maximum label string size (include null char at the end of string).
+
+#define OT_DNS_TXT_KEY_MIN_LENGTH 1 ///< Minimum length of TXT record key string (RFC 6763 - section 6.4).
+
+#define OT_DNS_TXT_KEY_MAX_LENGTH 9 ///< Recommended maximum length of TXT record key string (RFC 6763 - section 6.4).
/**
- * This structure implements DNS Query parameters.
+ * This structure represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3).
+ *
+ * The string buffers pointed to by `mKey` and `mValue` MUST persist and remain unchanged after an instance of such
+ * structure is passed to OpenThread (as part of `otSrpClientService` instance).
+ *
+ * An array of `otDnsTxtEntry` entries are used in `otSrpClientService` to specify the full TXT record (a list of
+ * entries).
*
*/
-typedef struct otDnsQuery
+typedef struct otDnsTxtEntry
{
- const char * mHostname; ///< Identifies hostname to be found. It shall not change during resolving.
- const otMessageInfo *mMessageInfo; ///< A reference to the message info related with DNS Server.
- bool mNoRecursion; ///< If cleared, it directs name server to pursue the query recursively.
-} otDnsQuery;
+ /**
+ * The TXT record key string.
+ *
+ * If `mKey` is not NULL, then it MUST be a null-terminated C string. The entry is treated as key/value pair with
+ * `mValue` buffer providing the value.
+ * - The entry is encoded as follows:
+ * - A single string length byte followed by "key=value" format (without the quotation marks).
+ - In this case, the overall encoded length must be 255 bytes or less.
+ * - If `mValue` is NULL, then key is treated as a boolean attribute and encoded as "key" (with no `=`).
+ * - If `mValue` is not NULL but `mValueLength` is zero, then it is treated as empty value and encoded as "key=".
+ *
+ * If `mKey` is NULL, then `mValue` buffer is treated as an already encoded TXT-DATA and is appended as is in the
+ * DNS message.
+ *
+ */
+ const char * mKey;
+ const uint8_t *mValue; ///< The TXT record value or already encoded TXT-DATA (depending on `mKey`).
+ uint16_t mValueLength; ///< Number of bytes in `mValue` buffer.
+} otDnsTxtEntry;
/**
- * This function pointer is called when a DNS response is received.
+ * This structure represents an iterator for TXT record entires (key/value pairs).
*
- * @param[in] aContext A pointer to application-specific context.
- * @param[in] aHostname Identifies hostname related with DNS response.
- * @param[in] aAddress A pointer to the IPv6 address received in DNS response. May be null.
- * @param[in] aTtl Specifies the maximum time in seconds that the resource record may be cached.
- * @param[in] aResult A result of the DNS transaction.
- *
- * @retval OT_ERROR_NONE A response was received successfully and IPv6 address is provided
- * in @p aAddress.
- * @retval OT_ERROR_ABORT A DNS transaction was aborted by stack.
- * @retval OT_ERROR_RESPONSE_TIMEOUT No DNS response has been received within timeout.
- * @retval OT_ERROR_NOT_FOUND A response was received but no IPv6 address has been found.
- * @retval OT_ERROR_FAILED A response was received but status code is different than success.
+ * The data fields in this structure are intended for use by OpenThread core and caller should not read or change them.
*
*/
-typedef void (*otDnsResponseHandler)(void * aContext,
- const char * aHostname,
- const otIp6Address *aAddress,
- uint32_t aTtl,
- otError aResult);
+typedef struct otDnsTxtEntryIterator
+{
+ const void *mPtr;
+ uint16_t mData[2];
+ char mChar[OT_DNS_TXT_KEY_MAX_LENGTH + 1];
+} otDnsTxtEntryIterator;
/**
- * This function sends a DNS query for AAAA (IPv6) record.
+ * This function initializes a TXT record iterator.
*
- * This function is available only if feature `OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE` is enabled.
+ * The buffer pointer @p aTxtData and its content MUST persist and remain unchanged while @p aIterator object
+ * is being used.
*
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aQuery A pointer to specify DNS query parameters.
- * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
- * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aIterator A pointer to the iterator to initialize (MUST NOT be NULL).
+ * @param[in] aTxtData A pointer to buffer containing the encoded TXT data.
+ * @param[in] aTxtDataLength The length (number of bytes) of @p aTxtData.
*
*/
-otError otDnsClientQuery(otInstance * aInstance,
- const otDnsQuery * aQuery,
- otDnsResponseHandler aHandler,
- void * aContext);
+void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t *aTxtData, uint16_t aTxtDataLength);
+
+/**
+ * This function parses the TXT data from an iterator and gets the next TXT record entry (key/value pair).
+ *
+ * The @p aIterator MUST be initialized using `otDnsInitTxtEntryIterator()` before calling this function and the TXT
+ * data buffer used to initialize the iterator MUST persist and remain unchanged. Otherwise the behavior of this
+ * function is undefined.
+ *
+ * If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_MAX_LENGTH` (recommended max key length)
+ * the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and the
+ * entire encoded TXT entry string is returned in `mValue` and `mValueLength`.
+ *
+ * @param[in] aIterator A pointer to the iterator (MUST NOT be NULL).
+ * @param[out] aEntry A pointer to a `otDnsTxtEntry` structure to output the parsed/read entry (MUST NOT be NULL).
+ *
+ * @retval OT_ERROR_NONE The next entry was parsed successfully. @p aEntry is updated.
+ * @retval OT_ERROR_NOT_FOUND No more entries in the TXT data.
+ * @retval OT_ERROR_PARSE The TXT data from @p aIterator is not well-formed.
+ *
+ */
+otError otDnsGetNextTxtEntry(otDnsTxtEntryIterator *aIterator, otDnsTxtEntry *aEntry);
/**
* @}
diff --git a/include/openthread/dns_client.h b/include/openthread/dns_client.h
new file mode 100644
index 0000000..04450ce
--- /dev/null
+++ b/include/openthread/dns_client.h
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2017-2021, 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 top-level DNS functions for the OpenThread library.
+ */
+
+#ifndef OPENTHREAD_DNS_CLIENT_H_
+#define OPENTHREAD_DNS_CLIENT_H_
+
+#include <openthread/dns.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-dns
+ *
+ * @brief
+ * This module includes functions that control DNS communication.
+ *
+ * The functions in this module are available only if feature `OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE` is enabled.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This enumeration type represents the "Recursion Desired" (RD) flag in an `otDnsQueryConfig`.
+ *
+ */
+typedef enum
+{
+ OT_DNS_FLAG_UNSPECIFIED = 0, ///< Indicates the flag is not specified.
+ OT_DNS_FLAG_RECURSION_DESIRED = 1, ///< Indicates DNS name server can resolve the query recursively.
+ OT_DNS_FLAG_NO_RECURSION = 2, ///< Indicates DNS name server can not resolve the query recursively.
+} otDnsRecursionFlag;
+
+/**
+ * This structure represents a DNS query configuration.
+ *
+ * Any of the fields in this structure can be set to zero to indicate that it is not specified. How the unspecified
+ * fields are treated is determined by the function which uses the instance of `otDnsQueryConfig`.
+ *
+ */
+typedef struct otDnsQueryConfig
+{
+ otSockAddr mServerSockAddr; ///< Server address (IPv6 address/port). All zero or zero port for unspecified.
+ uint32_t mResponseTimeout; ///< Wait time (in msec) to rx response. Zero indicates unspecified value.
+ uint8_t mMaxTxAttempts; ///< Maximum tx attempts before reporting failure. Zero for unspecified value.
+ otDnsRecursionFlag mRecursionFlag; ///< Indicates whether the server can resolve the query recursively or not.
+} otDnsQueryConfig;
+
+/**
+ * This function gets the current default query config used by DNS client.
+ *
+ * When OpenThread stack starts, the default DNS query config is determined from a set of OT config options such as
+ * `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS`, `_DEFAULT_SERVER_PORT`, `_DEFAULT_RESPONSE_TIMEOUT`, etc.
+ * (see `config/dns_clinet.h` for all related config options).
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns A pointer to the current default config being used by DNS client.
+ *
+ */
+const otDnsQueryConfig *otDnsClientGetDefaultConfig(otInstance *aInstance);
+
+/**
+ * This function sets the default query config on DNS client.
+ *
+ * @note Any ongoing query will continue to use the config from when it was started. The new default config will be
+ * used for any future DNS queries.
+ *
+ * The @p aConfig can be NULL. In this case the default config will be set to the defaults from OT config options
+ * `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_{}`. This resets the default query config back to to the config when the
+ * OpenThread stack starts.
+ *
+ * In a non-NULL @p aConfig, caller can choose to leave some of the fields in `otDnsQueryConfig` instance unspecified
+ * (value zero). The unspecified fields are replaced by the corresponding OT config option definitions
+ * `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_{}` to form the default query config.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aConfig A pointer to the new query config to use as default.
+ *
+ */
+void otDnsClientSetDefaultConfig(otInstance *aInstance, const otDnsQueryConfig *aConfig);
+
+/**
+ * This type is an opaque representation of a response to an address resolution DNS query.
+ *
+ * Pointers to instance of this type are provided from callback `otDnsAddressCallback`.
+ *
+ */
+typedef struct otDnsAddressResponse otDnsAddressResponse;
+
+/**
+ * This function pointer is called when a DNS response is received for an address resolution query.
+ *
+ * Within this callback the user can use `otDnsAddressResponseGet{Item}()` functions along with the @p aResponse
+ * pointer to get more info about the response.
+ *
+ * The @p aResponse pointer can only be used within this callback and after returning from this function it will not
+ * stay valid, so the user MUST NOT retain the @p aResponse pointer for later use.
+ *
+ * @param[in] aError The result of the DNS transaction.
+ * @param[in] aResponse A pointer to the response (it is always non-NULL).
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ * The @p aError can have the following:
+ *
+ * - OT_ERROR_NONE A response was received successfully.
+ * - OT_ERROR_ABORT A DNS transaction was aborted by stack.
+ * - OT_ERROR_RESPONSE_TIMEOUT No DNS response has been received within timeout.
+ *
+ * If the server rejects the address resolution request the error code from server is mapped as follow:
+ *
+ * - (0) NOERROR Success (no error condition) -> OT_ERROR_NONE
+ * - (1) FORMERR Server unable to interpret due to format error -> OT_ERROR_PARSE
+ * - (2) SERVFAIL Server encountered an internal failure -> OT_ERROR_FAILED
+ * - (3) NXDOMAIN Name that ought to exist, does not exist -> OT_ERROR_NOT_FOUND
+ * - (4) NOTIMP Server does not support the query type (OpCode) -> OT_ERROR_NOT_IMPLEMENTED
+ * - (5) REFUSED Server refused for policy/security reasons -> OT_ERROR_SECURITY
+ * - (6) YXDOMAIN Some name that ought not to exist, does exist -> OT_ERROR_DUPLICATED
+ * - (7) YXRRSET Some RRset that ought not to exist, does exist -> OT_ERROR_DUPLICATED
+ * - (8) NXRRSET Some RRset that ought to exist, does not exist -> OT_ERROR_NOT_FOUND
+ * - (9) NOTAUTH Service is not authoritative for zone -> OT_ERROR_SECURITY
+ * - (10) NOTZONE A name is not in the zone -> OT_ERROR_PARSE
+ * - (20) BADNAME Bad name -> OT_ERROR_PARSE
+ * - (21) BADALG Bad algorithm -> OT_ERROR_SECURITY
+ * - (22) BADTRUN Bad truncation -> OT_ERROR_PARSE
+ * - Other response codes -> OT_ERROR_FAILED
+ *
+ */
+typedef void (*otDnsAddressCallback)(otError aError, const otDnsAddressResponse *aResponse, void *aContext);
+
+/**
+ * This function sends an address resolution DNS query for AAAA (IPv6) record(s) for a given host name.
+ *
+ * The @p aConfig can be NULL. In this case the default config (from `otDnsClientGetDefaultConfig()`) will be used as
+ * the config for this query. In a non-NULL @p aConfig, some of the fields can be left unspecified (value zero). The
+ * unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aHostName The host name for which to query the address (MUST NOT be NULL).
+ * @param[in] aCallback A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aConfig A pointer to the config to use for this query.
+ *
+ * @retval OT_ERROR_NONE Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffer to prepare and send query.
+ *
+ */
+otError otDnsClientResolveAddress(otInstance * aInstance,
+ const char * aHostName,
+ otDnsAddressCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig);
+
+/**
+ * This function gets the full host name associated with an address resolution DNS response.
+ *
+ * This function MUST only be used from `otDnsAddressCallback`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[out] aNameBuffer A buffer to char array to output the full host name (MUST NOT be NULL).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval OT_ERROR_NONE The full host name was read successfully.
+ * @retval OT_ERROR_NO_BUFS The name does not fit in @p aNameBuffer.
+ *
+ */
+otError otDnsAddressResponseGetHostName(const otDnsAddressResponse *aResponse,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize);
+
+/**
+ * This function gets an IPv6 address associated with an address resolution DNS response.
+ *
+ * This function MUST only be used from `otDnsAddressCallback`.
+ *
+ * The response may include multiple IPv6 address records. @p aIndex can be used to iterate through the list of
+ * addresses. Index zero gets the first address and so on. When we reach end of the list, `OT_ERROR_NOT_FOUND` is
+ * returned.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A pointer to a IPv6 address to output the address (MUST NOT be NULL).
+ * @param[out] aTtl A pointer to an `uint32_t` to output TTL for the address. It can be NULL if caller does not
+ * want to get the TTL.
+ *
+ * @retval OT_ERROR_NONE The address was read successfully.
+ * @retval OT_ERROR_NOT_FOUND No address record in @p aResponse at @p aIndex.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsAddressResponseGetAddress(const otDnsAddressResponse *aResponse,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl);
+
+/**
+ * This type is an opaque representation of a response to a browse (service instance enumeration) DNS query.
+ *
+ * Pointers to instance of this type are provided from callback `otDnsBrowseCallback`.
+ *
+ */
+typedef struct otDnsBrowseResponse otDnsBrowseResponse;
+
+/**
+ * This function pointer is called when a DNS response is received for a browse (service instance enumeration) query.
+ *
+ * Within this callback the user can use `otDnsBrowseResponseGet{Item}()` functions along with the @p aResponse
+ * pointer to get more info about the response.
+ *
+ * The @p aResponse pointer can only be used within this callback and after returning from this function it will not
+ * stay valid, so the user MUST NOT retain the @p aResponse pointer for later use.
+ *
+ * @param[in] aError The result of the DNS transaction.
+ * @param[in] aResponse A pointer to the response (it is always non-NULL).
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ * For the full list of possible values for @p aError, please see `otDnsAddressCallback()`.
+ *
+ */
+typedef void (*otDnsBrowseCallback)(otError aError, const otDnsBrowseResponse *aResponse, void *aContext);
+
+/**
+ * This structure provides info for a DNS service instance.
+ *
+ */
+typedef struct otDnsServiceInfo
+{
+ uint32_t mTtl; ///< Service record TTL (in seconds).
+ uint16_t mPort; ///< Service port number.
+ uint16_t mPriority; ///< Service priority.
+ uint16_t mWeight; ///< Service weight.
+ char * mHostNameBuffer; ///< Buffer to output the service host name (can be NULL if not needed).
+ uint16_t mHostNameBufferSize; ///< Size of `mHostNameBuffer`.
+ otIp6Address mHostAddress; ///< The host IPv6 address. Set to all zero if not available.
+ uint32_t mHostAddressTtl; ///< The host address TTL.
+ uint8_t * mTxtData; ///< Buffer to output TXT data (can be NULL if not needed).
+ uint16_t mTxtDataSize; ///< On input, size of `mTxtData` buffer. On output `mTxtData` length.
+ uint32_t mTxtDataTtl; ///< The TXT data TTL.
+} otDnsServiceInfo;
+
+/**
+ * This function sends a DNS browse (service instance enumeration) query for a given service name.
+ *
+ * This function is available when `OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE` is enabled.
+ *
+ * The @p aConfig can be NULL. In this case the default config (from `otDnsClientGetDefaultConfig()`) will be used as
+ * the config for this query. In a non-NULL @p aConfig, some of the fields can be left unspecified (value zero). The
+ * unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aServiceName The service name to query for (MUST NOT be NULL).
+ * @param[in] aCallback A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aConfig A pointer to the config to use for this query.
+ *
+ * @retval OT_ERROR_NONE Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffer to prepare and send query.
+ *
+ */
+otError otDnsClientBrowse(otInstance * aInstance,
+ const char * aServiceName,
+ otDnsBrowseCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig);
+
+/**
+ * This function gets the service name associated with a DNS browse (service instance enumeration) response.
+ *
+ * This function MUST only be used from `otDnsBrowseCallback`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[out] aNameBuffer A buffer to char array to output the service name (MUST NOT be NULL).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval OT_ERROR_NONE The service name was read successfully.
+ * @retval OT_ERROR_NO_BUFS The name does not fit in @p aNameBuffer.
+ *
+ */
+otError otDnsBrowseResponseGetServiceName(const otDnsBrowseResponse *aResponse,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize);
+
+/**
+ * This function gets a service instance associated with a DNS browse (service instance enumeration) response.
+ *
+ * This function 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.
+ *
+ * Note that this function gets the service instance label and not the full service instance name which is of the form
+ * `<Instance>.<Service>.<Domain>`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[in] aIndex The service instance record index to retrieve.
+ * @param[out] aLabelBuffer A buffer to char array to output the service instance label (MUST NOT be NULL).
+ * @param[in] aLabelBufferSize The size of @p aLabelBuffer.
+ *
+ * @retval OT_ERROR_NONE The service instance was read successfully.
+ * @retval OT_ERROR_NO_BUFS The name does not fit in @p aNameBuffer.
+ * @retval OT_ERROR_NOT_FOUND No service instance record in @p aResponse at @p aIndex.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsBrowseResponseGetServiceInstance(const otDnsBrowseResponse *aResponse,
+ uint16_t aIndex,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize);
+
+/**
+ * This function gets info for a service instance from a DNS browse (service instance enumeration) response.
+ *
+ * This function MUST only be used from `otDnsBrowseCallback`.
+ *
+ * A browse DNS response should include the SRV, TXT, and AAAA records for the service instances that are enumerated
+ * (note that it is a SHOULD and not a MUST requirement). This function tries to retrieve this info for a given service
+ * instance when available.
+ *
+ * - If no matching SRV record is found in @p aResponse, `OT_ERROR_NOT_FOUND` is returned.
+ * - If a matching SRV record is found in @p aResponse, @p aServiceInfo is updated and `OT_ERROR_NONE` is returned.
+ * - If no matching TXT record is found in @p aResponse, `mTxtDataSize` in @p aServiceInfo is set to zero.
+ * - If no matching AAAA record is found in @p aResponse, `mHostAddress is set to all zero or unspecified address.
+ * - If there are multiple AAAA records for the host name in @p aResponse, `mHostAddress` is set to the first one. The
+ * other addresses can be retrieved using `otDnsBrowseResponseGetHostAddress()`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[in] aInstanceLabel The service instance label (MUST NOT be NULL).
+ * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information (MUST NOT be NULL).
+ *
+ * @retval OT_ERROR_NONE The service instance info was read. @p aServiceInfo is updated.
+ * @retval OT_ERROR_NOT_FOUND Could not find a matching SRV record for @p aInstanceLabel.
+ * @retval OT_ERROR_NO_BUFS The host name and/or TXT data could not fit in the given buffers.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsBrowseResponseGetServiceInfo(const otDnsBrowseResponse *aResponse,
+ const char * aInstanceLabel,
+ otDnsServiceInfo * aServiceInfo);
+
+/**
+ * This function gets the host IPv6 address from a DNS browse (service instance enumeration) response.
+ *
+ * This function MUST only be used from `otDnsBrowseCallback`.
+ *
+ * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the list of
+ * addresses. Index zero gets the first address and so on. When we reach end of the list, `OT_ERROR_NOT_FOUND` is
+ * returned.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[in] aHostName The host name to get the address (MUST NOT be NULL).
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A pointer to a IPv6 address to output the address (MUST NOT be NULL).
+ * @param[out] aTtl A pointer to an `uint32_t` to output TTL for the address. It can be NULL if caller does
+ * not want to get the TTL.
+ *
+ * @retval OT_ERROR_NONE The address was read successfully.
+ * @retval OT_ERROR_NOT_FOUND No address record for @p aHostname in @p aResponse at @p aIndex.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsBrowseResponseGetHostAddress(const otDnsBrowseResponse *aResponse,
+ const char * aHostName,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl);
+
+/**
+ * This type is an opaque representation of a response to a service instance resolution DNS query.
+ *
+ * Pointers to instance of this type are provided from callback `otDnsAddressCallback`.
+ *
+ */
+typedef struct otDnsServiceResponse otDnsServiceResponse;
+
+/**
+ * This function pointer is called when a DNS response is received for a service instance resolution query.
+ *
+ * Within this callback the user can use `otDnsServiceResponseGet{Item}()` functions along with the @p aResponse
+ * pointer to get more info about the response.
+ *
+ * The @p aResponse pointer can only be used within this callback and after returning from this function it will not
+ * stay valid, so the user MUST NOT retain the @p aResponse pointer for later use.
+ *
+ * @param[in] aError The result of the DNS transaction.
+ * @param[in] aResponse A pointer to the response (it is always non-NULL).
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ * For the full list of possible values for @p aError, please see `otDnsAddressCallback()`.
+ *
+ */
+typedef void (*otDnsServiceCallback)(otError aError, const otDnsServiceResponse *aResponse, void *aContext);
+
+/**
+ * This function sends a DNS service instance resolution query for a given service instance.
+ *
+ * This function is available when `OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE` is enabled.
+ *
+ * The @p aConfig can be NULL. In this case the default config (from `otDnsClientGetDefaultConfig()`) will be used as
+ * the config for this query. In a non-NULL @p aConfig, some of the fields can be left unspecified (value zero). The
+ * unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aInstanceLabel The service instance label.
+ * @param[in] aServiceName The service name (together with @p aInstanceLabel form full instance name).
+ * @param[in] aCallback A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aConfig A pointer to the config to use for this query.
+ *
+ * @retval OT_ERROR_NONE Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval OT_ERROR_NO_BUFS Insufficient buffer to prepare and send query.
+ * @retval OT_ERROR_INVALID_ARGS @p aInstanceLabel is NULL.
+ *
+ */
+otError otDnsClientResolveService(otInstance * aInstance,
+ const char * aInstanceLabel,
+ const char * aServiceName,
+ otDnsServiceCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig);
+
+/**
+ * This function gets the service instance name associated with a DNS service instance resolution response.
+ *
+ * This function MUST only be used from `otDnsServiceCallback`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[out] aLabelBuffer A buffer to char array to output the service instance label (MUST NOT be NULL).
+ * @param[in] aLabelBufferSize The size of @p aLabelBuffer.
+ * @param[out] aNameBuffer A buffer to char array to output the rest of service name (can be NULL if user is
+ * not interested in getting the name.
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval OT_ERROR_NONE The service name was read successfully.
+ * @retval OT_ERROR_NO_BUFS Either the label or name does not fit in the given buffers.
+ *
+ */
+otError otDnsServiceResponseGetServiceName(const otDnsServiceResponse *aResponse,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize);
+
+/**
+ * This function gets info for a service instance from a DNS service instance resolution response.
+ *
+ * This function MUST only be used from `otDnsServiceCallback`.
+ *
+ * - If no matching SRV record is found in @p aResponse, `OT_ERROR_NOT_FOUND` is returned.
+ * - If a matching SRV record is found in @p aResponse, @p aServiceInfo is updated and `OT_ERROR_NONE` is returned.
+ * - If no matching TXT record is found in @p aResponse, `mTxtDataSize` in @p aServiceInfo is set to zero.
+ * - If no matching AAAA record is found in @p aResponse, `mHostAddress is set to all zero or unspecified address.
+ * - If there are multiple AAAA records for the host name in @p aResponse, `mHostAddress` is set to the first one. The
+ * other addresses can be retrieved using `otDnsServiceResponseGetHostAddress()`.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information (MUST NOT be NULL).
+ *
+ * @retval OT_ERROR_NONE The service instance info was read. @p aServiceInfo is updated.
+ * @retval OT_ERROR_NOT_FOUND Could not find a matching SRV record in @p aResponse.
+ * @retval OT_ERROR_NO_BUFS The host name and/or TXT data could not fit in the given buffers.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsServiceResponseGetServiceInfo(const otDnsServiceResponse *aResponse, otDnsServiceInfo *aServiceInfo);
+
+/**
+ * This function gets the host IPv6 address from a DNS service instance resolution response.
+ *
+ * This function MUST only be used from `otDnsServiceCallback`.
+ *
+ * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the list of
+ * addresses. Index zero gets the first address and so on. When we reach end of the list, `OT_ERROR_NOT_FOUND` is
+ * returned.
+ *
+ * @param[in] aResponse A pointer to the response.
+ * @param[in] aHostName The host name to get the address (MUST NOT be NULL).
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A pointer to a IPv6 address to output the address (MUST NOT be NULL).
+ * @param[out] aTtl A pointer to an `uint32_t` to output TTL for the address. It can be NULL if caller does
+ * not want to get the TTL.
+ *
+ * @retval OT_ERROR_NONE The address was read successfully.
+ * @retval OT_ERROR_NOT_FOUND No address record for @p aHostname in @p aResponse at @p aIndex.
+ * @retval OT_ERROR_PARSE Could not parse the records in the @p aResponse.
+ *
+ */
+otError otDnsServiceResponseGetHostAddress(const otDnsServiceResponse *aResponse,
+ const char * aHostName,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_DNS_CLIENT_H_
diff --git a/include/openthread/heap.h b/include/openthread/heap.h
index ca93be3..b3484b8 100644
--- a/include/openthread/heap.h
+++ b/include/openthread/heap.h
@@ -51,27 +51,6 @@
*
*/
-/**
- * Function pointer used to set external CAlloc function for OpenThread.
- *
- * @param[in] aCount Number of allocate units.
- * @param[in] aSize Unit size in bytes.
- *
- * @returns A pointer to the allocated memory.
- *
- * @retval NULL Indicates not enough memory.
- *
- */
-typedef void *(*otHeapCAllocFn)(size_t aCount, size_t aSize);
-
-/**
- * Function pointer used to set external Free function for OpenThread.
- *
- * @param[in] aPointer A pointer to the memory to free.
- *
- */
-typedef void (*otHeapFreeFn)(void *aPointer);
-
// This is a temporary API and would be removed after moving heap to platform.
// TODO: Remove after moving heap to platform.
/**
@@ -89,18 +68,6 @@
void otHeapFree(void *aPointer);
/**
- * This function sets the external heap CAlloc and Free
- * functions to be used by the OpenThread stack.
- *
- * This function must be used before invoking instance initialization.
- *
- * @param[in] aCAlloc A pointer to external CAlloc function.
- * @param[in] aFree A pointer to external Free function.
- *
- */
-void otHeapSetCAllocFree(otHeapCAllocFn aCAlloc, otHeapFreeFn aFree);
-
-/**
* @}
*
*/
diff --git a/include/openthread/icmp6.h b/include/openthread/icmp6.h
index ca8c624..5a02c76 100644
--- a/include/openthread/icmp6.h
+++ b/include/openthread/icmp6.h
@@ -64,6 +64,8 @@
OT_ICMP6_TYPE_PARAMETER_PROBLEM = 4, ///< Parameter Problem
OT_ICMP6_TYPE_ECHO_REQUEST = 128, ///< Echo Request
OT_ICMP6_TYPE_ECHO_REPLY = 129, ///< Echo Reply
+ OT_ICMP6_TYPE_ROUTER_SOLICIT = 133, ///< Router Solicitation
+ OT_ICMP6_TYPE_ROUTER_ADVERT = 134, ///< Router Advertisement
} otIcmp6Type;
/**
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index 7e3d3bb..1b73e29 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@
* @note This number versions both OpenThread platform and user APIs.
*
*/
-#define OPENTHREAD_API_VERSION (57)
+#define OPENTHREAD_API_VERSION (87)
/**
* @addtogroup api-instance
diff --git a/include/openthread/message.h b/include/openthread/message.h
index ba35279..9c59b52 100644
--- a/include/openthread/message.h
+++ b/include/openthread/message.h
@@ -53,12 +53,10 @@
*/
/**
- * This structure points to an OpenThread message buffer.
+ * This type is an opaque representation of an OpenThread message buffer.
+ *
*/
-typedef struct otMessage
-{
- struct otMessage *mNext; ///< A pointer to the next Message buffer.
-} otMessage;
+typedef struct otMessage otMessage;
/**
* This structure represents the message buffer information.
diff --git a/include/openthread/ncp.h b/include/openthread/ncp.h
index b5f07fe..7289672 100644
--- a/include/openthread/ncp.h
+++ b/include/openthread/ncp.h
@@ -55,12 +55,47 @@
*/
/**
- * Initialize the NCP.
+ * This function pointer is called to send HDLC encoded NCP data.
+ *
+ * @param[in] aBuf A pointer to a buffer with an output.
+ * @param[in] aBufLength A length of the output data stored in the buffer.
+ *
+ * @returns Number of bytes processed by the callback.
+ *
+ */
+typedef int (*otNcpHdlcSendCallback)(const uint8_t *aBuf, uint16_t aBufLength);
+
+/**
+ * This function is called after NCP send finished.
+ *
+ */
+void otNcpHdlcSendDone(void);
+
+/**
+ * This function is called after HDLC encoded NCP data received.
+ *
+ * @param[in] aBuf A pointer to a buffer.
+ * @param[in] aBufLength The length of the data stored in the buffer.
+ *
+ */
+void otNcpHdlcReceive(const uint8_t *aBuf, uint16_t aBufLength);
+
+/**
+ * Initialize the NCP based on HDLC framing.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aSendCallback The function pointer used to send NCP data.
+ *
+ */
+void otNcpHdlcInit(otInstance *aInstance, otNcpHdlcSendCallback aSendCallback);
+
+/**
+ * Initialize the NCP based on SPI framing.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
-void otNcpInit(otInstance *aInstance);
+void otNcpSpiInit(otInstance *aInstance);
/**
* @brief Send data to the host via a specific stream.
diff --git a/include/openthread/netdiag.h b/include/openthread/netdiag.h
index 376780f..2d291a0 100644
--- a/include/openthread/netdiag.h
+++ b/include/openthread/netdiag.h
@@ -297,34 +297,26 @@
void * aContext);
/**
- * This function registers a callback to provide received raw Network Diagnostic Get response payload.
+ * Send a Network Diagnostic Get request.
*
* @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aDestination A pointer to destination address.
+ * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
+ * @param[in] aCount Number of types in aTlvTypes.
* @param[in] aCallback A pointer to a function that is called when Network Diagnostic Get response
* is received or NULL to disable the callback.
* @param[in] aCallbackContext A pointer to application-specific context.
*
- */
-void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
- otReceiveDiagnosticGetCallback aCallback,
- void * aCallbackContext);
-
-/**
- * Send a Network Diagnostic Get request.
- *
- * @param[in] aInstance A pointer to an OpenThread instance.
- * @param[in] aDestination A pointer to destination address.
- * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
- * @param[in] aCount Number of types in aTlvTypes.
- *
* @retval OT_ERROR_NONE Successfully queued the DIAG_GET.req.
* @retval OT_ERROR_NO_BUFS Insufficient message buffers available to send DIAG_GET.req.
*
*/
-otError otThreadSendDiagnosticGet(otInstance * aInstance,
- const otIp6Address *aDestination,
- const uint8_t aTlvTypes[],
- uint8_t aCount);
+otError otThreadSendDiagnosticGet(otInstance * aInstance,
+ const otIp6Address * aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount,
+ otReceiveDiagnosticGetCallback aCallback,
+ void * aCallbackContext);
/**
* Send a Network Diagnostic Reset request.
diff --git a/include/openthread/ping_sender.h b/include/openthread/ping_sender.h
new file mode 100644
index 0000000..61f4b05
--- /dev/null
+++ b/include/openthread/ping_sender.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2021, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file includes the OpenThread API for ping sender module.
+ */
+
+#ifndef OPENTHREAD_PING_SENDER_H_
+#define OPENTHREAD_PING_SENDER_H_
+
+#include <stdint.h>
+
+#include <openthread/error.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-ping-sender
+ *
+ * @brief
+ * This file includes the OpenThread API for the ping sender module.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This structure represents a ping reply.
+ *
+ */
+typedef struct otPingSenderReply
+{
+ otIp6Address mSenderAddress; ///< Sender IPv6 address (address from which ping reply was received).
+ uint32_t mRoundTripTime; ///< Round trip time in msec.
+ uint16_t mSize; ///< Data size (number of bytes) in reply (excluding IPv6 and ICMP6 headers).
+ uint16_t mSequenceNumber; ///< Sequence number.
+ uint8_t mHopLimit; ///< Hop limit.
+} otPingSenderReply;
+
+/**
+ * This function pointer type specifies the callback to notify receipt of a ping reply.
+ *
+ * @param[in] aReply A pointer to a `otPingSenderReply` containing info about the received ping reply.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ */
+typedef void (*otPingSenderCallback)(const otPingSenderReply *aReply, void *aContext);
+
+/**
+ * This structure represents a ping request configuration.
+ *
+ */
+typedef struct otPingSenderConfig
+{
+ otIp6Address mDestination; ///< Destination address to ping.
+ otPingSenderCallback mCallback; ///< Callback function to report replies (can be NULL if not needed).
+ void * mCallbackContext; ///< A pointer to the callback application-specific context.
+ uint16_t mSize; ///< Data size (# of bytes) excludes IPv6/ICMPv6 header. Zero for default.
+ uint16_t mCount; ///< Number of ping messages to send. Zero to use default.
+ uint32_t mInterval; ///< Ping tx interval in milliseconds. Zero to use default.
+ uint8_t mHopLimit; ///< Hop limit (used if `mAllowZeroHopLimit` is false). Zero for default.
+ bool mAllowZeroHopLimit; ///< Indicates whether hop limit is zero.
+} otPingSenderConfig;
+
+/**
+ * This function starts a ping.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aConfig The ping config to use.
+ *
+ * @retval OT_ERROR_NONE The ping started successfully.
+ * @retval OT_ERROR_BUSY Could not start since busy with a previous ongoing ping request.
+ * @retval OT_ERROR_INVALID_ARGS The @p aConfig contains invalid parameters (e.g., ping interval is too long).
+
+ *
+ */
+otError otPingSenderPing(otInstance *aInstance, const otPingSenderConfig *aConfig);
+
+/**
+ * This function stops an ongoing ping.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ */
+void otPingSenderStop(otInstance *aInstance);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_PING_SENDER_H_
diff --git a/include/openthread/platform/infra_if.h b/include/openthread/platform/infra_if.h
new file mode 100644
index 0000000..d052eb2
--- /dev/null
+++ b/include/openthread/platform/infra_if.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file includes the platform abstraction for the infrastructure network interface.
+ *
+ */
+
+#ifndef OPENTHREAD_PLATFORM_INFRA_IF_H_
+#define OPENTHREAD_PLATFORM_INFRA_IF_H_
+
+#include <stdint.h>
+
+#include <openthread/error.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This method sends an ICMPv6 Neighbor Discovery message on given infrastructure interface.
+ *
+ * See RFC 4861: https://tools.ietf.org/html/rfc4861.
+ *
+ * @param[in] aInfraIfIndex The index of the infrastructure interface this message is sent to.
+ * @param[in] aDestAddress The destination address this message is sent to.
+ * @param[in] aBuffer The ICMPv6 message buffer.
+ * @param[in] aBufferLength The length of the message buffer.
+ *
+ * @note Per RFC 4861, the implementation should send the message with IPv6 link-local source address
+ * of interface @p aInfraIfIndex and IP Hop Limit 255.
+ *
+ * @retval OT_ERROR_NONE Successfully sent the ICMPv6 message.
+ * @retval OT_ERROR_FAILED Failed to send the ICMPv6 message.
+ *
+ */
+otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
+ const otIp6Address *aDestAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength);
+
+/**
+ * The infra interface driver calls this method to notify OpenThread
+ * that an ICMPv6 Neighbor Discovery message is received.
+ *
+ * See RFC 4861: https://tools.ietf.org/html/rfc4861.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aInfraIfIndex The index of the infrastructure interface on which the ICMPv6 message is received.
+ * @param[in] aSrcAddress The source address this message is received from.
+ * @param[in] aBuffer The ICMPv6 message buffer.
+ * @param[in] aBufferLength The length of the ICMPv6 message buffer.
+ *
+ * @note Per RFC 4861, the caller should enforce that the source address MUST be a IPv6 link-local
+ * address and the IP Hop Limit MUST be 255.
+ *
+ */
+extern void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ const otIp6Address *aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength);
+
+/**
+ * The infra interface driver calls this method to notify OpenThread
+ * of the interface state changes.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aInfraIfIndex The index of the infrastructure interface.
+ * @param[in] aIsRunning A boolean that indicates whether the infrastructure
+ * interface is running.
+ * @param[in] aLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure
+ * interface. NULL if the IPv6 link-local address is lost.
+ *
+ * @retval OT_ERROR_NONE Successfully updated the infra interface status.
+ * @retval OT_ERROR_INVALID_STATE The Routing Manager is not initialized.
+ * @retval OT_ERROR_INVALID_ARGS The @p aInfraIfIndex doesn't match the infra interface the
+ * Routing Manager are initialized with, or the @p aLinkLocalAddress
+ * is not a valid IPv6 link-local address.
+ *
+ */
+extern otError otPlatInfraIfStateChanged(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ bool aIsRunning,
+ const otIp6Address *aLinkLocalAddress);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_PLATFORM_INFRA_IF_H_
diff --git a/include/openthread/platform/logging.h b/include/openthread/platform/logging.h
index 2867660..bfa1eee 100644
--- a/include/openthread/platform/logging.h
+++ b/include/openthread/platform/logging.h
@@ -137,6 +137,9 @@
OT_LOG_REGION_BBR = 17, ///< Backbone Router (available since Thread 1.2)
OT_LOG_REGION_MLR = 18, ///< Multicast Listener Registration (available since Thread 1.2)
OT_LOG_REGION_DUA = 19, ///< Domain Unicast Address (available since Thread 1.2)
+ OT_LOG_REGION_BR = 20, ///< Border Router
+ OT_LOG_REGION_SRP = 21, ///< Service Registration Protocol (SRP)
+ OT_LOG_REGION_DNS = 22, ///< DNS
} otLogRegion;
/**
diff --git a/include/openthread/platform/memory.h b/include/openthread/platform/memory.h
index b1de90a..ba569ea 100644
--- a/include/openthread/platform/memory.h
+++ b/include/openthread/platform/memory.h
@@ -61,7 +61,7 @@
* memory each and returns a pointer to the allocated memory. The allocated memory is filled with bytes
* of value zero."
*
- * This function is available and can ONLY be used only when support for multiple OpenThread instances is enabled.
+ * This function is required for OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE.
*
* @param[in] aNum The number of blocks to allocate
* @param[in] aSize The size of each block to allocate
@@ -74,7 +74,7 @@
/**
* Frees memory that was dynamically allocated.
*
- * This function is available and can ONLY be used only when support for multiple OpenThread instances is enabled.
+ * This function is required for OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE.
*
* @param[in] aPtr A pointer the memory blocks to free. The pointer may be NULL.
*/
diff --git a/include/openthread/platform/messagepool.h b/include/openthread/platform/messagepool.h
index 3391c4a..6f369c7 100644
--- a/include/openthread/platform/messagepool.h
+++ b/include/openthread/platform/messagepool.h
@@ -54,11 +54,22 @@
#endif
/**
+ * This struct represents an OpenThread message buffer.
+ *
+ */
+typedef struct otMessageBuffer
+{
+ struct otMessageBuffer *mNext; ///< Pointer to the next buffer.
+} otMessageBuffer;
+
+/**
* Initialize the platform implemented message pool.
*
+ * This function is used when `OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT` is enabled.
+ *
* @param[in] aInstance A pointer to the OpenThread instance.
* @param[in] aMinNumFreeBuffers An uint16 containing the minimum number of free buffers desired by OpenThread.
- * @param[in] aBufferSize The size in bytes of a Buffer object.
+ * @param[in] aBufferSize The size in bytes of a buffer object.
*
*/
void otPlatMessagePoolInit(otInstance *aInstance, uint16_t aMinNumFreeBuffers, size_t aBufferSize);
@@ -66,25 +77,33 @@
/**
* Allocate a buffer from the platform managed buffer pool.
*
+ * This function is used when `OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT` is enabled.
+ *
+ * The returned buffer instance MUST have at least `aBufferSize` bytes (as specified in `otPlatMessagePoolInit()`).
+ *
* @param[in] aInstance A pointer to the OpenThread instance.
*
- * @returns A pointer to the Buffer or NULL if no Buffers are available.
+ * @returns A pointer to the buffer or NULL if no buffers are available.
*
*/
-otMessage *otPlatMessagePoolNew(otInstance *aInstance);
+otMessageBuffer *otPlatMessagePoolNew(otInstance *aInstance);
/**
- * This function is used to free a Buffer back to the platform managed buffer pool.
+ * This function is used to free a buffer back to the platform managed buffer pool.
+ *
+ * This function is used when `OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT` is enabled.
*
* @param[in] aInstance A pointer to the OpenThread instance.
- * @param[in] aBuffer The Buffer to free.
+ * @param[in] aBuffer The buffer to free.
*
*/
-void otPlatMessagePoolFree(otInstance *aInstance, otMessage *aBuffer);
+void otPlatMessagePoolFree(otInstance *aInstance, otMessageBuffer *aBuffer);
/**
* Get the number of free buffers.
*
+ * This function is used when `OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT` is enabled.
+ *
* @param[in] aInstance A pointer to the OpenThread instance.
*
* @returns The number of buffers currently free and available to OpenThread.
diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h
index c245bc7..325394f 100644
--- a/include/openthread/platform/radio.h
+++ b/include/openthread/platform/radio.h
@@ -985,6 +985,37 @@
otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower);
/**
+ * Set the region code.
+ *
+ * The radio region format is the 2-bytes ascii representation of the
+ * ISO 3166 alpha-2 code.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aRegionCode The radio region.
+ *
+ * @retval OT_ERROR_FAILED Other platform specific errors.
+ * @retval OT_ERROR_NONE Successfully set region code.
+ *
+ */
+otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode);
+
+/**
+ * Get the region code.
+ *
+ * The radio region format is the 2-bytes ascii representation of the
+ * ISO 3166 alpha-2 code.
+
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[out] aRegionCode The radio region.
+ *
+ * @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr.
+ * @retval OT_ERROR_FAILED Other platform specific errors.
+ * @retval OT_ERROR_NONE Successfully got region code.
+ *
+ */
+otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode);
+
+/**
* Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
*
* After Enhanced-ACK Based Probing is configured by a specific Probing Initiator, the Enhanced-ACK sent to that
diff --git a/include/openthread/platform/settings.h b/include/openthread/platform/settings.h
index 4a4208a..cb51993 100644
--- a/include/openthread/platform/settings.h
+++ b/include/openthread/platform/settings.h
@@ -52,6 +52,28 @@
*/
/**
+ * This enumeration defines the keys of settings.
+ *
+ * Note: When adding a new setings key, if the settings corresponding to the key contains security sensitive
+ * information, the developer MUST add the key to the array `kCriticalKeys`.
+ *
+ */
+enum
+{
+ OT_SETTINGS_KEY_ACTIVE_DATASET = 0x0001, ///< Active Operational Dataset.
+ OT_SETTINGS_KEY_PENDING_DATASET = 0x0002, ///< Pending Operational Dataset.
+ OT_SETTINGS_KEY_NETWORK_INFO = 0x0003, ///< Thread network information.
+ OT_SETTINGS_KEY_PARENT_INFO = 0x0004, ///< Parent information.
+ OT_SETTINGS_KEY_CHILD_INFO = 0x0005, ///< Child information.
+ OT_SETTINGS_KEY_RESERVED = 0x0006, ///< Reserved (previously auto-start).
+ OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
+ OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information.
+ OT_SETTINGS_KEY_OMR_PREFIX = 0x0009, ///< Off-mesh routable (OMR) prefix.
+ OT_SETTINGS_KEY_ON_LINK_PREFIX = 0x000a, ///< On-link prefix for infrastructure link.
+ OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair.
+};
+
+/**
* Performs any initialization for the settings subsystem, if necessary.
*
* @param[in] aInstance The OpenThread instance structure.
@@ -67,6 +89,18 @@
*/
void otPlatSettingsDeinit(otInstance *aInstance);
+/**
+ * This function sets the critical keys that should be stored in the secure area.
+ *
+ * Note that the memory pointed by @p aKeys MUST not be released before @p aInstance is destroyed.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aKeys A pointer to an array containing the list of critical keys.
+ * @param[in] aKeysLength The number of entries in the @p aKeys array.
+ *
+ */
+void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength);
+
/// Fetches the value of a setting
/** This function fetches the value of the setting identified
* by aKey and write it to the memory pointed to by aValue.
diff --git a/include/openthread/platform/toolchain.h b/include/openthread/platform/toolchain.h
index c1f3a00..5610985 100644
--- a/include/openthread/platform/toolchain.h
+++ b/include/openthread/platform/toolchain.h
@@ -258,6 +258,25 @@
#endif
/**
+ * @def OT_FALL_THROUGH
+ *
+ * Suppress fall through warning in specific compiler.
+ *
+ */
+#if defined(__cplusplus) && (__cplusplus >= 201703L)
+#define OT_FALL_THROUGH [[fallthrough]]
+#elif defined(__clang__)
+#define OT_FALL_THROUGH [[clang::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+#define OT_FALL_THROUGH __attribute__((fallthrough))
+#else
+#define OT_FALL_THROUGH \
+ do \
+ { \
+ } while (false) /* fallthrough */
+#endif
+
+/**
* @}
*
*/
diff --git a/include/openthread/srp_client.h b/include/openthread/srp_client.h
new file mode 100644
index 0000000..2f7b9df
--- /dev/null
+++ b/include/openthread/srp_client.h
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the OpenThread SRP (Service Registration Protocol) client APIs.
+ */
+
+#ifndef OPENTHREAD_SRP_CLIENT_H_
+#define OPENTHREAD_SRP_CLIENT_H_
+
+#include <openthread/dns.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-srp
+ *
+ * @brief
+ * This module includes functions that control SRP client behavior.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This enumeration specifies an SRP client item (service or host info) state.
+ *
+ */
+typedef enum
+{
+ OT_SRP_CLIENT_ITEM_STATE_TO_ADD, ///< Item to be added/registered.
+ OT_SRP_CLIENT_ITEM_STATE_ADDING, ///< Item is being added/registered.
+ OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH, ///< Item to be refreshed (re-register to renew lease).
+ OT_SRP_CLIENT_ITEM_STATE_REFRESHING, ///< Item is being refreshed.
+ OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE, ///< Item to be removed.
+ OT_SRP_CLIENT_ITEM_STATE_REMOVING, ///< Item is being removed.
+ OT_SRP_CLIENT_ITEM_STATE_REGISTERED, ///< Item is registered with server.
+ OT_SRP_CLIENT_ITEM_STATE_REMOVED, ///< Item is removed.
+} otSrpClientItemState;
+
+/**
+ * This structure represents an SRP client host info.
+ *
+ */
+typedef struct otSrpClientHostInfo
+{
+ const char * mName; ///< Host name (label) string (NULL if not yet set).
+ const otIp6Address * mAddresses; ///< Pointer to an array of host IPv6 addresses (NULL if not yet set).
+ uint8_t mNumAddresses; ///< Number of IPv6 addresses in `mAddresses` array.
+ otSrpClientItemState mState; ///< Host info state.
+} otSrpClientHostInfo;
+
+/**
+ * This structure represents an SRP client service.
+ *
+ * The values in this structure, including the string buffers for the names and the TXT record entries, MUST persist
+ * and stay constant after an instance of this structure is passed to OpenThread from `otSrpClientAddService()` or
+ * `otSrpClientRemoveService()`.
+ *
+ */
+typedef struct otSrpClientService
+{
+ const char * mName; ///< The service name labels (e.g., "_chip._udp", not the full domain name).
+ const char * mInstanceName; ///< The service instance name label (not the full name).
+ const otDnsTxtEntry *mTxtEntries; ///< Array of TXT entries (number of entries is given by `mNumTxtEntries`).
+ uint16_t mPort; ///< The service port number.
+ uint16_t mPriority; ///< The service priority.
+ uint16_t mWeight; ///< The service weight.
+ uint8_t mNumTxtEntries; ///< Number of entries in the `mTxtEntries` array.
+
+ /**
+ * @note The following fields are used/managed by OT core only. Their values do not matter and are ignored when an
+ * instance of `otSrpClientService` is passed in `otSrpClientAddService()` or `otSrpClientRemoveService()`. The
+ * user should not modify these fields.
+ *
+ */
+
+ otSrpClientItemState mState; ///< Service state (managed by OT core).
+ uint32_t mData; ///< Internal data (used by OT core).
+ struct otSrpClientService *mNext; ///< Pointer to next entry in a linked-list (managed by OT core).
+} otSrpClientService;
+
+/**
+ * This function pointer type defines the callback used by SRP client to notify user of changes/events/errors.
+ *
+ * This callback is invoked on a successful registration of an update (i.e., add/remove of host-info and/or some
+ * service(s)) with the SRP server, or if there is a failure or error (e.g., server rejects a update request or client
+ * times out waiting for response, etc).
+ *
+ * In case of a successful reregistration of an update, `aError` parameter would be `OT_ERROR_NONE` and the host info
+ * and the full list of services is provided as input parameters to the callback. Note that host info and services each
+ * track its own state in the corresponding `mState` member variable of the related data structure (the state
+ * indicating whether the host-info/service is registered or removed or still being added/removed, etc).
+ *
+ * The list of removed services is passed as its own linked-list `aRemovedServices` in the callback. Note that when the
+ * callback is invoked, the SRP client (OpenThread implementation) is done with the removed service instances listed in
+ * `aRemovedServices` and no longer tracks/stores them (i.e., if from the callback we call `otSrpClientGetServices()`
+ * the removed services will not be present in the returned list). Providing a separate list of removed services in
+ * the callback helps indicate to user which items are now removed and allow user to re-claim/reuse the instances.
+ *
+ * If the server rejects an SRP update request, the DNS response code (RFC 2136) is mapped to the following errors:
+ *
+ * - (0) NOERROR Success (no error condition) -> OT_ERROR_NONE
+ * - (1) FORMERR Server unable to interpret due to format error -> OT_ERROR_PARSE
+ * - (2) SERVFAIL Server encountered an internal failure -> OT_ERROR_FAILED
+ * - (3) NXDOMAIN Name that ought to exist, does not exist -> OT_ERROR_NOT_FOUND
+ * - (4) NOTIMP Server does not support the query type (OpCode) -> OT_ERROR_NOT_IMPLEMENTED
+ * - (5) REFUSED Server refused for policy/security reasons -> OT_ERROR_SECURITY
+ * - (6) YXDOMAIN Some name that ought not to exist, does exist -> OT_ERROR_DUPLICATED
+ * - (7) YXRRSET Some RRset that ought not to exist, does exist -> OT_ERROR_DUPLICATED
+ * - (8) NXRRSET Some RRset that ought to exist, does not exist -> OT_ERROR_NOT_FOUND
+ * - (9) NOTAUTH Service is not authoritative for zone -> OT_ERROR_SECURITY
+ * - (10) NOTZONE A name is not in the zone -> OT_ERROR_PARSE
+ * - (20) BADNAME Bad name -> OT_ERROR_PARSE
+ * - (21) BADALG Bad algorithm -> OT_ERROR_SECURITY
+ * - (22) BADTRUN Bad truncation -> OT_ERROR_PARSE
+ * - Other response codes -> OT_ERROR_FAILED
+ *
+ * The following errors are also possible:
+ *
+ * - OT_ERROR_RESPONSE_TIMEOUT : Timed out waiting for response from server (client would continue to retry).
+ * - OT_ERROR_INVALID_ARGS : The provided service structure is invalid (e.g., bad service name or `otDnsTxtEntry`).
+ * - OT_ERROR_NO_BUFS : Insufficient buffer to prepare or send the update message.
+ *
+ * Note that in case of any failure, the client continues the operation, i.e. it prepares and (re)transmits the SRP
+ * update message to the server, after some wait interval. The retry wait interval starts from the minimum value and
+ * is increased by the growth factor every failure up to the max value (please see configuration parameter
+ * `OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL` and the related ones for more details).
+ *
+ * @param[in] aError The error (see above).
+ * @param[in] aHostInfo A pointer to host info.
+ * @param[in] aService The head of linked-list containing all services (excluding the ones removed). NULL if
+ * the list is empty.
+ * @param[in] aRemovedServices The head of linked-list containing all removed services. NULL if the list is empty.
+ * @param[in] aContext A pointer to an arbitrary context (provided when callback was registered).
+ *
+ */
+typedef void (*otSrpClientCallback)(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices,
+ void * aContext);
+
+/**
+ * This function pointer type defines the callback used by SRP client to notify user when it is auto-started or stopped.
+ *
+ * This is only used when auto-start feature `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled.
+ *
+ * This callback is invoked when auto-start mode is enabled and the SRP client is either automatically started or
+ * stopped.
+ *
+ * @param[in] aSeverSockAddress A non-NULL pointer indicates SRP sever was started and pointer will give the
+ * selected server socket address. A NULL pointer indicates SRP sever was stopped.
+ * @param[in] aContext A pointer to an arbitrary context (provided when callback was registered).
+ *
+ */
+typedef void (*otSrpClientAutoStartCallback)(const otSockAddr *aServerSockAddr, void *aContext);
+
+/**
+ * This function starts the SRP client operation.
+ *
+ * SRP client will prepare and send "SRP Update" message to the SRP server once all the following conditions are met:
+ *
+ * - The SRP client is started - `otSrpClientStart()` is called.
+ * - Host name is set - `otSrpClientSetHostName()` is called.
+ * - At least one host IPv6 address is set - `otSrpClientSetHostName()` is called.
+ * - At least one service is added - `otSrpClientAddService()` is called.
+ *
+ * It does not matter in which order these functions are called. When all conditions are met, the SRP client will
+ * wait for a short delay before preparing an "SRP Update" message and sending it to server. This delay allows for user
+ * to add multiple services and/or IPv6 addresses before the first SRP Update message is sent (ensuring a single SRP
+ * Update is sent containing all the info). The config `OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY` specifies the
+ * delay interval.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aServerSockAddr The socket address (IPv6 address and port number) of the SRP server.
+ *
+ * @retval OT_ERROR_NONE SRP client operation started successfully or it is already running with same server
+ * socket address and callback.
+ * @retval OT_ERROR_BUSY SRP client is busy running with a different socket address.
+ * @retval OT_ERROR_FAILED Failed to open/connect the client's UDP socket.
+ *
+ */
+otError otSrpClientStart(otInstance *aInstance, const otSockAddr *aServerSockAddr);
+
+/**
+ * This function stops the SRP client operation.
+ *
+ * This function stops any further interactions with the SRP server. Note that it does not remove or clear host info
+ * and/or list of services. It marks all services to be added/removed again once the client is (re)started.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ */
+void otSrpClientStop(otInstance *aInstance);
+
+/**
+ * This function indicates whether the SRP client is running or not.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns TRUE if the SRP client is running, FALSE otherwise.
+ *
+ */
+bool otSrpClientIsRunning(otInstance *aInstance);
+
+/**
+ * This function gets the socket address (IPv6 address and port number) of the SRP server which is being used by SRP
+ * client.
+ *
+ * If the client is not running, the address is unspecified (all zero) with zero port number.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns A pointer to the SRP server's socket address (is always non-NULL).
+ *
+ */
+const otSockAddr *otSrpClientGetServerAddress(otInstance *aInstance);
+
+/**
+ * This function sets the callback to notify caller of events/changes from SRP client.
+ *
+ * The SRP client allows a single callback to be registered. So consecutive calls to this function will overwrite any
+ * previously set callback functions.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aCallback The callback to notify of events and changes. Can be NULL if not needed.
+ * @param[in] aContext An arbitrary context used with @p aCallback.
+ *
+ */
+void otSrpClientSetCallback(otInstance *aInstance, otSrpClientCallback aCallback, void *aContext);
+
+/**
+ * This function enables the auto-start mode.
+ *
+ * This is only available when auto-start feature `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled.
+ *
+ * Config option `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE` specifies the default auto-start mode (whether
+ * it is enabled or disabled at the start of OT stack).
+ *
+ * When auto-start is enabled, the SRP client will monitor the Thread Network Data for SRP Server Service entries
+ * and automatically start and stop the client when an SRP server is detected.
+ *
+ * If multiple SRP servers are found, a random one will be selected. If the selected SRP server is no longer
+ * detected (not longer present in the Thread Network Data), the SRP client will be stopped and then it may switch
+ * to another SRP server (if available).
+ *
+ * When the SRP client is explicitly started through a successful call to `otSrpClientStart()`, the given SRP server
+ * address in `otSrpClientStart()` will continue to be used regardless of the state of auto-start mode and whether the
+ * same SRP server address is discovered or not in the Thread Network Data. In this case, only an explicit
+ * `otSrpClientStop()` call will stop the client.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aCallback A callback to notify when client is auto-started/stopped. Can be NULL if not needed.
+ * @param[in] aContext A context to be passed when invoking @p aCallback.
+ *
+ */
+void otSrpClientEnableAutoStartMode(otInstance *aInstance, otSrpClientAutoStartCallback aCallback, void *aContext);
+
+/**
+ * This function disables the auto-start mode.
+ *
+ * This is only available when auto-start feature `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled.
+ *
+ * Disabling the auto-start mode will not stop the client if it is already running but the client stops monitoring
+ * the Thread Network Data to verify that the selected SRP server is still present in it.
+ *
+ * Note that a call to `otSrpClientStop()` will also disable the auto-start mode.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ */
+void otSrpClientDisableAutoStartMode(otInstance *aInstance);
+
+/**
+ * This function indicates the current state of auto-start mode (enabled or disabled).
+ *
+ * This is only available when auto-start feature `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns TRUE if the auto-start mode is enabled, FALSE otherwise.
+ *
+ */
+bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance);
+
+/**
+ * This function gets the lease interval used in SRP update requests.
+ *
+ * Note that this is the lease duration requested by the SRP client. The server may choose to accept a different lease
+ * interval.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns The lease interval (in seconds).
+ *
+ */
+uint32_t otSrpClientGetLeaseInterval(otInstance *aInstance);
+
+/**
+ * This function sets the lease interval used in SRP update requests.
+ *
+ * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
+ * It only affects any future SRP update messages (i.e., adding new services and/or refreshes of the existing services).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aInterval The lease interval (in seconds). If zero, the default value specified by
+ * `OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE` would be used.
+ *
+ */
+void otSrpClientSetLeaseInterval(otInstance *aInstance, uint32_t aInterval);
+
+/**
+ * This function gets the key lease interval used in SRP update requests.
+ *
+ * Note that this is the lease duration requested by the SRP client. The server may choose to accept a different lease
+ * interval.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns The key lease interval (in seconds).
+ *
+ */
+uint32_t otSrpClientGetKeyLeaseInterval(otInstance *aInstance);
+
+/**
+ * This function sets the key lease interval used in SRP update requests.
+ *
+ * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
+ * It only affects any future SRP update messages (i.e., adding new services and/or refreshes of existing services).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aInterval The key lease interval (in seconds). If zero, the default value specified by
+ * `OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE` would be used.
+ *
+ */
+void otSrpClientSetKeyLeaseInterval(otInstance *aInstance, uint32_t aInterval);
+
+/**
+ * This function gets the host info.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns A pointer to host info structure.
+ *
+ */
+const otSrpClientHostInfo *otSrpClientGetHostInfo(otInstance *aInstance);
+
+/**
+ * This function sets the host name label.
+ *
+ * After a successful call to this function, `otSrpClientCallback` will be called to report the status of host info
+ * registration with SRP server.
+ *
+ * The name string buffer pointed to by @p aName MUST persist and stay unchanged after returning from this function.
+ * OpenThread will keep the pointer to the string.
+ *
+ * The host name can be set before client is started or after start but before host info is registered with server
+ * (host info should be in either `STATE_TO_ADD` or `STATE_REMOVED`).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aName A pointer to host name label string (MUST NOT be NULL). Pointer to the string buffer MUST
+ * persist and remain valid and constant after return from this function.
+ *
+ * @retval OT_ERROR_NONE The host name label was set successfully.
+ * @retval OT_ERROR_INVALID_ARGS The @p aName is NULL.
+ * @retval OT_ERROR_INVALID_STATE The host name is already set and registered with the server.
+ *
+ */
+otError otSrpClientSetHostName(otInstance *aInstance, const char *aName);
+
+/**
+ * This function sets/updates the list of host IPv6 address.
+ *
+ * Host IPv6 addresses can be set/changed before start or during operation of SRP client (e.g. to add/remove or change
+ * a previously registered host address), except when the host info is being removed (client is busy handling a remove
+ * request from an earlier call to `otSrpClientRemoveHostAndServices()` and host info still being in either
+ * `STATE_TO_REMOVE` or `STATE_REMOVING` states).
+ *
+ * The host IPv6 address array pointed to by @p aAddresses MUST persist and remain unchanged after returning from this
+ * function (with `OT_ERROR_NONE`). OpenThread will save the pointer to the array.
+ *
+ * After a successful call to this function, `otSrpClientCallback` will be called to report the status of the address
+ * registration with SRP server.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aAddresses A pointer to the an array containing the host IPv6 addresses.
+ * @param[in] aNumAddresses The number of addresses in the @p aAddresses array.
+ *
+ * @retval OT_ERROR_NONE The host IPv6 address list change started successfully. The `otSrpClientCallback`
+ * will be called to report the status of registering addresses with server.
+ * @retval OT_ERROR_INVALID_ARGS The address list is invalid (e.g., must contain at least one address).
+ * @retval OT_ERROR_INVALID_STATE Host is being removed and therefore cannot change host address.
+ *
+ */
+otError otSrpClientSetHostAddresses(otInstance *aInstance, const otIp6Address *aIp6Addresses, uint8_t aNumAddresses);
+
+/**
+ * This function adds a service to be registered with server.
+ *
+ * After a successful call to this function, `otSrpClientCallback` will be called to report the status of the service
+ * addition/registration with SRP server.
+ *
+ * The `otSrpClientService` instance being pointed to by @p aService MUST persist and remain unchanged after returning
+ * from this function (with `OT_ERROR_NONE`). OpenThread will save the pointer to the service instance.
+ *
+ * The `otSrpClientService` instance is not longer tracked by OpenThread and can be reclaimed only when
+ *
+ * - It is removed explicitly by a call to `otSrpClientRemoveService()` or removed along with other services by a
+ * call to `otSrpClientRemoveHostAndServices() and only after the `otSrpClientCallback` is called indicating the
+ * service was removed. Or,
+ * - A call to `otSrpClientClearHostAndServices()` which removes the host and all related services immediately.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aService A pointer to a `otSrpClientService` instance to add.
+
+ * @retval OT_ERROR_NONE The addition of service started successfully. The `otSrpClientCallback` will be
+ * called to report the status.
+ * @retval OT_ERROR_ALREADY The same service is already in the list.
+ * @retval OT_ERROR_INVALID_ARGS The service structure is invalid (e.g., bad service name or `otDnsTxtEntry`).
+ *
+ */
+otError otSrpClientAddService(otInstance *aInstance, otSrpClientService *aService);
+
+/**
+ * This function requests a service to be unregistered with server.
+ *
+ * After a successful call to this function, `otSrpClientCallback` will be called to report the status of remove
+ * request with SRP server.
+
+ * The `otSrpClientService` instance being pointed to by @p aService MUST persist and remain unchanged after returning
+ * from this function (with `OT_ERROR_NONE`). OpenThread will keep the service instance during the remove process.
+ * Only after the `otSrpClientCallback` is called indicating the service instance is removed from SRP client
+ * service list and can be be freed/reused.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aService A pointer to a `otSrpClientService` instance to remove.
+ *
+ * @retval OT_ERROR_NONE The removal of service started successfully. The `otSrpClientCallback` will be called to
+ * report the status.
+ * @retval OT_ERROR_NOT_FOUND The service could not be found in the list.
+ *
+ */
+otError otSrpClientRemoveService(otInstance *aInstance, otSrpClientService *aService);
+
+/**
+ * This function gets the list of services being managed by client.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns A pointer to the head of linked-list of all services or NULL if the list is empty.
+ *
+ */
+const otSrpClientService *otSrpClientGetServices(otInstance *aInstance);
+
+/**
+ * This function starts the remove process of the host info and all services.
+ *
+ * After returning from this function, `otSrpClientCallback` will be called to report the status of remove request with
+ * SRP server.
+ *
+ * If the host info is to be permanently removed from server, @p aRemoveKeyLease should be set to `true` which removes
+ * the key lease associated with host on server. Otherwise, the key lease record is kept as before, which ensures
+ * that the server holds the host name in reserve for when the client is once again able to provide and register its
+ * service(s).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aRemoveKeyLease A boolean indicating whether or not the host key lease should also be removed.
+ *
+ * @retval OT_ERROR_NONE The removal of host info and services started successfully. The `otSrpClientCallback`
+ * will be called to report the status.
+ * @retval OT_ERROR_ALREADY The host info is already removed.
+ *
+ */
+otError otSrpClientRemoveHostAndServices(otInstance *aInstance, bool aRemoveKeyLease);
+
+/**
+ * This function clears all host info and all the services.
+ *
+ * Unlike `otSrpClientRemoveHostAndServices()` which sends an update message to server to remove/unregister all the
+ * info, this function clears all the info immediately without any interaction with server.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ */
+void otSrpClientClearHostAndServices(otInstance *aInstance);
+
+/**
+ * This function gets the domain name being used by SRP client.
+ *
+ * This function requires `OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE` to be enabled.
+ *
+ * If domain name is not set, "default.service.arpa" will be used.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ * @returns The domain name string.
+ *
+ */
+const char *otSrpClientGetDomainName(otInstance *aInstance);
+
+/**
+ * This function sets the domain name to be used by SRP client.
+ *
+ * This function requires `OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE` to be enabled.
+ *
+ * If not set "default.service.arpa" will be used.
+ *
+ * The name string buffer pointed to by @p aName MUST persist and stay unchanged after returning from this function.
+ * OpenThread will keep the pointer to the string.
+ *
+ * The domain name can be set before client is started or after start but before host info is registered with server
+ * (host info should be in either `STATE_TO_ADD` or `STATE_TO_REMOVE`).
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aName A pointer to the domain name string. If NULL sets it to default "default.service.arpa".
+ *
+ * @retval OT_ERROR_NONE The domain name label was set successfully.
+ * @retval OT_ERROR_INVALID_STATE The host info is already registered with server.
+ *
+ */
+otError otSrpClientSetDomainName(otInstance *aInstance, const char *aName);
+
+/**
+ * This function converts a `otSrpClientItemState` to a string.
+ *
+ * @param[in] aItemState An item state.
+ *
+ * @returns A string representation of @p aItemState.
+ *
+ */
+const char *otSrpClientItemStateToString(otSrpClientItemState aItemState);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_SRP_CLIENT_H_
diff --git a/include/openthread/srp_server.h b/include/openthread/srp_server.h
new file mode 100644
index 0000000..0105621
--- /dev/null
+++ b/include/openthread/srp_server.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the API for server of the Service Registration Protocol (SRP).
+ */
+
+#ifndef OPENTHREAD_SRP_SERVER_H_
+#define OPENTHREAD_SRP_SERVER_H_
+
+#include <stdint.h>
+
+#include <openthread/dns.h>
+#include <openthread/instance.h>
+#include <openthread/ip6.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup api-srp
+ *
+ * @brief
+ * This module includes functions of the Service Registration Protocol.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This opaque type represents a SRP service host.
+ *
+ */
+typedef void otSrpServerHost;
+
+/**
+ * This opaque type represents a SRP service.
+ *
+ */
+typedef void otSrpServerService;
+
+/**
+ * This method returns the domain authorized to the SRP server.
+ *
+ * If the domain if not set by SetDomain, "default.service.arpa." will be returned.
+ * A trailing dot is always appended even if the domain is set without it.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns A pointer to the dot-joined domain string.
+ *
+ */
+const char *otSrpServerGetDomain(otInstance *aInstance);
+
+/**
+ * This method sets the domain on the SRP server.
+ *
+ * A trailing dot will be appended to @p aDomain if it is not already there.
+ * This method should only be called before the SRP server is enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aDomain The domain to be set. MUST NOT be nullptr.
+ *
+ * @retval OT_ERROR_NONE Successfully set the domain to @p aDomain.
+ * @retval OT_ERROR_INVALID_STATE The SRP server is already enabled and the Domain cannot be changed.
+ * @retval OT_ERROR_INVALID_ARGS The argument @p aDomain is not a valid DNS domain name.
+ * @retval OT_ERROR_NO_BUFS There is no memory to store content of @p aDomain.
+ *
+ */
+otError otSrpServerSetDomain(otInstance *aInstance, const char *aDomain);
+
+/**
+ * This method enables/disables the SRP server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aEnabled A boolean to enable/disable the SRP server.
+ *
+ */
+void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled);
+
+/**
+ * This method sets LEASE & KEY-LEASE range that is acceptable by the SRP server.
+ *
+ * When a non-zero LEASE time is requested from a client, the granted value will be
+ * limited in range [aMinLease, aMaxLease]; and a non-zero KEY-LEASE will be granted
+ * in range [aMinKeyLease, aMaxKeyLease]. For zero LEASE or KEY-LEASE time, zero will
+ * be granted.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aMinLease The minimum LEASE interval in seconds.
+ * @param[in] aMaxLease The maximum LEASE interval in seconds.
+ * @param[in] aMinKeyLease The minimum KEY-LEASE interval in seconds.
+ * @param[in] aMaxKeyLease The maximum KEY-LEASE interval in seconds.
+ *
+ * @retval OT_ERROR_NONE Successfully set the LEASE and KEY-LEASE ranges.
+ * @retval OT_ERROR_INVALID_ARGS The LEASE or KEY-LEASE range is not valid.
+ *
+ */
+otError otSrpServerSetLeaseRange(otInstance *aInstance,
+ uint32_t aMinLease,
+ uint32_t aMaxLease,
+ uint32_t aMinKeyLease,
+ uint32_t aMaxKeyLease);
+
+/**
+ * This method handles SRP service updates.
+ *
+ * This function is called by the SRP server to notify that a SRP host and possibly SRP services
+ * are being updated. It is important that the SRP updates are not commited until the handler
+ * returns the result by calling otSrpServerHandleServiceUpdateResult or times out after @p aTimeout.
+ *
+ * A SRP service observer should always call otSrpServerHandleServiceUpdateResult with error code
+ * OT_ERROR_NONE immediately after receiving the update events.
+ *
+ * A more generic handler may perform validations on the SRP host/services and rejects the SRP updates
+ * if any validation fails. For example, an Advertising Proxy should advertise (or remove) the host and
+ * services on a multicast-capable link and returns specific error code if any failure occurs.
+ *
+ * @param[in] aHost A pointer to the otSrpServerHost object which contains the SRP updates.
+ * The pointer should be passed back to otSrpServerHandleServiceUpdateResult, but
+ * the content MUST not be accessed after this method returns. The handler
+ * should publish/un-publish the host and each service points to this host
+ * with below rules:
+ * 1. If the host is not deleted (indicated by `otSrpServerHostIsDeleted`),
+ * then it should be published or updated with mDNS. Otherwise, the host
+ * should be un-published (remove AAAA RRs).
+ * 2. For each service points to this host, it must be un-published if the host
+ * is to be un-published. Otherwise, the handler should publish or update the
+ * service when it is not deleted (indicated by `otSrpServerServiceIsDeleted`)
+ * and un-publish it when deleted.
+ * @param[in] aTimeout The maximum time in milliseconds for the handler to process the service event.
+ * @param[in] aContext A pointer to application-specific context.
+ *
+ * @sa otSrpServerSetServiceUpdateHandler
+ * @sa otSrpServerHandleServiceUpdateResult
+ *
+ */
+typedef void (*otSrpServerServiceUpdateHandler)(const otSrpServerHost *aHost, uint32_t aTimeout, void *aContext);
+
+/**
+ * This method sets the SRP service updates handler on SRP server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aServiceHandler A pointer to a service handler. Use NULL to remove the handler.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * May be NULL if not used.
+ *
+ */
+void otSrpServerSetServiceUpdateHandler(otInstance * aInstance,
+ otSrpServerServiceUpdateHandler aServiceHandler,
+ void * aContext);
+
+/**
+ * This method reports the result of processing a SRP update to the SRP server.
+ *
+ * The Service Update Handler should call this function to return the result of its
+ * processing of a SRP update.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aHost A pointer to the Host object which represents a SRP update.
+ * @param[in] aError An error to be returned to the SRP server. Use OT_ERROR_DUPLICATED
+ * to represent DNS name conflicts.
+ *
+ */
+void otSrpServerHandleServiceUpdateResult(otInstance *aInstance, const otSrpServerHost *aHost, otError aError);
+
+/**
+ * This method returns the next registered host on the SRP server.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aHost A pointer to current host; use NULL to get the first host.
+ *
+ * @returns A pointer to the registered host. NULL, if no more hosts can be found.
+ *
+ */
+const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrpServerHost *aHost);
+
+/**
+ * This method tells if the SRP service host has been deleted.
+ *
+ * A SRP service host can be deleted but retains its name for future uses.
+ * In this case, the host instance is not removed from the SRP server/registry.
+ *
+ * @param[in] aHost A pointer to the SRP service host.
+ *
+ * @returns TRUE if the host has been deleted, FALSE if not.
+ *
+ */
+bool otSrpServerHostIsDeleted(const otSrpServerHost *aHost);
+
+/**
+ * This method returns the full name of the host.
+ *
+ * @param[in] aHost A pointer to the SRP service host.
+ *
+ * @returns A pointer to the null-terminated host name string.
+ *
+ */
+const char *otSrpServerHostGetFullName(const otSrpServerHost *aHost);
+
+/**
+ * This method returns the addresses of given host.
+ *
+ * @param[in] aHost A pointer to the SRP service host.
+ * @param[out] aAddressesNum A pointer to where we should output the number of the addresses to.
+ *
+ * @returns A pointer to the array of IPv6 Address.
+ *
+ */
+const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, uint8_t *aAddressesNum);
+
+/**
+ * This method returns the next service of given host.
+ *
+ * @param[in] aHost A pointer to the SRP service host.
+ * @param[in] aService A pointer to current SRP service instance; use NULL to get the first service.
+ *
+ * @returns A pointer to the next service or NULL if there is no more services.
+ *
+ */
+const otSrpServerService *otSrpServerHostGetNextService(const otSrpServerHost * aHost,
+ const otSrpServerService *aService);
+
+/**
+ * This method tells if the SRP service has been deleted.
+ *
+ * A SRP service can be deleted but retains its name for future uses.
+ * In this case, the service instance is not removed from the SRP server/registry.
+ * It is guaranteed that all services are deleted if the host is deleted.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns TRUE if the service has been deleted, FALSE if not.
+ *
+ */
+bool otSrpServerServiceIsDeleted(const otSrpServerService *aService);
+
+/**
+ * This method returns the full name of the service.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns A pointer to the null-terminated service name string.
+ *
+ */
+const char *otSrpServerServiceGetFullName(const otSrpServerService *aService);
+
+/**
+ * This method returns the port of the service instance.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns The port of the service.
+ *
+ */
+uint16_t otSrpServerServiceGetPort(const otSrpServerService *aService);
+
+/**
+ * This method returns the weight of the service instance.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns The weight of the service.
+ *
+ */
+uint16_t otSrpServerServiceGetWeight(const otSrpServerService *aService);
+
+/**
+ * This method returns the priority of the service instance.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns The priority of the service.
+ *
+ */
+uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService);
+
+/**
+ * This function returns the TXT record data of the service instance.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ * @param[out] aDataLength A pointer to return the TXT record data length. MUST NOT be NULL.
+ *
+ * @returns A pointer to the buffer containing the TXT record data (the TXT data length is returned in @p aDataLength).
+ *
+ */
+const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService, uint16_t *aDataLength);
+
+/**
+ * This method returns the host which the service instance reside on.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns A pointer to the host instance.
+ *
+ */
+const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aService);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_SRP_SERVER_H_
diff --git a/ot_version.gni b/ot_version.gni
index 853e369..53b8058 100644
--- a/ot_version.gni
+++ b/ot_version.gni
@@ -1,5 +1,5 @@
# Note: This file is added only to support soft-transition
# it will be removed afterwards
-openthread_version = "before_update_on_20210324"
+openthread_version = "after_update_on_20210324"
diff --git a/script/bootstrap b/script/bootstrap
index 845c7b0..1fcd832 100755
--- a/script/bootstrap
+++ b/script/bootstrap
@@ -33,6 +33,23 @@
set -euxo pipefail
+install_packages_pretty_format()
+{
+ echo 'Installing pretty tools useful for code contributions...'
+
+ # add clang-format and clang-tidy for pretty
+ sudo apt-get --no-install-recommends install -y clang-format-9 clang-tidy-9 || echo 'WARNING: could not install clang-format-9 and clang-tidy-9, which is useful if you plan to contribute C/C++ code to the OpenThread project.'
+
+ # add yapf for pretty
+ python3 -m pip install yapf==0.29.0 || echo 'WARNING: could not install yapf, which is useful if you plan to contribute python code to the OpenThread project.'
+
+ # add mdv for local size report
+ python3 -m pip install mdv || echo 'WARNING: could not install mdv, which is required to post markdown size report for OpenThread.'
+
+ # add shfmt for shell pretty, try brew only because snap does not support home directory not being /home and doesn't work in docker.
+ command -v shfmt || brew install shfmt || echo 'WARNING: could not install shfmt, which is useful if you plan to contribute shell scripts to the OpenThread project.'
+}
+
install_packages_apt()
{
echo 'Installing toolchain dependencies...'
@@ -51,24 +68,14 @@
sudo apt-get --no-install-recommends install -y ca-certificates wget
(cd /tmp \
&& wget -c https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 \
- && tar xjf gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 \
+ && tar xjf gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 -C /opt \
&& rm gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 \
- && sudo ln -s /opt/gcc-arm-none-eabi-9-2020-q2-update/bin/* /usr/local/bin/.)
+ && sudo ln -s -f /opt/gcc-arm-none-eabi-9-2020-q2-update/bin/* /usr/local/bin/.)
fi
- echo 'Installing pretty tools useful for code contributions...'
-
- # add clang-format and clang-tidy for pretty
- sudo apt-get --no-install-recommends install -y clang-format-9 clang-tidy-9 || echo 'WARNING: could not install clang-format-9 and clang-tidy-9, which is useful if you plan to contribute C/C++ code to the OpenThread project.'
-
- # add yapf for pretty
- python3 -m pip install yapf==0.29.0 || echo 'WARNING: could not install yapf, which is useful if you plan to contribute python code to the OpenThread project.'
-
- # add mdv for local size report
- python3 -m pip install mdv || echo 'WARNING: could not install mdv, which is useful if you plan to contribute markdown to the OpenThread project.'
-
- # add shfmt for shell pretty, try brew only because snap does not support home directory not being /home and doesn't work in docker.
- command -v shfmt || brew install shfmt || echo 'WARNING: could not install shfmt, which is useful if you plan to contribute shell scripts to the OpenThread project.'
+ if [ "$PLATFORM" != "Raspbian" ]; then
+ install_packages_pretty_format
+ fi
}
install_packages_opkg()
diff --git a/script/check-android-build b/script/check-android-build
index 5acc038..8587fde 100755
--- a/script/check-android-build
+++ b/script/check-android-build
@@ -47,8 +47,8 @@
main()
{
- USE_OTBR_DAEMON=1 check_targets ot-cli ot-ctl ot-ncp
- check_targets ot-cli ot-ncp spi-hdlc-adapter
+ OPENTHREAD_ENABLE_ANDROID_MK=1 ANDROID_NDK=1 USE_OTBR_DAEMON=1 check_targets ot-cli ot-ctl
+ OPENTHREAD_ENABLE_ANDROID_MK=1 ANDROID_NDK=1 check_targets ot-cli spi-hdlc-adapter
}
main "$@"
diff --git a/script/check-arm-build-autotools b/script/check-arm-build-autotools
index dee5ce3..6c1de79 100755
--- a/script/check-arm-build-autotools
+++ b/script/check-arm-build-autotools
@@ -58,6 +58,8 @@
"DNS_CLIENT=1"
"JOINER=1"
"SLAAC=1"
+ # cc2538 does not have enough resources to support Thread 1.2
+ "THREAD_VERSION=1.1"
)
reset_source
@@ -133,7 +135,6 @@
build_nrf52811()
{
local options=(
- "BORDER_ROUTER=1"
"COAP=1"
"DNS_CLIENT=1"
"LINK_RAW=1"
@@ -172,9 +173,11 @@
"LINK_RAW=1"
"MAC_FILTER=1"
"MTD_NETDIAG=1"
+ "PING_SENDER=1"
"SERVICE=1"
"SLAAC=1"
"SNTP_CLIENT=1"
+ "SRP_CLIENT=1"
"UDP_FORWARD=1"
)
@@ -214,9 +217,11 @@
"LINK_RAW=1"
"MAC_FILTER=1"
"MTD_NETDIAG=1"
+ "PING_SENDER=1"
"SERVICE=1"
"SLAAC=1"
"SNTP_CLIENT=1"
+ "SRP_CLIENT=1"
"UDP_FORWARD=1"
)
diff --git a/script/check-arm-build-cmake b/script/check-arm-build-cmake
index 5eddf85..17a8b65 100755
--- a/script/check-arm-build-cmake
+++ b/script/check-arm-build-cmake
@@ -56,8 +56,13 @@
build_cc2538()
{
+ local options=(
+ # cc2538 does not have enough resources to support Thread 1.2
+ "-DOT_THREAD_VERSION=1.1"
+ )
+
reset_source
- "$(dirname "$0")"/cmake-build cc2538 "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+ "$(dirname "$0")"/cmake-build cc2538 "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}" "${options[@]}"
}
build_cc2650()
@@ -78,12 +83,48 @@
"$(dirname "$0")"/cmake-build kw41z "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
}
+build_nrf52811()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build nrf52811 "$1" "${OT_COMMON_OPTIONS[@]}"
+}
+
+build_nrf52833()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build nrf52833 "$1" "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+}
+
+build_nrf52840()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build nrf52840 "$1" "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+}
+
build_qpg6095()
{
reset_source
"$(dirname "$0")"/cmake-build qpg6095 "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
}
+build_qpg6100()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build qpg6100 "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+}
+
+build_gp712()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build gp712 "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+}
+
+build_qpg7015m()
+{
+ reset_source
+ "$(dirname "$0")"/cmake-build qpg7015m "${OT_COMMON_OPTIONS[@]}" "${OT_BASIC_CHECK_OPTIONS[@]}"
+}
+
build_samr21()
{
reset_source
@@ -107,7 +148,20 @@
build_cc2652
build_kw41z
build_qpg6095
+ build_qpg6100
+ build_gp712
+ build_qpg7015m
build_samr21
+ # UART transport
+ build_nrf52840 UART_trans
+ # USB transport with bootloader e.g. to support PCA10059 dongle
+ build_nrf52840 USB_trans_bl
+ # SPI transport for NCP
+ build_nrf52840 SPI_trans_NCP
+ # Software cryptography
+ build_nrf52840 soft_crypto
+ # Software cryptography with threading support
+ build_nrf52840 soft_crypto_threading
return 0
fi
diff --git a/tests/scripts/expect/cli-anycast.exp b/script/check-core-makefiles
old mode 100644
new mode 100755
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to script/check-core-makefiles
index 3081a6b..b55066b
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/script/check-core-makefiles
@@ -1,6 +1,6 @@
-#!/usr/bin/expect -f
+#!/bin/bash
#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +27,25 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+set -euo pipefail
-
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
+die()
+{
+ echo >&2 "ERROR: $*"
+ exit 1
}
-dispose
+main()
+{
+ ./script/update-makefiles.py || die "Could not run ./script/update-makefiles.py"
+
+ status=$(git status --porcelain)
+
+ if [ -n "${status}" ]; then
+ die "Missing files in makefiles - run ./script/update-makefiles.py"
+ else
+ echo 'PASS: Makefiles-check'
+ fi
+}
+
+main "$@"
diff --git a/script/check-posix-pty b/script/check-posix-pty
index 68b57eb..f468a1d 100755
--- a/script/check-posix-pty
+++ b/script/check-posix-pty
@@ -83,7 +83,7 @@
# Cover setting a valid network interface name.
readonly VALID_NETIF_NAME="wan$(date +%H%M%S)"
- RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
+ RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?region=US&max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
if [[ ${DAEMON} == 1 ]]; then
sudo "$PWD/output/posix/bin/ot-daemon" -I "${VALID_NETIF_NAME}" "${RADIO_URL}" &
@@ -113,6 +113,9 @@
send "radiourl\r\n"
expect "${RADIO_URL}"
expect "Done"
+send "region\r\n"
+expect "US"
+expect "Done"
send "panid 0xface\r\n"
expect "Done"
send "ifconfig up\r\n"
@@ -125,6 +128,8 @@
expect "Done"
send "extaddr\r\n"
expect "Done"
+send "dataset active\r\n"
+expect "Done"
send "ipaddr\r\n"
expect "Done"
send "coex\r\n"
@@ -150,7 +155,7 @@
netstat -an | grep -q 5683 || die 'Application CoAP port is not available!'
- extaddr=$(grep -aoE '[0-9a-z]{16}' $OT_OUTPUT)
+ extaddr=$(grep -azoP 'extaddr[\r\n]+\K[0-9a-z]{16}' $OT_OUTPUT | tr -d '\0')
echo "Extended address is: ${extaddr}"
if [[ ${DAEMON} == 1 ]]; then
@@ -162,9 +167,10 @@
|| die 'multicast group join failed'
fi
- LEADER_ALOC=fdde:ad00:beef::ff:fe00:fc00
+ prefix=$(grep -aoP 'Mesh Local Prefix: \K[0-9a-f:]+(?=::\/64)' $OT_OUTPUT | tr -d '\r\n')
+ LEADER_ALOC="$prefix::ff:fe00:fc00"
# Retrievie test resource through application CoAP
- coap_response=$(coap-client -B 5 -m GET coap://[${LEADER_ALOC}]:5683/TestResource)
+ coap_response=$(coap-client -B 5 -m GET "coap://[${LEADER_ALOC}]:5683/TestResource")
echo "CoAP response is: ${coap_response}"
# Verify CoAP response contains the test content
@@ -173,6 +179,14 @@
else
die 'Failed to access application CoAP'
fi
+
+ # Retrievie extended address through network diagnostic get
+ coap_response=$(echo -n '120100' | xxd -r -p | coap-client -B 5 -m POST "coap://[${LEADER_ALOC}]:61631/d/dg" -f-)
+
+ # Verify Tmf CoAP is blocked
+ if [[ -z ${coap_response} ]]; then
+ die 'Tmf is not blocked'
+ fi
}
main()
diff --git a/script/check-scan-build b/script/check-scan-build
index 3c38f1e..c30889a 100755
--- a/script/check-scan-build
+++ b/script/check-scan-build
@@ -68,11 +68,14 @@
"-DOPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_ENABLE=1"
"-DOPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE=1"
"-DOPENTHREAD_CONFIG_MPL_DYNAMIC_INTERVAL_ENABLE"
+ "-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE=1"
"-DOPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE=1"
"-DOPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_SRP_SERVER_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE=1"
"-DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1"
@@ -100,7 +103,7 @@
scan-build-9 ./configure "${configure_options[@]}"
scan-build-9 --status-bugs -analyze-headers -v make -j"${OT_BUILD_JOBS}"
- export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
scan-build-9 ./configure "${configure_options[@]}"
scan-build-9 --status-bugs -analyze-headers -v make -j"${OT_BUILD_JOBS}"
}
diff --git a/script/check-simulation-build-autotools b/script/check-simulation-build-autotools
index 590c3c0..ec71578 100755
--- a/script/check-simulation-build-autotools
+++ b/script/check-simulation-build-autotools
@@ -73,13 +73,15 @@
"-DOPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_ENABLE=1"
"-DOPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE=1"
"-DOPENTHREAD_CONFIG_MPL_DYNAMIC_INTERVAL_ENABLE"
+ "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
"-DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1"
- "-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE=1"
"-DOPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE=1"
"-DOPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE=1"
"-DOPENTHREAD_CONFIG_UDP_FORWARD_ENABLE=1"
@@ -132,6 +134,7 @@
"-DOPENTHREAD_CONFIG_JAM_DETECTION_ENABLE=1"
"-DOPENTHREAD_CONFIG_LEGACY_ENABLE=1"
"-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1"
"-DOPENTHREAD_CONFIG_NCP_SPI_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1"
@@ -153,7 +156,7 @@
"-DOPENTHREAD_CONFIG_ANOUNCE_SENDER_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_TIME_SYNC_ENABLE=1"
- "-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
)
export CPPFLAGS="${options[*]}"
@@ -172,7 +175,7 @@
cd ..
options=(
- "-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
)
export CPPFLAGS="${options[*]}"
@@ -196,7 +199,7 @@
{
# TREL radio link only.
local options=(
- "-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG"
"-DOPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE=0"
@@ -220,7 +223,7 @@
# Multi radio link - 15.4 and TREL.
options=(
- "-DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1"
"-DOPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE=1"
"-DOPENTHREAD_CONFIG_DIAG_ENABLE=1"
"-DOPENTHREAD_CONFIG_LINK_RAW_ENABLE=1"
diff --git a/script/check-size b/script/check-size
index b4c5897..572c264 100755
--- a/script/check-size
+++ b/script/check-size
@@ -48,9 +48,15 @@
arm-none-eabi-gcc --version
}
+setup_ninja_build()
+{
+ sudo apt-get --no-install-recommends install -y ninja-build
+}
+
setup()
{
setup_arm_gcc_7
+ setup_ninja_build
}
markdown_init()
@@ -98,60 +104,73 @@
esac
}
+nm_size()
+{
+ arm-none-eabi-nm --print-size --defined-only -C "$1" | cut -d' ' -f2- >nmsize_old
+ arm-none-eabi-nm --print-size --defined-only -C "$2" | cut -d' ' -f2- >nmsize_new
+ diff -Nuar nmsize_old nmsize_new || true
+}
+
size_nrf52840_version()
{
- local flags=(
- "BORDER_AGENT=1"
- "BORDER_ROUTER=1"
- "CHANNEL_MANAGER=1"
- "CHANNEL_MONITOR=1"
- "CHILD_SUPERVISION=1"
- "COAP=1"
- "COAPS=1"
- "COMMISSIONER=1"
- "DATASET_UPDATER=1"
- "DHCP6_CLIENT=1"
- "DHCP6_SERVER=1"
- "DIAGNOSTIC=1"
- "DISABLE_DOC=1"
- "DNS_CLIENT=1"
- "ECDSA=1"
- "FULL_LOGS=1"
- "JAM_DETECTION=1"
- "JOINER=1"
- "LINK_RAW=1"
- "MAC_FILTER=1"
- "MESSAGE_USE_HEAP=1"
- "MTD_NETDIAG=1"
- "SERVICE=1"
- "SLAAC=1"
- "SNTP_CLIENT=1"
- "TIME_SYNC=1"
- "UDP_FORWARD=1"
+ local options=(
+ "-DOT_BORDER_AGENT=ON"
+ "-DOT_BORDER_ROUTER=ON"
+ "-DOT_CHANNEL_MANAGER=ON"
+ "-DOT_CHANNEL_MONITOR=ON"
+ "-DOT_CHILD_SUPERVISION=ON"
+ "-DOT_COAP=ON"
+ "-DOT_COAPS=ON"
+ "-DOT_COMMISSIONER=ON"
+ "-DOT_DATASET_UPDATER=ON"
+ "-DOT_DHCP6_CLIENT=ON"
+ "-DOT_DHCP6_SERVER=ON"
+ "-DOT_DIAGNOSTIC=ON"
+ "-DOT_DNSSD_SERVER=ON"
+ "-DOT_DNS_CLIENT=ON"
+ "-DOT_ECDSA=ON"
+ "-DOT_FULL_LOGS=ON"
+ "-DOT_JAM_DETECTION=ON"
+ "-DOT_JOINER=ON"
+ "-DOT_LINK_RAW=ON"
+ "-DOT_MAC_FILTER=ON"
+ "-DOT_MESSAGE_USE_HEAP=ON"
+ "-DOT_MTD_NETDIAG=ON"
+ "-DOT_PING_SENDER=ON"
+ "-DOT_SERVICE=ON"
+ "-DOT_SLAAC=ON"
+ "-DOT_SNTP_CLIENT=ON"
+ "-DOT_SRP_CLIENT=ON"
+ "-DOT_SRP_SERVER=ON"
+ "-DOT_TIME_SYNC=ON"
+ "-DOT_UDP_FORWARD=ON"
)
local thread_version=$1
if [[ ${thread_version} == "1.2" ]]; then
- flags+=(
- "THREAD_VERSION=1.2"
- "BACKBONE_ROUTER=1"
- "DUA=1"
- "MLR=1"
- "CSL_RECEIVER=1"
- "LINK_METRICS=1"
+ options+=(
+ "-DOT_THREAD_VERSION=1.2"
+ "-DOT_BACKBONE_ROUTER=ON"
+ "-DOT_DUA=ON"
+ "-DOT_MLR=ON"
+ "-DOT_CSL_RECEIVER=ON"
+ "-DOT_LINK_METRICS=ON"
)
fi
rm -rf "${OT_TMP_DIR}"
+ local build_dir="build"
+
# new commit
mkdir -p "${OT_TMP_DIR}/b"
- git archive "${OT_SHA_NEW}" | tar x -C "${OT_TMP_DIR}/b"
+ script/git-tool clone https://github.com/openthread/ot-nrf528xx.git "${OT_TMP_DIR}/b"
+ rm -rf "${OT_TMP_DIR}/b/openthread/*" # replace openthread submodule with latest commit
+ git archive "${OT_SHA_NEW}" | tar x -C "${OT_TMP_DIR}/b/openthread"
(cd "${OT_TMP_DIR}/b" \
- && ./bootstrap \
- && make -f examples/Makefile-nrf52840 "${flags[@]}")
+ && OT_CMAKE_BUILD_DIR=${build_dir} script/build nrf52840 UART_trans "${options[@]}")
# old commit
if [[ "${GITHUB_ACTIONS+x}" ]]; then
@@ -159,39 +178,57 @@
fi
mkdir -p "${OT_TMP_DIR}/a"
- git archive "${OT_SHA_OLD}" | tar x -C "${OT_TMP_DIR}/a"
+ git clone https://github.com/openthread/ot-nrf528xx.git "${OT_TMP_DIR}/a"
+ rm -rf "${OT_TMP_DIR}/a/openthread/*" # replace openthread submodule with last commit
+ git archive "${OT_SHA_OLD}" | tar x -C "${OT_TMP_DIR}/a/openthread"
+
(cd "${OT_TMP_DIR}/a" \
- && ./bootstrap \
- && make -f examples/Makefile-nrf52840 "${flags[@]}")
+ && OT_CMAKE_BUILD_DIR=${build_dir} script/build nrf52840 UART_trans "${options[@]}")
# rename the generated files to be ready for size-report
# shellcheck disable=SC2011
(
- cd "${OT_TMP_DIR}"/a/output/nrf52840/bin
+ cd "${OT_TMP_DIR}"/a/"${build_dir}"/bin
ls | xargs -I{} mv {} {}_"${thread_version}"
- cd "${OT_TMP_DIR}"/b/output/nrf52840/bin
+ cd "${OT_TMP_DIR}"/b/"${build_dir}"/bin
ls | xargs -I{} mv {} {}_"${thread_version}"
- cd "${OT_TMP_DIR}"/a/output/nrf52840/lib/
+ cd "${OT_TMP_DIR}"/a/"${build_dir}"/lib
ls ./*.a | xargs -I{} mv {} {}_"${thread_version}"
- cd "${OT_TMP_DIR}"/b/output/nrf52840/lib/
+ cd "${OT_TMP_DIR}"/b/"${build_dir}"/lib
ls ./*.a | xargs -I{} mv {} {}_"${thread_version}"
)
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/bin/ot-cli-ftd_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/bin/ot-cli-ftd_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/bin/ot-cli-mtd_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/bin/ot-cli-mtd_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/bin/ot-ncp-ftd_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/bin/ot-ncp-ftd_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/bin/ot-ncp-mtd_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/bin/ot-ncp-mtd_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/bin/ot-rcp_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/bin/ot-rcp_"${thread_version}"
+ local bins=(
+ "ot-cli-ftd"
+ "ot-cli-mtd"
+ "ot-ncp-ftd"
+ "ot-ncp-mtd"
+ "ot-rcp"
+ )
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-cli-ftd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-cli-ftd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-cli-mtd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-cli-mtd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-ftd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-ftd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-mtd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-mtd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-ncp-ftd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-ncp-ftd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-ncp-mtd.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-ncp-mtd.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-rcp.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-rcp.a_"${thread_version}"
- "${reporter}" size "${OT_TMP_DIR}"/a/output/nrf52840/lib/libopenthread-radio.a_"${thread_version}" "${OT_TMP_DIR}"/b/output/nrf52840/lib/libopenthread-radio.a_"${thread_version}"
+ local libs=(
+ "libopenthread-cli-ftd.a"
+ "libopenthread-cli-mtd.a"
+ "libopenthread-ftd.a"
+ "libopenthread-mtd.a"
+ "libopenthread-ncp-ftd.a"
+ "libopenthread-ncp-mtd.a"
+ "libopenthread-rcp.a"
+ "libopenthread-radio.a"
+ )
+
+ for file in "${bins[@]}"; do
+ "${reporter}" size "${OT_TMP_DIR}"/a/"${build_dir}"/bin/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/bin/"${file}"_"${thread_version}"
+ echo nm_size "${OT_TMP_DIR}"/a/"${build_dir}"/bin/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/bin/"${file}"_"${thread_version}"
+ nm_size "${OT_TMP_DIR}"/a/"${build_dir}"/bin/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/bin/"${file}"_"${thread_version}"
+ done
+
+ for file in "${libs[@]}"; do
+ "${reporter}" size "${OT_TMP_DIR}"/a/"${build_dir}"/lib/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/lib/"${file}"_"${thread_version}"
+ echo nm_size "${OT_TMP_DIR}"/a/"${build_dir}"/lib/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/lib/"${file}"_"${thread_version}"
+ nm_size "${OT_TMP_DIR}"/a/"${build_dir}"/lib/"${file}"_"${thread_version}" "${OT_TMP_DIR}"/b/"${build_dir}"/lib/"${file}"_"${thread_version}"
+ done
}
size_nrf52840()
diff --git a/script/cmake-build b/script/cmake-build
index e8f3d94..4b5e7db 100755
--- a/script/cmake-build
+++ b/script/cmake-build
@@ -42,6 +42,21 @@
#
# script/cmake-build ${platform} -D${option}=OFF
#
+# Need to add build type when compilling nrf528xx:
+#
+# script/cmake-build ${platform} ${nrf_build_type} -D${option}=ON -D${option}=OFF
+#
+# Need to add BOARD when compiling efr32:
+#
+# script/cmake-build ${platform} -DBOARD=${EFR32 board}
+#
+# Example:
+# script/cmake-build efr32mg21 -DBOARD=brd4180b
+#
+# To enable dynamic multiprotocol support on efr32:
+#
+# script/cmake-build ${platform} -DBOARD=${EFR32 board} -DDMP=ON
+#
# Compile with the specified ninja build target:
#
# OT_CMAKE_NINJA_TARGET="ot-cli-ftd" script/cmake-build ${platform}
@@ -64,11 +79,13 @@
OT_CMAKE_NINJA_TARGET=${OT_CMAKE_NINJA_TARGET:-}
readonly OT_SRCDIR="$(pwd)"
-readonly OT_PLATFORMS=(cc1352 cc2538 cc2650 cc2652 kw41z qpg6095 samr21 simulation posix)
+readonly OT_PLATFORMS=(cc1352 cc2538 cc2650 cc2652 efr32mg1 efr32mg12 efr32mg13 efr32mg21 kw41z nrf52811 nrf52833 nrf52840 gp712 qpg7015m qpg6095 qpg6100 samr21 simulation posix)
+readonly OT_NRF528XX_BUILD_TYPES=(UART_trans USB_trans_bl SPI_trans_NCP soft_crypto soft_crypto_threading)
readonly OT_POSIX_SIM_COMMON_OPTIONS=(
"-DOT_BORDER_AGENT=ON"
"-DOT_BORDER_ROUTER=ON"
"-DOT_COAP=ON"
+ "-DOT_COAP_BLOCK=ON"
"-DOT_COAP_OBSERVE=ON"
"-DOT_COAPS=ON"
"-DOT_COMMISSIONER=ON"
@@ -87,15 +104,67 @@
"-DOT_LEGACY=ON"
"-DOT_MAC_FILTER=ON"
"-DOT_MTD_NETDIAG=ON"
+ "-DOT_PING_SENDER=ON"
"-DOT_REFERENCE_DEVICE=ON"
"-DOT_SERVICE=ON"
"-DOT_SNTP_CLIENT=ON"
+ "-DOT_SRP_CLIENT=ON"
"-DOT_COVERAGE=ON"
"-DOT_LOG_LEVEL_DYNAMIC=ON"
"-DOT_COMPILE_WARNING_AS_ERROR=ON"
"-DOT_RCP_RESTORATION_MAX_COUNT=2"
)
+readonly OT_nrf52811_OPTIONS=(
+ "-DOT_BORDER_ROUTER=ON"
+ "-DOT_COAP=ON"
+ "-DOT_DNS_CLIENT=ON"
+ "-DOT_LINK_RAW=ON"
+ "-DOT_MAC_FILTER=ON"
+ "-DOT_MTD_NETDIAG=ON"
+)
+
+readonly OT_nrf52833_OPTIONS=(
+ "-DOT_BORDER_AGENT=ON"
+ "-DOT_BORDER_ROUTER=ON"
+ "-DOT_COAP=ON"
+ "-DOT_COAPS=ON"
+ "-DOT_ECDSA=ON"
+ "-DOT_FULL_LOGS=ON"
+ "-DOT_IP6_FRAGM=ON"
+ "-DOT_LINK_RAW=ON"
+ "-DOT_MAC_FILTER=ON"
+ "-DOT_MTD_NETDIAG=ON"
+ "-DOT_SERVICE=ON"
+ "-DOT_SNTP_CLIENT=ON"
+ "-DOT_UDP_FORWARD=ON"
+)
+
+readonly OT_nrf52840_OPTIONS=("${OT_nrf52833_OPTIONS[@]:0}")
+
+readonly OT_efr32_OPTIONS=(
+ "-DOT_DIAGNOSTIC=ON"
+ "-DOT_EXTERNAL_HEAP=ON"
+ "-DOT_EXTERNAL_MBEDTLS=silabs-mbedtls"
+ "-DOT_BUILTIN_MBEDTLS_MANAGEMENT=OFF"
+)
+
+readonly OT_efr32mg1_OPTIONS=(
+ "${OT_efr32_OPTIONS[@]:0}"
+)
+
+readonly OT_efr32mg12_OPTIONS=(
+ "${OT_efr32_OPTIONS[@]:0}"
+)
+
+readonly OT_efr32mg13_OPTIONS=(
+ "${OT_efr32_OPTIONS[@]:0}"
+)
+
+readonly OT_efr32mg21_OPTIONS=(
+ "${OT_efr32_OPTIONS[@]:0}"
+)
+
die()
{
echo " ** ERROR: Openthread CMake doesn't support platform \"$1\""
@@ -130,6 +199,16 @@
fi
local platform="$1"
+ # Check if the platform supports cmake.
+ echo "${OT_PLATFORMS[@]}" | grep -wq "${platform}" || die "${platform}"
+
+ local nrf_build_type=""
+ if [[ ${platform} == nrf528* ]]; then
+ nrf_build_type="$2"
+ echo "${OT_NRF528XX_BUILD_TYPES[@]}" | grep -wq "${nrf_build_type}" || die "${nrf_build_type}"
+ shift
+ fi
+
shift
local local_options=()
local options=(
@@ -137,9 +216,6 @@
"-DOT_SLAAC=ON"
)
- # Check if the platform supports cmake.
- echo "${OT_PLATFORMS[@]}" | grep -wq "${platform}" || die "${platform}"
-
case "${platform}" in
posix)
local_options+=(
@@ -156,9 +232,91 @@
OT_CMAKE_NINJA_TARGET=("ot-cli-mtd" "ot-ncp-mtd")
options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=MinSizeRel")
;;
- cc1352 | cc2538 | cc2652 | kw41z | qpg6095 | samr21)
+ cc1352 | cc2538 | cc2652 | kw41z | samr21)
options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=MinSizeRel")
;;
+ qpg6095 | qpg6100)
+ OT_CMAKE_NINJA_TARGET=("ot-cli-mtd" "ot-cli-ftd")
+ options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=MinSizeRel")
+ ;;
+ qpg7015m | gp712)
+ OT_CMAKE_NINJA_TARGET=("ot-cli-ftd" "ot-rcp")
+ options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/${platform}/arm-linux-gnueabihf.cmake" "-DCMAKE_BUILD_TYPE=Release")
+ ;;
+ efr32*)
+ options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/efr32/${platform}/arm-none-eabi.cmake")
+
+ case "${platform}" in
+ efr32mg1)
+ OT_CMAKE_NINJA_TARGET=("ot-rcp")
+ options+=("${OT_efr32mg1_OPTIONS[@]}")
+ ;;
+ efr32mg12)
+ OT_CMAKE_NINJA_TARGET=("ot-rcp" "ot-cli-ftd" "ot-cli-mtd" "ot-ncp-ftd" "ot-ncp-mtd")
+ OT_CMAKE_NINJA_TARGET+=("sleepy-demo-ftd" "sleepy-demo-mtd")
+ options+=("${OT_efr32mg12_OPTIONS[@]}")
+ ;;
+ efr32mg13)
+ OT_CMAKE_NINJA_TARGET=("ot-rcp" "ot-cli-ftd" "ot-cli-mtd" "ot-ncp-ftd" "ot-ncp-mtd")
+ OT_CMAKE_NINJA_TARGET+=("sleepy-demo-ftd" "sleepy-demo-mtd")
+ options+=("${OT_efr32mg13_OPTIONS[@]}")
+ ;;
+ efr32mg21)
+ OT_CMAKE_NINJA_TARGET=("ot-rcp" "ot-cli-ftd" "ot-cli-mtd" "ot-ncp-ftd" "ot-ncp-mtd")
+ OT_CMAKE_NINJA_TARGET+=("sleepy-demo-ftd" "sleepy-demo-mtd")
+ options+=("${OT_efr32mg21_OPTIONS[@]}")
+ ;;
+ esac
+ ;;
+ nrf52811)
+ local_options+=("${OT_nrf52811_OPTIONS[@]}" "-DCMAKE_TOOLCHAIN_FILE=examples/platforms/nrf528xx/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=Release")
+ case "${nrf_build_type}" in
+ UART_trans)
+ OT_CMAKE_NINJA_TARGET=("ot-cli-mtd" "ot-ncp-mtd" "ot-rcp")
+ options+=("${local_options[@]}")
+ ;;
+ SPI_trans_NCP)
+ OT_CMAKE_NINJA_TARGET=("ot-ncp-mtd" "ot-rcp")
+ options+=("${local_options[@]}" "-DOT_NCP_SPI=ON")
+ ;;
+ esac
+ ;;
+ nrf52833)
+ local_options+=("${OT_nrf52833_OPTIONS[@]}" "-DCMAKE_TOOLCHAIN_FILE=examples/platforms/nrf528xx/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=Release")
+ case "${nrf_build_type}" in
+ UART_trans)
+ options+=("${local_options[@]}")
+ ;;
+ USB_trans_bl)
+ options+=("${local_options[@]}" "-DOT_USB=ON" "-DOT_BOOTLOADER=USB")
+ ;;
+ SPI_trans_NCP)
+ OT_CMAKE_NINJA_TARGET=("ot-ncp-ftd" "ot-ncp-mtd" "ot-rcp")
+ options+=("${local_options[@]}" "-DOT_NCP_SPI=ON")
+ ;;
+ esac
+ ;;
+ nrf52840)
+ local_options+=("${OT_nrf52840_OPTIONS[@]}" "-DCMAKE_TOOLCHAIN_FILE=examples/platforms/nrf528xx/${platform}/arm-none-eabi.cmake" "-DCMAKE_BUILD_TYPE=Release")
+ case "${nrf_build_type}" in
+ UART_trans)
+ options+=("${local_options[@]}" "-DOT_EXTERNAL_MBEDTLS=nordicsemi-mbedtls")
+ ;;
+ USB_trans_bl)
+ options+=("${local_options[@]}" "-DOT_USB=ON" "-DOT_BOOTLOADER=USB" "-DOT_EXTERNAL_MBEDTLS=nordicsemi-mbedtls")
+ ;;
+ SPI_trans_NCP)
+ OT_CMAKE_NINJA_TARGET=("ot-ncp-ftd" "ot-ncp-mtd" "ot-rcp")
+ options+=("${local_options[@]}" "-DOT_NCP_SPI=ON" "-DOT_EXTERNAL_MBEDTLS=nordicsemi-mbedtls")
+ ;;
+ soft_crypto)
+ options+=("${local_options[@]}")
+ ;;
+ soft_crypto_threading)
+ options+=("${local_options[@]}" "-DOT_MBEDTLS_THREADING=ON")
+ ;;
+ esac
+ ;;
*)
options+=("-DCMAKE_TOOLCHAIN_FILE=examples/platforms/${platform}/arm-none-eabi.cmake")
;;
diff --git a/script/git-tool b/script/git-tool
index 4cf8ba1..4bcdae8 100755
--- a/script/git-tool
+++ b/script/git-tool
@@ -38,13 +38,16 @@
project_name=$(git remote get-url origin | grep -oE '[^/:]+/[^/:]+\.git$' | cut -d. -f1)
echo "project name: ${project_name}"
- depends_on_pr="$(grep -E "^Depends-On: *${project_name}" | cut -d# -f2)" || {
- echo "No dependency on ${project_name} found."
- return 0
- }
- echo "pr: #${depends_on_pr}"
- git fetch --depth 1 origin "pull/${depends_on_pr}/head"
- git checkout FETCH_HEAD
+
+ git config user.name || git config user.name 'OpenThread Git'
+ git config user.email || git config user.email 'git@openthread'
+
+ while read -r dependency; do
+ echo "${dependency}"
+ depends_on_pr="$(echo "${dependency}" | tr -d '\r\n' | cut -d# -f2)"
+ echo "pr: #${depends_on_pr}"
+ git pull --no-edit origin "pull/${depends_on_pr}/merge"
+ done < <(grep -E "^Depends-On: *${project_name}" || true)
}
get_pr_body()
diff --git a/script/make-pretty b/script/make-pretty
index 63f131d..1f7edae 100755
--- a/script/make-pretty
+++ b/script/make-pretty
@@ -85,6 +85,7 @@
'-DOT_CHANNEL_MONITOR=ON'
'-DOT_CHILD_SUPERVISION=ON'
'-DOT_COAP=ON'
+ '-DOT_COAP_BLOCK=ON'
'-DOT_COAP_OBSERVE=ON'
'-DOT_COAPS=ON'
'-DOT_COMMISSIONER=ON'
@@ -105,10 +106,12 @@
'-DOT_LINK_METRICS=ON'
'-DOT_MAC_FILTER=ON'
'-DOT_MTD_NETDIAG=ON'
+ '-DOT_PING_SENDER=ON'
'-DOT_REFERENCE_DEVICE=ON'
'-DOT_SERVICE=ON'
'-DOT_SLAAC=ON'
'-DOT_SNTP_CLIENT=ON'
+ '-DOT_SRP_CLIENT=ON'
'-DOT_THREAD_VERSION=1.2'
'-DOT_COVERAGE=ON'
'-DOT_LOG_LEVEL_DYNAMIC=ON'
diff --git a/script/test b/script/test
index 7e20f13..af73c54 100755
--- a/script/test
+++ b/script/test
@@ -32,23 +32,45 @@
set -euo pipefail
-readonly OT_BUILDDIR="${PWD}/build"
+readonly OT_BUILDDIR="${OT_BUILDDIR:-${PWD}/build}"
readonly OT_SRCDIR="${PWD}"
readonly COLOR_PASS='\033[0;32m'
readonly COLOR_FAIL='\033[0;31m'
+readonly COLOR_SKIP='\033[0;33m'
readonly COLOR_NONE='\033[0m'
readonly OT_NODE_TYPE="${OT_NODE_TYPE:-cli}"
readonly OT_NATIVE_IP="${OT_NATIVE_IP:-0}"
-readonly THREAD_VERSION="${THREAD_VERSION:-1.1}"
+readonly THREAD_VERSION="${THREAD_VERSION:-1.2}"
readonly INTER_OP="${INTER_OP:-0}"
readonly VERBOSE="${VERBOSE:-0}"
+readonly BORDER_ROUTING="${BORDER_ROUTING:-1}"
+readonly INTER_OP_BBR="${INTER_OP_BBR:-1}"
+
+readonly OT_COREDUMP_DIR="${PWD}/ot-core-dump"
+readonly FULL_LOGS=${FULL_LOGS:-0}
build_simulation()
{
local version="$1"
- local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON" "-DOT_REFERENCE_DEVICE=ON")
+ local options=(
+ "-DOT_MESSAGE_USE_HEAP=ON"
+ "-DOT_THREAD_VERSION=${version}"
+ "-DBUILD_TESTING=ON"
+ "-DOT_REFERENCE_DEVICE=ON"
+ "-DOT_SRP_SERVER=ON"
+ "-DOT_SRP_CLIENT=ON"
+ "-DOT_SERVICE=ON"
+ "-DOT_ECDSA=ON"
+ "-DOT_PING_SENDER=ON"
+ "-DOT_DNSSD_SERVER=ON"
+ "-DOT_DNS_CLIENT=ON"
+ )
+
+ if [[ ${FULL_LOGS} == 1 ]]; then
+ options+=("-DOT_FULL_LOGS=ON")
+ fi
if [[ ${version} == "1.2" ]]; then
options+=("-DOT_DUA=ON")
@@ -57,11 +79,6 @@
if [[ ${VIRTUAL_TIME} == 1 ]]; then
options+=("-DOT_SIMULATION_VIRTUAL_TIME=ON")
-
- if [[ ${OT_NODE_TYPE} == rcp* ]]; then
- options+=("-DOT_SIMULATION_VIRTUAL_TIME_UART=ON")
- fi
-
fi
if [[ ${version} == "1.2" ]]; then
@@ -75,12 +92,20 @@
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}"
- if [[ ${version} == "1.2" ]]; then
+ if [[ ${VIRTUAL_TIME} == 1 ]] && [[ ${OT_NODE_TYPE} == rcp* ]]; then
+ OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON"
+ fi
+
+ if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
options+=("-DOT_BACKBONE_ROUTER=ON")
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}-bbr" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}"
+ if [[ ${VIRTUAL_TIME} == 1 ]] && [[ ${OT_NODE_TYPE} == rcp* ]]; then
+ OT_CMAKE_NINJA_TARGET=ot-rcp OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-simulation-${version}-bbr" "${OT_SRCDIR}"/script/cmake-build simulation "${options[@]}" "-DOT_SIMULATION_VIRTUAL_TIME_UART=ON"
+ fi
+
fi
}
@@ -94,6 +119,10 @@
options+=("-DOT_MLR=ON")
fi
+ if [[ ${FULL_LOGS} == 1 ]]; then
+ options+=("-DOT_FULL_LOGS=ON")
+ fi
+
if [[ ${VIRTUAL_TIME} == 1 ]]; then
options+=("-DOT_POSIX_VIRTUAL_TIME=ON")
fi
@@ -108,7 +137,7 @@
OT_CMAKE_BUILD_DIR="${OT_BUILDDIR}/openthread-posix-${version}" "${OT_SRCDIR}"/script/cmake-build posix "${options[@]}"
- if [[ ${version} == "1.2" ]]; then
+ if [[ ${version} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
options+=("-DOT_BACKBONE_ROUTER=ON")
@@ -162,7 +191,7 @@
{
do_unit_version "${THREAD_VERSION}"
- if [[ ${THREAD_VERSION} == "1.2" ]]; then
+ if [[ ${THREAD_VERSION} == "1.2" && ${INTER_OP_BBR} == 1 ]]; then
do_unit_version "1.2-bbr"
fi
}
@@ -188,8 +217,11 @@
fi
fi
+ export PYTHONPATH=tests/scripts/thread-cert
+
[[ ! -d tmp ]] || rm -rvf tmp
- PYTHONUNBUFFERED=1 "$1"
+ PYTHONUNBUFFERED=1 "$@"
+ exit 0
}
do_cert_suite()
@@ -231,7 +263,7 @@
echo "Building OTBR Docker ..."
local otdir
local otbrdir
- local otbr_options="-DOT_DUA=ON -DOT_MLR=ON -DOT_COVERAGE=ON -DOTBR_REST=OFF -DOTBR_WEB=OFF"
+ local otbr_options="-DOT_DNSSD_SERVER=ON -DOT_DNS_CLIENT=ON -DOT_SRP_CLIENT=ON -DOT_SLAAC=ON -DOT_DUA=ON -DOT_MLR=ON -DOT_COVERAGE=ON -DOTBR_REST=OFF -DOTBR_WEB=OFF -DOTBR_DUA_ROUTING=ON"
local otbr_docker_image=${OTBR_DOCKER_IMAGE:-otbr-ot12-backbone-ci}
otbrdir=$(mktemp -d -t otbr_XXXXXX)
@@ -244,6 +276,8 @@
cp -r "${otdir}" third_party/openthread/repo
rm -rf .git
docker build -t "${otbr_docker_image}" -f etc/docker/Dockerfile . \
+ --build-arg BORDER_ROUTING="${BORDER_ROUTING}" \
+ --build-arg INFRA_IF_NAME=eth0 \
--build-arg BACKBONE_ROUTER=1 \
--build-arg REFERENCE_DEVICE=1 \
--build-arg OT_BACKBONE_CI=1 \
@@ -259,6 +293,43 @@
python3 ./tests/scripts/thread-cert/pktverify/verify.py "$1"
}
+ot_exec_expect_script()
+{
+ local log_file="tmp/log_expect"
+ local script="$1"
+
+ echo -e "\n${COLOR_PASS}EXEC${COLOR_NONE} ${script}"
+ sudo killall ot-rcp || true
+ sudo killall ot-cli || true
+ sudo killall ot-cli-ftd || true
+ sudo killall ot-cli-mtd || true
+ sudo rm -rf tmp
+ mkdir tmp
+ {
+ if [[ ${OT_NATIVE_IP} == 1 ]]; then
+ sudo -E expect -df "${script}" 2>"${log_file}"
+ else
+ expect -df "${script}" 2>"${log_file}"
+ fi
+ } || {
+ local EXIT_CODE=$?
+
+ # The exit status 77 for skipping is inherited from automake's test driver for script-based testsuites
+ if [[ ${EXIT_CODE} == 77 ]]; then
+ echo -e "\n${COLOR_SKIP}SKIP${COLOR_NONE} ${script}"
+ return 0
+ else
+ echo -e "\n${COLOR_FAIL}FAIL${COLOR_NONE} ${script}"
+ cat "${log_file}" >&2
+ return "${EXIT_CODE}"
+ fi
+ }
+ echo -e "\n${COLOR_PASS}PASS${COLOR_NONE} ${script}"
+ if [[ ${VERBOSE} == 1 ]]; then
+ cat "${log_file}" >&2
+ fi
+}
+
do_expect()
{
local test_patterns
@@ -275,33 +346,13 @@
test_patterns=(-name 'cli-*.exp' -o -name 'simulation-*.exp')
fi
- local log_file="tmp/log_expect"
- while read -r script; do
- sudo rm -rf tmp
- mkdir tmp
- {
- if [[ ${OT_NATIVE_IP} == 1 ]]; then
- sudo -E expect -df "${script}" 2>"${log_file}"
- else
- expect -df "${script}" 2>"${log_file}"
- fi
- } || {
- local exit_code=$?
- cat "${log_file}" >&2
- echo -e "${COLOR_FAIL}FAIL${COLOR_NONE} ${script}"
- exit "${exit_code}"
- }
- if [[ ${VERBOSE} == 1 ]]; then
- cat "${log_file}" >&2
- fi
- echo -e "${COLOR_PASS}PASS${COLOR_NONE} ${script}"
- done < <(
- if [[ $# != 0 ]]; then
- for script in "$@"; do echo ${script}; done
- else
- find tests/scripts/expect -type f -executable \( "${test_patterns[@]}" \)
- fi
- )
+ export -f ot_exec_expect_script
+
+ if [[ $# != 0 ]]; then
+ for script in "$@"; do bash -c "ot_exec_expect_script ${script}"; done
+ else
+ find tests/scripts/expect -type f -perm "$([[ $OSTYPE == darwin* ]] && echo '+' || echo '/')"111 \( "${test_patterns[@]}" \) -exec bash -c 'ot_exec_expect_script "$1"' _ {} \;
+ fi
exit 0
}
@@ -316,10 +367,14 @@
'rcp-ncp' for NCP on POSIX platform.
The default is 'cli'.
OT_NATIVE_IP 1 to enable platform UDP and netif on POSIX platform. The default is 0.
+ OT_BUILDDIR The output directory for cmake build. By default the directory is './build'. For example,
+ 'OT_BUILDDIR=\${PWD}/my_awesome_build ./script/test clean build'.
VERBOSE 1 to build or test verbosely. The default is 0.
- VIRTUAL_TIME 1 for virtual time, otherwise real time. The default is 1.
- THREAD_VERSION 1.1 for Thread 1.1 stack, 1.2 for Thread 1.2 stack. The default is 1.1.
+ VIRTUAL_TIME 1 for virtual time, otherwise real time. The default value is 0 when running expect tests,
+ otherwise default value is 1.
+ THREAD_VERSION 1.1 for Thread 1.1 stack, 1.2 for Thread 1.2 stack. The default is 1.2.
INTER_OP 1 to build 1.1 together. Only works when THREAD_VERSION is 1.2. The default is 0.
+ INTER_OP_BBR 1 to build bbr version together. Only works when THREAD_VERSION is 1.2. The default is 1.
COMMANDS:
clean Clean built files to prepare for new build.
@@ -347,10 +402,14 @@
VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
VIRTUAL_TIME=0 $0 cert tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
+ # Test Thread 1.1 CLI with real time
+ THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/Cert_5_1_01_RouterAttach.py
+ THREAD_VERSION=1.1 VIRTUAL_TIME=0 $0 cert tests/scripts/thread-cert/Cert_5_1_02_ChildAddressTimeout.py
+
# Test Thread 1.2 with real time, use 'INTER_OP=1' when the case needs both versions.
- THREAD_VERSION=1.2 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
- THREAD_VERSION=1.2 INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_router_5_1_1.py
- THREAD_VERSION=1.2 INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert_suite tests/scripts/thread-cert/v1_2_*
+ VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_test_enhanced_keep_alive.py
+ INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert tests/scripts/thread-cert/v1_2_router_5_1_1.py
+ INTER_OP=1 VIRTUAL_TIME=0 $0 clean build cert_suite tests/scripts/thread-cert/v1_2_*
# Run a single expect test
$0 clean build expect tests/scripts/expect/cli-log-level.exp
@@ -365,7 +424,7 @@
do_package()
{
local builddir
- local options=("-DCMAKE_BUILD_TYPE=Release" "-DOT_LOG_LEVEL=INFO")
+ local options=("-DCMAKE_BUILD_TYPE=Release" "-DOT_LOG_LEVEL=INFO" "-DOT_THREAD_VERSION=${THREAD_VERSION}")
if [[ ${ot_extra_options[*]+x} ]]; then
options+=("${ot_extra_options[@]}")
@@ -386,16 +445,47 @@
do_prepare_coredump_upload()
{
- echo "$PWD/ot-core-dump/corefile-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
- mkdir -p ot-core-dump
+ echo "$OT_COREDUMP_DIR/corefile-%e-%p-%t" | sudo tee /proc/sys/kernel/core_pattern
+ rm -rf "$OT_COREDUMP_DIR"
+ mkdir -p "$OT_COREDUMP_DIR"
}
do_copy_so_lib()
{
- mkdir -p so-lib
- cp /lib/x86_64-linux-gnu/libgcc_s.so.1 ./so-lib
- cp /lib/x86_64-linux-gnu/libc.so.6 ./so-lib
- cp /lib64/ld-linux-x86-64.so.2 ./so-lib
+ mkdir -p "$OT_COREDUMP_DIR/so-lib"
+ cp /lib/x86_64-linux-gnu/libgcc_s.so.1 "$OT_COREDUMP_DIR/so-lib"
+ cp /lib/x86_64-linux-gnu/libc.so.6 "$OT_COREDUMP_DIR/so-lib"
+ cp /lib64/ld-linux-x86-64.so.2 "$OT_COREDUMP_DIR/so-lib"
+}
+
+do_check_crash()
+{
+ shopt -s nullglob
+
+ # Scan core dumps and collect binaries which crashed
+ declare -A bin_list=([dummy]='')
+ for f in "$OT_COREDUMP_DIR"/core*; do
+ bin=$(file "$f" | grep -E -o "execfn: '(.*')," | sed -r "s/execfn: '(.*)',/\1/")
+ bin_list[$bin]=''
+ done
+
+ for key in "${!bin_list[@]}"; do
+ if [ "$key" != "dummy" ]; then
+ # Add postfix for binaries to avoid conflicts caused by different Thread version
+ postfix=""
+ if [[ $key =~ openthread-(simulation|posix)-([0-9]\.[0-9]) ]]; then
+ postfix="-$(echo "$key" | sed -r "s/.*openthread-(simulation|posix)-([0-9]\.[0-9]).*/\2/")"
+ fi
+ bin_name=$(basename "$key")
+ cp "$key" "$OT_COREDUMP_DIR"/"$bin_name""$postfix"
+ fi
+ done
+
+ # echo 1 and copy so libs if crash found, echo 0 otherwise
+ [[ ${#bin_list[@]} -gt 1 ]] && (
+ echo 1
+ do_copy_so_lib
+ ) || echo 0
}
do_generate_coverage()
@@ -517,11 +607,13 @@
;;
cert)
shift
- do_cert "$1"
+ do_cert "$@"
+ shift $#
;;
cert_suite)
shift
do_cert_suite "$@"
+ shift $#
;;
get_thread_wireshark)
do_get_thread_wireshark
@@ -549,8 +641,8 @@
prepare_coredump_upload)
do_prepare_coredump_upload
;;
- copy_so_lib)
- do_copy_so_lib
+ check_crash)
+ do_check_crash
;;
generate_coverage)
shift
diff --git a/script/update-makefiles.py b/script/update-makefiles.py
new file mode 100755
index 0000000..4d0c4d7
--- /dev/null
+++ b/script/update-makefiles.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+# This script updates different make/build files (CMakeLists.txt, BUILD.gn,
+# Andriod.mk, Andriod.bp, auto-make) in OpenThread repo based on the
+# current files present in `./src/core/` & `./include/openthread/`
+# folders. This script MUST be called from openthread root folder.
+
+import os
+
+#----------------------------------------------------------------------------------------------
+# Helper functions
+
+
+def get_file_list(path, extension):
+ """Get a sorted list of full file names (with path) in a given `path` folder having a given `extension`"""
+ return sorted([
+ "{}/{}".format(dir_path, file_name)[2:]
+ for dir_path, dir_names, file_names in os.walk(path)
+ for file_name in file_names
+ if file_name.endswith(extension)
+ ])
+
+
+def read_txt_file(file_name):
+ """Read the content of a text file with name `file_name` and return content as a list of lines"""
+ with open(file_name, 'r') as file:
+ lines = file.readlines()
+ return lines
+
+
+def write_txt_file(file_name, lines):
+ """Write a text file with name `file_name` with the content given as a list of `lines`"""
+ with open(file_name, 'w') as file:
+ file.writelines(lines)
+
+
+def update_build_file(file_name, start_string, end_string, new_list, search_string=None):
+ """
+ Update the file given by `file_name` by replacing the list after the first occurrence of `start_string` up to
+ `end_string` with the `new_list`. If `search_string` is given, then the search for `start_string` only starts
+ after seeing the `search_string` line in the file.
+ """
+ STATE_SEARCH = 1
+ STATE_MATCH_START = 2
+ STATE_MATCH_END = 3
+ STATE_DONE = 4
+
+ lines = read_txt_file(file_name)
+ new_lines = []
+ state = STATE_SEARCH if search_string else STATE_MATCH_START
+
+ for line in lines:
+ if state == STATE_SEARCH:
+ new_lines.append(line)
+ if line.startswith(search_string):
+ state = STATE_MATCH_START
+ elif state == STATE_MATCH_START:
+ new_lines.append(line)
+ if line.startswith(start_string):
+ new_lines.extend(new_list)
+ state = STATE_MATCH_END
+ elif state == STATE_MATCH_END:
+ if line.startswith(end_string):
+ new_lines.append(line)
+ state = STATE_DONE
+ else:
+ new_lines.append(line)
+
+ if state != STATE_DONE:
+ raise RuntimeError('failed to update build file: {}'.format(file_name))
+
+ if new_lines != lines:
+ write_txt_file(file_name, new_lines)
+
+
+#----------------------------------------------------------------------------------------------
+
+# Get the list of hpp/h/cpp files in different folders.
+
+src_core_path = "./src/core"
+core_h_files = get_file_list(src_core_path, '.h')
+core_hpp_files = get_file_list(src_core_path, '.hpp')
+core_cpp_files = get_file_list(src_core_path, '.cpp')
+core_cpp_files = [item for item in core_cpp_files if not item.endswith("extension_example.cpp")]
+core_hpp_cpp_files = sorted(core_hpp_files + core_cpp_files)
+core_h_hpp_files = sorted(core_h_files + core_hpp_files)
+
+include_path = "./include/openthread"
+include_h_files = get_file_list(include_path, '.h')
+include_ot_h_files = [name[8:] for name in include_h_files if not name.startswith("include/openthread/platform")]
+include_platform_h_files = [name[8:] for name in include_h_files if name.startswith("include/openthread/platform")]
+
+#----------------------------------------------------------------------------------------------
+# Update CMakeLists.txt files
+
+core_cmakelist_txt_file = "./src/core/CMakeLists.txt"
+
+formatted_list = [" {}\n".format(file_name[9:]) for file_name in core_cpp_files]
+update_build_file(core_cmakelist_txt_file, "set(COMMON_SOURCES\n", ")\n", formatted_list)
+
+print("Updated " + core_cmakelist_txt_file)
+
+#----------------------------------------------------------------------------------------------
+# Update Build.gn files
+
+core_build_gn_file = "./src/core/BUILD.gn"
+
+formatted_list = [" \"{}\",\n".format(file_name[9:]) for file_name in core_hpp_cpp_files]
+update_build_file(core_build_gn_file, "openthread_core_files = [\n", "]\n", formatted_list)
+
+formatted_list = [" \"{}\",\n".format(file_name[9:]) for file_name in core_h_files]
+update_build_file(core_build_gn_file, " public = [\n", " ]\n", formatted_list)
+
+print("Updated " + core_build_gn_file)
+
+include_build_gn_file = "./include/openthread/BUILD.gn"
+
+formatted_list = [" \"{}\",\n".format(file_name[19:]) for file_name in include_h_files]
+update_build_file(include_build_gn_file, " public = [\n", " ]\n", formatted_list)
+
+print("Updated " + include_build_gn_file)
+
+#----------------------------------------------------------------------------------------------
+# Update Android.mk file
+
+android_mk_file = "./Android.mk"
+
+formatted_list = [" {:<55} \\\n".format(file_name) for file_name in core_cpp_files]
+start_string = "LOCAL_SRC_FILES := \\\n"
+end_string = " src/lib/hdlc/hdlc.cpp"
+update_build_file(android_mk_file, start_string, end_string, formatted_list)
+
+print("Updated " + android_mk_file)
+
+#----------------------------------------------------------------------------------------------
+# Update Makefile.am files
+
+core_makefile_am_file = "./src/core/Makefile.am"
+
+formatted_list = [" {:<45} \\\n".format(file_name[9:]) for file_name in core_cpp_files]
+start_string = "SOURCES_COMMON = \\\n"
+end_string = " $(NULL)\n"
+update_build_file(core_makefile_am_file, start_string, end_string, formatted_list)
+
+formatted_list = [" {:<45} \\\n".format(file_name[9:]) for file_name in core_h_hpp_files]
+start_string = "HEADERS_COMMON = \\\n"
+end_string = " $(NULL)\n"
+update_build_file(core_makefile_am_file, start_string, end_string, formatted_list)
+
+print("Updated " + core_makefile_am_file)
+
+include_makefile_am_file = "./include/Makefile.am"
+
+formatted_list = [" {:<37} \\\n".format(file_name) for file_name in include_ot_h_files]
+start_string = "openthread_headers = \\\n"
+end_string = " $(NULL)\n"
+update_build_file(include_makefile_am_file, start_string, end_string, formatted_list)
+
+formatted_list = [" {:<37} \\\n".format(file_name) for file_name in include_platform_h_files]
+start_string = "ot_platform_headers = \\\n"
+end_string = " $(NULL)\n"
+update_build_file(include_makefile_am_file, start_string, end_string, formatted_list)
+
+print("Updated " + include_makefile_am_file)
diff --git a/src/Makefile.am b/src/Makefile.am
index b06a7e4..97622dc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,10 @@
if OPENTHREAD_ENABLE_NCP
SUBDIRS += ncp
+else
+if OPENTHREAD_ENABLE_RADIO_ONLY
+SUBDIRS += ncp
+endif
endif
if OPENTHREAD_PLATFORM_POSIX
diff --git a/src/cli/BUILD.gn b/src/cli/BUILD.gn
index 1eeb4aa..cce5768 100644
--- a/src/cli/BUILD.gn
+++ b/src/cli/BUILD.gn
@@ -37,16 +37,16 @@
"cli_commissioner.cpp",
"cli_commissioner.hpp",
"cli_config.h",
- "cli_console.cpp",
- "cli_console.hpp",
"cli_dataset.cpp",
"cli_dataset.hpp",
"cli_joiner.cpp",
"cli_joiner.hpp",
"cli_network_data.cpp",
"cli_network_data.hpp",
- "cli_uart.cpp",
- "cli_uart.hpp",
+ "cli_srp_client.cpp",
+ "cli_srp_client.hpp",
+ "cli_srp_server.cpp",
+ "cli_srp_server.hpp",
"cli_udp.cpp",
"cli_udp.hpp",
"x509_cert_key.hpp",
@@ -54,11 +54,6 @@
config("cli_config") {
defines = []
- if (openthread_posix) {
- defines += ["OPENTHREAD_POSIX=1"]
- } else {
- defines += ["OPENTHREAD_POSIX=0"]
- }
}
static_library("libopenthread-cli-ftd") {
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index 2a1456e..c60eb05 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -26,13 +26,6 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-set(OT_CLI_TRANSPORT "UART" CACHE STRING "set the CLI transport")
-set(OT_CLI_TRANSPORT_VALUES
- "UART"
- "CONSOLE"
-)
-set_property(CACHE OT_CLI_TRANSPORT PROPERTY STRINGS ${OT_CLI_TRANSPORT_VALUES})
-
set(COMMON_INCLUDES
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/core
@@ -43,11 +36,11 @@
cli_coap.cpp
cli_coap_secure.cpp
cli_commissioner.cpp
- cli_console.cpp
cli_dataset.cpp
cli_joiner.cpp
cli_network_data.cpp
- cli_uart.cpp
+ cli_srp_client.cpp
+ cli_srp_server.cpp
cli_udp.cpp
)
diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am
index b1b89c2..060ff15 100644
--- a/src/cli/Makefile.am
+++ b/src/cli/Makefile.am
@@ -125,16 +125,6 @@
$(OPENTHREAD_TARGET_DEFINES) \
$(NULL)
-if OPENTHREAD_POSIX
-CPPFLAGS_COMMON += \
- -DOPENTHREAD_POSIX=1 \
- $(NULL)
-else
-CPPFLAGS_COMMON += \
- -DOPENTHREAD_POSIX=0 \
- $(NULL)
-endif
-
libopenthread_cli_mtd_a_CPPFLAGS = \
-DOPENTHREAD_MTD=1 \
-DOPENTHREAD_FTD=0 \
@@ -154,11 +144,11 @@
cli_coap.cpp \
cli_coap_secure.cpp \
cli_commissioner.cpp \
- cli_console.cpp \
cli_dataset.cpp \
cli_joiner.cpp \
cli_network_data.cpp \
- cli_uart.cpp \
+ cli_srp_client.cpp \
+ cli_srp_server.cpp \
cli_udp.cpp \
$(NULL)
@@ -176,11 +166,11 @@
cli_coap_secure.hpp \
cli_commissioner.hpp \
cli_config.h \
- cli_console.hpp \
cli_dataset.hpp \
cli_joiner.hpp \
cli_network_data.hpp \
- cli_uart.hpp \
+ cli_srp_client.hpp \
+ cli_srp_server.hpp \
cli_udp.hpp \
x509_cert_key.hpp \
$(NULL)
diff --git a/src/cli/README.md b/src/cli/README.md
index 6969ddd..f9c0321 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -22,6 +22,7 @@
## OpenThread Command List
- [bbr](#bbr)
+- [br](#br)
- [bufferinfo](#bufferinfo)
- [ccathreshold](#ccathreshold)
- [channel](#channel)
@@ -40,7 +41,7 @@
- [delaytimermin](#delaytimermin)
- [diag](#diag)
- [discover](#discover-channel)
-- [dns](#dns-resolve-hostname-dns-server-ip-dns-server-port)
+- [dns](#dns-config)
- [domainname](#domainname)
- [dua](#dua-iid)
- [eidcache](#eidcache)
@@ -66,6 +67,7 @@
- [masterkey](#masterkey)
- [mlr](#mlr-reg-ipaddr--timeout)
- [mode](#mode)
+- [multiradio](#multiradio)
- [neighbor](#neighbor-list)
- [netdata](README_NETDATA.md)
- [netstat](#netstat)
@@ -84,6 +86,7 @@
- [promiscuous](#promiscuous)
- [pskc](#pskc--p-keypassphrase)
- [rcp](#rcp)
+- [region](#region)
- [releaserouterid](#releaserouterid-routerid)
- [reset](#reset)
- [rloc16](#rloc16)
@@ -98,6 +101,7 @@
- [singleton](#singleton)
- [sntp](#sntp-query-sntp-server-ip-sntp-server-port)
- [state](#state)
+- [srp](README_SRP.md)
- [thread](#thread-start)
- [txpower](#txpower)
- [unsecureport](#unsecureport-add-port)
@@ -311,6 +315,20 @@
Done
```
+### br
+
+Enbale/disable the Border Routing functionality.
+
+```bash
+> br enable
+Done
+```
+
+```bash
+> br disable
+Done
+```
+
### bufferinfo
Show the current message buffer information.
@@ -729,18 +747,91 @@
Done
```
-### dns resolve \<hostname\> \[DNS server IP\] \[DNS server port\]
+### dns config
-Send DNS Query to obtain IPv6 address for given hostname. The latter two parameters have following default values:
+Get the default query config used by DNS client.
-- DNS server IP: 2001:4860:4860::8888 (Google DNS Server)
-- DNS server port: 53
+The config includes the server IPv6 address and port, response timeout in msec (wait time to rx response), maximum tx attempts before reporting failure, boolean flag to indicate whether the server can resolve the query recursively or not.
+
+```bash
+> dns config
+Server: [fd00:0:0:0:0:0:0:1]:1234
+ResponseTimeout: 5000 ms
+MaxTxAttempts: 2
+RecursionDesired: no
+Done
+>
+```
+
+### dns config \[DNS server IP\] \[DNS server port\] \[response timeout (ms)\] \[max tx attempts\] \[recursion desired (boolean)\]
+
+Set the default query config.
+
+```bash
+> dns config fd00::1 1234 5000 2 0
+Done
+
+> dns config
+Server: [fd00:0:0:0:0:0:0:1]:1234
+ResponseTimeout: 5000 ms
+MaxTxAttempts: 2
+RecursionDesired: no
+Done
+```
+
+We can leave some of the fields as unspecified (or use value zero). The unspecified fields are replaced by the corresponding OT config option definitions `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_{}` to form the default query config.
+
+```bash
+> dns config fd00::2
+Done
+
+> dns config
+Server: [fd00:0:0:0:0:0:0:2]:53
+ResponseTimeout: 3000 ms
+MaxTxAttempts: 3
+RecursionDesired: yes
+Done
+```
+
+### dns resolve \<hostname\> \[DNS server IP\] \[DNS server port\] \[response timeout (ms)\] \[max tx attempts\] \[recursion desired (boolean)\]
+
+Send DNS Query to obtain IPv6 address for given hostname.
+
+The parameters after `hostname` are optional. Any unspecified (or zero) value for these optional parameters is replaced by the value from the current default config (`dns config`).
```bash
> dns resolve ipv6.google.com
> DNS response for ipv6.google.com - 2a00:1450:401b:801:0:0:0:200e TTL: 300
```
+### dns browse \<service-name\> \[DNS server IP\] \[DNS server port\] \[response timeout (ms)\] \[max tx attempts\] \[recursion desired (boolean)\]
+
+Send a browse (service instance enumeration) DNS query to get the list of services for given service-name.
+
+The parameters after `service-name` are optional. Any unspecified (or zero) value for these optional parameters is replaced by the value from the current default config (`dns config`).
+
+```bash
+> dns browse _service._udp.example.com
+DNS browse response for _service._udp.example.com.
+inst1
+ Port:1234, Priority:1, Weight:2, TTL:7200
+ Host:host.example.com.
+ HostAddress:fd00:0:0:0:0:0:0:abcd TTL:7200
+ TXT:[a=6531, b=6c12] TTL:7300
+instance2
+ Port:1234, Priority:1, Weight:2, TTL:7200
+ Host:host.example.com.
+ HostAddress:fd00:0:0:0:0:0:0:abcd TTL:7200
+ TXT:[a=1234] TTL:7300
+Done
+```
+
+### dns service \<service-instance-label\> \<service-name\> \[DNS server IP\] \[DNS server port\] \[response timeout (ms)\] \[max tx attempts\] \[recursion desired (boolean)\]
+
+Send a service instance resolution DNS query for a given service instance. Service instance label is provided first, followed by the service name (note that service instance label can contain dot '.' character).
+
+The parameters after `service-name` are optional. Any unspecified (or zero) value for these optional parameters is replaced by the value from the current default config (`dns config`).
+
### domainname
Get the Thread Domain Name for Thread 1.2 device.
@@ -1363,6 +1454,43 @@
Done
```
+### multiradio
+
+Get the list of supported radio links by the device.
+
+This command is always available, even when only a single radio is supported by the device.
+
+```bash
+> multiradio
+[15.4, TREL]
+Done
+```
+
+### multiradio neighbor list
+
+Get the list of neighbors and their supported radios and their preference.
+
+This command is only available when device supports more than one radio link.
+
+```bash
+> multiradio neighbor list
+ExtAddr:3a65bc38dbe4a5be, RLOC16:0xcc00, Radios:[15.4(255), TREL(255)]
+ExtAddr:17df23452ee4a4be, RLOC16:0x1300, Radios:[15.4(255)]
+Done
+```
+
+### multiradio neighbor \<ext address\>
+
+Get the radio info for specific neighbor with a given extended address.
+
+This command is only available when device supports more than one radio link.
+
+```bash
+> multiradio neighbor 3a65bc38dbe4a5be
+[15.4(255), TREL(255)]
+Done
+```
+
### neighbor list
List RLOC16 of neighbors.
@@ -1709,6 +1837,18 @@
RCP-related commands.
+### region
+
+Set the radio region, this can affect the transmit power limit.
+
+```bash
+> region US
+Done
+> region
+US
+Done
+```
+
### rcp version
Print RCP version string.
@@ -1793,10 +1933,10 @@
```bash
> router table
-| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC |
-+----+--------+----------+-----------+-------+--------+-----+------------------+
-| 21 | 0x5400 | 21 | 0 | 3 | 3 | 5 | d28d7f875888fccb |
-| 56 | 0xe000 | 56 | 0 | 0 | 0 | 182 | f2d92a82c8d8fe43 |
+| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | Link |
++----+--------+----------+-----------+-------+--------+-----+------------------+------+
+| 22 | 0x5800 | 63 | 0 | 0 | 0 | 0 | 0aeb8196c9f61658 | 0 |
+| 49 | 0xc400 | 63 | 0 | 3 | 3 | 0 | faa1c03908e2dbf2 | 1 |
Done
```
diff --git a/src/cli/README_COAP.md b/src/cli/README_COAP.md
index 1dc8630..755f2d5 100644
--- a/src/cli/README_COAP.md
+++ b/src/cli/README_COAP.md
@@ -115,13 +115,18 @@
- address: IPv6 address of the CoAP server.
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" if the response should be transferred block-wise. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
```bash
> coap get fdde:ad00:beef:0:2780:9423:166c:1aac test-resource
Done
```
+```bash
+> coap get fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024
+Done
+```
+
### observe \<address\> \<uri-path\> \[type\]
This is the same a `get`, but the `Observe` parameter will be sent, set to 0 triggering a subscription request.
@@ -176,26 +181,36 @@
- address: IPv6 address of the CoAP server.
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
-- payload: CoAP request payload.
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" to send blocks with random payload. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
+- payload: CoAP request payload. If \[type\] is "block-<block-size>", the amount of blocks to be sent can be set here.
```bash
> coap post fdde:ad00:beef:0:2780:9423:166c:1aac test-resource con payload
Done
```
+```bash
+> coap post fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024 10
+Done
+```
+
### put \<address\> \<uri-path\> \[type\] \[payload\]
- address: IPv6 address of the CoAP server.
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
-- payload: CoAP request payload.
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" to send blocks with random payload. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
+- payload: CoAP request payload. If \[type\] is "block-<block-size>", the amount of blocks to be sent can be set here.
```bash
> coap put fdde:ad00:beef:0:2780:9423:166c:1aac test-resource con payload
Done
```
+```bash
+> coap put fdde:ad00:beef:0:2780:9423:166c:1aac test-resource block-1024 10
+Done
+```
+
### resource \[uri-path\]
Sets the URI path for the test resource.
diff --git a/src/cli/README_COAPS.md b/src/cli/README_COAPS.md
index 2d31fee..0cb4f99 100644
--- a/src/cli/README_COAPS.md
+++ b/src/cli/README_COAPS.md
@@ -163,24 +163,34 @@
### get \<uri-path\> \[type\]
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" if the response should be transferred block-wise. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
```bash
> coaps get test-resource
Done
```
+```bash
+> coaps get test-resource block-1024
+Done
+```
+
### post \<uri-path\> \[type\] \[payload\]
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
-- payload: CoAPS request payload.
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" to send blocks with random payload. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
+- payload: CoAP request payload. If \[type\] is "block-<block-size>", the amount of blocks to be sent can be set here.
```bash
> coaps post test-resource con payload
Done
```
+```bash
+> coaps post test-resource block-1024 10
+Done
+```
+
### psk \<psk\> \<pskid\>
Set DTLS ciphersuite to `TLS_PSK_WITH_AES_128_CCM_8`.
@@ -196,14 +206,19 @@
### put \<uri-path\> \[type\] \[payload\]
- uri-path: URI path of the resource.
-- type: "con" for Confirmable or "non-con" for Non-confirmable (default).
-- payload: CoAPS request payload.
+- type: "con" for Confirmable or "non-con" for Non-confirmable (default). Use "block-<block-size>" to send blocks with random payload. ("block-16","block-32","block-64","block-128","block-256","block-512","block-1024")
+- payload: CoAP request payload. If \[type\] is "block-<block-size>", the amount of blocks to be sent can be set here.
```bash
> coaps put test-resource con payload
Done
```
+```bash
+> coaps put test-resource block-1024 10
+Done
+```
+
### resource \[uri-path\]
Sets the URI path for the test resource.
diff --git a/src/cli/README_JOINER.md b/src/cli/README_JOINER.md
index 6d8c2ab..715ccdb 100644
--- a/src/cli/README_JOINER.md
+++ b/src/cli/README_JOINER.md
@@ -18,7 +18,7 @@
Usage: `joiner help`
-Print dataset help menu.
+Print joiner help menu.
```bash
> joiner help
diff --git a/src/cli/README_SRP.md b/src/cli/README_SRP.md
new file mode 100644
index 0000000..08c0b6f
--- /dev/null
+++ b/src/cli/README_SRP.md
@@ -0,0 +1,197 @@
+# OpenThread CLI - SRP (Service Registration Protocol)
+
+## Quick Start
+
+### Build with SRP Server & Client support
+
+Use the `SRP_SERVER=1 SERVICE=1 ECDSA=1` build switches to enable SRP Server API support, and the `SRP_CLIENT=1 ECDSA=1` build switches for SRP Client API support.
+
+Make simulation SRP Server & Client:
+
+```bash
+./bootstrap
+make -f examples/Makefile-simulation SRP_SERVER=1 SRP_CLIENT=1 SERVICE=1 ECDSA=1
+```
+
+## Simulation Example
+
+### Start SRP Server
+
+Start the SRP Server node:
+
+```bash
+./output/simulation/bin/ot-cli-ftd 1
+```
+
+Setup a Thread network and start the SRP Server:
+
+```bash
+> dataset init new
+Done
+> dataset
+Active Timestamp: 1
+Channel: 22
+Channel Mask: 0x07fff800
+Ext PAN ID: 8d6ed7a05a28fb3b
+Mesh Local Prefix: fded:5114:8263:1fe1::/64
+Master Key: 7fcbae4153cc2955c28440c15d4d4219
+Network Name: OpenThread-f7af
+PAN ID: 0xf7af
+PSKc: b658e40f174e3a11be149b302ef07a0f
+Security Policy: 672, onrcb
+Done
+> dataset commit active
+Done
+> ifconfig up
+Done
+> thread start
+Done
+> state
+leader
+Done
+>ipaddr
+fded:5114:8263:1fe1:0:ff:fe00:fc00
+fded:5114:8263:1fe1:0:ff:fe00:c000
+fded:5114:8263:1fe1:68bc:ec03:c1ad:9325
+fe80:0:0:0:a8cd:6e23:df3d:4193
+Done
+> srp server enable
+Done
+```
+
+### Start SRP Client
+
+Start the SRP Client node:
+
+```bash
+./output/simulation/bin/ot-cli-ftd 2
+```
+
+Join the Thread Network and register a `_ipps._tcp` service:
+
+```bash
+> dataset masterkey 7fcbae4153cc2955c28440c15d4d4219
+Done
+> dataset commit active
+Done
+> ifconfig up
+Done
+> thread start
+Done
+> state
+child
+Done
+> ipaddr
+fded:5114:8263:1fe1:0:ff:fe00:c001
+fded:5114:8263:1fe1:44f9:cc06:4a2d:534
+fe80:0:0:0:38dd:fdf7:5fd:24e
+Done
+> srp client host name my-host
+Done
+> srp client host address fded:5114:8263:1fe1:44f9:cc06:4a2d:534
+Done
+> srp client service add my-service _ipps._tcp 12345
+Done
+> srp client autostart enable
+Done
+```
+
+The last command enables the auto-start mode on the client which then monitors the network data to discover available SRP servers within the Thread network and automatically starts the client.
+
+Alternatively, the client can be started manually using the `srp client start`.
+
+The SRP Server listening UDP port (which is `c002`(`49154`) in the example below) can be found from the Server Data (listed by the `netdata show` command).
+
+Make sure the SRP Server address & port are used for the `srp client start` command.
+
+```bash
+> netdata show
+Prefixes:
+Routes:
+Services:
+44970 5d c002 s 8400
+Done
+srp client start fded:5114:8263:1fe1:68bc:ec03:c1ad:9325 49154
+Done
+```
+
+### Verify the service status
+
+Check if the host and service has been successfully registered on the client node:
+
+```bash
+> srp client host
+name:"my-host", state:Registered, addrs:[fded:5114:8263:1fe1:44f9:cc06:4a2d:534]
+Done
+> srp client service
+instance:"my-service", name:"_ipps._tcp", state:Registered, port:12345, priority:0, weight:0
+Done
+```
+
+Make sure it shows `state:Registered` for both host and service commands.
+
+Check the host & service on the server node:
+
+```bash
+> srp server host
+my-host.default.service.arpa.
+ deleted: false
+ addresses: [fded:5114:8263:1fe1:44f9:cc06:4a2d:534]
+Done
+> srp server service
+my-service._ipps._tcp.default.service.arpa.
+ deleted: false
+ port: 12345
+ priority: 0
+ weight: 0
+ TXT: 00
+ host: my-host.default.service.arpa.
+ addresses: [fded:5114:8263:1fe1:44f9:cc06:4a2d:534]
+Done
+```
+
+Make sure it shows `deleted: false` for both host and service commands.
+
+### Remove the service
+
+A service can be removed through the client node:
+
+```bash
+> srp client service remove my-service _ipps._tcp
+Done
+```
+
+Confirm on the server node that the service has been removed:
+
+```bash
+> srp server service
+my-service._ipps._tcp.default.service.arpa.
+ deleted: true
+Done
+```
+
+The service entry is listed because the name of service is not removed.
+
+### Remove the host and service names
+
+A host and service, along with their names, can be removed through the client node:
+
+```bash
+> srp client host remove 1
+Done
+```
+
+Confirm on the server node that no host or service entries are listed:
+
+```bash
+> srp server host
+Done
+> srp server service
+Done
+>
+```
+
+## CLI Reference
+
+- [SRP Client CLI Reference](README_SRP_CLIENT.md)
+- [SRP Server CLI Reference](README_SRP_SERVER.md)
diff --git a/src/cli/README_SRP_CLIENT.md b/src/cli/README_SRP_CLIENT.md
new file mode 100644
index 0000000..0baa1f5
--- /dev/null
+++ b/src/cli/README_SRP_CLIENT.md
@@ -0,0 +1,363 @@
+# OpenThread CLI - SRP Client
+
+## Command List
+
+Usage : `srp client [command] ...`
+
+- [help](#help)
+- [autostart](#autostart)
+- [callback](#callback)
+- [host](#host)
+- [keyleaseinterval](#keyleaseinterval)
+- [leaseinterval](#leaseinterval)
+- [server](#server)
+- [service](#service)
+- [start](#start)
+- [state](#state)
+- [stop](#stop)
+
+## Command Details
+
+### help
+
+Usage: `srp client help`
+
+Print SRP client help menu.
+
+```bash
+> srp client help
+autostart
+callback
+help
+host
+keyleaseinterval
+leaseinterval
+service
+start
+state
+stop
+Done
+```
+
+### autostart
+
+Usage `srp client autostart [enable|disable]`
+
+Enable/Disable auto start mode in SRP client. This command requires `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` feature to be enabled.
+
+Get the current autostart mode.
+
+```bash
+> srp client autostart
+Disabled
+Done
+```
+
+Set the autostart mode.
+
+```bash
+> srp client autostart enable
+Done
+
+> srp client autostart
+Enabled
+Done
+```
+
+### callback
+
+Usage `srp client callback [enable|disable]`
+
+Enable/Disable printing callback events from SRP client.
+
+Get current callback mode
+
+```bash
+> srp client callback
+Disabled
+Done
+```
+
+Set callback mode
+
+```bash
+> srp client callback enable
+Done
+
+> srp client callback
+Enabled
+Done
+```
+
+#### Example
+
+When two services are successfully registered:
+
+```bash
+SRP client callback - error:OK
+Host info:
+ name:"dev4312", state:Registered, addrs:[fd00:0:0:0:0:0:0:1]
+Service list:
+ instance:"ins2", name:"_test2._udp", state:Registered, port:111, priority:1, weight:1
+ instance:"ins1", name:"_test1._udp", state:Registered, port:777, priority:0, weight:0
+```
+
+When service `ins2` is removed:
+
+```bash
+SRP client callback - error:OK
+Host info:
+ name:"dev4312", state:Registered, addrs:[fd00:0:0:0:0:0:0:1]
+Service list:
+ instance:"ins1", name:"_test1._udp", state:Registered, port:777, priority:0, weight:0
+Removed service list:
+ instance:"ins2", name:"_test2._udp", state:Removed, port:111, priority:1, weight:1
+```
+
+When host info (and all services) is removed:
+
+```bash
+SRP client callback - error:OK
+Host info:
+ name:"dev4312", state:Removed, addrs:[fd00:0:0:0:0:0:0:1]
+Service list:
+Removed service list:
+ instance:"ins1", name:"_test1._udp", state:Removed, port:777, priority:0, weight:0
+```
+
+### host
+
+Usage: `srp client host`
+
+Print the full host info (host name, state, list of host addresses).
+
+```bash
+> srp client host
+name:"dev4312", state:Registered, addrs:[fd00:0:0:0:0:0:0:1234, fd00:0:0:0:0:0:0:beef]
+Done
+```
+
+### host name
+
+Usage: `srp client host name [name]`
+
+Get the host name.
+
+```bash
+> srp client host name
+dev4312
+Done
+```
+
+Set host name (can be set when the host is removed or not yet registered with server).
+
+```bash
+srp client host name dev4312
+Done
+```
+
+### host address
+
+Usage : `srp client host address [<address> ...]`
+
+Get the list of host addresses.
+
+```bash
+> srp client host address
+fd00:0:0:0:0:0:0:1234
+fd00:0:0:0:0:0:0:beef
+Done
+```
+
+Set the list of host addresses (can be set while client is running to update the host addresses)
+
+```bash
+> srp client host address fd00::cafe
+Done
+```
+
+### host state
+
+Usage: `srp client host state`
+
+Get the host state.
+
+```bash
+> srp client host state
+Registered
+Done
+```
+
+The possible states are (same value for service state):
+
+- `ToAdd`: item to be added/registered.
+- `Adding`: item is being added/registered.
+- `ToRefresh`: item to be refreshed (renew lease).
+- `Refreshing`: item is being refreshed.
+- `ToRemove`: item to be removed.
+- `Removing`: item is being removed.
+- `Registered`: item is registered with server.
+- `Removed`: item is removed.
+
+### host remove
+
+Usage: `srp client host remove [removekeylease]`
+
+Remove host info and all services from server. `removekeylease` is boolean value indicating whether or not the host key lease should also be removed
+
+```bash
+> srp client host remove 1
+Done
+```
+
+### host clear
+
+Usage: `srp client host clear`
+
+Clear host info and all services on client (unlike `host remove`, with `host clear` no update is sent to server).
+
+```bash
+> srp client host clear
+Done
+```
+
+### keyleaseinterval
+
+Usage: `srp client keyleaseinterval [interval]`
+
+Get the key lease interval (in seconds).
+
+```bash
+> srp client keyleaseinterval
+1209600
+Done
+>
+```
+
+Set the key lease interval.
+
+```bash
+> srp client keyleaseinterval 864000
+Done
+```
+
+### leaseinterval
+
+Usage: `srp client leaseinterval [interval]`
+
+Get the lease interval (in seconds).
+
+```bash
+> srp client leaseinterval
+7200
+Done
+>
+```
+
+Set the lease interval.
+
+```bash
+> srp client leaseinterval 3600
+Done
+```
+
+### server
+
+Usage: `srp client server`
+
+Print the server socket address (IPv6 address and port number).
+
+```bash
+> srp client server
+[fd00:0:0:0:d88a:618b:384d:e760]:4724
+Done
+```
+
+### server address
+
+Print the server IPv6 address.
+
+```bash
+> srp client server address
+fd00:0:0:0:d88a:618b:384d:e760
+Done
+```
+
+### server port
+
+Print the server port number
+
+```bash
+> srp client server port
+4724
+Done
+```
+
+### service
+
+Usage: `srp client service`
+
+Print the list of services.
+
+```bash
+> srp client service
+instance:"ins2", name:"_test2._udp", state:Registered, port:111, priority:1, weight:1
+instance:"ins1", name:"_test1._udp", state:Registered, port:777, priority:0, weight:0
+Done
+```
+
+### service add
+
+Usage: `srp client service add <instancename> <servicename> <port> [priority] [weight] [txt]`
+
+Add a service with a given instance name, service name, port number, priority, weight and txt values. The priority and weight are optional and if not provided zero will be used. The txt should follow hex-string format and is treated as an already encoded TXT data byte sequence. It is also optional and if not provided it is considered empty.
+
+```bash
+> srp client service add ins2 _test2._udp 111 1 1
+Done
+```
+
+### service remove
+
+Usage: `srp client service remove <instancename> <servicename>`
+
+Remove a service with a give instance name and service name.
+
+```bash
+> srp client service remove ins2 _test2._udp
+Done
+```
+
+### start
+
+Usage: `srp client start <serveraddr> <serverport>`
+
+Start the SRP client with a given server IPv6 address and port number.
+
+```bash
+> srp client start fd00::d88a:618b:384d:e760 4724
+Done
+```
+
+### state
+
+Usage: `srp client state`
+
+Indicates the state of SRP client, i.e., whether it is enabled or disabled.
+
+```bash
+> srp client state
+Enabled
+Done
+```
+
+### stop
+
+Usage: `srp client stop`
+
+Stop the SRP client.
+
+```bash
+> srp client stop
+Done
+```
diff --git a/src/cli/README_SRP_SERVER.md b/src/cli/README_SRP_SERVER.md
new file mode 100644
index 0000000..effa638
--- /dev/null
+++ b/src/cli/README_SRP_SERVER.md
@@ -0,0 +1,120 @@
+# OpenThread CLI - SRP Server
+
+## Quick Start
+
+See [README_SRP.md](README_SRP.md).
+
+## Command List
+
+- [help](#help)
+- [disable](#disable)
+- [domain](#domain)
+- [enable](#enable)
+- [host](#host)
+- [lease](#lease)
+- [service](#service)
+
+## Command Details
+
+### help
+
+Usage: `srp server help`
+
+Print SRP server help menu.
+
+```bash
+> srp server help
+disable
+domain
+enable
+help
+host
+lease
+service
+Done
+```
+
+### disable
+
+Usage: `srp server disable`
+
+Disable the SRP server.
+
+```bash
+> srp server disable
+Done
+```
+
+### domain
+
+Usage: `srp server domain [domain-name]`
+
+Get the domain.
+
+```bash
+> srp server domain
+default.service.arpa.
+Done
+```
+
+Set the domain.
+
+```bash
+> srp server domain thread.service.arpa.
+Done
+```
+
+### enable
+
+Usage: `srp server enable`
+
+Enable the SRP server.
+
+```bash
+> srp server enable
+Done
+```
+
+### host
+
+Usage: `srp server host`
+
+Print information of all registered hosts.
+
+```bash
+> srp server host
+srp-api-test-1.default.service.arpa.
+ deleted: false
+ addresses: [fdde:ad00:beef:0:0:ff:fe00:fc10]
+srp-api-test-0.default.service.arpa.
+ deleted: false
+ addresses: [fdde:ad00:beef:0:0:ff:fe00:fc10]
+Done
+```
+
+### srp server service
+
+Usage: `srp server service`
+
+Print information of all registered services.
+
+```bash
+> srp server service
+srp-api-test-1._ipps._tcp.default.service.arpa.
+ deleted: false
+ port: 49152
+ priority: 0
+ weight: 0
+ TXT: 0130
+ host: srp-api-test-1.default.service.arpa.
+ addresses: [fdde:ad00:beef:0:0:ff:fe00:fc10]
+srp-api-test-0._ipps._tcp.default.service.arpa.
+ deleted: false
+ port: 49152
+ priority: 0
+ weight: 0
+ TXT: 0130
+ host: srp-api-test-0.default.service.arpa.
+ addresses: [fdde:ad00:beef:0:0:ff:fe00:fc10]
+Done
+```
diff --git a/src/cli/README_UDP.md b/src/cli/README_UDP.md
index 08ca4fc..b473935 100644
--- a/src/cli/README_UDP.md
+++ b/src/cli/README_UDP.md
@@ -152,8 +152,10 @@
- ip: the IPv6 destination address.
- port: the UDP destination port.
-- type: the type of the message: _ `-t`: text payload in the `value`, same as without specifying the type. _ `-s`: autogenerated payload with specified length indicated in the `value`.
- \* `-x`: binary data in hexadecimal representation in the `value`.
+- type: the type of the message:
+ - `-t`: text payload in the `value`, same as without specifying the type.
+ - `-s`: autogenerated payload with specified length indicated in the `value`.
+ - `-x`: binary data in hexadecimal representation in the `value`.
```bash
> udp send fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234 -t hello
@@ -182,7 +184,10 @@
Send a few bytes over UDP.
-- type: the type of the message: _ `-t`: text payload in the `value`, same as without specifying the type. _ `-s`: autogenerated payload with specified length indicated in the `value`. \* `-x`: binary data in hexadecimal representation in the `value`.
+- type: the type of the message:
+ - `-t`: text payload in the `value`, same as without specifying the type.
+ - `-s`: autogenerated payload with specified length indicated in the `value`.
+ - `-x`: binary data in hexadecimal representation in the `value`.
```bash
> udp send -t hello
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index 658feb9..cfbc556 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -35,14 +35,15 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <openthread/diag.h>
+#include <openthread/dns.h>
#include <openthread/icmp6.h>
#include <openthread/link.h>
#include <openthread/logging.h>
#include <openthread/ncp.h>
#include <openthread/thread.h>
-#include <openthread/platform/uart.h>
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
#include <openthread/network_time.h>
#endif
@@ -85,12 +86,9 @@
#include "common/new.hpp"
#include "common/string.hpp"
#include "mac/channel_mask.hpp"
-#include "net/ip6.hpp"
-#include "utils/otns.hpp"
#include "utils/parse_cmdline.hpp"
using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
using ot::Utils::CmdLineParser::ParseAsBool;
using ot::Utils::CmdLineParser::ParseAsHexString;
@@ -108,20 +106,14 @@
constexpr Interpreter::Command Interpreter::sCommands[];
Interpreter *Interpreter::sInterpreter = nullptr;
+static OT_DEFINE_ALIGNED_VAR(sInterpreterRaw, sizeof(Interpreter), uint64_t);
-Interpreter::Interpreter(Instance *aInstance)
- : mUserCommands(nullptr)
+Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext)
+ : mInstance(aInstance)
+ , mOutputCallback(aCallback)
+ , mOutputContext(aContext)
+ , mUserCommands(nullptr)
, mUserCommandsLength(0)
- , mPingLength(kDefaultPingLength)
- , mPingCount(kDefaultPingCount)
- , mPingInterval(kDefaultPingInterval)
- , mPingHopLimit(0)
- , mPingAllowZeroHopLimit(false)
- , mPingIdentifier(0)
- , mPingTimer(*aInstance, Interpreter::HandlePingTimer, this)
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- , mResolvingInProgress(false)
-#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
, mSntpQueryingInProgress(false)
#endif
@@ -140,22 +132,16 @@
#if OPENTHREAD_CONFIG_JOINER_ENABLE
, mJoiner(*this)
#endif
- , mInstance(aInstance)
-{
-#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
- otThreadSetReceiveDiagnosticGetCallback(mInstance, &Interpreter::HandleDiagnosticGetResponse, this);
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ , mSrpClient(*this)
#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ , mSrpServer(*this)
+#endif
+{
#if OPENTHREAD_FTD
otThreadSetDiscoveryRequestCallback(mInstance, &Interpreter::HandleDiscoveryRequest, this);
#endif
-
- mIcmpHandler.mReceiveCallback = Interpreter::HandleIcmpReceive;
- mIcmpHandler.mContext = this;
- IgnoreError(otIcmp6RegisterHandler(mInstance, &mIcmpHandler));
-
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- memset(mResolvingHostname, 0, sizeof(mResolvingHostname));
-#endif
}
void Interpreter::OutputResult(otError aError)
@@ -174,14 +160,19 @@
}
}
-void Interpreter::OutputBytes(const uint8_t *aBytes, uint8_t aLength)
+void Interpreter::OutputBytes(const uint8_t *aBytes, uint16_t aLength)
{
- for (int i = 0; i < aLength; i++)
+ for (uint16_t i = 0; i < aLength; i++)
{
OutputFormat("%02x", aBytes[i]);
}
}
+void Interpreter::OutputEnabledDisabledStatus(bool aEnabled)
+{
+ OutputLine(aEnabled ? "Enabled" : "Disabled");
+}
+
int Interpreter::OutputIp6Address(const otIp6Address &aAddress)
{
return OutputFormat(
@@ -206,6 +197,8 @@
return error;
}
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
otError Interpreter::ParsePingInterval(const char *aString, uint32_t &aInterval)
{
otError error = OT_ERROR_NONE;
@@ -252,6 +245,8 @@
return error;
}
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
otError Interpreter::ProcessHelp(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
@@ -270,6 +265,34 @@
return OT_ERROR_NONE;
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+otError Interpreter::ProcessBorderRouting(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ bool enable = false;
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+
+ if (strcmp(aArgs[0], "enable") == 0)
+ {
+ enable = true;
+ }
+ else if (strcmp(aArgs[0], "disable") == 0)
+ {
+ enable = false;
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_COMMAND);
+ }
+
+ SuccessOrExit(error = otBorderRoutingSetEnabled(mInstance, enable));
+
+exit:
+ return error;
+}
+#endif
+
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otError Interpreter::ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[])
{
@@ -1048,7 +1071,7 @@
if (aArgsLength == 0)
{
- OutputLine(otPlatRadioIsCoexEnabled(mInstance) ? "Enabled" : "Disabled");
+ OutputEnabledDisabledStatus(otPlatRadioIsCoexEnabled(mInstance));
}
else if (strcmp(aArgs[0], "enable") == 0)
{
@@ -1301,87 +1324,271 @@
return error;
}
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
-otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[])
+void Interpreter::OutputDnsTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength)
{
- otError error = OT_ERROR_NONE;
- uint16_t port = OT_DNS_DEFAULT_SERVER_PORT;
- Ip6::MessageInfo messageInfo;
- otDnsQuery query;
+ otDnsTxtEntry entry;
+ otDnsTxtEntryIterator iterator;
+ bool isFirst = true;
- VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
+ otDnsInitTxtEntryIterator(&iterator, aTxtData, aTxtDataLength);
- if (strcmp(aArgs[0], "resolve") == 0)
+ OutputFormat("[");
+
+ while (otDnsGetNextTxtEntry(&iterator, &entry) == OT_ERROR_NONE)
{
- VerifyOrExit(!mResolvingInProgress, error = OT_ERROR_BUSY);
- VerifyOrExit(aArgsLength > 1, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(strlen(aArgs[1]) < OT_DNS_MAX_HOSTNAME_LENGTH, error = OT_ERROR_INVALID_ARGS);
-
- strcpy(mResolvingHostname, aArgs[1]);
-
- if (aArgsLength > 2)
+ if (!isFirst)
{
- SuccessOrExit(error = ParseAsIp6Address(aArgs[2], messageInfo.GetPeerAddr()));
+ OutputFormat(", ");
+ }
+
+ if (entry.mKey == nullptr)
+ {
+ // A null `mKey` indicates that the key in the entry is
+ // longer than the recommended max key length, so the entry
+ // could not be parsed. In this case, the whole entry is
+ // returned encoded in `mValue`.
+
+ OutputFormat("[");
+ OutputBytes(entry.mValue, entry.mValueLength);
+ OutputFormat("]");
}
else
{
- // Use IPv6 address of default DNS server.
- SuccessOrExit(error = messageInfo.GetPeerAddr().FromString(OT_DNS_DEFAULT_SERVER_IP));
+ OutputFormat("%s", entry.mKey);
+
+ if (entry.mValue != nullptr)
+ {
+ OutputFormat("=");
+ OutputBytes(entry.mValue, entry.mValueLength);
+ }
}
- if (aArgsLength > 3)
- {
- SuccessOrExit(error = ParseAsUint16(aArgs[3], port));
- }
-
- messageInfo.SetPeerPort(port);
-
- query.mHostname = mResolvingHostname;
- query.mMessageInfo = static_cast<const otMessageInfo *>(&messageInfo);
- query.mNoRecursion = false;
-
- SuccessOrExit(error = otDnsClientQuery(mInstance, &query, &Interpreter::HandleDnsResponse, this));
-
- mResolvingInProgress = true;
- }
- else
- {
- ExitNow(error = OT_ERROR_INVALID_COMMAND);
+ isFirst = false;
}
- error = OT_ERROR_PENDING;
+ OutputFormat("]");
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
+
+otError Interpreter::GetDnsConfig(uint8_t aArgsLength,
+ char * aArgs[],
+ otDnsQueryConfig *&aConfig,
+ uint8_t aStartArgsIndex)
+{
+ // This method gets the optional config from given `aArgs` after the
+ // `aStartArgsIndex`. The format: `[server IPv6 address] [server
+ // port] [timeout] [max tx attempt] [recursion desired]`.
+
+ otError error = OT_ERROR_NONE;
+ bool recursionDesired;
+
+ memset(aConfig, 0, sizeof(otDnsQueryConfig));
+
+ VerifyOrExit(aArgsLength > aStartArgsIndex, aConfig = nullptr);
+
+ SuccessOrExit(error = ParseAsIp6Address(aArgs[aStartArgsIndex], aConfig->mServerSockAddr.mAddress));
+
+ VerifyOrExit(aArgsLength > aStartArgsIndex + 1);
+ SuccessOrExit(error = ParseAsUint16(aArgs[aStartArgsIndex + 1], aConfig->mServerSockAddr.mPort));
+
+ VerifyOrExit(aArgsLength > aStartArgsIndex + 2);
+ SuccessOrExit(error = ParseAsUint32(aArgs[aStartArgsIndex + 2], aConfig->mResponseTimeout));
+
+ VerifyOrExit(aArgsLength > aStartArgsIndex + 3);
+ SuccessOrExit(error = ParseAsUint8(aArgs[aStartArgsIndex + 3], aConfig->mMaxTxAttempts));
+
+ VerifyOrExit(aArgsLength > aStartArgsIndex + 4);
+ SuccessOrExit(error = ParseAsBool(aArgs[aStartArgsIndex + 4], recursionDesired));
+ aConfig->mRecursionFlag = recursionDesired ? OT_DNS_FLAG_RECURSION_DESIRED : OT_DNS_FLAG_NO_RECURSION;
exit:
return error;
}
-void Interpreter::HandleDnsResponse(void * aContext,
- const char * aHostname,
- const otIp6Address *aAddress,
- uint32_t aTtl,
- otError aResult)
+otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[])
{
- static_cast<Interpreter *>(aContext)->HandleDnsResponse(aHostname, static_cast<const Ip6::Address *>(aAddress),
- aTtl, aResult);
-}
+ otError error = OT_ERROR_NONE;
+ otDnsQueryConfig queryConfig;
+ otDnsQueryConfig *config = &queryConfig;
-void Interpreter::HandleDnsResponse(const char *aHostname, const Ip6::Address *aAddress, uint32_t aTtl, otError aResult)
-{
- OutputFormat("DNS response for %s - ", aHostname);
+ VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
- if (aResult == OT_ERROR_NONE)
+ if (strcmp(aArgs[0], "config") == 0)
{
- if (aAddress != nullptr)
+ if (aArgsLength == 1)
{
- OutputIp6Address(*aAddress);
+ const otDnsQueryConfig *defaultConfig = otDnsClientGetDefaultConfig(mInstance);
+
+ OutputFormat("Server: [");
+ OutputIp6Address(defaultConfig->mServerSockAddr.mAddress);
+ OutputLine("]:%d", defaultConfig->mServerSockAddr.mPort);
+ OutputLine("ResponseTimeout: %u ms", defaultConfig->mResponseTimeout);
+ OutputLine("MaxTxAttempts: %u", defaultConfig->mMaxTxAttempts);
+ OutputLine("RecursionDesired: %s",
+ (defaultConfig->mRecursionFlag == OT_DNS_FLAG_RECURSION_DESIRED) ? "yes" : "no");
}
- OutputLine(" TTL: %d", aTtl);
+ else
+ {
+ SuccessOrExit(error = GetDnsConfig(aArgsLength, aArgs, config, 1));
+ otDnsClientSetDefaultConfig(mInstance, config);
+ }
+ }
+ else if (strcmp(aArgs[0], "resolve") == 0)
+ {
+ SuccessOrExit(error = GetDnsConfig(aArgsLength, aArgs, config, 2));
+ SuccessOrExit(error = otDnsClientResolveAddress(mInstance, aArgs[1], &Interpreter::HandleDnsAddressResponse,
+ this, config));
+ error = OT_ERROR_PENDING;
+ }
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ else if (strcmp(aArgs[0], "browse") == 0)
+ {
+ SuccessOrExit(error = GetDnsConfig(aArgsLength, aArgs, config, 2));
+ SuccessOrExit(error =
+ otDnsClientBrowse(mInstance, aArgs[1], &Interpreter::HandleDnsBrowseResponse, this, config));
+ error = OT_ERROR_PENDING;
+ }
+ else if (strcmp(aArgs[0], "service") == 0)
+ {
+ SuccessOrExit(error = GetDnsConfig(aArgsLength, aArgs, config, 3));
+ SuccessOrExit(error = otDnsClientResolveService(mInstance, aArgs[1], aArgs[2],
+ &Interpreter::HandleDnsServiceResponse, this, config));
+ error = OT_ERROR_PENDING;
+ }
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_COMMAND);
}
- OutputResult(aResult);
-
- mResolvingInProgress = false;
+exit:
+ return error;
}
+
+void Interpreter::HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse, void *aContext)
+{
+ static_cast<Interpreter *>(aContext)->HandleDnsAddressResponse(aError, aResponse);
+}
+
+void Interpreter::HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse)
+{
+ char hostName[OT_DNS_MAX_NAME_SIZE];
+ otIp6Address address;
+ uint32_t ttl;
+
+ IgnoreError(otDnsAddressResponseGetHostName(aResponse, hostName, sizeof(hostName)));
+
+ OutputFormat("DNS response for %s - ", hostName);
+
+ if (aError == OT_ERROR_NONE)
+ {
+ uint16_t index = 0;
+
+ while (otDnsAddressResponseGetAddress(aResponse, index, &address, &ttl) == OT_ERROR_NONE)
+ {
+ OutputIp6Address(address);
+ OutputFormat(" TTL:%u ", ttl);
+ index++;
+ }
+
+ OutputLine("");
+ }
+
+ OutputResult(aError);
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+void Interpreter::OutputDnsServiceInfo(uint8_t aIndentSize, const otDnsServiceInfo &aServiceInfo)
+{
+ OutputLine(aIndentSize, "Port:%d, Priority:%d, Weight:%d, TTL:%u", aServiceInfo.mPort, aServiceInfo.mPriority,
+ aServiceInfo.mWeight, aServiceInfo.mTtl);
+ OutputLine(aIndentSize, "Host:%s", aServiceInfo.mHostNameBuffer);
+ OutputFormat(aIndentSize, "HostAddress:");
+ OutputIp6Address(aServiceInfo.mHostAddress);
+ OutputLine(" TTL:%u", aServiceInfo.mHostAddressTtl);
+ OutputFormat(aIndentSize, "TXT:");
+ OutputDnsTxtData(aServiceInfo.mTxtData, aServiceInfo.mTxtDataSize);
+ OutputLine(" TTL:%u", aServiceInfo.mTxtDataTtl);
+}
+
+void Interpreter::HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse, void *aContext)
+{
+ static_cast<Interpreter *>(aContext)->HandleDnsBrowseResponse(aError, aResponse);
+}
+
+void Interpreter::HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse)
+{
+ char name[OT_DNS_MAX_NAME_SIZE];
+ char label[OT_DNS_MAX_LABEL_SIZE];
+ uint8_t txtBuffer[255];
+ otDnsServiceInfo serviceInfo;
+
+ IgnoreError(otDnsBrowseResponseGetServiceName(aResponse, name, sizeof(name)));
+
+ OutputLine("DNS browse response for %s", name);
+
+ if (aError == OT_ERROR_NONE)
+ {
+ uint16_t index = 0;
+
+ while (otDnsBrowseResponseGetServiceInstance(aResponse, index, label, sizeof(label)) == OT_ERROR_NONE)
+ {
+ OutputLine("%s", label);
+ index++;
+
+ serviceInfo.mHostNameBuffer = name;
+ serviceInfo.mHostNameBufferSize = sizeof(name);
+ serviceInfo.mTxtData = txtBuffer;
+ serviceInfo.mTxtDataSize = sizeof(txtBuffer);
+
+ if (otDnsBrowseResponseGetServiceInfo(aResponse, label, &serviceInfo) == OT_ERROR_NONE)
+ {
+ OutputDnsServiceInfo(kIndentSize, serviceInfo);
+ }
+
+ OutputLine("");
+ }
+ }
+
+ OutputResult(aError);
+}
+
+void Interpreter::HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse, void *aContext)
+{
+ static_cast<Interpreter *>(aContext)->HandleDnsServiceResponse(aError, aResponse);
+}
+
+void Interpreter::HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse)
+{
+ char name[OT_DNS_MAX_NAME_SIZE];
+ char label[OT_DNS_MAX_LABEL_SIZE];
+ uint8_t txtBuffer[255];
+ otDnsServiceInfo serviceInfo;
+
+ IgnoreError(otDnsServiceResponseGetServiceName(aResponse, label, sizeof(label), name, sizeof(name)));
+
+ OutputLine("DNS service resolution response for %s for service %s", label, name);
+
+ if (aError == OT_ERROR_NONE)
+ {
+ serviceInfo.mHostNameBuffer = name;
+ serviceInfo.mHostNameBufferSize = sizeof(name);
+ serviceInfo.mTxtData = txtBuffer;
+ serviceInfo.mTxtDataSize = sizeof(txtBuffer);
+
+ if (otDnsServiceResponseGetServiceInfo(aResponse, &serviceInfo) == OT_ERROR_NONE)
+ {
+ OutputDnsServiceInfo(/* aIndetSize */ 0, serviceInfo);
+ OutputLine("");
+ }
+ }
+
+ OutputResult(aError);
+}
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
#if OPENTHREAD_FTD
@@ -1447,7 +1654,7 @@
return error;
}
-#if OPENTHREAD_POSIX
+#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
otError Interpreter::ProcessExit(uint8_t aArgsLength, char *aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
@@ -1757,14 +1964,7 @@
if (aArgsLength == 0)
{
- if (otIp6IsMulticastPromiscuousEnabled(mInstance))
- {
- OutputLine("Enabled");
- }
- else
- {
- OutputLine("Disabled");
- }
+ OutputEnabledDisabledStatus(otIp6IsMulticastPromiscuousEnabled(mInstance));
}
else
{
@@ -2364,14 +2564,14 @@
otError Interpreter::ProcessMlrReg(uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
- otIp6Address addresses[kIPv6AddressesNumMax];
+ otIp6Address addresses[kIp6AddressesNumMax];
uint32_t timeout;
uint8_t i;
VerifyOrExit(aArgsLength >= 1, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aArgsLength <= kIPv6AddressesNumMax + 1, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength <= kIp6AddressesNumMax + 1, error = OT_ERROR_INVALID_ARGS);
- for (i = 0; i < aArgsLength && i < kIPv6AddressesNumMax; i++)
+ for (i = 0; i < aArgsLength && i < kIp6AddressesNumMax; i++)
{
if (ParseAsIp6Address(aArgs[i], addresses[i]) != OT_ERROR_NONE)
{
@@ -2495,6 +2695,94 @@
return error;
}
+otError Interpreter::ProcessMultiRadio(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ OT_UNUSED_VARIABLE(aArgs);
+
+ if (aArgsLength == 0)
+ {
+ bool isFirst = true;
+
+ OutputFormat("[");
+#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+ OutputFormat("15.4");
+ isFirst = false;
+#endif
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+ OutputFormat("%sTREL", isFirst ? "" : ", ");
+#endif
+ OutputLine("]");
+
+ OT_UNUSED_VARIABLE(isFirst);
+ }
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+ else if (strcmp(aArgs[0], "neighbor") == 0)
+ {
+ otMultiRadioNeighborInfo multiRadioInfo;
+
+ VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+
+ if (strcmp(aArgs[1], "list") == 0)
+ {
+ otNeighborInfoIterator iterator = OT_NEIGHBOR_INFO_ITERATOR_INIT;
+ otNeighborInfo neighInfo;
+
+ while (otThreadGetNextNeighborInfo(mInstance, &iterator, &neighInfo) == OT_ERROR_NONE)
+ {
+ if (otMultiRadioGetNeighborInfo(mInstance, &neighInfo.mExtAddress, &multiRadioInfo) != OT_ERROR_NONE)
+ {
+ continue;
+ }
+
+ OutputFormat("ExtAddr:");
+ OutputExtAddress(neighInfo.mExtAddress);
+ OutputFormat(", RLOC16:0x%04x, Radios:", neighInfo.mRloc16);
+ OutputMultiRadioInfo(multiRadioInfo);
+ }
+ }
+ else
+ {
+ otExtAddress extAddress;
+
+ SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddress.m8));
+ SuccessOrExit(error = otMultiRadioGetNeighborInfo(mInstance, &extAddress, &multiRadioInfo));
+ OutputMultiRadioInfo(multiRadioInfo);
+ }
+ }
+#endif // OPENTHREAD_CONFIG_MULTI_RADIO
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_COMMAND);
+ }
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+void Interpreter::OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo)
+{
+ bool isFirst = true;
+
+ OutputFormat("[");
+
+ if (aMultiRadioInfo.mSupportsIeee802154)
+ {
+ OutputFormat("15.4(%d)", aMultiRadioInfo.mIeee802154Info.mPreference);
+ isFirst = false;
+ }
+
+ if (aMultiRadioInfo.mSupportsTrelUdp6)
+ {
+ OutputFormat("%sTREL(%d)", isFirst ? "" : ", ", aMultiRadioInfo.mTrelUdp6Info.mPreference);
+ }
+
+ OutputLine("]");
+}
+#endif // OPENTHREAD_CONFIG_MULTI_RADIO
+
#if OPENTHREAD_FTD
otError Interpreter::ProcessNeighbor(uint8_t aArgsLength, char *aArgs[])
{
@@ -2853,153 +3141,70 @@
}
#endif
-void Interpreter::HandleIcmpReceive(void * aContext,
- otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- const otIcmp6Header *aIcmpHeader)
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+void Interpreter::HandlePingReply(const otPingSenderReply *aReply, void *aContext)
{
- static_cast<Interpreter *>(aContext)->HandleIcmpReceive(aMessage, aMessageInfo, aIcmpHeader);
+ static_cast<Interpreter *>(aContext)->HandlePingReply(aReply);
}
-void Interpreter::HandleIcmpReceive(otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- const otIcmp6Header *aIcmpHeader)
+void Interpreter::HandlePingReply(const otPingSenderReply *aReply)
{
- uint32_t timestamp = 0;
- uint16_t dataSize;
-
- VerifyOrExit(aIcmpHeader->mType == OT_ICMP6_TYPE_ECHO_REPLY);
- VerifyOrExit((mPingIdentifier != 0) && (mPingIdentifier == HostSwap16(aIcmpHeader->mData.m16[0])));
-
- dataSize = otMessageGetLength(aMessage) - otMessageGetOffset(aMessage);
- OutputFormat("%u bytes from ", dataSize + static_cast<uint16_t>(sizeof(otIcmp6Header)));
-
- OutputIp6Address(aMessageInfo->mPeerAddr);
-
- OutputFormat(": icmp_seq=%d hlim=%d", HostSwap16(aIcmpHeader->mData.m16[1]), aMessageInfo->mHopLimit);
-
- if (otMessageRead(aMessage, otMessageGetOffset(aMessage), ×tamp, sizeof(uint32_t)) == sizeof(uint32_t))
- {
- OutputFormat(" time=%dms", TimerMilli::GetNow().GetValue() - HostSwap32(timestamp));
- }
-
- OutputLine("");
-
- SignalPingReply(static_cast<const Ip6::MessageInfo *>(aMessageInfo)->GetPeerAddr(), dataSize, HostSwap32(timestamp),
- aMessageInfo->mHopLimit);
-
-exit:
- return;
+ OutputFormat("%u bytes from ", static_cast<uint16_t>(aReply->mSize + sizeof(otIcmp6Header)));
+ OutputIp6Address(aReply->mSenderAddress);
+ OutputLine(": icmp_seq=%d hlim=%d time=%dms", aReply->mSequenceNumber, aReply->mHopLimit, aReply->mRoundTripTime);
}
otError Interpreter::ProcessPing(uint8_t aArgsLength, char *aArgs[])
{
- otError error = OT_ERROR_NONE;
- uint8_t index = 1;
- uint32_t interval;
+ otError error = OT_ERROR_NONE;
+ otPingSenderConfig config;
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
if (strcmp(aArgs[0], "stop") == 0)
{
- mPingIdentifier = 0;
- VerifyOrExit(mPingTimer.IsRunning(), error = OT_ERROR_INVALID_STATE);
- mPingTimer.Stop();
+ otPingSenderStop(mInstance);
ExitNow();
}
- VerifyOrExit(!mPingTimer.IsRunning(), error = OT_ERROR_BUSY);
+ memset(&config, 0, sizeof(config));
- SuccessOrExit(error = ParseAsIp6Address(aArgs[0], mPingDestAddress));
+ SuccessOrExit(error = ParseAsIp6Address(aArgs[0], config.mDestination));
- mPingLength = kDefaultPingLength;
- mPingCount = kDefaultPingCount;
- mPingInterval = kDefaultPingInterval;
- mPingHopLimit = 0;
- mPingAllowZeroHopLimit = false;
-
- while (index < aArgsLength)
+ if (aArgsLength > 1)
{
- switch (index)
- {
- case 1:
- SuccessOrExit(error = ParseAsUint16(aArgs[index], mPingLength));
- break;
-
- case 2:
- SuccessOrExit(error = ParseAsUint16(aArgs[index], mPingCount));
- break;
-
- case 3:
- SuccessOrExit(error = ParsePingInterval(aArgs[index], interval));
- VerifyOrExit(0 < interval && interval <= Timer::kMaxDelay, error = OT_ERROR_INVALID_ARGS);
- mPingInterval = interval;
- break;
-
- case 4:
- SuccessOrExit(error = ParseAsUint8(aArgs[index], mPingHopLimit));
- mPingAllowZeroHopLimit = (mPingHopLimit == 0);
- break;
-
- default:
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
-
- index++;
+ SuccessOrExit(error = ParseAsUint16(aArgs[1], config.mSize));
}
- mPingIdentifier++;
-
- if (mPingIdentifier == 0)
+ if (aArgsLength > 2)
{
- mPingIdentifier++;
+ SuccessOrExit(error = ParseAsUint16(aArgs[2], config.mCount));
}
- SendPing();
+ if (aArgsLength > 3)
+ {
+ SuccessOrExit(error = ParsePingInterval(aArgs[3], config.mInterval));
+ }
+
+ if (aArgsLength > 4)
+ {
+ SuccessOrExit(error = ParseAsUint8(aArgs[4], config.mHopLimit));
+ config.mAllowZeroHopLimit = (config.mHopLimit == 0);
+ }
+
+ VerifyOrExit(aArgsLength <= 5, error = OT_ERROR_INVALID_ARGS);
+
+ config.mCallback = Interpreter::HandlePingReply;
+ config.mCallbackContext = this;
+
+ error = otPingSenderPing(mInstance, &config);
exit:
return error;
}
-void Interpreter::HandlePingTimer(Timer &aTimer)
-{
- GetOwner(aTimer).SendPing();
-}
-
-void Interpreter::SendPing(void)
-{
- uint32_t timestamp = HostSwap32(TimerMilli::GetNow().GetValue());
- otMessage * message = nullptr;
- otMessageInfo messageInfo;
-
- memset(&messageInfo, 0, sizeof(messageInfo));
- messageInfo.mPeerAddr = mPingDestAddress;
- messageInfo.mHopLimit = mPingHopLimit;
- messageInfo.mAllowZeroHopLimit = mPingAllowZeroHopLimit;
-
- message = otIp6NewMessage(mInstance, nullptr);
- VerifyOrExit(message != nullptr);
-
- SuccessOrExit(otMessageAppend(message, ×tamp, sizeof(timestamp)));
- SuccessOrExit(otMessageSetLength(message, mPingLength));
- SuccessOrExit(otIcmp6SendEchoRequest(mInstance, message, &messageInfo, mPingIdentifier));
-
- SignalPingRequest(static_cast<Ip6::MessageInfo *>(&messageInfo)->GetPeerAddr(), mPingLength, HostSwap32(timestamp),
- messageInfo.mHopLimit);
-
- message = nullptr;
-
-exit:
- if (message != nullptr)
- {
- otMessageFree(message);
- }
-
- if (--mPingCount)
- {
- mPingTimer.Start(mPingInterval);
- }
-}
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
otError Interpreter::ProcessPollPeriod(uint8_t aArgsLength, char *aArgs[])
{
@@ -3027,14 +3232,7 @@
if (aArgsLength == 0)
{
- if (otLinkIsPromiscuous(mInstance) && otPlatRadioGetPromiscuous(mInstance))
- {
- OutputLine("Enabled");
- }
- else
- {
- OutputLine("Disabled");
- }
+ OutputEnabledDisabledStatus(otLinkIsPromiscuous(mInstance) && otPlatRadioGetPromiscuous(mInstance));
}
else
{
@@ -3316,6 +3514,29 @@
return error;
}
+otError Interpreter::ProcessRegion(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ uint16_t regionCode;
+
+ if (aArgsLength == 0)
+ {
+ SuccessOrExit(error = otPlatRadioGetRegion(mInstance, ®ionCode));
+ OutputLine("%c%c", regionCode >> 8, regionCode & 0xff);
+ }
+ else
+ {
+ VerifyOrExit(strlen(aArgs[0]) == 2, error = OT_ERROR_INVALID_ARGS);
+
+ regionCode =
+ static_cast<uint16_t>(static_cast<uint16_t>(aArgs[0][0]) << 8) + static_cast<uint16_t>(aArgs[0][1]);
+ error = otPlatRadioSetRegion(mInstance, regionCode);
+ }
+
+exit:
+ return error;
+}
+
#if OPENTHREAD_FTD
otError Interpreter::ProcessReleaseRouterId(uint8_t aArgsLength, char *aArgs[])
{
@@ -3468,8 +3689,8 @@
if (isTable)
{
- OutputLine("| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC |");
- OutputLine("+----+--------+----------+-----------+-------+--------+-----+------------------+");
+ OutputLine("| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC | Link |");
+ OutputLine("+----+--------+----------+-----------+-------+--------+-----+------------------+------+");
}
maxRouterId = otThreadGetMaxRouterId(mInstance);
@@ -3492,7 +3713,7 @@
OutputFormat("| %3d ", routerInfo.mAge);
OutputFormat("| ");
OutputExtAddress(routerInfo.mExtAddress);
- OutputLine(" |");
+ OutputLine(" | %4d |", routerInfo.mLinkEstablished);
}
else
{
@@ -3558,14 +3779,7 @@
if (aArgsLength == 0)
{
- if (otThreadIsRouterEligible(mInstance))
- {
- OutputLine("Enabled");
- }
- else
- {
- OutputLine("Disabled");
- }
+ OutputEnabledDisabledStatus(otThreadIsRouterEligible(mInstance));
}
else if (strcmp(aArgs[0], "enable") == 0)
{
@@ -3817,6 +4031,42 @@
}
#endif // OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+otError Interpreter::ProcessSrp(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ OutputLine("client");
+#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ OutputLine("server");
+#endif
+ ExitNow();
+ }
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ if (strcmp(aArgs[0], "client") == 0)
+ {
+ ExitNow(error = mSrpClient.Process(aArgsLength - 1, aArgs + 1));
+ }
+#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ if (strcmp(aArgs[0], "server") == 0)
+ {
+ ExitNow(error = mSrpServer.Process(aArgsLength - 1, aArgs + 1));
+ }
+#endif
+
+ error = OT_ERROR_INVALID_COMMAND;
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
otError Interpreter::ProcessState(uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -4436,23 +4686,23 @@
output[sizeof(output) - 1] = '\0';
error = otDiagProcessCmd(mInstance, aArgsLength, aArgs, output, sizeof(output) - 1);
- Output(output, static_cast<uint16_t>(strlen(output)));
+ OutputFormat("%s", output);
return error;
}
#endif
-void Interpreter::ProcessLine(char *aBuf, uint16_t aBufLength)
+void Interpreter::ProcessLine(char *aBuf)
{
char * args[kMaxArgs] = {nullptr};
uint8_t argsLength;
const Command *command;
- VerifyOrExit(aBuf != nullptr && StringLength(aBuf, aBufLength + 1) <= aBufLength);
+ VerifyOrExit(aBuf != nullptr && StringLength(aBuf, kMaxLineLength) <= kMaxLineLength - 1);
VerifyOrExit(Utils::CmdLineParser::ParseCmd(aBuf, argsLength, args, kMaxArgs) == OT_ERROR_NONE,
OutputLine("Error: too many args (max %d)", kMaxArgs));
- VerifyOrExit(argsLength >= 1, OutputLine("Error: no given command."));
+ VerifyOrExit(argsLength >= 1);
#if OPENTHREAD_CONFIG_DIAG_ENABLE
VerifyOrExit((!otDiagIsEnabled(mInstance) || (strcmp(args[0], "diag") == 0)),
@@ -4506,7 +4756,8 @@
if (strcmp(aArgs[0], "get") == 0)
{
- IgnoreError(otThreadSendDiagnosticGet(mInstance, &address, tlvTypes, count));
+ SuccessOrExit(error = otThreadSendDiagnosticGet(mInstance, &address, tlvTypes, count,
+ &Interpreter::HandleDiagnosticGetResponse, this));
ExitNow(error = OT_ERROR_PENDING);
}
else if (strcmp(aArgs[0], "reset") == 0)
@@ -4727,48 +4978,6 @@
mUserCommandsContext = aContext;
}
-Interpreter &Interpreter::GetOwner(OwnerLocator &aOwnerLocator)
-{
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- Interpreter &interpreter = (aOwnerLocator.GetOwner<Interpreter>());
-#else
- OT_UNUSED_VARIABLE(aOwnerLocator);
-
- Interpreter &interpreter = Interpreter::GetInterpreter();
-#endif
- return interpreter;
-}
-
-void Interpreter::SignalPingRequest(const Ip6::Address &aPeerAddress,
- uint16_t aPingLength,
- uint32_t aTimestamp,
- uint8_t aHopLimit)
-{
- OT_UNUSED_VARIABLE(aPeerAddress);
- OT_UNUSED_VARIABLE(aPingLength);
- OT_UNUSED_VARIABLE(aTimestamp);
- OT_UNUSED_VARIABLE(aHopLimit);
-
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
- mInstance->Get<Utils::Otns>().EmitPingRequest(aPeerAddress, aPingLength, aTimestamp, aHopLimit);
-#endif
-}
-
-void Interpreter::SignalPingReply(const Ip6::Address &aPeerAddress,
- uint16_t aPingLength,
- uint32_t aTimestamp,
- uint8_t aHopLimit)
-{
- OT_UNUSED_VARIABLE(aPeerAddress);
- OT_UNUSED_VARIABLE(aPingLength);
- OT_UNUSED_VARIABLE(aTimestamp);
- OT_UNUSED_VARIABLE(aHopLimit);
-
-#if OPENTHREAD_CONFIG_OTNS_ENABLE
- mInstance->Get<Utils::Otns>().EmitPingReply(aPeerAddress, aPingLength, aTimestamp, aHopLimit);
-#endif
-}
-
void Interpreter::HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo)
{
OutputFormat("~ Discovery Request from ");
@@ -4825,24 +5034,33 @@
void Interpreter::OutputSpaces(uint8_t aCount)
{
- static const char kSpaces[] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
+ char format[sizeof("%256s")];
- while (aCount > 0)
- {
- uint8_t len = OT_MIN(aCount, sizeof(kSpaces));
+ snprintf(format, sizeof(format), "%%%us", aCount);
- Output(kSpaces, len);
- aCount -= len;
- }
+ OutputFormat(format, "");
}
int Interpreter::OutputFormatV(const char *aFormat, va_list aArguments)
{
- char buf[kMaxLineLength];
+ return mOutputCallback(mOutputContext, aFormat, aArguments);
+}
- vsnprintf(buf, sizeof(buf), aFormat, aArguments);
+void Interpreter::Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
+{
+ Instance *instance = static_cast<Instance *>(aInstance);
- return Output(buf, static_cast<uint16_t>(strlen(buf)));
+ Interpreter::sInterpreter = new (&sInterpreterRaw) Interpreter(instance, aCallback, aContext);
+}
+
+extern "C" void otCliInit(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext)
+{
+ Interpreter::Initialize(aInstance, aCallback, aContext);
+}
+
+extern "C" void otCliInputLine(char *aBuf)
+{
+ Interpreter::GetInterpreter().ProcessLine(aBuf);
}
extern "C" void otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength, void *aContext)
@@ -4863,11 +5081,6 @@
va_end(aAp);
}
-extern "C" void otCliOutput(const char *aString, uint16_t aLength)
-{
- Interpreter::GetInterpreter().Output(aString, aLength);
-}
-
extern "C" void otCliAppendResult(otError aError)
{
Interpreter::GetInterpreter().OutputResult(aError);
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index 35c7912..a632be8 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -41,15 +41,22 @@
#include <stdarg.h>
#include <openthread/cli.h>
-#include <openthread/dns.h>
+#include <openthread/dataset.h>
+#include <openthread/dns_client.h>
+#include <openthread/instance.h>
#include <openthread/ip6.h>
+#include <openthread/link.h>
#include <openthread/sntp.h>
+#include <openthread/thread.h>
+#include <openthread/thread_ftd.h>
#include <openthread/udp.h>
#include "cli/cli_commissioner.hpp"
#include "cli/cli_dataset.hpp"
#include "cli/cli_joiner.hpp"
#include "cli/cli_network_data.hpp"
+#include "cli/cli_srp_client.hpp"
+#include "cli/cli_srp_server.hpp"
#include "cli/cli_udp.hpp"
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
#include "cli/cli_coap.hpp"
@@ -57,10 +64,10 @@
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
#include "cli/cli_coap_secure.hpp"
#endif
+
#include "common/code_utils.hpp"
+#include "common/debug.hpp"
#include "common/instance.hpp"
-#include "common/timer.hpp"
-#include "net/icmp6.hpp"
#include "utils/lookup_table.hpp"
namespace ot {
@@ -86,15 +93,19 @@
friend class Dataset;
friend class Joiner;
friend class NetworkData;
+ friend class SrpClient;
+ friend class SrpServer;
friend class UdpExample;
public:
/**
* Constructor
*
- * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aCallback A callback method called to process CLI output.
+ * @param[in] aContext A user context pointer.
*/
- explicit Interpreter(Instance *aInstance);
+ explicit Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext);
/**
* This method returns a reference to the interpreter object.
@@ -110,6 +121,16 @@
}
/**
+ * This method initializes the Console interpreter.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aCallback A pointer to a callback method.
+ * @param[in] aContext A pointer to a user context.
+ *
+ */
+ static void Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
+
+ /**
* This method returns whether the interpreter is initialized.
*
* @returns Whether the interpreter is initialized.
@@ -121,10 +142,9 @@
* This method interprets a CLI command.
*
* @param[in] aBuf A pointer to a string.
- * @param[in] aBufLength The length of the string in bytes.
*
*/
- void ProcessLine(char *aBuf, uint16_t aBufLength);
+ void ProcessLine(char *aBuf);
/**
* This method delivers raw characters to the client.
@@ -146,7 +166,7 @@
* @param[in] aLength @p aBytes length.
*
*/
- void OutputBytes(const uint8_t *aBytes, uint8_t aLength);
+ void OutputBytes(const uint8_t *aBytes, uint16_t aLength);
/**
* This method writes a number of bytes to the CLI console as a hex string.
@@ -255,6 +275,14 @@
void OutputResult(otError aError);
/**
+ * This method delivers "Enabled" or "Disabled" status to the CLI client (it also appends newline `\r\n`).
+ *
+ * @param[in] aEnabled A boolean indicating the status. TRUE outputs "Enabled", FALSE outputs "Disabled".
+ *
+ */
+ void OutputEnabledDisabledStatus(bool aEnabled);
+
+ /**
* This method sets the user command table.
*
* @param[in] aUserCommands A pointer to an array with user commands.
@@ -273,12 +301,7 @@
kIndentSize = 4,
kMaxArgs = 32,
kMaxAutoAddresses = 8,
-
- kDefaultPingInterval = 1000, // (in mses)
- kDefaultPingLength = 8, // (in bytes)
- kDefaultPingCount = 1,
-
- kMaxLineLength = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH,
+ kMaxLineLength = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH,
};
struct Command
@@ -287,13 +310,18 @@
otError (Interpreter::*mHandler)(uint8_t aArgsLength, char *aArgs[]);
};
- otError ParsePingInterval(const char *aString, uint32_t &aInterval);
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ otError ParsePingInterval(const char *aString, uint32_t &aInterval);
+#endif
static otError ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aDiscerner);
otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
otError ProcessCcaThreshold(uint8_t aArgsLength, char *aArgs[]);
otError ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]);
otError ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ otError ProcessBorderRouting(uint8_t aArgsLength, char *aArgs[]);
+#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otError ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]);
@@ -353,7 +381,7 @@
otError ProcessEidCache(uint8_t aArgsLength, char *aArgs[]);
#endif
otError ProcessEui64(uint8_t aArgsLength, char *aArgs[]);
-#if OPENTHREAD_POSIX
+#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
otError ProcessExit(uint8_t aArgsLength, char *aArgs[]);
#endif
otError ProcessLog(uint8_t aArgsLength, char *aArgs[]);
@@ -409,6 +437,10 @@
uint8_t aFailedAddressNum);
#endif
otError ProcessMode(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessMultiRadio(uint8_t aArgsLength, char *aArgsp[]);
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+ void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
+#endif
#if OPENTHREAD_FTD
otError ProcessNeighbor(uint8_t aArgsLength, char *aArgs[]);
#endif
@@ -444,17 +476,10 @@
#if OPENTHREAD_FTD
otError ProcessParentPriority(uint8_t aArgsLength, char *aArgs[]);
#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
otError ProcessPing(uint8_t aArgsLength, char *aArgs[]);
+#endif
otError ProcessPollPeriod(uint8_t aArgsLength, char *aArgs[]);
- void SignalPingRequest(const Ip6::Address &aPeerAddress,
- uint16_t aPingLength,
- uint32_t aTimestamp,
- uint8_t aHopLimit);
- void SignalPingReply(const Ip6::Address &aPeerAddress,
- uint16_t aPingLength,
- uint32_t aTimestamp,
- uint8_t aHopLimit);
-
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
otError ProcessPrefix(uint8_t aArgsLength, char *aArgs[]);
otError ProcessPrefixAdd(uint8_t aArgsLength, char *aArgs[]);
@@ -467,6 +492,7 @@
otError ProcessPskc(uint8_t aArgsLength, char *aArgs[]);
#endif
otError ProcessRcp(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessRegion(uint8_t aArgsLength, char *aArgs[]);
#if OPENTHREAD_FTD
otError ProcessReleaseRouterId(uint8_t aArgsLength, char *aArgs[]);
#endif
@@ -490,6 +516,9 @@
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
otError ProcessSntp(uint8_t aArgsLength, char *aArgs[]);
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ otError ProcessSrp(uint8_t aArgsLength, char *aArgs[]);
+#endif
otError ProcessState(uint8_t aArgsLength, char *aArgs[]);
otError ProcessThread(uint8_t aArgsLength, char *aArgs[]);
otError ProcessDataset(uint8_t aArgsLength, char *aArgs[]);
@@ -509,11 +538,9 @@
otError ProcessMacSend(uint8_t aArgsLength, char *aArgs[]);
#endif
- static void HandleIcmpReceive(void * aContext,
- otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- const otIcmp6Header *aIcmpHeader);
- static void HandlePingTimer(Timer &aTimer);
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ static void HandlePingReply(const otPingSenderReply *aReply, 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);
@@ -534,26 +561,31 @@
void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
#endif
+ void OutputDnsTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength);
+
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- static void HandleDnsResponse(void * aContext,
- const char * aHostname,
- const otIp6Address *aAddress,
- uint32_t aTtl,
- otError aResult);
+ otError GetDnsConfig(uint8_t aArgsLength, char *aArgs[], otDnsQueryConfig *&aConfig, uint8_t aStartArgsIndex);
+ static void HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse, void *aContext);
+ void HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse);
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ void OutputDnsServiceInfo(uint8_t aIndentSize, const otDnsServiceInfo &aServiceInfo);
+ static void HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse, void *aContext);
+ void HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse);
+ static void HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse, void *aContext);
+ void HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse);
+#endif
#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
#endif
- void HandleIcmpReceive(otMessage *aMessage, const otMessageInfo *aMessageInfo, const otIcmp6Header *aIcmpHeader);
- void SendPing(void);
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ void HandlePingReply(const otPingSenderReply *aReply);
+#endif
void HandleActiveScanResult(otActiveScanResult *aResult);
void HandleEnergyScanResult(otEnergyScanResult *aResult);
void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- void HandleDnsResponse(const char *aHostname, const Ip6::Address *aAddress, uint32_t aTtl, otError aResult);
-#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
void HandleSntpResponse(uint64_t aTime, otError aResult);
#endif
@@ -585,8 +617,6 @@
const char *LinkMetricsStatusToStr(uint8_t aStatus);
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
- static Interpreter &GetOwner(OwnerLocator &aOwnerLocator);
-
static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext)
{
static_cast<Interpreter *>(aContext)->HandleDiscoveryRequest(*aInfo);
@@ -597,6 +627,9 @@
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
{"bbr", &Interpreter::ProcessBackboneRouter},
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ {"br", &Interpreter::ProcessBorderRouting},
+#endif
{"bufferinfo", &Interpreter::ProcessBufferInfo},
{"ccathreshold", &Interpreter::ProcessCcaThreshold},
{"channel", &Interpreter::ProcessChannel},
@@ -649,7 +682,7 @@
{"eidcache", &Interpreter::ProcessEidCache},
#endif
{"eui64", &Interpreter::ProcessEui64},
-#if OPENTHREAD_POSIX
+#if OPENTHREAD_POSIX && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
{"exit", &Interpreter::ProcessExit},
#endif
{"extaddr", &Interpreter::ProcessExtAddress},
@@ -687,6 +720,7 @@
{"mlr", &Interpreter::ProcessMlr},
#endif
{"mode", &Interpreter::ProcessMode},
+ {"multiradio", &Interpreter::ProcessMultiRadio},
#if OPENTHREAD_FTD
{"neighbor", &Interpreter::ProcessNeighbor},
#endif
@@ -711,7 +745,9 @@
{"parentpriority", &Interpreter::ProcessParentPriority},
{"partitionid", &Interpreter::ProcessPartitionId},
#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
{"ping", &Interpreter::ProcessPing},
+#endif
{"pollperiod", &Interpreter::ProcessPollPeriod},
#if OPENTHREAD_FTD
{"preferrouterid", &Interpreter::ProcessPreferRouterId},
@@ -724,6 +760,7 @@
{"pskc", &Interpreter::ProcessPskc},
#endif
{"rcp", &Interpreter::ProcessRcp},
+ {"region", &Interpreter::ProcessRegion},
#if OPENTHREAD_FTD
{"releaserouterid", &Interpreter::ProcessReleaseRouterId},
#endif
@@ -747,6 +784,9 @@
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
{"sntp", &Interpreter::ProcessSntp},
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE || OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ {"srp", &Interpreter::ProcessSrp},
+#endif
{"state", &Interpreter::ProcessState},
{"thread", &Interpreter::ProcessThread},
{"txpower", &Interpreter::ProcessTxPower},
@@ -757,23 +797,12 @@
static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+ Instance * mInstance;
+ otCliOutputCallback mOutputCallback;
+ void * mOutputContext;
const otCliCommand *mUserCommands;
uint8_t mUserCommandsLength;
void * mUserCommandsContext;
- uint16_t mPingLength;
- uint16_t mPingCount;
- uint32_t mPingInterval;
- uint8_t mPingHopLimit;
- bool mPingAllowZeroHopLimit;
- uint16_t mPingIdentifier;
- otIp6Address mPingDestAddress;
- TimerMilli mPingTimer;
- otIcmp6Handler mIcmpHandler;
-#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- bool mResolvingInProgress;
- char mResolvingHostname[OT_DNS_MAX_HOSTNAME_LENGTH];
-#endif
-
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
bool mSntpQueryingInProgress;
#endif
@@ -798,7 +827,13 @@
Joiner mJoiner;
#endif
- Instance *mInstance;
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ SrpClient mSrpClient;
+#endif
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ SrpServer mSrpServer;
+#endif
};
} // namespace Cli
diff --git a/src/cli/cli_coap.cpp b/src/cli/cli_coap.cpp
index d106175..867d280 100644
--- a/src/cli/cli_coap.cpp
+++ b/src/cli/cli_coap.cpp
@@ -35,6 +35,8 @@
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
+#include <openthread/random_noncrypto.h>
+
#include <ctype.h>
#include "cli/cli.hpp"
@@ -60,6 +62,9 @@
, mSubscriberTokenLength(0)
, mSubscriberConfirmableNotifications(false)
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ , mBlockCount(1)
+#endif
{
memset(&mResource, 0, sizeof(mResource));
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
@@ -180,8 +185,22 @@
mResource.mContext = this;
mResource.mHandler = &Coap::HandleRequest;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ mResource.mReceiveHook = &Coap::BlockwiseReceiveHook;
+ mResource.mTransmitHook = &Coap::BlockwiseTransmitHook;
+
+ if (aArgsLength > 2)
+ {
+ SuccessOrExit(error = ParseAsUint32(aArgs[2], mBlockCount));
+ }
+#endif
+
strncpy(mUriPath, aArgs[1], sizeof(mUriPath) - 1);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapAddBlockWiseResource(mInterpreter.mInstance, &mResource);
+#else
otCoapAddResource(mInterpreter.mInstance, &mResource);
+#endif
}
else
{
@@ -267,7 +286,11 @@
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapRemoveBlockWiseResource(mInterpreter.mInstance, &mResource);
+#else
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
+#endif
return otCoapStop(mInterpreter.mInstance);
}
@@ -348,6 +371,11 @@
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
bool coapObserve = false;
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ bool coapBlock = false;
+ otCoapBlockSzx coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
+ ot::Coap::Message::BlockType coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
@@ -355,6 +383,9 @@
if (strcmp(aArgs[0], "get") == 0)
{
coapCode = OT_COAP_CODE_GET;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType2;
+#endif
}
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
else if (strcmp(aArgs[0], "observe") == 0)
@@ -367,10 +398,16 @@
else if (strcmp(aArgs[0], "post") == 0)
{
coapCode = OT_COAP_CODE_POST;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
}
else if (strcmp(aArgs[0], "put") == 0)
{
coapCode = OT_COAP_CODE_PUT;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
}
else if (strcmp(aArgs[0], "delete") == 0)
{
@@ -409,6 +446,50 @@
{
coapType = OT_COAP_TYPE_CONFIRMABLE;
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ else if (strcmp(aArgs[3], "block-16") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
+ }
+ else if (strcmp(aArgs[3], "block-32") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_32;
+ }
+ else if (strcmp(aArgs[3], "block-64") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_64;
+ }
+ else if (strcmp(aArgs[3], "block-128") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_128;
+ }
+ else if (strcmp(aArgs[3], "block-256") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_256;
+ }
+ else if (strcmp(aArgs[3], "block-512") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_512;
+ }
+ else if (strcmp(aArgs[3], "block-1024") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_1024;
+ }
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
}
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
@@ -434,14 +515,39 @@
SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
+ {
+ if (coapBlockType == ot::Coap::Message::kBlockType1)
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock1Option(message, 0, true, coapBlockSize));
+ }
+ else
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock2Option(message, 0, false, coapBlockSize));
+ }
+ }
+#endif
+
if (aArgsLength > 4)
{
- payloadLength = static_cast<uint16_t>(strlen(aArgs[4]));
-
- if (payloadLength > 0)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
{
- SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
+ SuccessOrExit(error = ParseAsUint32(aArgs[4], mBlockCount));
}
+ else
+ {
+#endif
+ payloadLength = static_cast<uint16_t>(strlen(aArgs[4]));
+
+ if (payloadLength > 0)
+ {
+ SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
+ }
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
// Embed content into message if given
@@ -468,8 +574,25 @@
if ((coapType == OT_COAP_TYPE_CONFIRMABLE) || (coapCode == OT_COAP_CODE_GET))
{
- error = otCoapSendRequestWithParameters(mInterpreter.mInstance, message, &messageInfo, &Coap::HandleResponse,
- this, GetRequestTxParameters());
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
+ {
+ if (coapCode == OT_COAP_CODE_PUT || coapCode == OT_COAP_CODE_POST)
+ {
+ SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
+ }
+ error = otCoapSendRequestBlockWiseWithParameters(mInterpreter.mInstance, message, &messageInfo,
+ &Coap::HandleResponse, this, GetRequestTxParameters(),
+ Coap::BlockwiseTransmitHook, Coap::BlockwiseReceiveHook);
+ }
+ else
+ {
+#endif
+ error = otCoapSendRequestWithParameters(mInterpreter.mInstance, message, &messageInfo,
+ &Coap::HandleResponse, this, GetRequestTxParameters());
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
else
{
@@ -514,8 +637,14 @@
otMessage *responseMessage = nullptr;
otCoapCode responseCode = OT_COAP_CODE_EMPTY;
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
- uint64_t observe = 0;
- bool observePresent = false;
+ uint64_t observe = 0;
+ bool observePresent = false;
+#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint64_t blockValue = 0;
+ bool blockPresent = false;
+#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE || OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
otCoapOptionIterator iterator;
#endif
@@ -527,9 +656,11 @@
{
case OT_COAP_CODE_GET:
mInterpreter.OutputFormat("GET");
-#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE || OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
SuccessOrExit(error = otCoapOptionIteratorInit(&iterator, aMessage));
- if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_OBSERVE) != nullptr)
+#endif
+#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
+ if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_OBSERVE) != NULL)
{
SuccessOrExit(error = otCoapOptionIteratorGetOptionUintValue(&iterator, &observe));
observePresent = true;
@@ -537,6 +668,13 @@
mInterpreter.OutputFormat(" OBS=%lu", static_cast<uint32_t>(observe));
}
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_BLOCK2) != nullptr)
+ {
+ SuccessOrExit(error = otCoapOptionIteratorGetOptionUintValue(&iterator, &blockValue));
+ blockPresent = true;
+ }
+#endif
break;
case OT_COAP_CODE_DELETE:
@@ -626,13 +764,40 @@
SuccessOrExit(error = otCoapMessageAppendObserveOption(responseMessage, mObserveSerial++));
}
#endif
- SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
- SuccessOrExit(error = otMessageAppend(responseMessage, mResourceContent,
- static_cast<uint16_t>(strlen(mResourceContent))));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (blockPresent)
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock2Option(responseMessage,
+ static_cast<uint32_t>(blockValue >> 4), true,
+ static_cast<otCoapBlockSzx>(blockValue & 0x7)));
+ SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
+ }
+ else
+ {
+#endif
+ SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
+ SuccessOrExit(error = otMessageAppend(responseMessage, mResourceContent,
+ static_cast<uint16_t>(strlen(mResourceContent))));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
- SuccessOrExit(error = otCoapSendResponseWithParameters(mInterpreter.mInstance, responseMessage, aMessageInfo,
- GetResponseTxParameters()));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (blockPresent)
+ {
+ SuccessOrExit(error = otCoapSendResponseBlockWiseWithParameters(mInterpreter.mInstance, responseMessage,
+ aMessageInfo, GetResponseTxParameters(),
+ this, mResource.mTransmitHook));
+ }
+ else
+ {
+#endif
+ SuccessOrExit(error = otCoapSendResponseWithParameters(mInterpreter.mInstance, responseMessage,
+ aMessageInfo, GetResponseTxParameters()));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
exit:
@@ -726,6 +891,77 @@
}
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError Coap::BlockwiseReceiveHook(void * aContext,
+ const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength)
+{
+ return static_cast<Coap *>(aContext)->BlockwiseReceiveHook(aBlock, aPosition, aBlockLength, aMore, aTotalLength);
+}
+
+otError Coap::BlockwiseReceiveHook(const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength)
+{
+ OT_UNUSED_VARIABLE(aMore);
+ OT_UNUSED_VARIABLE(aTotalLength);
+
+ mInterpreter.OutputLine("received block: Num %i Len %i", aPosition / aBlockLength, aBlockLength);
+
+ for (uint16_t i = 0; i < aBlockLength / 16; i++)
+ {
+ mInterpreter.OutputBytes(&aBlock[i * 16], 16);
+ mInterpreter.OutputLine("");
+ }
+
+ return OT_ERROR_NONE;
+}
+
+otError Coap::BlockwiseTransmitHook(void * aContext,
+ uint8_t * aBlock,
+ uint32_t aPosition,
+ uint16_t *aBlockLength,
+ bool * aMore)
+{
+ return static_cast<Coap *>(aContext)->BlockwiseTransmitHook(aBlock, aPosition, aBlockLength, aMore);
+}
+
+otError Coap::BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore)
+{
+ static uint32_t blockCount = 0;
+ OT_UNUSED_VARIABLE(aPosition);
+
+ // Send a random payload
+ otRandomNonCryptoFillBuffer(aBlock, *aBlockLength);
+
+ mInterpreter.OutputLine("send block: Num %i Len %i", blockCount, *aBlockLength);
+
+ for (uint16_t i = 0; i < *aBlockLength / 16; i++)
+ {
+ mInterpreter.OutputBytes(&aBlock[i * 16], 16);
+ mInterpreter.OutputLine("");
+ }
+
+ if (blockCount == mBlockCount - 1)
+ {
+ blockCount = 0;
+ *aMore = false;
+ }
+ else
+ {
+ *aMore = true;
+ blockCount++;
+ }
+
+ return OT_ERROR_NONE;
+}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
} // namespace Cli
} // namespace ot
diff --git a/src/cli/cli_coap.hpp b/src/cli/cli_coap.hpp
index 0325781..586386a 100644
--- a/src/cli/cli_coap.hpp
+++ b/src/cli/cli_coap.hpp
@@ -115,6 +115,27 @@
static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
void HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+ static otError BlockwiseReceiveHook(void * aContext,
+ const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength);
+ otError BlockwiseReceiveHook(const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength);
+ static otError BlockwiseTransmitHook(void * aContext,
+ uint8_t * aBlock,
+ uint32_t aPosition,
+ uint16_t *aBlockLength,
+ bool * aMore);
+ otError BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore);
+#endif
+
const otCoapTxParameters *GetRequestTxParameters(void) const
{
return mUseDefaultRequestTxParameters ? nullptr : &mRequestTxParameters;
@@ -154,7 +175,11 @@
otCoapTxParameters mRequestTxParameters;
otCoapTxParameters mResponseTxParameters;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapBlockwiseResource mResource;
+#else
otCoapResource mResource;
+#endif
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
otIp6Address mRequestAddr;
otSockAddr mSubscriberSock;
@@ -170,6 +195,9 @@
uint8_t mSubscriberTokenLength;
bool mSubscriberConfirmableNotifications;
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint32_t mBlockCount;
+#endif
};
} // namespace Cli
diff --git a/src/cli/cli_coap_secure.cpp b/src/cli/cli_coap_secure.cpp
index 2f1b586..880c66d 100644
--- a/src/cli/cli_coap_secure.cpp
+++ b/src/cli/cli_coap_secure.cpp
@@ -37,6 +37,7 @@
#include <mbedtls/debug.h>
#include <openthread/ip6.h>
+#include <openthread/random_noncrypto.h>
#include "cli/cli.hpp"
#include "utils/parse_cmdline.hpp"
@@ -46,6 +47,7 @@
using ot::Utils::CmdLineParser::ParseAsIp6Address;
using ot::Utils::CmdLineParser::ParseAsUint16;
+using ot::Utils::CmdLineParser::ParseAsUint32;
namespace ot {
namespace Cli {
@@ -58,6 +60,9 @@
, mUseCertificate(false)
, mPskLength(0)
, mPskIdLength(0)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ , mBlockCount(1)
+#endif
{
memset(&mResource, 0, sizeof(mResource));
memset(&mPsk, 0, sizeof(mPsk));
@@ -117,8 +122,22 @@
mResource.mContext = this;
mResource.mHandler = &CoapSecure::HandleRequest;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ mResource.mReceiveHook = &CoapSecure::BlockwiseReceiveHook;
+ mResource.mTransmitHook = &CoapSecure::BlockwiseTransmitHook;
+
+ if (aArgsLength > 2)
+ {
+ SuccessOrExit(error = ParseAsUint32(aArgs[2], mBlockCount));
+ }
+#endif
+
strncpy(mUriPath, aArgs[1], sizeof(mUriPath) - 1);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapSecureAddBlockWiseResource(mInterpreter.mInstance, &mResource);
+#else
otCoapSecureAddResource(mInterpreter.mInstance, &mResource);
+#endif
}
else
{
@@ -183,7 +202,11 @@
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapRemoveBlockWiseResource(mInterpreter.mInstance, &mResource);
+#else
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
+#endif
if (otCoapSecureIsConnectionActive(mInterpreter.mInstance))
{
@@ -211,6 +234,11 @@
otCoapType coapType = OT_COAP_TYPE_NON_CONFIRMABLE;
otCoapCode coapCode = OT_COAP_CODE_GET;
otIp6Address coapDestinationIp;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ bool coapBlock = false;
+ otCoapBlockSzx coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
+ ot::Coap::Message::BlockType coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
@@ -218,14 +246,23 @@
if (strcmp(aArgs[0], "get") == 0)
{
coapCode = OT_COAP_CODE_GET;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType2;
+#endif
}
else if (strcmp(aArgs[0], "post") == 0)
{
coapCode = OT_COAP_CODE_POST;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
}
else if (strcmp(aArgs[0], "put") == 0)
{
coapCode = OT_COAP_CODE_PUT;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ coapBlockType = ot::Coap::Message::kBlockType1;
+#endif
}
else if (strcmp(aArgs[0], "delete") == 0)
{
@@ -270,6 +307,50 @@
{
coapType = OT_COAP_TYPE_CONFIRMABLE;
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ else if (strcmp(aArgs[3 - indexShifter], "block-16") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_16;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-32") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_32;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-64") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_64;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-128") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_128;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-256") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_256;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-512") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_512;
+ }
+ else if (strcmp(aArgs[3 - indexShifter], "block-1024") == 0)
+ {
+ coapType = OT_COAP_TYPE_CONFIRMABLE;
+ coapBlock = true;
+ coapBlockSize = OT_COAP_OPTION_BLOCK_SZX_1024;
+ }
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
}
message = otCoapNewMessage(mInterpreter.mInstance, nullptr);
@@ -279,14 +360,39 @@
otCoapMessageGenerateToken(message, OT_COAP_DEFAULT_TOKEN_LENGTH);
SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
+ {
+ if (coapBlockType == ot::Coap::Message::kBlockType1)
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock1Option(message, 0, true, coapBlockSize));
+ }
+ else
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock2Option(message, 0, false, coapBlockSize));
+ }
+ }
+#endif
+
if (aArgsLength > (4 - indexShifter))
{
- payloadLength = static_cast<uint16_t>(strlen(aArgs[4 - indexShifter]));
-
- if (payloadLength > 0)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
{
- SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
+ SuccessOrExit(error = ParseAsUint32(aArgs[4 - indexShifter], mBlockCount));
}
+ else
+ {
+#endif
+ payloadLength = static_cast<uint16_t>(strlen(aArgs[4 - indexShifter]));
+
+ if (payloadLength > 0)
+ {
+ SuccessOrExit(error = otCoapMessageSetPayloadMarker(message));
+ }
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
// add payload
@@ -301,7 +407,20 @@
if ((coapType == OT_COAP_TYPE_CONFIRMABLE) || (coapCode == OT_COAP_CODE_GET))
{
- error = otCoapSecureSendRequest(mInterpreter.mInstance, message, &CoapSecure::HandleResponse, this);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (coapBlock)
+ {
+ error =
+ otCoapSecureSendRequestBlockWise(mInterpreter.mInstance, message, &CoapSecure::HandleResponse, this,
+ &CoapSecure::BlockwiseTransmitHook, &CoapSecure::BlockwiseReceiveHook);
+ }
+ else
+ {
+#endif
+ error = otCoapSecureSendRequest(mInterpreter.mInstance, message, &CoapSecure::HandleResponse, this);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
else
{
@@ -415,7 +534,11 @@
void CoapSecure::Stop(void)
{
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapRemoveBlockWiseResource(mInterpreter.mInstance, &mResource);
+#else
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
+#endif
otCoapSecureStop(mInterpreter.mInstance);
}
@@ -452,6 +575,11 @@
otError error = OT_ERROR_NONE;
otMessage *responseMessage = nullptr;
otCoapCode responseCode = OT_COAP_CODE_EMPTY;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint64_t blockValue = 0;
+ bool blockPresent = false;
+ otCoapOptionIterator iterator;
+#endif
mInterpreter.OutputFormat("coaps request from ");
mInterpreter.OutputIp6Address(aMessageInfo->mPeerAddr);
@@ -461,6 +589,14 @@
{
case OT_COAP_CODE_GET:
mInterpreter.OutputFormat("GET");
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ SuccessOrExit(error = otCoapOptionIteratorInit(&iterator, aMessage));
+ if (otCoapOptionIteratorGetFirstOptionMatching(&iterator, OT_COAP_OPTION_BLOCK2) != nullptr)
+ {
+ SuccessOrExit(error = otCoapOptionIteratorGetOptionUintValue(&iterator, &blockValue));
+ blockPresent = true;
+ }
+#endif
break;
case OT_COAP_CODE_DELETE:
@@ -502,16 +638,39 @@
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
{
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (blockPresent)
+ {
+ SuccessOrExit(error = otCoapMessageAppendBlock2Option(responseMessage,
+ static_cast<uint32_t>(blockValue >> 4), true,
+ static_cast<otCoapBlockSzx>(blockValue & 0x7)));
+ }
+#endif
SuccessOrExit(error = otCoapMessageSetPayloadMarker(responseMessage));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (!blockPresent)
+ {
+#endif
+ SuccessOrExit(error = otMessageAppend(responseMessage, &mResourceContent,
+ static_cast<uint16_t>(strlen(mResourceContent))));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
- if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ if (blockPresent)
{
- SuccessOrExit(error = otMessageAppend(responseMessage, &mResourceContent,
- static_cast<uint16_t>(strlen(mResourceContent))));
+ SuccessOrExit(error = otCoapSecureSendResponseBlockWise(mInterpreter.mInstance, responseMessage,
+ aMessageInfo, this, mResource.mTransmitHook));
}
-
- SuccessOrExit(error = otCoapSecureSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo));
+ else
+ {
+#endif
+ SuccessOrExit(error = otCoapSecureSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ }
+#endif
}
exit:
@@ -583,6 +742,78 @@
}
#endif // CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError CoapSecure::BlockwiseReceiveHook(void * aContext,
+ const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength)
+{
+ return static_cast<CoapSecure *>(aContext)->BlockwiseReceiveHook(aBlock, aPosition, aBlockLength, aMore,
+ aTotalLength);
+}
+
+otError CoapSecure::BlockwiseReceiveHook(const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength)
+{
+ OT_UNUSED_VARIABLE(aMore);
+ OT_UNUSED_VARIABLE(aTotalLength);
+
+ mInterpreter.OutputLine("received block: Num %i Len %i", aPosition / aBlockLength, aBlockLength);
+
+ for (uint16_t i = 0; i < aBlockLength / 16; i++)
+ {
+ mInterpreter.OutputBytes(&aBlock[i * 16], 16);
+ mInterpreter.OutputLine("");
+ }
+
+ return OT_ERROR_NONE;
+}
+
+otError CoapSecure::BlockwiseTransmitHook(void * aContext,
+ uint8_t * aBlock,
+ uint32_t aPosition,
+ uint16_t *aBlockLength,
+ bool * aMore)
+{
+ return static_cast<CoapSecure *>(aContext)->BlockwiseTransmitHook(aBlock, aPosition, aBlockLength, aMore);
+}
+
+otError CoapSecure::BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore)
+{
+ static uint32_t blockCount = 0;
+ OT_UNUSED_VARIABLE(aPosition);
+
+ // Send a random payload
+ otRandomNonCryptoFillBuffer(aBlock, *aBlockLength);
+
+ mInterpreter.OutputLine("send block: Num %i Len %i", blockCount, *aBlockLength);
+
+ for (uint16_t i = 0; i < *aBlockLength / 16; i++)
+ {
+ mInterpreter.OutputBytes(&aBlock[i * 16], 16);
+ mInterpreter.OutputLine("");
+ }
+
+ if (blockCount == mBlockCount - 1)
+ {
+ blockCount = 0;
+ *aMore = false;
+ }
+ else
+ {
+ *aMore = true;
+ blockCount++;
+ }
+
+ return OT_ERROR_NONE;
+}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
} // namespace Cli
} // namespace ot
diff --git a/src/cli/cli_coap_secure.hpp b/src/cli/cli_coap_secure.hpp
index 18f0d1f..fa52c17 100644
--- a/src/cli/cli_coap_secure.hpp
+++ b/src/cli/cli_coap_secure.hpp
@@ -111,6 +111,27 @@
static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
void HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+ static otError BlockwiseReceiveHook(void * aContext,
+ const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength);
+ otError BlockwiseReceiveHook(const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength);
+ static otError BlockwiseTransmitHook(void * aContext,
+ uint8_t * aBlock,
+ uint32_t aPosition,
+ uint16_t *aBlockLength,
+ bool * aMore);
+ otError BlockwiseTransmitHook(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore);
+#endif
+
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
static void DefaultHandler(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void DefaultHandler(otMessage *aMessage, const otMessageInfo *aMessageInfo);
@@ -143,9 +164,13 @@
Interpreter &mInterpreter;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapBlockwiseResource mResource;
+#else
otCoapResource mResource;
- char mUriPath[kMaxUriLength];
- char mResourceContent[kMaxBufferSize];
+#endif
+ char mUriPath[kMaxUriLength];
+ char mResourceContent[kMaxBufferSize];
bool mShutdownFlag;
bool mUseCertificate;
@@ -153,6 +178,9 @@
uint8_t mPskLength;
uint8_t mPskId[kPskIdMaxLength];
uint8_t mPskIdLength;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint32_t mBlockCount;
+#endif
};
} // namespace Cli
diff --git a/src/cli/cli_config.h b/src/cli/cli_config.h
index 3dc2512..7c8fda0 100644
--- a/src/cli/cli_config.h
+++ b/src/cli/cli_config.h
@@ -37,6 +37,15 @@
#include "openthread-core-config.h"
+#ifndef OPENTHREAD_POSIX
+#if defined(__ANDROID__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(__NetBSD__) || \
+ defined(__unix__)
+#define OPENTHREAD_POSIX 1
+#else
+#define OPENTHREAD_POSIX 0
+#endif
+#endif
+
/**
* @def OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
*
@@ -44,59 +53,31 @@
*
*/
#ifndef OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH
-#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 128
+#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 384
#endif
/**
- * @def OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
+ * @def OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES
*
- * The size of CLI UART RX buffer in bytes.
+ * The maximum number of service entries supported by SRP client.
+ *
+ * This is only applicable when SRP client is enabled, i.e. OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set.
*
*/
-#ifndef OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 640
-#else
-#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 512
-#endif
+#ifndef OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES
+#define OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES 2
#endif
/**
- * @def OPENTHREAD_CONFIG_CLI_TX_BUFFER_SIZE
+ * @def OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES
*
- * The size of CLI message buffer in bytes.
+ * The maximum number of host IPv6 address entries supported by SRP client.
+ *
+ * This is only applicable when SRP client is enabled, i.e. OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set.
*
*/
-#ifndef OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE
-#define OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE 1024
-#endif
-
-/**
- * @def OPENTHREAD_CONFIG_UART_CLI_RAW
- *
- * TODO: complete.
- *
- */
-#ifndef OPENTHREAD_CONFIG_UART_CLI_RAW
-#define OPENTHREAD_CONFIG_UART_CLI_RAW 0
-#endif
-
-#define OT_CLI_TRANSPORT_UART (1)
-#define OT_CLI_TRANSPORT_CONSOLE (2)
-
-/**
- * @def OPENTHREAD_CONFIG_CLI_TRANSPORT
- *
- * The transport of the CLI.
- *
- */
-#ifndef OPENTHREAD_CONFIG_CLI_TRANSPORT
-#define OPENTHREAD_CONFIG_CLI_TRANSPORT OT_CLI_TRANSPORT_UART
-#endif
-
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT != OT_CLI_TRANSPORT_UART && \
- OPENTHREAD_CONFIG_CLI_TRANSPORT != OT_CLI_TRANSPORT_CONSOLE
-#error "Unsupported CLI transport!"
+#ifndef OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES
+#define OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES 2
#endif
#endif // CONFIG_CLI_H_
diff --git a/src/cli/cli_console.cpp b/src/cli/cli_console.cpp
deleted file mode 100644
index 55ef6bf..0000000
--- a/src/cli/cli_console.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2016, 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 on the CONSOLE service.
- */
-
-#include "cli_console.hpp"
-
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_CONSOLE
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cli/cli.hpp"
-#include "common/instance.hpp"
-#include "common/new.hpp"
-
-namespace ot {
-namespace Cli {
-
-static OT_DEFINE_ALIGNED_VAR(sCliConsoleRaw, sizeof(Console), uint64_t);
-
-extern "C" void otCliConsoleInit(otInstance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext)
-{
- Console::Initialize(aInstance, aCallback, aContext);
-}
-
-extern "C" void otCliConsoleInputLine(char *aBuf, uint16_t aBufLength)
-{
- Interpreter::GetInterpreter().ProcessLine(aBuf, aBufLength);
-}
-
-// Add stubs for simulation
-extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
-{
- OT_UNUSED_VARIABLE(aBuf);
- OT_UNUSED_VARIABLE(aBufLength);
-}
-
-extern "C" void otPlatUartSendDone(void)
-{
-}
-
-void Console::Initialize(otInstance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext)
-{
- Instance *instance = static_cast<Instance *>(aInstance);
-
- Interpreter::sInterpreter = new (&sCliConsoleRaw) Console(instance, aCallback, aContext);
-}
-
-Console::Console(Instance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext)
- : Interpreter(aInstance)
- , mCallback(aCallback)
- , mContext(aContext)
-{
-}
-
-int Interpreter::Output(const char *aBuf, uint16_t aBufLength)
-{
- return static_cast<Console *>(this)->Output(aBuf, aBufLength);
-}
-
-int Console::Output(const char *aBuf, uint16_t aBufLength)
-{
- return mCallback(aBuf, aBufLength, mContext);
-}
-
-} // namespace Cli
-} // namespace ot
-
-#endif // OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_CONSOLE
diff --git a/src/cli/cli_console.hpp b/src/cli/cli_console.hpp
deleted file mode 100644
index a197b45..0000000
--- a/src/cli/cli_console.hpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2016, 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 a CLI interpreter on the CONSOLE service.
- */
-
-#ifndef CLI_CONSOLE_HPP_
-#define CLI_CONSOLE_HPP_
-
-#include "cli_config.h"
-
-#include <openthread/cli.h>
-
-#include "cli/cli.hpp"
-
-namespace ot {
-namespace Cli {
-
-/**
- * This class implements the CLI interpreter on top of the CONSOLE platform abstraction.
- *
- */
-class Console : public Interpreter
-{
-public:
- /**
- * This method initializes the Console interpreter.
- *
- * @param[in] aInstance The OpenThread instance structure.
- * @param[in] aCallback A pointer to a callback method.
- * @param[in] aContext A pointer to a user context.
- *
- */
- static void Initialize(otInstance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext);
-
- /**
- * This method delivers raw characters to the client.
- *
- * @param[in] aBuf A pointer to a buffer.
- * @param[in] aBufLength Number of bytes in the buffer.
- *
- * @returns The number of bytes placed in the output queue.
- *
- */
- int Output(const char *aBuf, uint16_t aBufLength);
-
-private:
- explicit Console(Instance *aInstance, otCliConsoleOutputCallback aCallback, void *aContext);
-
- otCliConsoleOutputCallback mCallback;
- void * mContext;
-
- static Console *sConsole;
-
- friend class Interpreter;
-};
-
-} // namespace Cli
-} // namespace ot
-
-#endif // CLI_CONSOLE_HPP_
diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp
index d8331d2..ddbe2ff 100644
--- a/src/cli/cli_dataset.cpp
+++ b/src/cli/cli_dataset.cpp
@@ -38,6 +38,7 @@
#include <openthread/dataset.h>
#include <openthread/dataset_ftd.h>
+#include <openthread/dataset_updater.h>
#include "cli/cli.hpp"
#include "common/string.hpp"
@@ -910,5 +911,46 @@
return error;
}
+#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
+
+otError Dataset::ProcessUpdater(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputEnabledDisabledStatus(otDatasetUpdaterIsUpdateOngoing(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ if (strcmp(aArgs[0], "start") == 0)
+ {
+ error = otDatasetUpdaterRequestUpdate(mInterpreter.mInstance, &sDataset, &Dataset::HandleDatasetUpdater, this);
+ }
+ else if (strcmp(aArgs[0], "cancel") == 0)
+ {
+ otDatasetUpdaterCancelUpdate(mInterpreter.mInstance);
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+void Dataset::HandleDatasetUpdater(otError aError, void *aContext)
+{
+ static_cast<Dataset *>(aContext)->HandleDatasetUpdater(aError);
+}
+
+void Dataset::HandleDatasetUpdater(otError aError)
+{
+ mInterpreter.OutputLine("Dataset update complete: %s", otThreadErrorToString(aError));
+}
+
+#endif // OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
+
} // namespace Cli
} // namespace ot
diff --git a/src/cli/cli_dataset.hpp b/src/cli/cli_dataset.hpp
index f3f7e5d..a3c0837 100644
--- a/src/cli/cli_dataset.hpp
+++ b/src/cli/cli_dataset.hpp
@@ -99,6 +99,12 @@
otError ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[]);
otError ProcessSet(uint8_t aArgsLength, char *aArgs[]);
+#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
+ otError ProcessUpdater(uint8_t aArgsLength, char *aArgs[]);
+ static void HandleDatasetUpdater(otError aError, void *aContext);
+ void HandleDatasetUpdater(otError aError);
+#endif
+
static constexpr Command sCommands[] = {
{"active", &Dataset::ProcessActive},
{"activetimestamp", &Dataset::ProcessActiveTimestamp},
@@ -121,6 +127,9 @@
{"pskc", &Dataset::ProcessPskc},
{"securitypolicy", &Dataset::ProcessSecurityPolicy},
{"set", &Dataset::ProcessSet},
+#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
+ {"updater", &Dataset::ProcessUpdater},
+#endif
};
static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
diff --git a/src/cli/cli_srp_client.cpp b/src/cli/cli_srp_client.cpp
new file mode 100644
index 0000000..be3f403
--- /dev/null
+++ b/src/cli/cli_srp_client.cpp
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements a simple CLI for the SRP Client.
+ */
+
+#include "cli_srp_client.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+#include <string.h>
+
+#include "cli/cli.hpp"
+#include "utils/parse_cmdline.hpp"
+
+using ot::Utils::CmdLineParser::ParseAsBool;
+using ot::Utils::CmdLineParser::ParseAsHexString;
+using ot::Utils::CmdLineParser::ParseAsIp6Address;
+using ot::Utils::CmdLineParser::ParseAsUint16;
+using ot::Utils::CmdLineParser::ParseAsUint32;
+
+namespace ot {
+namespace Cli {
+
+constexpr SrpClient::Command SrpClient::sCommands[];
+
+template <uint16_t kDestSize> static otError CopyString(char (&aDestination)[kDestSize], const char *aSource)
+{
+ // Copies a string from `aSource` to `aDestination` (char array),
+ // verifying that the string fits in the destination array.
+
+ otError error = OT_ERROR_NONE;
+ size_t len = strlen(aSource);
+
+ VerifyOrExit(len + 1 <= kDestSize, error = OT_ERROR_INVALID_ARGS);
+ memcpy(aDestination, aSource, len + 1);
+
+exit:
+ return error;
+}
+
+SrpClient::SrpClient(Interpreter &aInterpreter)
+ : mInterpreter(aInterpreter)
+ , mCallbackEnabled(false)
+{
+ for (Service &service : mServicePool)
+ {
+ service.MarkAsNotInUse();
+ }
+
+ memset(mHostAddresses, 0, sizeof(mHostAddresses));
+
+ otSrpClientSetCallback(mInterpreter.mInstance, SrpClient::HandleCallback, this);
+}
+
+otError SrpClient::Process(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_INVALID_COMMAND;
+ const Command *command;
+
+ VerifyOrExit(aArgsLength != 0, IgnoreError(ProcessHelp(0, nullptr)));
+
+ command = Utils::LookupTable::Find(aArgs[0], sCommands);
+ VerifyOrExit(command != nullptr);
+
+ error = (this->*command->mHandler)(aArgsLength - 1, aArgs + 1);
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+otError SrpClient::ProcessAutoStart(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputEnabledDisabledStatus(otSrpClientIsAutoStartModeEnabled(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+
+ if (strcmp(aArgs[0], "enable") == 0)
+ {
+ otSrpClientEnableAutoStartMode(mInterpreter.mInstance, /* aCallback */ nullptr, /* aContext */ nullptr);
+ }
+ else if (strcmp(aArgs[0], "disable") == 0)
+ {
+ otSrpClientDisableAutoStartMode(mInterpreter.mInstance);
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_COMMAND;
+ }
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+otError SrpClient::ProcessCallback(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputEnabledDisabledStatus(mCallbackEnabled);
+ ExitNow();
+ }
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+
+ if (strcmp(aArgs[0], "enable") == 0)
+ {
+ mCallbackEnabled = true;
+ }
+ else if (strcmp(aArgs[0], "disable") == 0)
+ {
+ mCallbackEnabled = false;
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessHelp(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgsLength);
+ OT_UNUSED_VARIABLE(aArgs);
+
+ for (const Command &command : sCommands)
+ {
+ mInterpreter.OutputLine(command.mName);
+ }
+
+ return OT_ERROR_NONE;
+}
+
+otError SrpClient::ProcessHost(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+ OutputHostInfo(0, *otSrpClientGetHostInfo(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ if (strcmp(aArgs[0], "name") == 0)
+ {
+ if (aArgsLength == 1)
+ {
+ const char *name = otSrpClientGetHostInfo(mInterpreter.mInstance)->mName;
+ mInterpreter.OutputLine("%s", (name != nullptr) ? name : "(null)");
+ }
+ else
+ {
+ VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+ SuccessOrExit(error = CopyString(mHostName, aArgs[1]));
+ error = otSrpClientSetHostName(mInterpreter.mInstance, mHostName);
+ }
+ }
+ else if (strcmp(aArgs[0], "state") == 0)
+ {
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ mInterpreter.OutputLine("%s",
+ otSrpClientItemStateToString(otSrpClientGetHostInfo(mInterpreter.mInstance)->mState));
+ }
+ else if (strcmp(aArgs[0], "address") == 0)
+ {
+ if (aArgsLength == 1)
+ {
+ const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(mInterpreter.mInstance);
+
+ for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
+ {
+ mInterpreter.OutputIp6Address(hostInfo->mAddresses[index]);
+ mInterpreter.OutputLine("");
+ }
+ }
+ else
+ {
+ uint8_t numAddresses;
+ otIp6Address addresses[kMaxHostAddresses];
+
+ numAddresses = 0;
+ memset(addresses, 0, sizeof(addresses));
+
+ while (aArgsLength > 1)
+ {
+ VerifyOrExit(numAddresses < kMaxHostAddresses, error = OT_ERROR_NO_BUFS);
+ aArgsLength--;
+ aArgs++;
+ SuccessOrExit(error = ParseAsIp6Address(aArgs[0], addresses[numAddresses++]));
+ }
+
+ VerifyOrExit(numAddresses > 0, error = OT_ERROR_INVALID_ARGS);
+ memcpy(mHostAddresses, addresses, sizeof(addresses));
+
+ error = otSrpClientSetHostAddresses(mInterpreter.mInstance, mHostAddresses, numAddresses);
+ }
+ }
+ else if (strcmp(aArgs[0], "remove") == 0)
+ {
+ bool removeKeyLease = false;
+
+ if (aArgsLength > 1)
+ {
+ VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+ SuccessOrExit(error = ParseAsBool(aArgs[1], removeKeyLease));
+ }
+
+ error = otSrpClientRemoveHostAndServices(mInterpreter.mInstance, removeKeyLease);
+ }
+ else if (strcmp(aArgs[0], "clear") == 0)
+ {
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ otSrpClientClearHostAndServices(mInterpreter.mInstance);
+
+ for (Service &poolEntry : mServicePool)
+ {
+ poolEntry.MarkAsNotInUse();
+ }
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_COMMAND;
+ }
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessLeaseInterval(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ uint32_t interval;
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputLine("%u", otSrpClientGetLeaseInterval(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ SuccessOrExit(error = ParseAsUint32(aArgs[0], interval));
+ otSrpClientSetLeaseInterval(mInterpreter.mInstance, interval);
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessKeyLeaseInterval(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ uint32_t interval;
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputLine("%u", otSrpClientGetKeyLeaseInterval(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ SuccessOrExit(error = ParseAsUint32(aArgs[0], interval));
+ otSrpClientSetKeyLeaseInterval(mInterpreter.mInstance, interval);
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessServer(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ const otSockAddr *serverSockAddr = otSrpClientGetServerAddress(mInterpreter.mInstance);
+
+ if (aArgsLength == 0)
+ {
+ mInterpreter.OutputFormat("[");
+ mInterpreter.OutputIp6Address(serverSockAddr->mAddress);
+ mInterpreter.OutputLine("]:%u", serverSockAddr->mPort);
+ ExitNow();
+ }
+
+ VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+
+ if (strcmp(aArgs[0], "address") == 0)
+ {
+ mInterpreter.OutputIp6Address(serverSockAddr->mAddress);
+ mInterpreter.OutputLine("");
+ }
+ else if (strcmp(aArgs[0], "port") == 0)
+ {
+ mInterpreter.OutputLine("%u", serverSockAddr->mPort);
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_COMMAND;
+ }
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessService(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength == 0)
+ {
+ OutputServiceList(0, otSrpClientGetServices(mInterpreter.mInstance));
+ ExitNow();
+ }
+
+ if (strcmp(aArgs[0], "add") == 0)
+ {
+ // `add` <instance-name> <service-name> <port> [priority] [weight] [txt]
+
+ Service *entry = nullptr;
+
+ VerifyOrExit(4 <= aArgsLength && aArgsLength <= 7, error = OT_ERROR_INVALID_ARGS);
+
+ for (Service &poolEntry : mServicePool)
+ {
+ if (!poolEntry.IsInUse())
+ {
+ entry = &poolEntry;
+ break;
+ }
+ }
+
+ VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+
+ memset(&entry->mService, 0, sizeof(entry->mService));
+
+ SuccessOrExit(error = CopyString(entry->mInstanceName, aArgs[1]));
+ entry->mService.mInstanceName = entry->mInstanceName;
+
+ SuccessOrExit(error = CopyString(entry->mServiceName, aArgs[2]));
+ entry->mService.mName = entry->mServiceName;
+
+ SuccessOrExit(error = ParseAsUint16(aArgs[3], entry->mService.mPort));
+
+ if (aArgsLength >= 5)
+ {
+ SuccessOrExit(error = ParseAsUint16(aArgs[4], entry->mService.mPriority));
+ }
+
+ if (aArgsLength >= 6)
+ {
+ SuccessOrExit(error = ParseAsUint16(aArgs[5], entry->mService.mWeight));
+ }
+
+ if (aArgsLength >= 7)
+ {
+ entry->mService.mNumTxtEntries = 1;
+ entry->mService.mTxtEntries = &entry->mTxtEntry;
+ entry->mTxtEntry.mKey = nullptr; // Treat `mValue` as an already encoded TXT-DATA
+ entry->mTxtEntry.mValue = entry->mTxtBuffer;
+ entry->mTxtEntry.mValueLength = sizeof(entry->mTxtBuffer);
+
+ SuccessOrExit(error = ParseAsHexString(aArgs[6], entry->mTxtEntry.mValueLength, entry->mTxtBuffer));
+ }
+
+ error = otSrpClientAddService(mInterpreter.mInstance, &entry->mService);
+
+ if (error != OT_ERROR_NONE)
+ {
+ entry->MarkAsNotInUse();
+ }
+ }
+ else if (strcmp(aArgs[0], "remove") == 0)
+ {
+ // `remove` <instance-name> <service-name>
+
+ Service *entry = nullptr;
+
+ VerifyOrExit(aArgsLength == 3, error = OT_ERROR_INVALID_ARGS);
+
+ for (Service &poolEntry : mServicePool)
+ {
+ if (poolEntry.IsInUse() && (strcmp(aArgs[1], poolEntry.mInstanceName) == 0) &&
+ (strcmp(aArgs[2], poolEntry.mServiceName) == 0))
+ {
+ entry = &poolEntry;
+ break;
+ }
+ }
+
+ VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
+
+ error = otSrpClientRemoveService(mInterpreter.mInstance, &entry->mService);
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_COMMAND;
+ }
+
+exit:
+ return error;
+}
+
+void SrpClient::OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &aHostInfo)
+{
+ mInterpreter.OutputFormat(aIndentSize, "name:");
+
+ if (aHostInfo.mName != nullptr)
+ {
+ mInterpreter.OutputFormat("\"%s\"", aHostInfo.mName);
+ }
+ else
+ {
+ mInterpreter.OutputFormat("(null)");
+ }
+
+ mInterpreter.OutputFormat(", state:%s, addrs:[", otSrpClientItemStateToString(aHostInfo.mState));
+
+ for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
+ {
+ if (index > 0)
+ {
+ mInterpreter.OutputFormat(", ");
+ }
+
+ mInterpreter.OutputIp6Address(aHostInfo.mAddresses[index]);
+ }
+
+ mInterpreter.OutputLine("]");
+}
+
+void SrpClient::OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices)
+{
+ while (aServices != nullptr)
+ {
+ OutputService(aIndentSize, *aServices);
+ aServices = aServices->mNext;
+ }
+}
+
+void SrpClient::OutputService(uint8_t aIndentSize, const otSrpClientService &aService)
+{
+ mInterpreter.OutputLine(aIndentSize, "instance:\"%s\", name:\"%s\", state:%s, port:%d, priority:%d, weight:%d",
+ aService.mInstanceName, aService.mName, otSrpClientItemStateToString(aService.mState),
+ aService.mPort, aService.mPriority, aService.mWeight);
+}
+
+otError SrpClient::ProcessStart(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otSockAddr serverSockAddr;
+
+ VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+
+ SuccessOrExit(error = ParseAsIp6Address(aArgs[0], serverSockAddr.mAddress));
+ SuccessOrExit(error = ParseAsUint16(aArgs[1], serverSockAddr.mPort));
+
+ error = otSrpClientStart(mInterpreter.mInstance, &serverSockAddr);
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessState(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgsLength == 0, error = OT_ERROR_INVALID_ARGS);
+
+ mInterpreter.OutputEnabledDisabledStatus(otSrpClientIsRunning(mInterpreter.mInstance));
+
+exit:
+ return error;
+}
+
+otError SrpClient::ProcessStop(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aArgsLength == 0, error = OT_ERROR_INVALID_ARGS);
+ otSrpClientStop(mInterpreter.mInstance);
+
+exit:
+ return error;
+}
+
+void SrpClient::HandleCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices,
+ void * aContext)
+{
+ static_cast<SrpClient *>(aContext)->HandleCallback(aError, aHostInfo, aServices, aRemovedServices);
+}
+
+void SrpClient::HandleCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices)
+{
+ otSrpClientService *next;
+
+ if (mCallbackEnabled)
+ {
+ mInterpreter.OutputLine("SRP client callback - error:%s", otThreadErrorToString(aError));
+ mInterpreter.OutputLine("Host info:");
+ OutputHostInfo(kIndentSize, *aHostInfo);
+
+ mInterpreter.OutputLine("Service list:");
+ OutputServiceList(kIndentSize, aServices);
+
+ if (aRemovedServices != nullptr)
+ {
+ mInterpreter.OutputLine("Removed service list:");
+ OutputServiceList(kIndentSize, aRemovedServices);
+ }
+ }
+
+ // Go through removed services and mark the corresponding entry in
+ // `mServicePool` as "not in use".
+
+ for (const otSrpClientService *service = aRemovedServices; service != nullptr; service = next)
+ {
+ next = service->mNext;
+
+ for (Service &poolEntry : mServicePool)
+ {
+ if (service == &poolEntry.mService)
+ {
+ poolEntry.MarkAsNotInUse();
+ break;
+ }
+ }
+ }
+}
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
diff --git a/src/cli/cli_srp_client.hpp b/src/cli/cli_srp_client.hpp
new file mode 100644
index 0000000..ef541c1
--- /dev/null
+++ b/src/cli/cli_srp_client.hpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file contains definitions for a simple CLI to control SRP Client.
+ */
+
+#ifndef CLI_SRP_CLIENT_HPP_
+#define CLI_SRP_CLIENT_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/srp_client.h>
+
+#include "cli/cli_config.h"
+#include "utils/lookup_table.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+namespace ot {
+namespace Cli {
+
+class Interpreter;
+
+/**
+ * This class implements the SRP Client CLI interpreter.
+ *
+ */
+class SrpClient
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param[in] aInterpreter The CLI interpreter.
+ *
+ */
+ explicit SrpClient(Interpreter &aInterpreter);
+
+ /**
+ * This method interprets a list of CLI arguments.
+ *
+ * @param[in] aArgsLength The number of elements in @p aArgs.
+ * @param[in] aArgs A pointer to an array of command line arguments.
+ *
+ */
+ otError Process(uint8_t aArgsLength, char *aArgs[]);
+
+private:
+ enum : uint8_t
+ {
+ kMaxServices = OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES,
+ kMaxHostAddresses = OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES,
+ kNameSize = 64,
+ kTxtSize = 255,
+ kIndentSize = 4,
+ };
+
+ struct Service
+ {
+ void MarkAsNotInUse(void) { mService.mNext = &mService; }
+ bool IsInUse(void) const { return (mService.mNext != &mService); }
+
+ otSrpClientService mService;
+ otDnsTxtEntry mTxtEntry;
+ char mInstanceName[kNameSize];
+ char mServiceName[kNameSize];
+ uint8_t mTxtBuffer[kTxtSize];
+ };
+
+ struct Command
+ {
+ const char *mName;
+ otError (SrpClient::*mHandler)(uint8_t aArgsLength, char *aArgs[]);
+ };
+
+ otError ProcessAutoStart(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessCallback(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessHost(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessLeaseInterval(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessKeyLeaseInterval(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessServer(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessService(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessStart(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessState(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessStop(uint8_t aArgsLength, char *aArgs[]);
+
+ void OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &aHostInfo);
+ void OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices);
+ void OutputService(uint8_t aIndentSize, const otSrpClientService &aService);
+
+ static void HandleCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices,
+ void * aContext);
+ void HandleCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices);
+
+ static constexpr Command sCommands[] = {
+ {"autostart", &SrpClient::ProcessAutoStart},
+ {"callback", &SrpClient::ProcessCallback},
+ {"help", &SrpClient::ProcessHelp},
+ {"host", &SrpClient::ProcessHost},
+ {"keyleaseinterval", &SrpClient::ProcessKeyLeaseInterval},
+ {"leaseinterval", &SrpClient::ProcessLeaseInterval},
+ {"server", &SrpClient::ProcessServer},
+ {"service", &SrpClient::ProcessService},
+ {"start", &SrpClient::ProcessStart},
+ {"state", &SrpClient::ProcessState},
+ {"stop", &SrpClient::ProcessStop},
+ };
+
+ static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+
+ Interpreter &mInterpreter;
+ bool mCallbackEnabled;
+ char mHostName[kNameSize];
+ otIp6Address mHostAddresses[kMaxHostAddresses];
+ Service mServicePool[kMaxServices];
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+#endif // CLI_SRP_CLIENT_HPP_
diff --git a/src/cli/cli_srp_server.cpp b/src/cli/cli_srp_server.cpp
new file mode 100644
index 0000000..3a5266e
--- /dev/null
+++ b/src/cli/cli_srp_server.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements a simple CLI for the SRP server.
+ */
+
+#include "cli_srp_server.hpp"
+
+#include <inttypes.h>
+
+#include "cli/cli.hpp"
+#include "common/string.hpp"
+#include "utils/parse_cmdline.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+namespace ot {
+namespace Cli {
+
+constexpr SrpServer::Command SrpServer::sCommands[];
+
+otError SrpServer::Process(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_INVALID_COMMAND;
+ const Command *command;
+
+ VerifyOrExit(aArgsLength != 0, IgnoreError(ProcessHelp(0, nullptr)));
+
+ command = Utils::LookupTable::Find(aArgs[0], sCommands);
+ VerifyOrExit(command != nullptr);
+
+ error = (this->*command->mHandler)(aArgsLength, aArgs);
+
+exit:
+ return error;
+}
+
+otError SrpServer::ProcessDomain(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+
+ if (aArgsLength > 1)
+ {
+ SuccessOrExit(error = otSrpServerSetDomain(mInterpreter.mInstance, aArgs[1]));
+ }
+ else
+ {
+ mInterpreter.OutputLine("%s", otSrpServerGetDomain(mInterpreter.mInstance));
+ }
+
+exit:
+ return error;
+}
+
+otError SrpServer::ProcessEnable(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgsLength);
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otSrpServerSetEnabled(mInterpreter.mInstance, /* aEnabled */ true);
+
+ return OT_ERROR_NONE;
+}
+
+otError SrpServer::ProcessDisable(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgsLength);
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otSrpServerSetEnabled(mInterpreter.mInstance, /* aEnabled */ false);
+
+ return OT_ERROR_NONE;
+}
+
+otError SrpServer::ProcessLease(uint8_t aArgsLength, char *aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ uint32_t minLease;
+ uint32_t maxLease;
+ uint32_t minKeyLease;
+ uint32_t maxKeyLease;
+
+ VerifyOrExit(aArgsLength == 5, error = OT_ERROR_INVALID_ARGS);
+ SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint32(aArgs[1], minLease));
+ SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint32(aArgs[2], maxLease));
+ SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint32(aArgs[3], minKeyLease));
+ SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint32(aArgs[4], maxKeyLease));
+
+ error = otSrpServerSetLeaseRange(mInterpreter.mInstance, minLease, maxLease, minKeyLease, maxKeyLease);
+
+exit:
+ return error;
+}
+
+otError SrpServer::ProcessHost(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otError error = OT_ERROR_NONE;
+ const otSrpServerHost *host;
+
+ VerifyOrExit(aArgsLength <= 1, error = OT_ERROR_INVALID_ARGS);
+
+ host = nullptr;
+ while ((host = otSrpServerGetNextHost(mInterpreter.mInstance, host)) != nullptr)
+ {
+ const otIp6Address *addresses;
+ uint8_t addressesNum;
+ bool isDeleted = otSrpServerHostIsDeleted(host);
+
+ mInterpreter.OutputLine("%s", otSrpServerHostGetFullName(host));
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "deleted: %s", isDeleted ? "true" : "false");
+ if (isDeleted)
+ {
+ continue;
+ }
+
+ mInterpreter.OutputSpaces(Interpreter::kIndentSize);
+ mInterpreter.OutputFormat("addresses: [");
+
+ addresses = otSrpServerHostGetAddresses(host, &addressesNum);
+
+ for (uint8_t i = 0; i < addressesNum; ++i)
+ {
+ mInterpreter.OutputIp6Address(addresses[i]);
+ if (i < addressesNum - 1)
+ {
+ mInterpreter.OutputFormat(", ");
+ }
+ }
+
+ mInterpreter.OutputFormat("]\r\n");
+ }
+
+exit:
+ return error;
+}
+
+void SrpServer::OutputHostAddresses(const otSrpServerHost *aHost)
+{
+ const otIp6Address *addresses;
+ uint8_t addressesNum;
+
+ addresses = otSrpServerHostGetAddresses(aHost, &addressesNum);
+
+ mInterpreter.OutputFormat("[");
+ for (uint8_t i = 0; i < addressesNum; ++i)
+ {
+ if (i != 0)
+ {
+ mInterpreter.OutputFormat(", ");
+ }
+
+ mInterpreter.OutputIp6Address(addresses[i]);
+ }
+ mInterpreter.OutputFormat("]");
+}
+
+otError SrpServer::ProcessService(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgs);
+
+ otError error = OT_ERROR_NONE;
+ const otSrpServerHost *host;
+
+ VerifyOrExit(aArgsLength <= 1, error = OT_ERROR_INVALID_ARGS);
+
+ host = nullptr;
+ while ((host = otSrpServerGetNextHost(mInterpreter.mInstance, host)) != nullptr)
+ {
+ const otSrpServerService *service = nullptr;
+
+ while ((service = otSrpServerHostGetNextService(host, service)) != nullptr)
+ {
+ bool isDeleted = otSrpServerServiceIsDeleted(service);
+ const uint8_t *txtData;
+ uint16_t txtDataLength;
+
+ mInterpreter.OutputLine("%s", otSrpServerServiceGetFullName(service));
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "deleted: %s", isDeleted ? "true" : "false");
+ if (isDeleted)
+ {
+ continue;
+ }
+
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "port: %hu", otSrpServerServiceGetPort(service));
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "priority: %hu", otSrpServerServiceGetPriority(service));
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "weight: %hu", otSrpServerServiceGetWeight(service));
+
+ txtData = otSrpServerServiceGetTxtData(service, &txtDataLength);
+ mInterpreter.OutputFormat(Interpreter::kIndentSize, "TXT: ");
+ mInterpreter.OutputDnsTxtData(txtData, txtDataLength);
+ mInterpreter.OutputLine("");
+
+ mInterpreter.OutputLine(Interpreter::kIndentSize, "host: %s", otSrpServerHostGetFullName(host));
+
+ mInterpreter.OutputFormat(Interpreter::kIndentSize, "addresses: ");
+ OutputHostAddresses(host);
+ mInterpreter.OutputLine("");
+ }
+ }
+
+exit:
+ return error;
+}
+
+otError SrpServer::ProcessHelp(uint8_t aArgsLength, char *aArgs[])
+{
+ OT_UNUSED_VARIABLE(aArgsLength);
+ OT_UNUSED_VARIABLE(aArgs);
+
+ for (const Command &command : sCommands)
+ {
+ mInterpreter.OutputLine(command.mName);
+ }
+
+ return OT_ERROR_NONE;
+}
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
diff --git a/src/cli/cli_srp_server.hpp b/src/cli/cli_srp_server.hpp
new file mode 100644
index 0000000..a619ee8
--- /dev/null
+++ b/src/cli/cli_srp_server.hpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file contains definitions for a simple CLI to control the SRP server.
+ */
+
+#ifndef CLI_SRP_SERVER_HPP_
+#define CLI_SRP_SERVER_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/srp_server.h>
+
+#include "utils/lookup_table.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+namespace ot {
+namespace Cli {
+
+class Interpreter;
+
+/**
+ * This class implements the SRP Server CLI interpreter.
+ *
+ */
+class SrpServer
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param[in] aInterpreter The CLI interpreter.
+ *
+ */
+ explicit SrpServer(Interpreter &aInterpreter)
+ : mInterpreter(aInterpreter)
+ {
+ }
+
+ /**
+ * This method interprets a list of CLI arguments.
+ *
+ * @param[in] aArgsLength The number of elements in @p aArgs.
+ * @param[in] aArgs A pointer to an array of command line arguments.
+ *
+ * @retval OT_ERROR_NONE Successfully executed the CLI command.
+ * @retval ... Failed to execute the CLI command.
+ *
+ */
+ otError Process(uint8_t aArgsLength, char *aArgs[]);
+
+private:
+ struct Command
+ {
+ const char *mName;
+ otError (SrpServer::*mHandler)(uint8_t aArgsLength, char *aArgs[]);
+ };
+
+ otError ProcessDomain(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessEnable(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessDisable(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessLease(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessHost(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessService(uint8_t aArgsLength, char *aArgs[]);
+ otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
+
+ void OutputHostAddresses(const otSrpServerHost *aHost);
+
+ static constexpr Command sCommands[] = {
+ {"disable", &SrpServer::ProcessDisable}, {"domain", &SrpServer::ProcessDomain},
+ {"enable", &SrpServer::ProcessEnable}, {"help", &SrpServer::ProcessHelp},
+ {"host", &SrpServer::ProcessHost}, {"lease", &SrpServer::ProcessLease},
+ {"service", &SrpServer::ProcessService},
+ };
+
+ static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
+
+ Interpreter &mInterpreter;
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+#endif // CLI_SRP_SERVER_HPP_
diff --git a/src/cli/cli_uart.cpp b/src/cli/cli_uart.cpp
deleted file mode 100644
index da408b0..0000000
--- a/src/cli/cli_uart.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (c) 2016, 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 on the UART service.
- */
-
-#include "cli_uart.hpp"
-
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_UART
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if OPENTHREAD_POSIX
-#include <signal.h>
-#include <sys/types.h>
-#endif
-
-#include <openthread/cli.h>
-#include <openthread/platform/logging.h>
-#include <openthread/platform/uart.h>
-#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART
-#include <openthread/platform/debug_uart.h>
-#endif
-
-#include "cli/cli.hpp"
-#include "common/code_utils.hpp"
-#include "common/encoding.hpp"
-#include "common/logging.hpp"
-#include "common/new.hpp"
-#include "common/tasklet.hpp"
-
-#ifdef OT_CLI_UART_LOCK_HDR_FILE
-
-#include OT_CLI_UART_LOCK_HDR_FILE
-
-#else
-
-/**
- * Macro to acquire an exclusive lock of uart cli output
- * Default implementation does nothing
- *
- */
-#ifndef OT_CLI_UART_OUTPUT_LOCK
-#define OT_CLI_UART_OUTPUT_LOCK() \
- do \
- { \
- } while (0)
-#endif
-
-/**
- * Macro to release the exclusive lock of uart cli output
- * Default implementation does nothing
- *
- */
-#ifndef OT_CLI_UART_OUTPUT_UNLOCK
-#define OT_CLI_UART_OUTPUT_UNLOCK() \
- do \
- { \
- } while (0)
-#endif
-
-#endif // OT_CLI_UART_LOCK_HDR_FILE
-
-#if OPENTHREAD_CONFIG_DIAG_ENABLE
-static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <= OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE,
- "diag output buffer should be smaller than CLI UART tx buffer");
-static_assert(OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE <= OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE,
- "diag command line should be smaller than CLI UART rx buffer");
-#endif
-
-static_assert(OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH <= OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE,
- "command line should be should be smaller than CLI rx buffer");
-
-namespace ot {
-namespace Cli {
-
-static OT_DEFINE_ALIGNED_VAR(sCliUartRaw, sizeof(Uart), uint64_t);
-
-void Uart::Initialize(otInstance *aInstance)
-{
- Instance *instance = static_cast<Instance *>(aInstance);
- Interpreter::sInterpreter = new (&sCliUartRaw) Uart(instance);
-}
-
-Uart::Uart(Instance *aInstance)
- : Interpreter(aInstance)
-{
- mRxLength = 0;
- mTxHead = 0;
- mTxLength = 0;
- mSendLength = 0;
-
- IgnoreError(otPlatUartEnable());
-}
-
-void Uart::ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength)
-{
-#if !OPENTHREAD_CONFIG_UART_CLI_RAW
- static const char sEraseString[] = {'\b', ' ', '\b'};
- static const char CRNL[] = {'\r', '\n'};
-#endif
- static const char sCommandPrompt[] = {'>', ' '};
- const uint8_t * end;
-
- end = aBuf + aBufLength;
-
- for (; aBuf < end; aBuf++)
- {
- switch (*aBuf)
- {
- case '\r':
- case '\n':
-#if !OPENTHREAD_CONFIG_UART_CLI_RAW
- Output(CRNL, sizeof(CRNL));
-#endif
- if (mRxLength > 0)
- {
- mRxBuffer[mRxLength] = '\0';
- IgnoreError(ProcessCommand());
- }
-
- Output(sCommandPrompt, sizeof(sCommandPrompt));
-
- break;
-
-#if !OPENTHREAD_CONFIG_UART_CLI_RAW
-#if OPENTHREAD_POSIX
-
- case 0x03: // ASCII for Ctrl-C
- kill(0, SIGINT);
- break;
-
- case 0x04: // ASCII for Ctrl-D
- exit(EXIT_SUCCESS);
- break;
-#endif
-
- case '\b':
- case 127:
- if (mRxLength > 0)
- {
- Output(sEraseString, sizeof(sEraseString));
- mRxBuffer[--mRxLength] = '\0';
- }
-
- break;
-#endif // !OPENTHREAD_CONFIG_UART_CLI_RAW
-
- default:
- if (mRxLength < kRxBufferSize - 1)
- {
-#if !OPENTHREAD_CONFIG_UART_CLI_RAW
- Output(reinterpret_cast<const char *>(aBuf), 1);
-#endif
- mRxBuffer[mRxLength++] = static_cast<char>(*aBuf);
- }
-
- break;
- }
- }
-}
-
-otError Uart::ProcessCommand(void)
-{
- otError error = OT_ERROR_NONE;
-
- while (mRxBuffer[mRxLength - 1] == '\n' || mRxBuffer[mRxLength - 1] == '\r')
- {
- mRxBuffer[--mRxLength] = '\0';
- }
-
-#if OPENTHREAD_CONFIG_LOG_OUTPUT != OPENTHREAD_CONFIG_LOG_OUTPUT_NONE
- /*
- * Note this is here for this reason:
- *
- * TEXT (command) input ... in a test automation script occurs
- * rapidly and often without gaps between the command and the
- * terminal CR
- *
- * In contrast as a human is typing there is a delay between the
- * last character of a command and the terminal CR which executes
- * a command.
- *
- * During that human induced delay a tasklet may be scheduled and
- * the LOG becomes confusing and it is hard to determine when
- * something happened. Which happened first? the command-CR or
- * the tasklet.
- *
- * Yes, while rare it is a race condition that is hard to debug.
- *
- * Thus this is here to affirmatively LOG exactly when the CLI
- * command is being executed.
- */
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- /* TODO: how exactly do we get the instance here? */
-#else
- otLogInfoCli("execute command: %s", mRxBuffer);
-#endif
-#endif
- if (mRxLength > 0)
- {
- ProcessLine(mRxBuffer, mRxLength);
- }
-
- mRxLength = 0;
-
- return error;
-}
-
-int Interpreter::Output(const char *aBuf, uint16_t aBufLength)
-{
- return static_cast<Uart *>(this)->Output(aBuf, aBufLength);
-}
-
-int Uart::Output(const char *aBuf, uint16_t aBufLength)
-{
- OT_CLI_UART_OUTPUT_LOCK();
- uint16_t sent = 0;
-
- while (aBufLength > 0)
- {
- uint16_t remaining = kTxBufferSize - mTxLength;
- uint16_t tail;
- uint16_t sendLength = aBufLength;
-
- if (sendLength > remaining)
- {
- sendLength = remaining;
- }
-
- for (uint16_t i = 0; i < sendLength; i++)
- {
- tail = (mTxHead + mTxLength) % kTxBufferSize;
- mTxBuffer[tail] = *aBuf++;
- aBufLength--;
- mTxLength++;
- }
-
- Send();
-
- sent += sendLength;
-
- if (aBufLength > 0)
- {
- // More to send, so flush what's waiting now
- otError err = otPlatUartFlush();
-
- if (err == OT_ERROR_NONE)
- {
- // Flush successful, reset the pointers
- SendDoneTask();
- }
- else
- {
- // Flush did not succeed, so abort here.
- break;
- }
- }
- }
-
- OT_CLI_UART_OUTPUT_UNLOCK();
-
- return sent;
-}
-
-void Uart::Send(void)
-{
- VerifyOrExit(mSendLength == 0);
-
- if (mTxLength > kTxBufferSize - mTxHead)
- {
- mSendLength = kTxBufferSize - mTxHead;
- }
- else
- {
- mSendLength = mTxLength;
- }
-
- if (mSendLength > 0)
- {
-#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART
- /* duplicate the output to the debug uart */
- otPlatDebugUart_write_bytes(reinterpret_cast<uint8_t *>(mTxBuffer + mTxHead), mSendLength);
-#endif
- IgnoreError(otPlatUartSend(reinterpret_cast<uint8_t *>(mTxBuffer + mTxHead), mSendLength));
- }
-
-exit:
- return;
-}
-
-void Uart::SendDoneTask(void)
-{
- mTxHead = (mTxHead + mSendLength) % kTxBufferSize;
- mTxLength -= mSendLength;
- mSendLength = 0;
-
- Send();
-}
-
-extern "C" void otCliUartInit(otInstance *aInstance)
-{
- Uart::Initialize(aInstance);
-}
-
-extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
-{
- static_cast<Uart &>(Interpreter::GetInterpreter()).ReceiveTask(aBuf, aBufLength);
-}
-
-extern "C" void otPlatUartSendDone(void)
-{
- static_cast<Uart &>(Interpreter::GetInterpreter()).SendDoneTask();
-}
-
-} // namespace Cli
-} // namespace ot
-
-#endif // OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_UART
diff --git a/src/cli/cli_uart.hpp b/src/cli/cli_uart.hpp
deleted file mode 100644
index 33164d5..0000000
--- a/src/cli/cli_uart.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2016, 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 a CLI interpreter on the UART service.
- */
-
-#ifndef CLI_UART_HPP_
-#define CLI_UART_HPP_
-
-#include "openthread-core-config.h"
-
-#include "cli/cli.hpp"
-#include "common/instance.hpp"
-#include "common/tasklet.hpp"
-
-namespace ot {
-namespace Cli {
-
-/**
- * This class implements the CLI interpreter on top of the UART platform abstraction.
- *
- */
-class Uart : public Interpreter
-{
-public:
- static void Initialize(otInstance *aInstance);
-
- /**
- * This method delivers raw characters to the client.
- *
- * @param[in] aBuf A pointer to a buffer.
- * @param[in] aBufLength Number of bytes in the buffer.
- *
- * @returns The number of bytes placed in the output queue.
- *
- */
- int Output(const char *aBuf, uint16_t aBufLength);
-
- void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength);
- void SendDoneTask(void);
-
-private:
- /**
- * Constructor
- *
- * @param[in] aInstance The OpenThread instance structure.
- *
- */
- explicit Uart(Instance *aInstance);
-
- enum
- {
- kRxBufferSize = OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE,
- kTxBufferSize = OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE,
- };
-
- otError ProcessCommand(void);
- void Send(void);
-
- char mRxBuffer[kRxBufferSize];
- uint16_t mRxLength;
-
- char mTxBuffer[kTxBufferSize];
- uint16_t mTxHead;
- uint16_t mTxLength;
-
- uint16_t mSendLength;
- static Uart *sUart;
-
- friend class Interpreter;
-};
-
-} // namespace Cli
-} // namespace ot
-
-#endif // CLI_UART_HPP_
diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp
index 501d29a..136df36 100644
--- a/src/cli/cli_udp.cpp
+++ b/src/cli/cli_udp.cpp
@@ -214,7 +214,7 @@
if (aArgsLength == 0)
{
- mInterpreter.OutputLine(mLinkSecurityEnabled ? "Enabled" : "Disabled");
+ mInterpreter.OutputEnabledDisabledStatus(mLinkSecurityEnabled);
}
else if (strcmp(aArgs[0], "enable") == 0)
{
diff --git a/src/cli/ftd.cmake b/src/cli/ftd.cmake
index e0385bb..3d50d0c 100644
--- a/src/cli/ftd.cmake
+++ b/src/cli/ftd.cmake
@@ -38,8 +38,6 @@
target_compile_definitions(openthread-cli-ftd
PRIVATE
OPENTHREAD_FTD=1
- PUBLIC
- "OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_${OT_CLI_TRANSPORT}"
)
target_compile_options(openthread-cli-ftd PRIVATE
diff --git a/src/cli/mtd.cmake b/src/cli/mtd.cmake
index dabb8b1..9c06fb3 100644
--- a/src/cli/mtd.cmake
+++ b/src/cli/mtd.cmake
@@ -38,8 +38,6 @@
target_compile_definitions(openthread-cli-mtd
PRIVATE
OPENTHREAD_MTD=1
- PUBLIC
- "OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_${OT_CLI_TRANSPORT}"
)
target_compile_options(openthread-cli-mtd PRIVATE
diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn
index 7d0aa52..42cf45f 100644
--- a/src/core/BUILD.gn
+++ b/src/core/BUILD.gn
@@ -74,6 +74,10 @@
defines += [ "OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE=1" ]
}
+ if (openthread_config_border_routing_enable) {
+ defines += [ "OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1" ]
+ }
+
if (openthread_external_mbedtls != "") {
defines += [ "OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS=0" ]
} else if (!openthread_config_enable_builtin_mbedtls_management) {
@@ -128,6 +132,10 @@
defines += [ "OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE=1" ]
}
+ if (openthread_config_dnssd_server_enable) {
+ defines += [ "OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE=1" ]
+ }
+
if (openthread_config_ecdsa_enable) {
defines += [ "OPENTHREAD_CONFIG_ECDSA_ENABLE=1" ]
}
@@ -220,6 +228,18 @@
defines += [ "OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE=1" ]
}
+ if (openthread_config_srp_client_enable) {
+ defines += [ "OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE=1" ]
+ }
+
+ if (openthread_config_srp_server_enable) {
+ defines += [ "OPENTHREAD_CONFIG_SRP_SERVER_ENABLE=1" ]
+ }
+
+ if (openthread_config_ping_sender) {
+ defines += [ "OPENTHREAD_CONFIG_PING_SENDER_ENABLE=1" ]
+ }
+
if (openthread_config_time_sync_enable) {
defines += [ "OPENTHREAD_CONFIG_TIME_SYNC_ENABLE=1" ]
}
@@ -229,28 +249,9 @@
}
if (openthread_config_full_logs) {
- defines += [
- "OPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG",
- "OPENTHREAD_CONFIG_LOG_API=1",
- "OPENTHREAD_CONFIG_LOG_ARP=1",
- "OPENTHREAD_CONFIG_LOG_BBR=1",
- "OPENTHREAD_CONFIG_LOG_CLI=1",
- "OPENTHREAD_CONFIG_LOG_COAP=1",
- "OPENTHREAD_CONFIG_LOG_DUA=1",
- "OPENTHREAD_CONFIG_LOG_ICMP=1",
- "OPENTHREAD_CONFIG_LOG_IP6=1",
- "OPENTHREAD_CONFIG_LOG_MAC=1",
- "OPENTHREAD_CONFIG_LOG_MEM=1",
- "OPENTHREAD_CONFIG_LOG_MESHCOP=1",
- "OPENTHREAD_CONFIG_LOG_MLE=1",
- "OPENTHREAD_CONFIG_LOG_MLR=1",
- "OPENTHREAD_CONFIG_LOG_NETDATA=1",
- "OPENTHREAD_CONFIG_LOG_NETDIAG=1",
- "OPENTHREAD_CONFIG_LOG_PKT_DUMP=1",
- "OPENTHREAD_CONFIG_LOG_PLATFORM=1",
- "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1",
- "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1",
- ]
+ defines += [ "OPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG" ]
+ defines += [ "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1" ]
+ defines += [ "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1" ]
}
if (openthread_config_otns_enable) {
@@ -307,6 +308,7 @@
"api/diags_api.cpp",
"api/dns_api.cpp",
"api/entropy_api.cpp",
+ "api/error_api.cpp",
"api/heap_api.cpp",
"api/icmp6_api.cpp",
"api/instance_api.cpp",
@@ -322,10 +324,13 @@
"api/netdata_api.cpp",
"api/netdiag_api.cpp",
"api/network_time_api.cpp",
+ "api/ping_sender_api.cpp",
"api/random_crypto_api.cpp",
"api/random_noncrypto_api.cpp",
"api/server_api.cpp",
"api/sntp_api.cpp",
+ "api/srp_client_api.cpp",
+ "api/srp_server_api.cpp",
"api/tasklet_api.cpp",
"api/thread_api.cpp",
"api/thread_ftd_api.cpp",
@@ -342,6 +347,11 @@
"backbone_router/multicast_listeners_table.hpp",
"backbone_router/ndproxy_table.cpp",
"backbone_router/ndproxy_table.hpp",
+ "border_router/infra_if_platform.cpp",
+ "border_router/router_advertisement.cpp",
+ "border_router/router_advertisement.hpp",
+ "border_router/routing_manager.cpp",
+ "border_router/routing_manager.hpp",
"coap/coap.cpp",
"coap/coap.hpp",
"coap/coap_message.cpp",
@@ -357,9 +367,12 @@
"common/debug.hpp",
"common/encoding.hpp",
"common/equatable.hpp",
+ "common/error.cpp",
+ "common/error.hpp",
"common/extension.hpp",
"common/instance.cpp",
"common/instance.hpp",
+ "common/iterator_utils.hpp",
"common/linked_list.hpp",
"common/locator-getters.hpp",
"common/locator.hpp",
@@ -405,7 +418,7 @@
"crypto/mbedtls.cpp",
"crypto/mbedtls.hpp",
"crypto/pbkdf2_cmac.cpp",
- "crypto/pbkdf2_cmac.h",
+ "crypto/pbkdf2_cmac.hpp",
"crypto/sha256.cpp",
"crypto/sha256.hpp",
"diags/factory_diags.cpp",
@@ -444,6 +457,8 @@
"meshcop/dataset_manager.cpp",
"meshcop/dataset_manager.hpp",
"meshcop/dataset_manager_ftd.cpp",
+ "meshcop/dataset_updater.cpp",
+ "meshcop/dataset_updater.hpp",
"meshcop/dtls.cpp",
"meshcop/dtls.hpp",
"meshcop/energy_scan_client.cpp",
@@ -471,8 +486,10 @@
"net/dhcp6_server.hpp",
"net/dns_client.cpp",
"net/dns_client.hpp",
- "net/dns_headers.cpp",
- "net/dns_headers.hpp",
+ "net/dns_types.cpp",
+ "net/dns_types.hpp",
+ "net/dnssd_server.cpp",
+ "net/dnssd_server.hpp",
"net/icmp6.cpp",
"net/icmp6.hpp",
"net/ip6.cpp",
@@ -489,10 +506,16 @@
"net/netif.hpp",
"net/sntp_client.cpp",
"net/sntp_client.hpp",
+ "net/socket.cpp",
"net/socket.hpp",
+ "net/srp_client.cpp",
+ "net/srp_client.hpp",
+ "net/srp_server.cpp",
+ "net/srp_server.hpp",
"net/tcp.hpp",
"net/udp6.cpp",
"net/udp6.hpp",
+ "radio/max_power_table.hpp",
"radio/radio.cpp",
"radio/radio.hpp",
"radio/radio_callbacks.cpp",
@@ -558,6 +581,8 @@
"thread/network_data_local.hpp",
"thread/network_data_notifier.cpp",
"thread/network_data_notifier.hpp",
+ "thread/network_data_service.cpp",
+ "thread/network_data_service.hpp",
"thread/network_data_tlvs.hpp",
"thread/network_diagnostic.cpp",
"thread/network_diagnostic.hpp",
@@ -587,8 +612,6 @@
"utils/channel_monitor.hpp",
"utils/child_supervision.cpp",
"utils/child_supervision.hpp",
- "utils/dataset_updater.cpp",
- "utils/dataset_updater.hpp",
"utils/flash.cpp",
"utils/flash.hpp",
"utils/heap.cpp",
@@ -601,17 +624,21 @@
"utils/otns.hpp",
"utils/parse_cmdline.cpp",
"utils/parse_cmdline.hpp",
+ "utils/ping_sender.cpp",
+ "utils/ping_sender.hpp",
"utils/slaac_address.cpp",
"utils/slaac_address.hpp",
]
openthread_radio_sources = [
"api/diags_api.cpp",
+ "api/error_api.cpp",
"api/instance_api.cpp",
"api/link_raw_api.cpp",
"api/logging_api.cpp",
"api/random_noncrypto_api.cpp",
"api/tasklet_api.cpp",
+ "common/error.hpp",
"common/instance.cpp",
"common/logging.cpp",
"common/random_manager.cpp",
@@ -657,6 +684,8 @@
"config/dhcp6_server.h",
"config/diag.h",
"config/dns_client.h",
+ "config/dnssd_server.h",
+ "config/dtls.h",
"config/ip6.h",
"config/joiner.h",
"config/link_quality.h",
@@ -667,9 +696,12 @@
"config/openthread-core-config-check.h",
"config/openthread-core-default-config.h",
"config/parent_search.h",
+ "config/ping_sender.h",
"config/platform.h",
"config/radio_link.h",
"config/sntp_client.h",
+ "config/srp_client.h",
+ "config/srp_server.h",
"config/time_sync.h",
"config/tmf.h",
"openthread-core-config.h",
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f1b9455..e1dafa0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -33,6 +33,7 @@
set(COMMON_SOURCES
api/backbone_router_api.cpp
api/backbone_router_ftd_api.cpp
+ api/border_agent_api.cpp
api/border_router_api.cpp
api/channel_manager_api.cpp
api/channel_monitor_api.cpp
@@ -47,6 +48,7 @@
api/diags_api.cpp
api/dns_api.cpp
api/entropy_api.cpp
+ api/error_api.cpp
api/heap_api.cpp
api/icmp6_api.cpp
api/instance_api.cpp
@@ -62,10 +64,13 @@
api/netdata_api.cpp
api/netdiag_api.cpp
api/network_time_api.cpp
+ api/ping_sender_api.cpp
api/random_crypto_api.cpp
api/random_noncrypto_api.cpp
api/server_api.cpp
api/sntp_api.cpp
+ api/srp_client_api.cpp
+ api/srp_server_api.cpp
api/tasklet_api.cpp
api/thread_api.cpp
api/thread_ftd_api.cpp
@@ -76,10 +81,14 @@
backbone_router/bbr_manager.cpp
backbone_router/multicast_listeners_table.cpp
backbone_router/ndproxy_table.cpp
+ border_router/infra_if_platform.cpp
+ border_router/router_advertisement.cpp
+ border_router/routing_manager.cpp
coap/coap.cpp
coap/coap_message.cpp
coap/coap_secure.cpp
common/crc16.cpp
+ common/error.cpp
common/instance.cpp
common/logging.cpp
common/message.cpp
@@ -119,6 +128,7 @@
meshcop/dataset_local.cpp
meshcop/dataset_manager.cpp
meshcop/dataset_manager_ftd.cpp
+ meshcop/dataset_updater.cpp
meshcop/dtls.cpp
meshcop/energy_scan_client.cpp
meshcop/joiner.cpp
@@ -132,7 +142,8 @@
net/dhcp6_client.cpp
net/dhcp6_server.cpp
net/dns_client.cpp
- net/dns_headers.cpp
+ net/dns_types.cpp
+ net/dnssd_server.cpp
net/icmp6.cpp
net/ip6.cpp
net/ip6_address.cpp
@@ -141,6 +152,9 @@
net/ip6_mpl.cpp
net/netif.cpp
net/sntp_client.cpp
+ net/socket.cpp
+ net/srp_client.cpp
+ net/srp_server.cpp
net/udp6.cpp
radio/radio.cpp
radio/radio_callbacks.cpp
@@ -174,6 +188,7 @@
thread/network_data_leader_ftd.cpp
thread/network_data_local.cpp
thread/network_data_notifier.cpp
+ thread/network_data_service.cpp
thread/network_diagnostic.cpp
thread/panid_query_server.cpp
thread/radio_selector.cpp
@@ -187,13 +202,13 @@
utils/channel_manager.cpp
utils/channel_monitor.cpp
utils/child_supervision.cpp
- utils/dataset_updater.cpp
utils/flash.cpp
utils/heap.cpp
utils/jam_detector.cpp
utils/lookup_table.cpp
utils/otns.cpp
utils/parse_cmdline.cpp
+ utils/ping_sender.cpp
utils/slaac_address.cpp
)
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 8daddd7..01c5f33 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -110,6 +110,7 @@
SOURCES_COMMON = \
api/backbone_router_api.cpp \
api/backbone_router_ftd_api.cpp \
+ api/border_agent_api.cpp \
api/border_router_api.cpp \
api/channel_manager_api.cpp \
api/channel_monitor_api.cpp \
@@ -124,6 +125,7 @@
api/diags_api.cpp \
api/dns_api.cpp \
api/entropy_api.cpp \
+ api/error_api.cpp \
api/heap_api.cpp \
api/icmp6_api.cpp \
api/instance_api.cpp \
@@ -139,10 +141,13 @@
api/netdata_api.cpp \
api/netdiag_api.cpp \
api/network_time_api.cpp \
+ api/ping_sender_api.cpp \
api/random_crypto_api.cpp \
api/random_noncrypto_api.cpp \
api/server_api.cpp \
api/sntp_api.cpp \
+ api/srp_client_api.cpp \
+ api/srp_server_api.cpp \
api/tasklet_api.cpp \
api/thread_api.cpp \
api/thread_ftd_api.cpp \
@@ -153,10 +158,14 @@
backbone_router/bbr_manager.cpp \
backbone_router/multicast_listeners_table.cpp \
backbone_router/ndproxy_table.cpp \
+ border_router/infra_if_platform.cpp \
+ border_router/router_advertisement.cpp \
+ border_router/routing_manager.cpp \
coap/coap.cpp \
coap/coap_message.cpp \
coap/coap_secure.cpp \
common/crc16.cpp \
+ common/error.cpp \
common/instance.cpp \
common/logging.cpp \
common/message.cpp \
@@ -196,6 +205,7 @@
meshcop/dataset_local.cpp \
meshcop/dataset_manager.cpp \
meshcop/dataset_manager_ftd.cpp \
+ meshcop/dataset_updater.cpp \
meshcop/dtls.cpp \
meshcop/energy_scan_client.cpp \
meshcop/joiner.cpp \
@@ -209,7 +219,8 @@
net/dhcp6_client.cpp \
net/dhcp6_server.cpp \
net/dns_client.cpp \
- net/dns_headers.cpp \
+ net/dns_types.cpp \
+ net/dnssd_server.cpp \
net/icmp6.cpp \
net/ip6.cpp \
net/ip6_address.cpp \
@@ -218,6 +229,9 @@
net/ip6_mpl.cpp \
net/netif.cpp \
net/sntp_client.cpp \
+ net/socket.cpp \
+ net/srp_client.cpp \
+ net/srp_server.cpp \
net/udp6.cpp \
radio/radio.cpp \
radio/radio_callbacks.cpp \
@@ -251,6 +265,7 @@
thread/network_data_leader_ftd.cpp \
thread/network_data_local.cpp \
thread/network_data_notifier.cpp \
+ thread/network_data_service.cpp \
thread/network_diagnostic.cpp \
thread/panid_query_server.cpp \
thread/radio_selector.cpp \
@@ -264,13 +279,13 @@
utils/channel_manager.cpp \
utils/channel_monitor.cpp \
utils/child_supervision.cpp \
- utils/dataset_updater.cpp \
utils/flash.cpp \
utils/heap.cpp \
utils/jam_detector.cpp \
utils/lookup_table.cpp \
utils/otns.cpp \
utils/parse_cmdline.cpp \
+ utils/ping_sender.cpp \
utils/slaac_address.cpp \
$(NULL)
@@ -280,12 +295,14 @@
libopenthread_radio_a_SOURCES = \
api/diags_api.cpp \
+ api/error_api.cpp \
api/heap_api.cpp \
api/instance_api.cpp \
api/link_raw_api.cpp \
api/logging_api.cpp \
api/random_noncrypto_api.cpp \
api/tasklet_api.cpp \
+ common/error.cpp \
common/instance.cpp \
common/logging.cpp \
common/random_manager.cpp \
@@ -339,13 +356,14 @@
endif # OPENTHREAD_ENABLE_VENDOR_EXTENSION
HEADERS_COMMON = \
- openthread-core-config.h \
backbone_router/backbone_tmf.hpp \
backbone_router/bbr_leader.hpp \
backbone_router/bbr_local.hpp \
backbone_router/bbr_manager.hpp \
backbone_router/multicast_listeners_table.hpp \
backbone_router/ndproxy_table.hpp \
+ border_router/router_advertisement.hpp \
+ border_router/routing_manager.hpp \
coap/coap.hpp \
coap/coap_message.hpp \
coap/coap_secure.hpp \
@@ -357,11 +375,13 @@
common/debug.hpp \
common/encoding.hpp \
common/equatable.hpp \
+ common/error.hpp \
common/extension.hpp \
common/instance.hpp \
+ common/iterator_utils.hpp \
common/linked_list.hpp \
- common/locator.hpp \
common/locator-getters.hpp \
+ common/locator.hpp \
common/logging.hpp \
common/message.hpp \
common/new.hpp \
@@ -393,6 +413,8 @@
config/dhcp6_server.h \
config/diag.h \
config/dns_client.h \
+ config/dnssd_server.h \
+ config/dtls.h \
config/ip6.h \
config/joiner.h \
config/link_quality.h \
@@ -403,9 +425,12 @@
config/openthread-core-config-check.h \
config/openthread-core-default-config.h \
config/parent_search.h \
+ config/ping_sender.h \
config/platform.h \
config/radio_link.h \
config/sntp_client.h \
+ config/srp_client.h \
+ config/srp_server.h \
config/time_sync.h \
config/tmf.h \
crypto/aes_ccm.hpp \
@@ -414,7 +439,7 @@
crypto/hkdf_sha256.hpp \
crypto/hmac_sha256.hpp \
crypto/mbedtls.hpp \
- crypto/pbkdf2_cmac.h \
+ crypto/pbkdf2_cmac.hpp \
crypto/sha256.hpp \
diags/factory_diags.hpp \
mac/channel_mask.hpp \
@@ -433,6 +458,7 @@
meshcop/dataset.hpp \
meshcop/dataset_local.hpp \
meshcop/dataset_manager.hpp \
+ meshcop/dataset_updater.hpp \
meshcop/dtls.hpp \
meshcop/energy_scan_client.hpp \
meshcop/joiner.hpp \
@@ -447,7 +473,8 @@
net/dhcp6_client.hpp \
net/dhcp6_server.hpp \
net/dns_client.hpp \
- net/dns_headers.hpp \
+ net/dns_types.hpp \
+ net/dnssd_server.hpp \
net/icmp6.hpp \
net/ip6.hpp \
net/ip6_address.hpp \
@@ -457,8 +484,12 @@
net/netif.hpp \
net/sntp_client.hpp \
net/socket.hpp \
+ net/srp_client.hpp \
+ net/srp_server.hpp \
net/tcp.hpp \
net/udp6.hpp \
+ openthread-core-config.h \
+ radio/max_power_table.hpp \
radio/radio.hpp \
radio/trel_interface.hpp \
radio/trel_link.hpp \
@@ -492,6 +523,7 @@
thread/network_data_leader_ftd.hpp \
thread/network_data_local.hpp \
thread/network_data_notifier.hpp \
+ thread/network_data_service.hpp \
thread/network_data_tlvs.hpp \
thread/network_diagnostic.hpp \
thread/network_diagnostic_tlvs.hpp \
@@ -508,13 +540,13 @@
utils/channel_manager.hpp \
utils/channel_monitor.hpp \
utils/child_supervision.hpp \
- utils/dataset_updater.hpp \
utils/flash.hpp \
utils/heap.hpp \
utils/jam_detector.hpp \
utils/lookup_table.hpp \
utils/otns.hpp \
utils/parse_cmdline.hpp \
+ utils/ping_sender.hpp \
utils/slaac_address.hpp \
$(NULL)
diff --git a/src/core/api/backbone_router_ftd_api.cpp b/src/core/api/backbone_router_ftd_api.cpp
index 82bd376..79ccdf5 100644
--- a/src/core/api/backbone_router_ftd_api.cpp
+++ b/src/core/api/backbone_router_ftd_api.cpp
@@ -75,16 +75,9 @@
otError otBackboneRouterRegister(otInstance *aInstance)
{
- otError error = OT_ERROR_NONE;
-
Instance &instance = *static_cast<Instance *>(aInstance);
- SuccessOrExit(error = instance.Get<BackboneRouter::Local>().AddService(true /* Force registration */));
-
- instance.Get<NetworkData::Notifier>().HandleServerDataUpdated();
-
-exit:
- return error;
+ return instance.Get<BackboneRouter::Local>().AddService(true /* Force registration */);
}
uint8_t otBackboneRouterGetRegistrationJitter(otInstance *aInstance)
diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp
index bf5b66f..10f9d5e 100644
--- a/src/core/api/border_router_api.cpp
+++ b/src/core/api/border_router_api.cpp
@@ -37,11 +37,32 @@
#include <openthread/border_router.h>
+#include "border_router/routing_manager.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
using namespace ot;
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+otError otBorderRoutingInit(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ bool aInfraIfIsRunning,
+ const otIp6Address *aInfraIfLinkLocalAddress)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<BorderRouter::RoutingManager>().Init(
+ aInfraIfIndex, aInfraIfIsRunning, static_cast<const Ip6::Address *>(aInfraIfLinkLocalAddress));
+}
+
+otError otBorderRoutingSetEnabled(otInstance *aInstance, bool aEnabled)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<BorderRouter::RoutingManager>().SetEnabled(aEnabled);
+}
+#endif
+
otError otBorderRouterGetNetData(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
{
Instance &instance = *static_cast<Instance *>(aInstance);
@@ -53,7 +74,7 @@
otError otBorderRouterAddOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig)
{
- otError error;
+ Error error;
Instance & instance = *static_cast<Instance *>(aInstance);
const NetworkData::OnMeshPrefixConfig *config = static_cast<const NetworkData::OnMeshPrefixConfig *>(aConfig);
@@ -78,7 +99,7 @@
otError otBorderRouterRemoveOnMeshPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
const Ip6::Prefix *prefix = static_cast<const Ip6::Prefix *>(aPrefix);
@@ -87,7 +108,7 @@
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
error = instance.Get<BackboneRouter::Local>().RemoveDomainPrefix(*prefix);
- if (error == OT_ERROR_NOT_FOUND)
+ if (error == kErrorNotFound)
#endif
{
error = instance.Get<NetworkData::Local>().RemoveOnMeshPrefix(*prefix);
@@ -145,7 +166,7 @@
instance.Get<NetworkData::Notifier>().HandleServerDataUpdated();
- return OT_ERROR_NONE;
+ return kErrorNone;
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp
index b84ec18..8507fcb 100644
--- a/src/core/api/coap_api.cpp
+++ b/src/core/api/coap_api.cpp
@@ -101,18 +101,18 @@
return static_cast<Coap::Message *>(aMessage)->AppendUriPathOptions(aUriPath);
}
-uint16_t otCoapBlockSizeFromExponent(otCoapBlockSize aSize)
+uint16_t otCoapBlockSizeFromExponent(otCoapBlockSzx aSize)
{
return static_cast<uint16_t>(
1 << (static_cast<uint8_t>(aSize) + static_cast<uint8_t>(Coap::Message::kBlockSzxBase)));
}
-otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSize aSize)
+otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize)
{
return static_cast<Coap::Message *>(aMessage)->AppendBlockOption(Coap::Message::kBlockType2, aNum, aMore, aSize);
}
-otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSize aSize)
+otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize)
{
return static_cast<Coap::Message *>(aMessage)->AppendBlockOption(Coap::Message::kBlockType1, aNum, aMore, aSize);
}
@@ -214,6 +214,34 @@
return static_cast<Coap::Option::Iterator *>(aIterator)->ReadOptionValue(aValue);
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError otCoapSendRequestBlockWiseWithParameters(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ otCoapResponseHandler aHandler,
+ void * aContext,
+ const otCoapTxParameters * aTxParameters,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
+{
+ Error error;
+ Instance & instance = *static_cast<Instance *>(aInstance);
+ const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
+
+ if (aTxParameters != nullptr)
+ {
+ VerifyOrExit(txParameters.IsValid(), error = kErrorInvalidArgs);
+ }
+
+ error = instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
+ *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
+ txParameters, aHandler, aContext, aTransmitHook, aReceiveHook);
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
otError otCoapSendRequestWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
@@ -221,13 +249,13 @@
void * aContext,
const otCoapTxParameters *aTxParameters)
{
- otError error;
+ Error error;
Instance & instance = *static_cast<Instance *>(aInstance);
const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
if (aTxParameters != nullptr)
{
- VerifyOrExit(txParameters.IsValid(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(txParameters.IsValid(), error = kErrorInvalidArgs);
}
error = instance.GetApplicationCoap().SendMessage(*static_cast<Coap::Message *>(aMessage),
@@ -252,6 +280,22 @@
return instance.GetApplicationCoap().Stop();
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+void otCoapAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.GetApplicationCoap().AddBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
+}
+
+void otCoapRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.GetApplicationCoap().RemoveBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
+}
+#endif
+
void otCoapAddResource(otInstance *aInstance, otCoapResource *aResource)
{
Instance &instance = *static_cast<Instance *>(aInstance);
@@ -273,6 +317,22 @@
instance.GetApplicationCoap().SetDefaultHandler(aHandler, aContext);
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError otCoapSendResponseBlockWiseWithParameters(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ const otCoapTxParameters * aTxParameters,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.GetApplicationCoap().SendMessage(
+ *static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
+ Coap::TxParameters::From(aTxParameters), nullptr, aContext, aTransmitHook, nullptr);
+}
+#endif
+
otError otCoapSendResponseWithParameters(otInstance * aInstance,
otMessage * aMessage,
const otMessageInfo * aMessageInfo,
diff --git a/src/core/api/coap_secure_api.cpp b/src/core/api/coap_secure_api.cpp
index 942bc78..6991316 100644
--- a/src/core/api/coap_secure_api.cpp
+++ b/src/core/api/coap_secure_api.cpp
@@ -151,6 +151,21 @@
instance.GetApplicationCoapSecure().Stop();
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError otCoapSecureSendRequestBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ otCoapResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.GetApplicationCoapSecure().SendMessage(*static_cast<Coap::Message *>(aMessage), aHandler, aContext,
+ aTransmitHook, aReceiveHook);
+}
+#endif
+
otError otCoapSecureSendRequest(otInstance * aInstance,
otMessage * aMessage,
otCoapResponseHandler aHandler,
@@ -161,6 +176,22 @@
return instance.GetApplicationCoapSecure().SendMessage(*static_cast<Coap::Message *>(aMessage), aHandler, aContext);
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+void otCoapSecureAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.GetApplicationCoapSecure().AddBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
+}
+
+void otCoapSecureRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.GetApplicationCoapSecure().RemoveBlockWiseResource(*static_cast<Coap::ResourceBlockWise *>(aResource));
+}
+#endif
+
void otCoapSecureAddResource(otInstance *aInstance, otCoapResource *aResource)
{
Instance &instance = *static_cast<Instance *>(aInstance);
@@ -191,6 +222,21 @@
instance.GetApplicationCoapSecure().SetDefaultHandler(aHandler, aContext);
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+otError otCoapSecureSendResponseBlockWise(otInstance * aInstance,
+ otMessage * aMessage,
+ const otMessageInfo * aMessageInfo,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.GetApplicationCoapSecure().SendMessage(*static_cast<Coap::Message *>(aMessage),
+ *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
+ nullptr, aContext, aTransmitHook);
+}
+#endif
+
otError otCoapSecureSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
Instance &instance = *static_cast<Instance *>(aInstance);
diff --git a/src/core/api/commissioner_api.cpp b/src/core/api/commissioner_api.cpp
index ae5c2cd..cda781b 100644
--- a/src/core/api/commissioner_api.cpp
+++ b/src/core/api/commissioner_api.cpp
@@ -60,7 +60,7 @@
otError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aEui64, const char *aPskd, uint32_t aTimeout)
{
- otError error;
+ Error error;
MeshCoP::Commissioner &commissioner = static_cast<Instance *>(aInstance)->Get<MeshCoP::Commissioner>();
if (aEui64 == nullptr)
@@ -95,7 +95,7 @@
otError otCommissionerRemoveJoiner(otInstance *aInstance, const otExtAddress *aEui64)
{
- otError error;
+ Error error;
MeshCoP::Commissioner &commissioner = static_cast<Instance *>(aInstance)->Get<MeshCoP::Commissioner>();
if (aEui64 == nullptr)
diff --git a/src/core/api/dataset_updater_api.cpp b/src/core/api/dataset_updater_api.cpp
index 63a61d0..fd9b862 100644
--- a/src/core/api/dataset_updater_api.cpp
+++ b/src/core/api/dataset_updater_api.cpp
@@ -37,7 +37,7 @@
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
-#include "utils/dataset_updater.hpp"
+#include "meshcop/dataset_updater.hpp"
using namespace ot;
@@ -46,27 +46,26 @@
otError otDatasetUpdaterRequestUpdate(otInstance * aInstance,
const otOperationalDataset *aDataset,
otDatasetUpdaterCallback aCallback,
- void * aContext,
- uint32_t aReryWaitInterval)
+ void * aContext)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- return instance.Get<Utils::DatasetUpdater>().RequestUpdate(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
- aCallback, aContext, aReryWaitInterval);
+ return instance.Get<MeshCoP::DatasetUpdater>().RequestUpdate(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
+ aCallback, aContext);
}
void otDatasetUpdaterCancelUpdate(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- instance.Get<Utils::DatasetUpdater>().CancelUpdate();
+ instance.Get<MeshCoP::DatasetUpdater>().CancelUpdate();
}
bool otDatasetUpdaterIsUpdateOngoing(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- return instance.Get<Utils::DatasetUpdater>().IsUpdateOngoing();
+ return instance.Get<MeshCoP::DatasetUpdater>().IsUpdateOngoing();
}
#endif // OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE && OPENTHREAD_FTD
diff --git a/src/core/api/dns_api.cpp b/src/core/api/dns_api.cpp
index b8bc4fb..5038a47 100644
--- a/src/core/api/dns_api.cpp
+++ b/src/core/api/dns_api.cpp
@@ -33,19 +33,179 @@
#include "openthread-core-config.h"
-#include <openthread/dns.h>
+#include <openthread/dns_client.h>
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "net/dns_client.hpp"
+#include "net/dns_types.hpp"
using namespace ot;
+void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t *aTxtData, uint16_t aTxtDataLength)
+{
+ static_cast<Dns::TxtEntry::Iterator *>(aIterator)->Init(aTxtData, aTxtDataLength);
+}
+
+otError otDnsGetNextTxtEntry(otDnsTxtEntryIterator *aIterator, otDnsTxtEntry *aEntry)
+{
+ return static_cast<Dns::TxtEntry::Iterator *>(aIterator)->GetNextEntry(*static_cast<Dns::TxtEntry *>(aEntry));
+}
+
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
-otError otDnsClientQuery(otInstance *aInstance, const otDnsQuery *aQuery, otDnsResponseHandler aHandler, void *aContext)
+
+const otDnsQueryConfig *otDnsClientGetDefaultConfig(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- return instance.Get<Dns::Client>().Query(*static_cast<const Dns::Client::QueryInfo *>(aQuery), aHandler, aContext);
+ return &instance.Get<Dns::Client>().GetDefaultConfig();
}
-#endif
+
+void otDnsClientSetDefaultConfig(otInstance *aInstance, const otDnsQueryConfig *aConfig)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ if (aConfig != nullptr)
+ {
+ instance.Get<Dns::Client>().SetDefaultConfig(*static_cast<const Dns::Client::QueryConfig *>(aConfig));
+ }
+ else
+ {
+ instance.Get<Dns::Client>().ResetDefaultConfig();
+ }
+}
+
+otError otDnsClientResolveAddress(otInstance * aInstance,
+ const char * aHostName,
+ otDnsAddressCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Dns::Client>().ResolveAddress(aHostName, aCallback, aContext,
+ static_cast<const Dns::Client::QueryConfig *>(aConfig));
+}
+
+otError otDnsAddressResponseGetHostName(const otDnsAddressResponse *aResponse,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize)
+{
+ const Dns::Client::AddressResponse &response = *static_cast<const Dns::Client::AddressResponse *>(aResponse);
+
+ return response.GetHostName(aNameBuffer, aNameBufferSize);
+}
+
+otError otDnsAddressResponseGetAddress(const otDnsAddressResponse *aResponse,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl)
+{
+ const Dns::Client::AddressResponse &response = *static_cast<const Dns::Client::AddressResponse *>(aResponse);
+ uint32_t ttl;
+
+ return response.GetAddress(aIndex, *static_cast<Ip6::Address *>(aAddress), (aTtl != nullptr) ? *aTtl : ttl);
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+otError otDnsClientBrowse(otInstance * aInstance,
+ const char * aServiceName,
+ otDnsBrowseCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Dns::Client>().Browse(aServiceName, aCallback, aContext,
+ static_cast<const Dns::Client::QueryConfig *>(aConfig));
+}
+
+otError otDnsBrowseResponseGetServiceName(const otDnsBrowseResponse *aResponse,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize)
+{
+ const Dns::Client::BrowseResponse &response = *static_cast<const Dns::Client::BrowseResponse *>(aResponse);
+
+ return response.GetServiceName(aNameBuffer, aNameBufferSize);
+}
+
+otError otDnsBrowseResponseGetServiceInstance(const otDnsBrowseResponse *aResponse,
+ uint16_t aIndex,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize)
+{
+ const Dns::Client::BrowseResponse &response = *static_cast<const Dns::Client::BrowseResponse *>(aResponse);
+
+ return response.GetServiceInstance(aIndex, aLabelBuffer, aLabelBufferSize);
+}
+
+otError otDnsBrowseResponseGetServiceInfo(const otDnsBrowseResponse *aResponse,
+ const char * aInstanceLabel,
+ otDnsServiceInfo * aServiceInfo)
+{
+ const Dns::Client::BrowseResponse &response = *static_cast<const Dns::Client::BrowseResponse *>(aResponse);
+
+ return response.GetServiceInfo(aInstanceLabel, *static_cast<Dns::Client::ServiceInfo *>(aServiceInfo));
+}
+
+otError otDnsBrowseResponseGetHostAddress(const otDnsBrowseResponse *aResponse,
+ const char * aHostName,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl)
+{
+ const Dns::Client::BrowseResponse &response = *static_cast<const Dns::Client::BrowseResponse *>(aResponse);
+ uint32_t ttl;
+
+ return response.GetHostAddress(aHostName, aIndex, *static_cast<Ip6::Address *>(aAddress),
+ aTtl != nullptr ? *aTtl : ttl);
+}
+
+otError otDnsClientResolveService(otInstance * aInstance,
+ const char * aInstanceLabel,
+ const char * aServiceName,
+ otDnsServiceCallback aCallback,
+ void * aContext,
+ const otDnsQueryConfig *aConfig)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Dns::Client>().ResolveService(aInstanceLabel, aServiceName, aCallback, aContext,
+ static_cast<const Dns::Client::QueryConfig *>(aConfig));
+}
+
+otError otDnsServiceResponseGetServiceName(const otDnsServiceResponse *aResponse,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize)
+{
+ const Dns::Client::ServiceResponse &response = *static_cast<const Dns::Client::ServiceResponse *>(aResponse);
+
+ return response.GetServiceName(aLabelBuffer, aLabelBufferSize, aNameBuffer, aNameBufferSize);
+}
+
+otError otDnsServiceResponseGetServiceInfo(const otDnsServiceResponse *aResponse, otDnsServiceInfo *aServiceInfo)
+{
+ const Dns::Client::ServiceResponse &response = *static_cast<const Dns::Client::ServiceResponse *>(aResponse);
+
+ return response.GetServiceInfo(*static_cast<Dns::Client::ServiceInfo *>(aServiceInfo));
+}
+
+otError otDnsServiceResponseGetHostAddress(const otDnsServiceResponse *aResponse,
+ const char * aHostName,
+ uint16_t aIndex,
+ otIp6Address * aAddress,
+ uint32_t * aTtl)
+{
+ const Dns::Client::ServiceResponse &response = *static_cast<const Dns::Client::ServiceResponse *>(aResponse);
+ uint32_t ttl;
+
+ return response.GetHostAddress(aHostName, aIndex, *static_cast<Ip6::Address *>(aAddress),
+ (aTtl != nullptr) ? *aTtl : ttl);
+}
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
diff --git a/src/core/api/error_api.cpp b/src/core/api/error_api.cpp
new file mode 100644
index 0000000..cc2b18d
--- /dev/null
+++ b/src/core/api/error_api.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2021, 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 OpenThread error code functions.
+ */
+
+#include "openthread-core-config.h"
+
+#include "common/error.hpp"
+
+using namespace ot;
+
+const char *otThreadErrorToString(otError aError)
+{
+ return ErrorToString(aError);
+}
diff --git a/src/core/api/heap_api.cpp b/src/core/api/heap_api.cpp
index d921954..e3cd90d 100644
--- a/src/core/api/heap_api.cpp
+++ b/src/core/api/heap_api.cpp
@@ -37,8 +37,6 @@
#include "common/instance.hpp"
-#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE || OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-
#if OPENTHREAD_RADIO
void *otHeapCAlloc(size_t aCount, size_t aSize)
@@ -61,25 +59,14 @@
OT_ASSERT(false);
}
-#else // OPENTHREAD_RADIO
-
+#else // OPENTHREAD_RADIO
void *otHeapCAlloc(size_t aCount, size_t aSize)
{
- return ot::Instance::Get().HeapCAlloc(aCount, aSize);
+ return ot::Instance::HeapCAlloc(aCount, aSize);
}
void otHeapFree(void *aPointer)
{
- ot::Instance::Get().HeapFree(aPointer);
+ ot::Instance::HeapFree(aPointer);
}
-
#endif // OPENTHREAD_RADIO
-
-#endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE || OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE && !OPENTHREAD_RADIO
-void otHeapSetCAllocFree(otHeapCAllocFn aCAlloc, otHeapFreeFn aFree)
-{
- ot::Instance::HeapSetCAllocFree(aCAlloc, aFree);
-}
-#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
diff --git a/src/core/api/instance_api.cpp b/src/core/api/instance_api.cpp
index 2ee1083..e6482d5 100644
--- a/src/core/api/instance_api.cpp
+++ b/src/core/api/instance_api.cpp
@@ -42,6 +42,14 @@
#include "common/new.hpp"
#include "radio/radio.hpp"
+#ifdef __ANDROID__
+#ifdef OPENTHREAD_ENABLE_ANDROID_NDK
+#include <sys/system_properties.h>
+#else
+#include <cutils/properties.h>
+#endif
+#endif
+
using namespace ot;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
@@ -134,6 +142,24 @@
* image will be undefined and may change.
*/
+#ifdef __ANDROID__
+
+#ifdef OPENTHREAD_ENABLE_ANDROID_NDK
+ static char sVersion[100 + PROP_VALUE_MAX];
+ char dateTime[PROP_VALUE_MAX];
+
+ __system_property_get("ro.build.date", dateTime);
+#else
+ static char sVersion[100 + PROPERTY_VALUE_MAX];
+ char dateTime[PROPERTY_VALUE_MAX];
+
+ property_get("ro.build.date", dateTime, "Thu Jan 1 1970 UTC 00:00:00");
+#endif
+
+ snprintf(sVersion, sizeof(sVersion), "%s/%s ;%s ; %s", PACKAGE_NAME, PACKAGE_VERSION,
+ OPENTHREAD_CONFIG_PLATFORM_INFO, dateTime);
+#else
+
#ifdef PLATFORM_VERSION_ATTR_PREFIX
PLATFORM_VERSION_ATTR_PREFIX
#else
@@ -148,6 +174,8 @@
#endif
; // Trailing semicolon to end statement.
+#endif
+
return sVersion;
}
diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp
index 65f2ad4..7439265 100644
--- a/src/core/api/ip6_api.cpp
+++ b/src/core/api/ip6_api.cpp
@@ -46,11 +46,11 @@
otError otIp6SetEnabled(otInstance *aInstance, bool aEnabled)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
- VerifyOrExit(!instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
#endif
if (aEnabled)
@@ -246,12 +246,12 @@
otError otIp6SelectSourceAddress(otInstance *aInstance, otMessageInfo *aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
const Ip6::NetifUnicastAddress *netifAddr;
netifAddr = instance.Get<Ip6::Ip6>().SelectSourceAddress(*static_cast<Ip6::MessageInfo *>(aMessageInfo));
- VerifyOrExit(netifAddr != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(netifAddr != nullptr, error = kErrorNotFound);
aMessageInfo->mSockAddr = netifAddr->GetAddress();
exit:
diff --git a/src/core/api/jam_detection_api.cpp b/src/core/api/jam_detection_api.cpp
index 6adcb14..c1a5bc5 100644
--- a/src/core/api/jam_detection_api.cpp
+++ b/src/core/api/jam_detection_api.cpp
@@ -48,7 +48,7 @@
instance.Get<Utils::JamDetector>().SetRssiThreshold(aRssiThreshold);
- return OT_ERROR_NONE;
+ return kErrorNone;
}
int8_t otJamDetectionGetRssiThreshold(otInstance *aInstance)
diff --git a/src/core/api/joiner_api.cpp b/src/core/api/joiner_api.cpp
index 9d82fbb..5562f41 100644
--- a/src/core/api/joiner_api.cpp
+++ b/src/core/api/joiner_api.cpp
@@ -80,7 +80,7 @@
otError otJoinerSetDiscerner(otInstance *aInstance, otJoinerDiscerner *aDiscerner)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::Joiner &joiner = static_cast<Instance *>(aInstance)->Get<MeshCoP::Joiner>();
if (aDiscerner != nullptr)
diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp
index 8c9f43a..7db8934 100644
--- a/src/core/api/link_api.cpp
+++ b/src/core/api/link_api.cpp
@@ -63,7 +63,7 @@
otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel)
{
- otError error;
+ Error error;
Instance &instance = *static_cast<Instance *>(aInstance);
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
@@ -74,7 +74,7 @@
}
#endif
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
SuccessOrExit(error = instance.Get<Mac::Mac>().SetPanChannel(aChannel));
instance.Get<MeshCoP::ActiveDataset>().Clear();
@@ -93,10 +93,10 @@
otError otLinkSetSupportedChannelMask(otInstance *aInstance, uint32_t aChannelMask)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetSupportedChannelMask(static_cast<Mac::ChannelMask>(aChannelMask));
@@ -113,11 +113,11 @@
otError otLinkSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aExtAddress != nullptr);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetExtAddress(*static_cast<const Mac::ExtAddress *>(aExtAddress));
@@ -143,10 +143,10 @@
otError otLinkSetPanId(otInstance *aInstance, otPanId aPanId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetPanId(aPanId);
instance.Get<MeshCoP::ActiveDataset>().Clear();
@@ -378,11 +378,11 @@
otError otLinkSetPromiscuous(otInstance *aInstance, bool aPromiscuous)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
// cannot enable IEEE 802.15.4 promiscuous mode if the Thread interface is enabled
- VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetPromiscuous(aPromiscuous);
@@ -392,11 +392,11 @@
otError otLinkSetEnabled(otInstance *aInstance, bool aEnable)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
// cannot disable the link layer if the Thread interface is enabled
- VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!instance.Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetEnabled(aEnable);
@@ -490,10 +490,10 @@
otError otLinkCslSetChannel(otInstance *aInstance, uint8_t aChannel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(Radio::IsCslChannelValid(aChannel), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(Radio::IsCslChannelValid(aChannel), error = kErrorInvalidArgs);
instance.Get<Mac::Mac>().SetCslChannel(aChannel);
@@ -508,10 +508,10 @@
otError otLinkCslSetPeriod(otInstance *aInstance, uint16_t aPeriod)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit((aPeriod == 0 || kMinCslPeriod <= aPeriod), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((aPeriod == 0 || kMinCslPeriod <= aPeriod), error = kErrorInvalidArgs);
instance.Get<Mac::Mac>().SetCslPeriod(aPeriod);
exit:
@@ -525,10 +525,10 @@
otError otLinkCslSetTimeout(otInstance *aInstance, uint32_t aTimeout)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(kMaxCslTimeout >= aTimeout, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(kMaxCslTimeout >= aTimeout, error = kErrorInvalidArgs);
instance.Get<Mac::Mac>().SetCslTimeout(aTimeout);
exit:
diff --git a/src/core/api/link_raw_api.cpp b/src/core/api/link_raw_api.cpp
index 9bf138e..6d92243 100644
--- a/src/core/api/link_raw_api.cpp
+++ b/src/core/api/link_raw_api.cpp
@@ -71,10 +71,10 @@
otError otLinkRawSetPromiscuous(otInstance *aInstance, bool aEnable)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
instance.Get<Radio>().SetPromiscuous(aEnable);
exit:
@@ -83,10 +83,10 @@
otError otLinkRawSleep(otInstance *aInstance)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
error = instance.Get<Radio>().Sleep();
@@ -129,10 +129,10 @@
otError otLinkRawSrcMatchEnable(otInstance *aInstance, bool aEnable)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
instance.Get<Radio>().EnableSrcMatch(aEnable);
@@ -142,10 +142,10 @@
otError otLinkRawSrcMatchAddShortEntry(otInstance *aInstance, uint16_t aShortAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
error = instance.Get<Radio>().AddSrcMatchShortEntry(aShortAddress);
@@ -156,10 +156,10 @@
otError otLinkRawSrcMatchAddExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
{
Mac::ExtAddress address;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
address.Set(aExtAddress->m8, Mac::ExtAddress::kReverseByteOrder);
error = instance.Get<Radio>().AddSrcMatchExtEntry(address);
@@ -170,10 +170,10 @@
otError otLinkRawSrcMatchClearShortEntry(otInstance *aInstance, uint16_t aShortAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
error = instance.Get<Radio>().ClearSrcMatchShortEntry(aShortAddress);
exit:
@@ -183,10 +183,10 @@
otError otLinkRawSrcMatchClearExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
{
Mac::ExtAddress address;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
address.Set(aExtAddress->m8, Mac::ExtAddress::kReverseByteOrder);
error = instance.Get<Radio>().ClearSrcMatchExtEntry(address);
@@ -197,10 +197,10 @@
otError otLinkRawSrcMatchClearShortEntries(otInstance *aInstance)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
instance.Get<Radio>().ClearSrcMatchShortEntries();
@@ -210,10 +210,10 @@
otError otLinkRawSrcMatchClearExtEntries(otInstance *aInstance)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
instance.Get<Radio>().ClearSrcMatchExtEntries();
diff --git a/src/core/api/logging_api.cpp b/src/core/api/logging_api.cpp
index 571ae1d..c3851c3 100644
--- a/src/core/api/logging_api.cpp
+++ b/src/core/api/logging_api.cpp
@@ -51,7 +51,7 @@
#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
otError otLoggingSetLevel(otLogLevel aLogLevel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aLogLevel <= OT_LOG_LEVEL_DEBG && aLogLevel >= OT_LOG_LEVEL_NONE)
{
@@ -59,7 +59,7 @@
}
else
{
- error = OT_ERROR_INVALID_ARGS;
+ error = kErrorInvalidArgs;
}
return error;
diff --git a/src/core/api/multi_radio_api.cpp b/src/core/api/multi_radio_api.cpp
index 9be05c2..dd70ea6 100644
--- a/src/core/api/multi_radio_api.cpp
+++ b/src/core/api/multi_radio_api.cpp
@@ -49,13 +49,13 @@
const otExtAddress * aExtAddress,
otMultiRadioNeighborInfo *aInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
Neighbor *neighbor;
neighbor = instance.Get<NeighborTable>().FindNeighbor(*static_cast<const Mac::ExtAddress *>(aExtAddress),
Neighbor::kInStateAnyExceptInvalid);
- VerifyOrExit(neighbor != NULL, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(neighbor != NULL, error = kErrorNotFound);
neighbor->PopulateMultiRadioInfo(*aInfo);
diff --git a/src/core/api/netdata_api.cpp b/src/core/api/netdata_api.cpp
index 8afa0be..17d79b2 100644
--- a/src/core/api/netdata_api.cpp
+++ b/src/core/api/netdata_api.cpp
@@ -53,11 +53,11 @@
otNetworkDataIterator *aIterator,
otBorderRouterConfig * aConfig)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
NetworkData::OnMeshPrefixConfig *config = static_cast<NetworkData::OnMeshPrefixConfig *>(aConfig);
- VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aIterator && aConfig, error = kErrorInvalidArgs);
error = instance.Get<NetworkData::Leader>().GetNextOnMeshPrefix(*aIterator, *config);
@@ -67,10 +67,10 @@
otError otNetDataGetNextRoute(otInstance *aInstance, otNetworkDataIterator *aIterator, otExternalRouteConfig *aConfig)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aIterator && aConfig, error = kErrorInvalidArgs);
error = instance.Get<NetworkData::Leader>().GetNextExternalRoute(
*aIterator, *static_cast<NetworkData::ExternalRouteConfig *>(aConfig));
@@ -81,10 +81,10 @@
otError otNetDataGetNextService(otInstance *aInstance, otNetworkDataIterator *aIterator, otServiceConfig *aConfig)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aIterator && aConfig, error = kErrorInvalidArgs);
error = instance.Get<NetworkData::Leader>().GetNextService(*aIterator,
*static_cast<NetworkData::ServiceConfig *>(aConfig));
diff --git a/src/core/api/netdiag_api.cpp b/src/core/api/netdiag_api.cpp
index 5b75e0e..3e8b836 100644
--- a/src/core/api/netdiag_api.cpp
+++ b/src/core/api/netdiag_api.cpp
@@ -49,24 +49,17 @@
*aIterator, *aNetworkDiagTlv);
}
-void otThreadSetReceiveDiagnosticGetCallback(otInstance * aInstance,
- otReceiveDiagnosticGetCallback aCallback,
- void * aCallbackContext)
-{
- Instance &instance = *static_cast<Instance *>(aInstance);
-
- instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SetReceiveDiagnosticGetCallback(aCallback, aCallbackContext);
-}
-
-otError otThreadSendDiagnosticGet(otInstance * aInstance,
- const otIp6Address *aDestination,
- const uint8_t aTlvTypes[],
- uint8_t aCount)
+otError otThreadSendDiagnosticGet(otInstance * aInstance,
+ const otIp6Address * aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount,
+ otReceiveDiagnosticGetCallback aCallback,
+ void * aCallbackContext)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<NetworkDiagnostic::NetworkDiagnostic>().SendDiagnosticGet(
- *static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount);
+ *static_cast<const Ip6::Address *>(aDestination), aTlvTypes, aCount, aCallback, aCallbackContext);
}
otError otThreadSendDiagnosticReset(otInstance * aInstance,
diff --git a/src/core/api/network_time_api.cpp b/src/core/api/network_time_api.cpp
index f555532..eef1c92 100644
--- a/src/core/api/network_time_api.cpp
+++ b/src/core/api/network_time_api.cpp
@@ -51,10 +51,10 @@
otError otNetworkTimeSetSyncPeriod(otInstance *aInstance, uint16_t aTimeSyncPeriod)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<TimeSync>().SetTimeSyncPeriod(aTimeSyncPeriod);
@@ -71,10 +71,10 @@
otError otNetworkTimeSetXtalThreshold(otInstance *aInstance, uint16_t aXtalThreshold)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<TimeSync>().SetXtalThreshold(aXtalThreshold);
diff --git a/src/core/api/ping_sender_api.cpp b/src/core/api/ping_sender_api.cpp
new file mode 100644
index 0000000..13bb45b
--- /dev/null
+++ b/src/core/api/ping_sender_api.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, 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 OpenThread ping sender APIs.
+ */
+
+#include "openthread-core-config.h"
+
+#include <openthread/ping_sender.h>
+
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+
+using namespace ot;
+
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+otError otPingSenderPing(otInstance *aInstance, const otPingSenderConfig *aConfig)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Utils::PingSender>().Ping(*static_cast<const Utils::PingSender::Config *>(aConfig));
+}
+
+void otPingSenderStop(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Utils::PingSender>().Stop();
+}
+
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
diff --git a/src/core/api/server_api.cpp b/src/core/api/server_api.cpp
index d6b94ce..1db358a 100644
--- a/src/core/api/server_api.cpp
+++ b/src/core/api/server_api.cpp
@@ -73,10 +73,10 @@
otError otServerGetNextService(otInstance *aInstance, otNetworkDataIterator *aIterator, otServiceConfig *aConfig)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aIterator && aConfig, error = kErrorInvalidArgs);
error = instance.Get<NetworkData::Local>().GetNextService(*aIterator,
*static_cast<NetworkData::ServiceConfig *>(aConfig));
@@ -91,7 +91,7 @@
instance.Get<NetworkData::Notifier>().HandleServerDataUpdated();
- return OT_ERROR_NONE;
+ return kErrorNone;
}
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
diff --git a/src/core/api/srp_client_api.cpp b/src/core/api/srp_client_api.cpp
new file mode 100644
index 0000000..0417d75
--- /dev/null
+++ b/src/core/api/srp_client_api.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements the OpenThread SRP client APIs.
+ */
+
+#include "openthread-core-config.h"
+
+#include <openthread/srp_client.h>
+
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "net/srp_client.hpp"
+
+using namespace ot;
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+otError otSrpClientStart(otInstance *aInstance, const otSockAddr *aServerSockAddr)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().Start(*static_cast<const Ip6::SockAddr *>(aServerSockAddr));
+}
+
+void otSrpClientStop(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().Stop();
+}
+
+bool otSrpClientIsRunning(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().IsRunning();
+}
+
+const otSockAddr *otSrpClientGetServerAddress(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return &instance.Get<Srp::Client>().GetServerAddress();
+}
+
+void otSrpClientSetCallback(otInstance *aInstance, otSrpClientCallback aCallback, void *aContext)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Client>().SetCallback(aCallback, aContext);
+}
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+void otSrpClientEnableAutoStartMode(otInstance *aInstance, otSrpClientAutoStartCallback aCallback, void *aContext)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Client>().EnableAutoStartMode(aCallback, aContext);
+}
+
+void otSrpClientDisableAutoStartMode(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Client>().DisableAutoStartMode();
+}
+
+bool otSrpClientIsAutoStartModeEnabled(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().IsAutoStartModeEnabled();
+}
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+uint32_t otSrpClientGetLeaseInterval(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().GetLeaseInterval();
+}
+
+void otSrpClientSetLeaseInterval(otInstance *aInstance, uint32_t aInterval)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().SetLeaseInterval(aInterval);
+}
+
+uint32_t otSrpClientGetKeyLeaseInterval(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().GetKeyLeaseInterval();
+}
+
+void otSrpClientSetKeyLeaseInterval(otInstance *aInstance, uint32_t aInterval)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().SetKeyLeaseInterval(aInterval);
+}
+
+const otSrpClientHostInfo *otSrpClientGetHostInfo(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return &instance.Get<Srp::Client>().GetHostInfo();
+}
+
+otError otSrpClientSetHostName(otInstance *aInstance, const char *aName)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().SetHostName(aName);
+}
+
+otError otSrpClientSetHostAddresses(otInstance *aInstance, const otIp6Address *aIp6Addresses, uint8_t aNumAddresses)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().SetHostAddresses(static_cast<const Ip6::Address *>(aIp6Addresses),
+ aNumAddresses);
+}
+
+otError otSrpClientAddService(otInstance *aInstance, otSrpClientService *aService)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().AddService(*static_cast<Srp::Client::Service *>(aService));
+}
+
+otError otSrpClientRemoveService(otInstance *aInstance, otSrpClientService *aService)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().RemoveService(*static_cast<Srp::Client::Service *>(aService));
+}
+
+const otSrpClientService *otSrpClientGetServices(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().GetServices().GetHead();
+}
+
+otError otSrpClientRemoveHostAndServices(otInstance *aInstance, bool aRemoveKeyLease)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().RemoveHostAndServices(aRemoveKeyLease);
+}
+
+void otSrpClientClearHostAndServices(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Client>().ClearHostAndServices();
+}
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+const char *otSrpClientGetDomainName(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().GetDomainName();
+}
+
+otError otSrpClientSetDomainName(otInstance *aInstance, const char *aDomainName)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Client>().SetDomainName(aDomainName);
+}
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+
+const char *otSrpClientItemStateToString(otSrpClientItemState aItemState)
+{
+ OT_ASSERT(aItemState <= OT_SRP_CLIENT_ITEM_STATE_REMOVED);
+
+ return Srp::Client::ItemStateToString(static_cast<Srp::Client::ItemState>(aItemState));
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
diff --git a/src/core/api/srp_server_api.cpp b/src/core/api/srp_server_api.cpp
new file mode 100644
index 0000000..57ddd64
--- /dev/null
+++ b/src/core/api/srp_server_api.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file defines the OpenThread SRP server API.
+ */
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+#include <openthread/srp_server.h>
+
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+
+using namespace ot;
+
+const char *otSrpServerGetDomain(otInstance *aInstance)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Server>().GetDomain();
+}
+
+otError otSrpServerSetDomain(otInstance *aInstance, const char *aDomain)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Server>().SetDomain(aDomain);
+}
+
+void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Server>().SetEnabled(aEnabled);
+}
+
+otError otSrpServerSetLeaseRange(otInstance *aInstance,
+ uint32_t aMinLease,
+ uint32_t aMaxLease,
+ uint32_t aMinKeyLease,
+ uint32_t aMaxKeyLease)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Server>().SetLeaseRange(aMinLease, aMaxLease, aMinKeyLease, aMaxKeyLease);
+}
+
+void otSrpServerSetServiceUpdateHandler(otInstance * aInstance,
+ otSrpServerServiceUpdateHandler aServiceHandler,
+ void * aContext)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Server>().SetServiceHandler(aServiceHandler, aContext);
+}
+
+void otSrpServerHandleServiceUpdateResult(otInstance *aInstance, const otSrpServerHost *aHost, otError aError)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<Srp::Server>().HandleServiceUpdateResult(static_cast<const Srp::Server::Host *>(aHost), aError);
+}
+
+const otSrpServerHost *otSrpServerGetNextHost(otInstance *aInstance, const otSrpServerHost *aHost)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<Srp::Server>().GetNextHost(static_cast<const Srp::Server::Host *>(aHost));
+}
+
+bool otSrpServerHostIsDeleted(const otSrpServerHost *aHost)
+{
+ return static_cast<const Srp::Server::Host *>(aHost)->IsDeleted();
+}
+
+const char *otSrpServerHostGetFullName(const otSrpServerHost *aHost)
+{
+ return static_cast<const Srp::Server::Host *>(aHost)->GetFullName();
+}
+
+const otIp6Address *otSrpServerHostGetAddresses(const otSrpServerHost *aHost, uint8_t *aAddressesNum)
+{
+ auto host = static_cast<const Srp::Server::Host *>(aHost);
+
+ return host->GetAddresses(*aAddressesNum);
+}
+
+const otSrpServerService *otSrpServerHostGetNextService(const otSrpServerHost * aHost,
+ const otSrpServerService *aService)
+{
+ auto host = static_cast<const Srp::Server::Host *>(aHost);
+
+ return host->GetNextService(static_cast<const Srp::Server::Service *>(aService));
+}
+
+bool otSrpServerServiceIsDeleted(const otSrpServerService *aService)
+{
+ return static_cast<const Srp::Server::Service *>(aService)->IsDeleted();
+}
+
+const char *otSrpServerServiceGetFullName(const otSrpServerService *aService)
+{
+ return static_cast<const Srp::Server::Service *>(aService)->GetFullName();
+}
+
+uint16_t otSrpServerServiceGetPort(const otSrpServerService *aService)
+{
+ return static_cast<const Srp::Server::Service *>(aService)->GetPort();
+}
+
+uint16_t otSrpServerServiceGetWeight(const otSrpServerService *aService)
+{
+ return static_cast<const Srp::Server::Service *>(aService)->GetWeight();
+}
+
+uint16_t otSrpServerServiceGetPriority(const otSrpServerService *aService)
+{
+ return static_cast<const Srp::Server::Service *>(aService)->GetPriority();
+}
+
+const uint8_t *otSrpServerServiceGetTxtData(const otSrpServerService *aService, uint16_t *aDataLength)
+{
+ const Srp::Server::Service &service = *static_cast<const Srp::Server::Service *>(aService);
+
+ *aDataLength = service.GetTxtDataLength();
+
+ return service.GetTxtData();
+}
+
+const otSrpServerHost *otSrpServerServiceGetHost(const otSrpServerService *aService)
+{
+ return &static_cast<const Srp::Server::Service *>(aService)->GetHost();
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp
index 2a2607c..1469336 100644
--- a/src/core/api/thread_api.cpp
+++ b/src/core/api/thread_api.cpp
@@ -66,12 +66,12 @@
otError otThreadSetExtendedPanId(otInstance *aInstance, const otExtendedPanId *aExtendedPanId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
const Mac::ExtendedPanId &extPanId = *static_cast<const Mac::ExtendedPanId *>(aExtendedPanId);
Mle::MeshLocalPrefix prefix;
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<Mac::Mac>().SetExtendedPanId(extPanId);
@@ -120,12 +120,12 @@
otError otThreadSetMasterKey(otInstance *aInstance, const otMasterKey *aKey)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aKey != nullptr);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
error = instance.Get<KeyManager>().SetMasterKey(*static_cast<const MasterKey *>(aKey));
instance.Get<MeshCoP::ActiveDataset>().Clear();
@@ -158,10 +158,10 @@
otError otThreadSetMeshLocalPrefix(otInstance *aInstance, const otMeshLocalPrefix *aMeshLocalPrefix)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<Mle::MleRouter>().SetMeshLocalPrefix(*static_cast<const Mle::MeshLocalPrefix *>(aMeshLocalPrefix));
instance.Get<MeshCoP::ActiveDataset>().Clear();
@@ -187,10 +187,10 @@
otError otThreadSetNetworkName(otInstance *aInstance, const char *aNetworkName)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
error = instance.Get<Mac::Mac>().SetNetworkName(aNetworkName);
instance.Get<MeshCoP::ActiveDataset>().Clear();
@@ -210,10 +210,10 @@
otError otThreadSetDomainName(otInstance *aInstance, const char *aDomainName)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
error = instance.Get<Mac::Mac>().SetDomainName(aDomainName);
@@ -225,7 +225,7 @@
otError otThreadSetFixedDuaInterfaceIdentifier(otInstance *aInstance, const otIp6InterfaceIdentifier *aIid)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aIid)
{
@@ -317,11 +317,11 @@
otError otThreadGetLeaderData(otInstance *aInstance, otLeaderData *aLeaderData)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
OT_ASSERT(aLeaderData != nullptr);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsAttached(), error = OT_ERROR_DETACHED);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsAttached(), error = kErrorDetached);
*aLeaderData = instance.Get<Mle::MleRouter>().GetLeaderData();
exit:
@@ -359,14 +359,14 @@
otError otThreadGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
{
Instance &instance = *static_cast<Instance *>(aInstance);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Router * parent;
OT_ASSERT(aParentInfo != nullptr);
// Reference device needs get the original parent's info even after the node state changed.
#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsChild(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsChild(), error = kErrorInvalidState);
#endif
parent = &instance.Get<Mle::MleRouter>().GetParent();
@@ -390,14 +390,14 @@
otError otThreadGetParentAverageRssi(otInstance *aInstance, int8_t *aParentRssi)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aParentRssi != nullptr);
*aParentRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetAverageRss();
- VerifyOrExit(*aParentRssi != OT_RADIO_RSSI_INVALID, error = OT_ERROR_FAILED);
+ VerifyOrExit(*aParentRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
exit:
return error;
@@ -405,14 +405,14 @@
otError otThreadGetParentLastRssi(otInstance *aInstance, int8_t *aLastRssi)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
OT_ASSERT(aLastRssi != nullptr);
*aLastRssi = instance.Get<Mle::MleRouter>().GetParent().GetLinkInfo().GetLastRss();
- VerifyOrExit(*aLastRssi != OT_RADIO_RSSI_INVALID, error = OT_ERROR_FAILED);
+ VerifyOrExit(*aLastRssi != OT_RADIO_RSSI_INVALID, error = kErrorFailed);
exit:
return error;
@@ -420,7 +420,7 @@
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
if (aEnabled)
diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp
index eb5dc3a..221ddda 100644
--- a/src/core/api/thread_ftd_api.cpp
+++ b/src/core/api/thread_ftd_api.cpp
@@ -139,7 +139,7 @@
instance.Get<MeshCoP::JoinerRouter>().SetJoinerUdpPort(aJoinerUdpPort);
- return OT_ERROR_NONE;
+ return kErrorNone;
}
uint32_t otThreadGetContextIdReuseDelay(otInstance *aInstance)
@@ -186,10 +186,10 @@
otError otThreadReleaseRouterId(otInstance *aInstance, uint8_t aRouterId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(aRouterId <= Mle::kMaxRouterId, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aRouterId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
error = instance.Get<RouterTable>().Release(aRouterId);
@@ -199,7 +199,7 @@
otError otThreadBecomeRouter(otInstance *aInstance)
{
- otError error = OT_ERROR_INVALID_STATE;
+ Error error = kErrorInvalidState;
Instance &instance = *static_cast<Instance *>(aInstance);
switch (instance.Get<Mle::MleRouter>().GetRole())
@@ -214,7 +214,7 @@
case Mle::kRoleRouter:
case Mle::kRoleLeader:
- error = OT_ERROR_NONE;
+ error = kErrorNone;
break;
}
@@ -279,20 +279,20 @@
otChildIp6AddressIterator *aIterator,
otIp6Address * aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance & instance = *static_cast<Instance *>(aInstance);
const Child *child;
OT_ASSERT(aIterator != nullptr && aAddress != nullptr);
child = instance.Get<ChildTable>().GetChildAtIndex(aChildIndex);
- VerifyOrExit(child != nullptr, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(child->IsStateValidOrRestoring(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(child != nullptr, error = kErrorInvalidArgs);
+ VerifyOrExit(child->IsStateValidOrRestoring(), error = kErrorInvalidArgs);
{
Child::AddressIterator iter(*child, *aIterator);
- VerifyOrExit(!iter.IsDone(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!iter.IsDone(), error = kErrorNotFound);
*aAddress = *iter.GetAddress();
iter++;
@@ -352,10 +352,10 @@
otError otThreadSetPskc(otInstance *aInstance, const otPskc *aPskc)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Instance &instance = *static_cast<Instance *>(aInstance);
- VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(instance.Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
instance.Get<KeyManager>().SetPskc(*static_cast<const Pskc *>(aPskc));
instance.Get<MeshCoP::ActiveDataset>().Clear();
diff --git a/src/core/api/udp_api.cpp b/src/core/api/udp_api.cpp
index bd907e7..7bd961b 100644
--- a/src/core/api/udp_api.cpp
+++ b/src/core/api/udp_api.cpp
@@ -68,7 +68,7 @@
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().Bind(*static_cast<Ip6::Udp::SocketHandle *>(aSocket),
- *static_cast<const Ip6::SockAddr *>(aSockName));
+ *static_cast<const Ip6::SockAddr *>(aSockName), OT_NETIF_THREAD);
}
otError otUdpConnect(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName)
diff --git a/src/core/backbone_router/backbone_tmf.cpp b/src/core/backbone_router/backbone_tmf.cpp
index 75ff364..ebc0f23 100644
--- a/src/core/backbone_router/backbone_tmf.cpp
+++ b/src/core/backbone_router/backbone_tmf.cpp
@@ -36,13 +36,14 @@
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
namespace ot {
namespace BackboneRouter {
-otError BackboneTmfAgent::Start(void)
+Error BackboneTmfAgent::Start(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = Coap::Start(kBackboneUdpPort, OT_NETIF_BACKBONE));
SubscribeMulticast(Get<Local>().GetAllNetworkBackboneRoutersAddress());
@@ -51,14 +52,11 @@
return error;
}
-otError BackboneTmfAgent::Filter(const ot::Coap::Message &aMessage,
- const Ip6::MessageInfo & aMessageInfo,
- void * aContext)
+Error BackboneTmfAgent::Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
{
OT_UNUSED_VARIABLE(aMessage);
- return static_cast<BackboneTmfAgent *>(aContext)->IsBackboneTmfMessage(aMessageInfo) ? OT_ERROR_NONE
- : OT_ERROR_NOT_TMF;
+ return static_cast<BackboneTmfAgent *>(aContext)->IsBackboneTmfMessage(aMessageInfo) ? kErrorNone : kErrorNotTmf;
}
bool BackboneTmfAgent::IsBackboneTmfMessage(const Ip6::MessageInfo &aMessageInfo) const
@@ -79,34 +77,20 @@
void BackboneTmfAgent::SubscribeMulticast(const Ip6::Address &aAddress)
{
- otError error;
+ Error error;
error = mSocket.JoinNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
- if (error != OT_ERROR_NONE)
- {
- otLogDebgBbr("Backbone TMF subscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
- }
- else
- {
- otLogCritBbr("Backbone TMF subscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
- }
+ otLogResultBbr(error, "Backbone TMF subscribes %s", aAddress.ToString().AsCString());
}
void BackboneTmfAgent::UnsubscribeMulticast(const Ip6::Address &aAddress)
{
- otError error;
+ Error error;
error = mSocket.LeaveNetifMulticastGroup(OT_NETIF_BACKBONE, aAddress);
- if (error == OT_ERROR_NONE)
- {
- otLogDebgBbr("Backbone TMF unsubscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
- }
- else
- {
- otLogCritBbr("Backbone TMF unsubscribes %s: %s", aAddress.ToString().AsCString(), otThreadErrorToString(error));
- }
+ otLogResultBbr(error, "Backbone TMF unsubscribes %s", aAddress.ToString().AsCString());
}
} // namespace BackboneRouter
diff --git a/src/core/backbone_router/backbone_tmf.hpp b/src/core/backbone_router/backbone_tmf.hpp
index 5137045..dddf14f 100644
--- a/src/core/backbone_router/backbone_tmf.hpp
+++ b/src/core/backbone_router/backbone_tmf.hpp
@@ -66,11 +66,11 @@
/**
* This method starts the Backbone TMF agent.
*
- * @retval OT_ERROR_NONE Successfully started the CoAP service.
- * @retval OT_ERROR_FAILED Failed to start the Backbone TMF agent.
+ * @retval kErrorNone Successfully started the CoAP service.
+ * @retval kErrorFailed Failed to start the Backbone TMF agent.
*
*/
- otError Start(void);
+ Error Start(void);
/**
* This method returns whether @p aMessageInfo meets Backbone Thread Management Framework Addressing Rules.
@@ -98,7 +98,7 @@
void UnsubscribeMulticast(const Ip6::Address &aAddress);
private:
- static otError Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
+ static Error Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
};
} // namespace BackboneRouter
diff --git a/src/core/backbone_router/bbr_leader.cpp b/src/core/backbone_router/bbr_leader.cpp
index 806f200..1ccfa46 100644
--- a/src/core/backbone_router/bbr_leader.cpp
+++ b/src/core/backbone_router/bbr_leader.cpp
@@ -57,11 +57,11 @@
mDomainPrefix.SetLength(0);
}
-otError Leader::GetConfig(BackboneRouterConfig &aConfig) const
+Error Leader::GetConfig(BackboneRouterConfig &aConfig) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(HasPrimary(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(HasPrimary(), error = kErrorNotFound);
aConfig = mConfig;
@@ -69,15 +69,13 @@
return error;
}
-otError Leader::GetServiceId(uint8_t &aServiceId) const
+Error Leader::GetServiceId(uint8_t &aServiceId) const
{
- otError error = OT_ERROR_NONE;
- uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter;
+ Error error = kErrorNone;
- VerifyOrExit(HasPrimary(), error = OT_ERROR_NOT_FOUND);
-
- error = Get<NetworkData::Leader>().GetServiceId(NetworkData::ServiceTlv::kThreadEnterpriseNumber, &serviceData,
- sizeof(serviceData), true, aServiceId);
+ VerifyOrExit(HasPrimary(), error = kErrorNotFound);
+ error = Get<NetworkData::Service::Manager>().GetServiceId<NetworkData::Service::BackboneRouter>(
+ /* aServerStable */ true, aServiceId);
exit:
return error;
@@ -182,7 +180,7 @@
State state;
uint32_t origMlrTimeout;
- IgnoreError(Get<NetworkData::Leader>().GetBackboneRouterPrimary(config));
+ Get<NetworkData::Service::Manager>().GetBackboneRouterPrimary(config);
if (config.mServer16 != mConfig.mServer16)
{
@@ -258,7 +256,7 @@
DomainPrefixState state;
bool found = false;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
if (config.mDp)
{
diff --git a/src/core/backbone_router/bbr_leader.hpp b/src/core/backbone_router/bbr_leader.hpp
index 53e373c..f437d9d 100644
--- a/src/core/backbone_router/bbr_leader.hpp
+++ b/src/core/backbone_router/bbr_leader.hpp
@@ -106,22 +106,22 @@
*
* @param[out] aConfig The Primary Backbone Router information.
*
- * @retval OT_ERROR_NONE Successfully got the Primary Backbone Router information.
- * @retval OT_ERROR_NOT_FOUND No Backbone Router in the Thread Network.
+ * @retval kErrorNone Successfully got the Primary Backbone Router information.
+ * @retval kErrorNotFound No Backbone Router in the Thread Network.
*
*/
- otError GetConfig(BackboneRouterConfig &aConfig) const;
+ Error GetConfig(BackboneRouterConfig &aConfig) const;
/**
* This method gets the Backbone Router Service ID.
*
* @param[out] aServiceId The reference whether to put the Backbone Router Service ID.
*
- * @retval OT_ERROR_NONE Successfully got the Backbone Router Service ID.
- * @retval OT_ERROR_NOT_FOUND Backbone Router service doesn't exist.
+ * @retval kErrorNone Successfully got the Backbone Router Service ID.
+ * @retval kErrorNotFound Backbone Router service doesn't exist.
*
*/
- otError GetServiceId(uint8_t &aServiceId) const;
+ Error GetServiceId(uint8_t &aServiceId) const;
/**
* This method gets the short address of the Primary Backbone Router.
diff --git a/src/core/backbone_router/bbr_local.cpp b/src/core/backbone_router/bbr_local.cpp
index 19a3a2f..6a0d9bd 100644
--- a/src/core/backbone_router/bbr_local.cpp
+++ b/src/core/backbone_router/bbr_local.cpp
@@ -92,12 +92,10 @@
else
{
RemoveDomainPrefixFromNetworkData();
- IgnoreError(RemoveService());
+ RemoveService();
SetState(OT_BACKBONE_ROUTER_STATE_DISABLED);
}
- Get<NetworkData::Notifier>().HandleServerDataUpdated();
-
exit:
return;
}
@@ -106,10 +104,7 @@
{
VerifyOrExit(mState != OT_BACKBONE_ROUTER_STATE_DISABLED);
- if (RemoveService() == OT_ERROR_NONE)
- {
- Get<NetworkData::Notifier>().HandleServerDataUpdated();
- }
+ RemoveService();
if (mState == OT_BACKBONE_ROUTER_STATE_PRIMARY)
{
@@ -130,19 +125,19 @@
aConfig.mMlrTimeout = mMlrTimeout;
}
-otError Local::SetConfig(const BackboneRouterConfig &aConfig)
+Error Local::SetConfig(const BackboneRouterConfig &aConfig)
{
- otError error = OT_ERROR_NONE;
- bool update = false;
+ Error error = kErrorNone;
+ bool update = false;
VerifyOrExit(aConfig.mMlrTimeout >= Mle::kMlrTimeoutMin && aConfig.mMlrTimeout <= Mle::kMlrTimeoutMax,
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
// Validate configuration according to Thread 1.2.1 Specification 5.21.3.3:
// "The Reregistration Delay in seconds MUST be lower than (0.5 * MLR Timeout). It MUST be at least 1."
- VerifyOrExit(aConfig.mReregistrationDelay >= 1, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aConfig.mReregistrationDelay >= 1, error = kErrorInvalidArgs);
static_assert(sizeof(aConfig.mReregistrationDelay) < sizeof(aConfig.mMlrTimeout),
"the calculation below might overflow");
- VerifyOrExit(aConfig.mReregistrationDelay * 2 < aConfig.mMlrTimeout, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aConfig.mReregistrationDelay * 2 < aConfig.mMlrTimeout, error = kErrorInvalidArgs);
if (aConfig.mReregistrationDelay != mReregistrationDelay)
{
@@ -166,10 +161,7 @@
{
Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
- if (AddService() == OT_ERROR_NONE)
- {
- Get<NetworkData::Notifier>().HandleServerDataUpdated();
- }
+ IgnoreError(AddService());
}
exit:
@@ -177,11 +169,10 @@
return error;
}
-otError Local::AddService(bool aForce)
+Error Local::AddService(bool aForce)
{
- otError error = OT_ERROR_INVALID_STATE;
- uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter;
- NetworkData::BackboneRouterServerData serverData;
+ Error error = kErrorInvalidState;
+ NetworkData::Service::BackboneRouter::ServerData serverData;
VerifyOrExit(mState != OT_BACKBONE_ROUTER_STATE_DISABLED && Get<Mle::Mle>().IsAttached());
@@ -195,10 +186,7 @@
serverData.SetReregistrationDelay(mReregistrationDelay);
serverData.SetMlrTimeout(mMlrTimeout);
- SuccessOrExit(error = Get<NetworkData::Local>().AddService(
- NetworkData::ServiceTlv::kThreadEnterpriseNumber, &serviceData, sizeof(serviceData), true,
- reinterpret_cast<const uint8_t *>(&serverData), sizeof(serverData)));
-
+ SuccessOrExit(error = Get<NetworkData::Service::Manager>().Add<NetworkData::Service::BackboneRouter>(serverData));
mIsServiceAdded = true;
exit:
@@ -206,19 +194,15 @@
return error;
}
-otError Local::RemoveService(void)
+void Local::RemoveService(void)
{
- otError error;
- uint8_t serviceData = NetworkData::ServiceTlv::kServiceDataBackboneRouter;
+ Error error;
- SuccessOrExit(error = Get<NetworkData::Local>().RemoveService(NetworkData::ServiceTlv::kThreadEnterpriseNumber,
- &serviceData, sizeof(serviceData)));
-
+ SuccessOrExit(error = Get<NetworkData::Service::Manager>().Remove<NetworkData::Service::BackboneRouter>());
mIsServiceAdded = false;
exit:
LogBackboneRouterService("Remove", error);
- return error;
}
void Local::SetState(BackboneRouterState aState)
@@ -282,7 +266,7 @@
mReregistrationDelay = aConfig.mReregistrationDelay;
mMlrTimeout = aConfig.mMlrTimeout;
Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
- if (AddService(true /* Force registration to refresh and restore Primary state */) == OT_ERROR_NONE)
+ if (AddService(true /* Force registration to refresh and restore Primary state */) == kErrorNone)
{
Get<NetworkData::Notifier>().HandleServerDataUpdated();
}
@@ -296,11 +280,11 @@
return;
}
-otError Local::GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig)
+Error Local::GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mDomainPrefixConfig.GetPrefix().GetLength() > 0, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(mDomainPrefixConfig.GetPrefix().GetLength() > 0, error = kErrorNotFound);
aConfig = mDomainPrefixConfig;
@@ -308,12 +292,12 @@
return error;
}
-otError Local::RemoveDomainPrefix(const Ip6::Prefix &aPrefix)
+Error Local::RemoveDomainPrefix(const Ip6::Prefix &aPrefix)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aPrefix.GetLength() > 0, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(mDomainPrefixConfig.GetPrefix() == aPrefix, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aPrefix.GetLength() > 0, error = kErrorInvalidArgs);
+ VerifyOrExit(mDomainPrefixConfig.GetPrefix() == aPrefix, error = kErrorNotFound);
if (IsEnabled())
{
@@ -334,7 +318,7 @@
}
mDomainPrefixConfig = aConfig;
- LogDomainPrefix("Set", OT_ERROR_NONE);
+ LogDomainPrefix("Set", kErrorNone);
if (IsEnabled())
{
@@ -406,7 +390,7 @@
void Local::RemoveDomainPrefixFromNetworkData(void)
{
- otError error = OT_ERROR_NOT_FOUND; // only used for logging.
+ Error error = kErrorNotFound; // only used for logging.
if (mDomainPrefixConfig.mPrefix.mLength > 0)
{
@@ -418,7 +402,7 @@
void Local::AddDomainPrefixToNetworkData(void)
{
- otError error = OT_ERROR_NOT_FOUND; // only used for logging.
+ Error error = kErrorNotFound; // only used for logging.
if (mDomainPrefixConfig.GetPrefix().GetLength() > 0)
{
@@ -429,16 +413,16 @@
}
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
-void Local::LogDomainPrefix(const char *aAction, otError aError)
+void Local::LogDomainPrefix(const char *aAction, Error aError)
{
otLogInfoBbr("%s Domain Prefix: %s, %s", aAction, mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
- otThreadErrorToString(aError));
+ ErrorToString(aError));
}
-void Local::LogBackboneRouterService(const char *aAction, otError aError)
+void Local::LogBackboneRouterService(const char *aAction, Error aError)
{
otLogInfoBbr("%s BBR Service: seqno (%d), delay (%ds), timeout (%ds), %s", aAction, mSequenceNumber,
- mReregistrationDelay, mMlrTimeout, otThreadErrorToString(aError));
+ mReregistrationDelay, mMlrTimeout, ErrorToString(aError));
}
#endif
diff --git a/src/core/backbone_router/bbr_local.hpp b/src/core/backbone_router/bbr_local.hpp
index 7d1b828..ba6d274 100644
--- a/src/core/backbone_router/bbr_local.hpp
+++ b/src/core/backbone_router/bbr_local.hpp
@@ -37,6 +37,15 @@
#include "openthread-core-config.h"
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE."
+#endif
+
+#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE."
+#endif
+
#include <openthread/backbone_router.h>
#include <openthread/backbone_router_ftd.h>
@@ -105,11 +114,11 @@
*
* @param[in] aConfig The configuration to set.
*
- * @retval OT_ERROR_NONE Successfully updated configuration.
- * @retval OT_ERROR_INVALID_ARGS The configuration in @p aConfig is invalid.
+ * @retval kErrorNone Successfully updated configuration.
+ * @retval kErrorInvalidArgs The configuration in @p aConfig is invalid.
*
*/
- otError SetConfig(const BackboneRouterConfig &aConfig);
+ Error SetConfig(const BackboneRouterConfig &aConfig);
/**
* This method registers Backbone Router Dataset to Leader.
@@ -118,12 +127,12 @@
* False to decide based on current BackboneRouterState.
*
*
- * @retval OT_ERROR_NONE Successfully added the Service entry.
- * @retval OT_ERROR_INVALID_STATE Not in the ready state to register.
- * @retval OT_ERROR_NO_BUFS Insufficient space to add the Service entry.
+ * @retval kErrorNone Successfully added the Service entry.
+ * @retval kErrorInvalidState Not in the ready state to register.
+ * @retval kErrorNoBufs Insufficient space to add the Service entry.
*
*/
- otError AddService(bool aForce = false);
+ Error AddService(bool aForce = false);
/**
* This method indicates whether or not the Backbone Router is Primary.
@@ -173,23 +182,23 @@
*
* @param[out] aConfig A reference to the Domain Prefix configuration.
*
- * @retval OT_ERROR_NONE Successfully got the Domain Prefix configuration.
- * @retval OT_ERROR_NOT_FOUND No Domain Prefix was configured.
+ * @retval kErrorNone Successfully got the Domain Prefix configuration.
+ * @retval kErrorNotFound No Domain Prefix was configured.
*
*/
- otError GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig);
+ Error GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig);
/**
* This method removes the local Domain Prefix configuration.
*
* @param[in] aPrefix A reference to the IPv6 Domain Prefix.
*
- * @retval OT_ERROR_NONE Successfully removed the Domain Prefix.
- * @retval OT_ERROR_INVALID_ARGS @p aPrefix is invalid.
- * @retval OT_ERROR_NOT_FOUND No Domain Prefix was configured or @p aPrefix doesn't match.
+ * @retval kErrorNone Successfully removed the Domain Prefix.
+ * @retval kErrorInvalidArgs @p aPrefix is invalid.
+ * @retval kErrorNotFound No Domain Prefix was configured or @p aPrefix doesn't match.
*
*/
- otError RemoveDomainPrefix(const Ip6::Prefix &aPrefix);
+ Error RemoveDomainPrefix(const Ip6::Prefix &aPrefix);
/**
* This method sets the local Domain Prefix configuration.
@@ -239,16 +248,16 @@
void SetDomainPrefixCallback(otBackboneRouterDomainPrefixCallback aCallback, void *aContext);
private:
- void SetState(BackboneRouterState aState);
- otError RemoveService(void);
- void AddDomainPrefixToNetworkData(void);
- void RemoveDomainPrefixFromNetworkData(void);
+ void SetState(BackboneRouterState aState);
+ void RemoveService(void);
+ void AddDomainPrefixToNetworkData(void);
+ void RemoveDomainPrefixFromNetworkData(void);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1)
- void LogBackboneRouterService(const char *aAction, otError aError);
- void LogDomainPrefix(const char *aAction, otError aError);
+ void LogBackboneRouterService(const char *aAction, Error aError);
+ void LogDomainPrefix(const char *aAction, Error aError);
#else
- void LogBackboneRouterService(const char *, otError) {}
- void LogDomainPrefix(const char *, otError) {}
+ void LogBackboneRouterService(const char *, Error) {}
+ void LogDomainPrefix(const char *, Error) {}
#endif
BackboneRouterState mState;
diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp
index 43519f3..e300a69 100644
--- a/src/core/backbone_router/bbr_manager.cpp
+++ b/src/core/backbone_router/bbr_manager.cpp
@@ -63,7 +63,7 @@
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
, mMulticastListenersTable(aInstance)
#endif
- , mTimer(aInstance, Manager::HandleTimer, this)
+ , mTimer(aInstance, Manager::HandleTimer)
, mBackboneTmfAgent(aInstance)
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
@@ -88,7 +88,7 @@
void Manager::HandleNotifierEvents(Events aEvents)
{
- otError error;
+ Error error;
if (aEvents.Contains(kEventThreadBackboneRouterStateChanged))
{
@@ -105,13 +105,13 @@
error = mBackboneTmfAgent.Stop();
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnBbr("Stop Backbone TMF agent: %s", otThreadErrorToString(error));
+ otLogWarnBbr("Stop Backbone TMF agent: %s", ErrorToString(error));
}
else
{
- otLogInfoBbr("Stop Backbone TMF agent: %s", otThreadErrorToString(error));
+ otLogInfoBbr("Stop Backbone TMF agent: %s", ErrorToString(error));
}
}
else
@@ -129,18 +129,16 @@
error = mBackboneTmfAgent.Start();
- if (error != OT_ERROR_NONE)
- {
- otLogCritBbr("Start Backbone TMF agent: %s", otThreadErrorToString(error));
- }
- else
- {
- otLogInfoBbr("Start Backbone TMF agent: %s", otThreadErrorToString(error));
- }
+ otLogResultBbr(error, "Start Backbone TMF agent");
}
}
}
+void Manager::HandleTimer(Timer &aTimer)
+{
+ aTimer.Get<Manager>().HandleTimer();
+}
+
void Manager::HandleTimer(void)
{
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
@@ -157,14 +155,14 @@
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
bool isPrimary = Get<BackboneRouter::Local>().IsPrimary();
ThreadStatusTlv::MlrStatus status = ThreadStatusTlv::kMlrSuccess;
BackboneRouterConfig config;
uint16_t addressesOffset, addressesLength;
Ip6::Address address;
- Ip6::Address addresses[kIPv6AddressesNumMax];
+ Ip6::Address addresses[kIp6AddressesNumMax];
uint8_t failedAddressNum = 0;
uint8_t successAddressNum = 0;
TimeMilli expireTime;
@@ -173,7 +171,7 @@
bool hasCommissionerSessionIdTlv = false;
bool processTimeoutTlv = false;
- VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
// Required by Test Specification 5.10.22 DUA-TC-26, only for certification purpose
@@ -188,7 +186,7 @@
// TODO: (MLR) send configured MLR response for Reference Device
- if (Tlv::Find<ThreadCommissionerSessionIdTlv>(aMessage, commissionerSessionId) == OT_ERROR_NONE)
+ if (Tlv::Find<ThreadCommissionerSessionIdTlv>(aMessage, commissionerSessionId) == kErrorNone)
{
const MeshCoP::CommissionerSessionIdTlv *commissionerSessionIdTlv =
static_cast<const MeshCoP::CommissionerSessionIdTlv *>(
@@ -201,14 +199,13 @@
hasCommissionerSessionIdTlv = true;
}
- processTimeoutTlv =
- hasCommissionerSessionIdTlv && (Tlv::Find<ThreadTimeoutTlv>(aMessage, timeout) == OT_ERROR_NONE);
+ processTimeoutTlv = hasCommissionerSessionIdTlv && (Tlv::Find<ThreadTimeoutTlv>(aMessage, timeout) == kErrorNone);
- VerifyOrExit(Tlv::FindTlvValueOffset(aMessage, IPv6AddressesTlv::kIPv6Addresses, addressesOffset,
- addressesLength) == OT_ERROR_NONE,
- error = OT_ERROR_PARSE);
+ VerifyOrExit(Tlv::FindTlvValueOffset(aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
+ kErrorNone,
+ error = kErrorParse);
VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
- VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIPv6AddressesNumMax,
+ VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIp6AddressesNumMax,
status = ThreadStatusTlv::kMlrGeneralFailure);
if (!processTimeoutTlv)
@@ -251,16 +248,16 @@
switch (mMulticastListenersTable.Add(address, expireTime))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
failed = false;
break;
- case OT_ERROR_INVALID_ARGS:
+ case kErrorInvalidArgs:
if (status == ThreadStatusTlv::kMlrSuccess)
{
status = ThreadStatusTlv::kMlrInvalid;
}
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
if (status == ThreadStatusTlv::kMlrSuccess)
{
status = ThreadStatusTlv::kMlrNoResources;
@@ -277,20 +274,20 @@
else
{
// Put successfully registered addresses at the end of `addresses`.
- addresses[kIPv6AddressesNumMax - (++successAddressNum)] = address;
+ addresses[kIp6AddressesNumMax - (++successAddressNum)] = address;
}
}
}
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
SendMulticastListenerRegistrationResponse(aMessage, aMessageInfo, status, addresses, failedAddressNum);
}
if (successAddressNum > 0)
{
- SendBackboneMulticastListenerRegistration(&addresses[kIPv6AddressesNumMax - successAddressNum],
+ SendBackboneMulticastListenerRegistration(&addresses[kIp6AddressesNumMax - successAddressNum],
successAddressNum, timeout);
}
}
@@ -301,10 +298,10 @@
Ip6::Address * aFailedAddresses,
uint8_t aFailedAddressNum)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message = nullptr;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(message->SetDefaultResponseHeader(aMessage));
SuccessOrExit(message->SetPayloadMarker());
@@ -313,7 +310,7 @@
if (aFailedAddressNum > 0)
{
- IPv6AddressesTlv addressesTlv;
+ Ip6AddressesTlv addressesTlv;
addressesTlv.Init();
addressesTlv.SetLength(sizeof(Ip6::Address) * aFailedAddressNum);
@@ -329,22 +326,22 @@
exit:
FreeMessageOnError(message, error);
- otLogInfoBbr("Sent MLR.rsp (status=%d): %s", aStatus, otThreadErrorToString(error));
+ otLogInfoBbr("Sent MLR.rsp (status=%d): %s", aStatus, ErrorToString(error));
}
void Manager::SendBackboneMulticastListenerRegistration(const Ip6::Address *aAddresses,
uint8_t aAddressNum,
uint32_t aTimeout)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- IPv6AddressesTlv addressesTlv;
+ Ip6AddressesTlv addressesTlv;
BackboneTmfAgent &backboneTmf = Get<BackboneRouter::BackboneTmfAgent>();
- OT_ASSERT(aAddressNum >= kIPv6AddressesNumMin && aAddressNum <= kIPv6AddressesNumMax);
+ OT_ASSERT(aAddressNum >= kIp6AddressesNumMin && aAddressNum <= kIp6AddressesNumMax);
- VerifyOrExit((message = backboneTmf.NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = backboneTmf.NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kBackboneMlr));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -366,14 +363,14 @@
exit:
FreeMessageOnError(message, error);
- otLogInfoBbr("Sent BMLR.ntf: %s", otThreadErrorToString(error));
+ otLogInfoBbr("Sent BMLR.ntf: %s", ErrorToString(error));
}
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
void Manager::HandleDuaRegistration(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ThreadStatusTlv::DuaStatus status = ThreadStatusTlv::kDuaSuccess;
bool isPrimary = Get<BackboneRouter::Local>().IsPrimary();
uint32_t lastTransactionTime;
@@ -384,8 +381,8 @@
Coap::Code duaRespCoapCode = Coap::kCodeEmpty;
#endif
- VerifyOrExit(aMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator(), error = OT_ERROR_DROP);
- VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator(), error = kErrorDrop);
+ VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMessage, target));
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMessage, meshLocalIid));
@@ -410,19 +407,19 @@
VerifyOrExit(Get<BackboneRouter::Leader>().HasDomainPrefix(), status = ThreadStatusTlv::kDuaGeneralFailure);
VerifyOrExit(Get<BackboneRouter::Leader>().IsDomainUnicast(target), status = ThreadStatusTlv::kDuaInvalid);
- hasLastTransactionTime = (Tlv::Find<ThreadLastTransactionTimeTlv>(aMessage, lastTransactionTime) == OT_ERROR_NONE);
+ hasLastTransactionTime = (Tlv::Find<ThreadLastTransactionTimeTlv>(aMessage, lastTransactionTime) == kErrorNone);
switch (mNdProxyTable.Register(target.GetIid(), meshLocalIid, aMessageInfo.GetPeerAddr().GetIid().GetLocator(),
hasLastTransactionTime ? &lastTransactionTime : nullptr))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
// TODO: update its EID-to-RLOC Map Cache based on the pair {DUA, RLOC16-source} which is gleaned from the
// DUA.req packet according to Thread Spec. 5.23.3.6.2
break;
- case OT_ERROR_DUPLICATED:
+ case kErrorDuplicated:
status = ThreadStatusTlv::kDuaDuplicate;
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
status = ThreadStatusTlv::kDuaNoResources;
break;
default:
@@ -431,9 +428,9 @@
}
exit:
- otLogInfoBbr("Received DUA.req on %s: %s", (isPrimary ? "PBBR" : "SBBR"), otThreadErrorToString(error));
+ otLogInfoBbr("Received DUA.req on %s: %s", (isPrimary ? "PBBR" : "SBBR"), ErrorToString(error));
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
if (duaRespCoapCode != Coap::kCodeEmpty)
@@ -453,10 +450,10 @@
const Ip6::Address & aTarget,
ThreadStatusTlv::DuaStatus aStatus)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message = nullptr;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(message->SetDefaultResponseHeader(aMessage));
SuccessOrExit(message->SetPayloadMarker());
@@ -469,7 +466,7 @@
exit:
FreeMessageOnError(message, error);
otLogInfoBbr("Sent DUA.rsp for DUA %s, status %d %s", aTarget.ToString().AsCString(), aStatus,
- otThreadErrorToString(error));
+ ErrorToString(error));
}
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
@@ -511,7 +508,7 @@
{
bool forwardToBackbone = false;
Mac::ShortAddress rloc16;
- otError error;
+ Error error;
VerifyOrExit(Get<Local>().IsPrimary());
VerifyOrExit(Get<Leader>().IsDomainUnicast(aAddress));
@@ -519,7 +516,7 @@
VerifyOrExit(!mNdProxyTable.IsRegistered(aAddress.GetIid()));
error = Get<AddressResolver>().Resolve(aAddress, rloc16, /* aAllowAddressQuery */ false);
- VerifyOrExit(error != OT_ERROR_NONE || rloc16 == Get<Mle::MleRouter>().GetRloc16());
+ VerifyOrExit(error != kErrorNone || rloc16 == Get<Mle::MleRouter>().GetRloc16());
// TODO: check if the DUA is an address of any Child?
forwardToBackbone = true;
@@ -528,15 +525,15 @@
return forwardToBackbone;
}
-otError Manager::SendBackboneQuery(const Ip6::Address &aDua, uint16_t aRloc16)
+Error Manager::SendBackboneQuery(const Ip6::Address &aDua, uint16_t aRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- VerifyOrExit(Get<BackboneRouter::Local>().IsPrimary(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(Get<BackboneRouter::Local>().IsPrimary(), error = kErrorInvalidState);
- VerifyOrExit((message = mBackboneTmfAgent.NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mBackboneTmfAgent.NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kBackboneQuery));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -558,7 +555,7 @@
exit:
otLogInfoBbr("SendBackboneQuery for %s (rloc16=%04x): %s", aDua.ToString().AsCString(), aRloc16,
- otThreadErrorToString(error));
+ ErrorToString(error));
FreeMessageOnError(message, error);
return error;
}
@@ -571,31 +568,31 @@
void Manager::HandleBackboneQuery(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address dua;
uint16_t rloc16 = Mac::kShortAddrInvalid;
NdProxyTable::NdProxy *ndProxy;
- VerifyOrExit(aMessageInfo.IsHostInterface(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessageInfo.IsHostInterface(), error = kErrorDrop);
- VerifyOrExit(Get<Local>().IsPrimary(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
+ VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMessage, dua));
error = Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16);
- VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_NOT_FOUND);
+ VerifyOrExit(error == kErrorNone || error == kErrorNotFound);
otLogInfoBbr("Received BB.qry from %s for %s (rloc16=%04x)", aMessageInfo.GetPeerAddr().ToString().AsCString(),
dua.ToString().AsCString(), rloc16);
ndProxy = mNdProxyTable.ResolveDua(dua);
- VerifyOrExit(ndProxy != nullptr && !ndProxy->GetDadFlag(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(ndProxy != nullptr && !ndProxy->GetDadFlag(), error = kErrorNotFound);
error = SendBackboneAnswer(aMessageInfo, dua, rloc16, *ndProxy);
exit:
- otLogInfoBbr("HandleBackboneQuery: %s", otThreadErrorToString(error));
+ otLogInfoBbr("HandleBackboneQuery: %s", ErrorToString(error));
}
void Manager::HandleBackboneAnswer(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
@@ -606,7 +603,7 @@
void Manager::HandleBackboneAnswer(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
bool proactive;
Ip6::Address dua;
Ip6::InterfaceIdentifier meshLocalIid;
@@ -614,10 +611,10 @@
uint32_t timeSinceLastTransaction;
uint16_t srcRloc16 = Mac::kShortAddrInvalid;
- VerifyOrExit(aMessageInfo.IsHostInterface(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessageInfo.IsHostInterface(), error = kErrorDrop);
- VerifyOrExit(Get<Local>().IsPrimary(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(aMessage.IsPostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(Get<Local>().IsPrimary(), error = kErrorInvalidState);
+ VerifyOrExit(aMessage.IsPostRequest(), error = kErrorParse);
proactive = !aMessage.IsConfirmable();
@@ -629,7 +626,7 @@
Tlv::FindTlvValueOffset(aMessage, ThreadTlv::kNetworkName, networkNameOffset, networkNameLength));
error = Tlv::Find<ThreadRloc16Tlv>(aMessage, srcRloc16);
- VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_NOT_FOUND);
+ VerifyOrExit(error == kErrorNone || error == kErrorNotFound);
if (proactive)
{
@@ -647,40 +644,40 @@
SuccessOrExit(error = mBackboneTmfAgent.SendEmptyAck(aMessage, aMessageInfo));
exit:
- otLogInfoBbr("HandleBackboneAnswer: %s", otThreadErrorToString(error));
+ otLogInfoBbr("HandleBackboneAnswer: %s", ErrorToString(error));
}
-otError Manager::SendProactiveBackboneNotification(const Ip6::Address & aDua,
- const Ip6::InterfaceIdentifier &aMeshLocalIid,
- uint32_t aTimeSinceLastTransaction)
+Error Manager::SendProactiveBackboneNotification(const Ip6::Address & aDua,
+ const Ip6::InterfaceIdentifier &aMeshLocalIid,
+ uint32_t aTimeSinceLastTransaction)
{
return SendBackboneAnswer(Get<BackboneRouter::Local>().GetAllDomainBackboneRoutersAddress(),
BackboneRouter::kBackboneUdpPort, aDua, aMeshLocalIid, aTimeSinceLastTransaction,
Mac::kShortAddrInvalid);
}
-otError Manager::SendBackboneAnswer(const Ip6::MessageInfo & aQueryMessageInfo,
- const Ip6::Address & aDua,
- uint16_t aSrcRloc16,
- const NdProxyTable::NdProxy &aNdProxy)
+Error Manager::SendBackboneAnswer(const Ip6::MessageInfo & aQueryMessageInfo,
+ const Ip6::Address & aDua,
+ uint16_t aSrcRloc16,
+ const NdProxyTable::NdProxy &aNdProxy)
{
return SendBackboneAnswer(aQueryMessageInfo.GetPeerAddr(), aQueryMessageInfo.GetPeerPort(), aDua,
aNdProxy.GetMeshLocalIid(), aNdProxy.GetTimeSinceLastTransaction(), aSrcRloc16);
}
-otError Manager::SendBackboneAnswer(const Ip6::Address & aDstAddr,
- uint16_t aDstPort,
- const Ip6::Address & aDua,
- const Ip6::InterfaceIdentifier &aMeshLocalIid,
- uint32_t aTimeSinceLastTransaction,
- uint16_t aSrcRloc16)
+Error Manager::SendBackboneAnswer(const Ip6::Address & aDstAddr,
+ uint16_t aDstPort,
+ const Ip6::Address & aDua,
+ const Ip6::InterfaceIdentifier &aMeshLocalIid,
+ uint32_t aTimeSinceLastTransaction,
+ uint16_t aSrcRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
bool proactive = aDstAddr.IsMulticast();
- VerifyOrExit((message = mBackboneTmfAgent.NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mBackboneTmfAgent.NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->Init(proactive ? Coap::kTypeNonConfirmable : Coap::kTypeConfirmable, Coap::kCodePost,
UriPath::kBackboneAnswer));
@@ -713,7 +710,7 @@
exit:
otLogInfoBbr("Send %s for %s (rloc16=%04x): %s", proactive ? "PRO_BB.ntf" : "BB.ans", aDua.ToString().AsCString(),
- aSrcRloc16, otThreadErrorToString(error));
+ aSrcRloc16, ErrorToString(error));
FreeMessageOnError(message, error);
return error;
@@ -721,13 +718,13 @@
void Manager::HandleDadBackboneAnswer(const Ip6::Address &aDua, const Ip6::InterfaceIdentifier &aMeshLocalIid)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NdProxyTable::NdProxy *ndProxy = mNdProxyTable.ResolveDua(aDua);
bool duplicate = false;
OT_UNUSED_VARIABLE(error);
- VerifyOrExit(ndProxy != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(ndProxy != nullptr, error = kErrorNotFound);
duplicate = ndProxy->GetMeshLocalIid() != aMeshLocalIid;
@@ -742,7 +739,7 @@
ot::BackboneRouter::NdProxyTable::NotifyDadComplete(*ndProxy, duplicate);
exit:
- otLogInfoBbr("HandleDadBackboneAnswer: %s, target=%s, mliid=%s, duplicate=%s", otThreadErrorToString(error),
+ otLogInfoBbr("HandleDadBackboneAnswer: %s, target=%s, mliid=%s, duplicate=%s", ErrorToString(error),
aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), duplicate ? "Y" : "N");
}
@@ -765,12 +762,12 @@
const Ip6::InterfaceIdentifier &aMeshLocalIid,
uint32_t aTimeSinceLastTransaction)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NdProxyTable::NdProxy *ndProxy = mNdProxyTable.ResolveDua(aDua);
OT_UNUSED_VARIABLE(error);
- VerifyOrExit(ndProxy != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(ndProxy != nullptr, error = kErrorNotFound);
if (ndProxy->GetMeshLocalIid() == aMeshLocalIid)
{
@@ -794,7 +791,7 @@
}
exit:
- otLogInfoBbr("HandleProactiveBackboneNotification: %s, target=%s, mliid=%s, LTT=%lds", otThreadErrorToString(error),
+ otLogInfoBbr("HandleProactiveBackboneNotification: %s, target=%s, mliid=%s, LTT=%lds", ErrorToString(error),
aDua.ToString().AsCString(), aMeshLocalIid.ToString().AsCString(), aTimeSinceLastTransaction);
}
#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
diff --git a/src/core/backbone_router/bbr_manager.hpp b/src/core/backbone_router/bbr_manager.hpp
index 597aa03..ae1301b 100644
--- a/src/core/backbone_router/bbr_manager.hpp
+++ b/src/core/backbone_router/bbr_manager.hpp
@@ -145,12 +145,12 @@
* @param[in] aRloc16 The short address of the address resolution initiator or `Mac::kShortAddrInvalid` for
* DUA DAD.
*
- * @retval OT_ERROR_NONE Successfully sent BB.qry on backbone link.
- * @retval OT_ERROR_INVALID_STATE If the Backbone Router is not primary, or not enabled.
- * @retval OT_ERROR_NO_BUFS If insufficient message buffers available.
+ * @retval kErrorNone Successfully sent BB.qry on backbone link.
+ * @retval kErrorInvalidState If the Backbone Router is not primary, or not enabled.
+ * @retval kErrorNoBufs If insufficient message buffers available.
*
*/
- otError SendBackboneQuery(const Ip6::Address &aDua, uint16_t aRloc16 = Mac::kShortAddrInvalid);
+ Error SendBackboneQuery(const Ip6::Address &aDua, uint16_t aRloc16 = Mac::kShortAddrInvalid);
/**
* This method send a Proactive Backbone Notification (PRO_BB.ntf) on the Backbone link.
@@ -159,13 +159,13 @@
* @param[in] aMeshLocalIid The Mesh-Local IID to notify.
* @param[in] aTimeSinceLastTransaction Time since last transaction (in seconds).
*
- * @retval OT_ERROR_NONE Successfully sent PRO_BB.ntf on backbone link.
- * @retval OT_ERROR_NO_BUFS If insufficient message buffers available.
+ * @retval kErrorNone Successfully sent PRO_BB.ntf on backbone link.
+ * @retval kErrorNoBufs If insufficient message buffers available.
*
*/
- otError SendProactiveBackboneNotification(const Ip6::Address & aDua,
- const Ip6::InterfaceIdentifier &aMeshLocalIid,
- uint32_t aTimeSinceLastTransaction);
+ Error SendProactiveBackboneNotification(const Ip6::Address & aDua,
+ const Ip6::InterfaceIdentifier &aMeshLocalIid,
+ uint32_t aTimeSinceLastTransaction);
private:
enum
@@ -204,11 +204,11 @@
void HandleBackboneQuery(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleBackboneAnswer(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleBackboneAnswer(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- otError SendBackboneAnswer(const Ip6::MessageInfo & aQueryMessageInfo,
+ Error SendBackboneAnswer(const Ip6::MessageInfo & aQueryMessageInfo,
const Ip6::Address & aDua,
uint16_t aSrcRloc16,
const NdProxyTable::NdProxy &aNdProxy);
- otError SendBackboneAnswer(const Ip6::Address & aDstAddr,
+ Error SendBackboneAnswer(const Ip6::Address & aDstAddr,
uint16_t aDstPort,
const Ip6::Address & aDua,
const Ip6::InterfaceIdentifier &aMeshLocalIid,
@@ -229,7 +229,7 @@
#endif
void HandleNotifierEvents(Events aEvents);
- static void HandleTimer(Timer &aTimer) { aTimer.GetOwner<Manager>().HandleTimer(); }
+ static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
diff --git a/src/core/backbone_router/multicast_listeners_table.cpp b/src/core/backbone_router/multicast_listeners_table.cpp
index 83e8d45..6eaf3ff 100644
--- a/src/core/backbone_router/multicast_listeners_table.cpp
+++ b/src/core/backbone_router/multicast_listeners_table.cpp
@@ -48,11 +48,11 @@
namespace BackboneRouter {
-otError MulticastListenersTable::Add(const Ip6::Address &aAddress, Time aExpireTime)
+Error MulticastListenersTable::Add(const Ip6::Address &aAddress, Time aExpireTime)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aAddress.IsMulticastLargerThanRealmLocal(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aAddress.IsMulticastLargerThanRealmLocal(), error = kErrorInvalidArgs);
for (uint16_t i = 0; i < mNumValidListeners; i++)
{
@@ -66,7 +66,7 @@
}
}
- VerifyOrExit(mNumValidListeners < OT_ARRAY_LENGTH(mListeners), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(mNumValidListeners < OT_ARRAY_LENGTH(mListeners), error = kErrorNoBufs);
mListeners[mNumValidListeners].SetAddress(aAddress);
mListeners[mNumValidListeners].SetExpireTime(aExpireTime);
@@ -87,7 +87,7 @@
void MulticastListenersTable::Remove(const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
for (uint16_t i = 0; i < mNumValidListeners; i++)
{
@@ -108,7 +108,7 @@
mCallback(mCallbackContext, OT_BACKBONE_ROUTER_MULTICAST_LISTENER_REMOVED, &aAddress);
}
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -124,7 +124,7 @@
while (mNumValidListeners > 0 && now >= mListeners[0].GetExpireTime())
{
- LogMulticastListenersTable("Expire", mListeners[0].GetAddress(), mListeners[0].GetExpireTime(), OT_ERROR_NONE);
+ LogMulticastListenersTable("Expire", mListeners[0].GetAddress(), mListeners[0].GetExpireTime(), kErrorNone);
address = mListeners[0].GetAddress();
mNumValidListeners--;
@@ -147,7 +147,7 @@
void MulticastListenersTable::LogMulticastListenersTable(const char * aAction,
const Ip6::Address &aAddress,
TimeMilli aExpireTime,
- otError aError)
+ Error aError)
{
OT_UNUSED_VARIABLE(aAction);
OT_UNUSED_VARIABLE(aAddress);
@@ -155,7 +155,7 @@
OT_UNUSED_VARIABLE(aError);
otLogDebgBbr("MulticastListenersTable: %s %s expire %u: %s", aAction, aAddress.ToString().AsCString(),
- aExpireTime.GetValue(), otThreadErrorToString(aError));
+ aExpireTime.GetValue(), ErrorToString(aError));
}
void MulticastListenersTable::FixHeap(uint16_t aIndex)
@@ -287,13 +287,13 @@
}
}
-otError MulticastListenersTable::GetNext(otBackboneRouterMulticastListenerIterator &aIterator,
- otBackboneRouterMulticastListenerInfo & aListenerInfo)
+Error MulticastListenersTable::GetNext(otBackboneRouterMulticastListenerIterator &aIterator,
+ otBackboneRouterMulticastListenerInfo & aListenerInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
TimeMilli now;
- VerifyOrExit(aIterator < mNumValidListeners, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aIterator < mNumValidListeners, error = kErrorNotFound);
now = TimerMilli::GetNow();
diff --git a/src/core/backbone_router/multicast_listeners_table.hpp b/src/core/backbone_router/multicast_listeners_table.hpp
index 0ff0159..56b1b78 100644
--- a/src/core/backbone_router/multicast_listeners_table.hpp
+++ b/src/core/backbone_router/multicast_listeners_table.hpp
@@ -119,12 +119,12 @@
* @param[in] aAddress The Multicast Listener address.
* @param[in] aExpireTime The Multicast Listener expire time.
*
- * @retval OT_ERROR_NONE If the Multicast Listener was successfully added.
- * @retval OT_ERROR_INVALID_ARGS If the Multicast Listener address was invalid.
- * @retval OT_ERROR_NO_BUFS No space available to save the Multicast Listener.
+ * @retval kErrorNone If the Multicast Listener was successfully added.
+ * @retval kErrorInvalidArgs If the Multicast Listener address was invalid.
+ * @retval kErrorNoBufs No space available to save the Multicast Listener.
*
*/
- otError Add(const Ip6::Address &aAddress, TimeMilli aExpireTime);
+ Error Add(const Ip6::Address &aAddress, TimeMilli aExpireTime);
/**
* This method removes a given Multicast Listener.
@@ -181,12 +181,12 @@
* @param[in] aIterator A pointer to the Multicast Listener Iterator.
* @param[out] aListenerInfo A pointer to where the Multicast Listener info is placed.
*
- * @retval OT_ERROR_NONE Successfully found the next Multicast Listener info.
- * @retval OT_ERROR_NOT_FOUND No subsequent Multicast Listener was found.
+ * @retval kErrorNone Successfully found the next Multicast Listener info.
+ * @retval kErrorNotFound No subsequent Multicast Listener was found.
*
*/
- otError GetNext(otBackboneRouterMulticastListenerIterator &aIterator,
- otBackboneRouterMulticastListenerInfo & aListenerInfo);
+ Error GetNext(otBackboneRouterMulticastListenerIterator &aIterator,
+ otBackboneRouterMulticastListenerInfo & aListenerInfo);
private:
enum
@@ -213,7 +213,7 @@
void LogMulticastListenersTable(const char * aAction,
const Ip6::Address &aAddress,
TimeMilli aExpireTime,
- otError aError);
+ Error aError);
void FixHeap(uint16_t aIndex);
bool SiftHeapElemDown(uint16_t aIndex);
diff --git a/src/core/backbone_router/ndproxy_table.cpp b/src/core/backbone_router/ndproxy_table.cpp
index d8f3a88..d2630be 100644
--- a/src/core/backbone_router/ndproxy_table.cpp
+++ b/src/core/backbone_router/ndproxy_table.cpp
@@ -95,9 +95,9 @@
{
NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();
- mCurrent = &table.mProxies[0];
+ mItem = &table.mProxies[0];
- if (!MatchesFilter(*mCurrent, mFilter))
+ if (!MatchesFilter(*mItem, mFilter))
{
Advance();
}
@@ -107,7 +107,7 @@
: InstanceLocator(aInstance)
{
NdProxyTable &table = GetInstance().Get<BackboneRouter::NdProxyTable>();
- mCurrent = OT_ARRAY_END(table.mProxies);
+ mItem = OT_ARRAY_END(table.mProxies);
}
void NdProxyTable::Iterator::Advance(void)
@@ -116,8 +116,8 @@
do
{
- mCurrent++;
- } while (mCurrent < OT_ARRAY_END(table.mProxies) && !MatchesFilter(*mCurrent, mFilter));
+ mItem++;
+ } while (mItem < OT_ARRAY_END(table.mProxies) && !MatchesFilter(*mItem, mFilter));
}
void NdProxyTable::Erase(NdProxy &aNdProxy)
@@ -149,18 +149,18 @@
otLogNoteBbr("NdProxyTable::Clear!");
}
-otError NdProxyTable::Register(const Ip6::InterfaceIdentifier &aAddressIid,
- const Ip6::InterfaceIdentifier &aMeshLocalIid,
- uint16_t aRloc16,
- const uint32_t * aTimeSinceLastTransaction)
+Error NdProxyTable::Register(const Ip6::InterfaceIdentifier &aAddressIid,
+ const Ip6::InterfaceIdentifier &aMeshLocalIid,
+ uint16_t aRloc16,
+ const uint32_t * aTimeSinceLastTransaction)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NdProxy *proxy = FindByAddressIid(aAddressIid);
uint32_t timeSinceLastTransaction = aTimeSinceLastTransaction == nullptr ? 0 : *aTimeSinceLastTransaction;
if (proxy != nullptr)
{
- VerifyOrExit(proxy->mMeshLocalIid == aMeshLocalIid, error = OT_ERROR_DUPLICATED);
+ VerifyOrExit(proxy->mMeshLocalIid == aMeshLocalIid, error = kErrorDuplicated);
proxy->Update(aRloc16, timeSinceLastTransaction);
NotifyDuaRegistrationOnBackboneLink(*proxy, /* aIsRenew */ true);
@@ -178,7 +178,7 @@
proxy = FindInvalid();
// TODO: evict stale DUA entries to have room for this new DUA.
- VerifyOrExit(proxy != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(proxy != nullptr, error = kErrorNoBufs);
}
proxy->Init(aAddressIid, aMeshLocalIid, aRloc16, timeSinceLastTransaction);
@@ -186,7 +186,7 @@
exit:
otLogInfoBbr("NdProxyTable::Register %s MLIID %s RLOC16 %04x LTT %u => %s", aAddressIid.ToString().AsCString(),
- aMeshLocalIid.ToString().AsCString(), aRloc16, timeSinceLastTransaction, otThreadErrorToString(error));
+ aMeshLocalIid.ToString().AsCString(), aRloc16, timeSinceLastTransaction, ErrorToString(error));
return error;
}
@@ -257,7 +257,7 @@
{
mIsAnyDadInProcess = true;
- if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == OT_ERROR_NONE)
+ if (Get<BackboneRouter::Manager>().SendBackboneQuery(GetDua(proxy)) == kErrorNone)
{
proxy.IncreaseDadAttampts();
}
@@ -335,11 +335,11 @@
}
}
-otError NdProxyTable::GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo)
+Error NdProxyTable::GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
- VerifyOrExit(Get<Leader>().IsDomainUnicast(aDua), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(Get<Leader>().IsDomainUnicast(aDua), error = kErrorInvalidArgs);
for (NdProxy &proxy : Iterate(kFilterValid))
{
@@ -349,7 +349,7 @@
aNdProxyInfo.mTimeSinceLastTransaction = proxy.GetTimeSinceLastTransaction();
aNdProxyInfo.mRloc16 = proxy.mRloc16;
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
diff --git a/src/core/backbone_router/ndproxy_table.hpp b/src/core/backbone_router/ndproxy_table.hpp
index ece89b9..e8d28d5 100644
--- a/src/core/backbone_router/ndproxy_table.hpp
+++ b/src/core/backbone_router/ndproxy_table.hpp
@@ -40,6 +40,7 @@
#include <openthread/backbone_router_ftd.h>
#include "backbone_router/bbr_leader.hpp"
+#include "common/iterator_utils.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/time.hpp"
@@ -146,15 +147,15 @@
* @param[in] aRloc16 The RLOC16.
* @param[in] aTimeSinceLastTransaction Time since last transaction (in seconds).
*
- * @retval OT_ERROR_NONE If registered successfully.
- * @retval OT_ERROR_DUPLICATED If the Ip6 address IID is a duplicate.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to register.
+ * @retval kErrorNone If registered successfully.
+ * @retval kErrorDuplicated If the Ip6 address IID is a duplicate.
+ * @retval kErrorNoBufs Insufficient buffer space available to register.
*
*/
- otError Register(const Ip6::InterfaceIdentifier &aAddressIid,
- const Ip6::InterfaceIdentifier &aMeshLocalIid,
- uint16_t aRloc16,
- const uint32_t * aTimeSinceLastTransaction);
+ Error Register(const Ip6::InterfaceIdentifier &aAddressIid,
+ const Ip6::InterfaceIdentifier &aMeshLocalIid,
+ uint16_t aRloc16,
+ const uint32_t * aTimeSinceLastTransaction);
/**
* This method checks if a given Ip6 address IID was registered.
@@ -223,11 +224,11 @@
* @param[in] aDua The Domain Unicast Address to get info.
* @param[in] aNdProxyInfo A pointer to the ND Proxy info.
*
- * @retval OT_ERROR_NONE Successfully retrieve the ND Proxy info.
- * @retval OT_ERROR_NOT_FOUND Failed to find the Domain Unicast Address in the ND Proxy table.
+ * @retval kErrorNone Successfully retrieve the ND Proxy info.
+ * @retval kErrorNotFound Failed to find the Domain Unicast Address in the ND Proxy table.
*
*/
- otError GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo);
+ Error GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo);
private:
enum
@@ -246,8 +247,9 @@
* This class represents an iterator for iterating through the NdProxy Table.
*
*/
- class Iterator : public InstanceLocator
+ class Iterator : public InstanceLocator, public ItemPtrIterator<NdProxy, Iterator>
{
+ friend class ItemPtrIterator<NdProxy, Iterator>;
friend class NdProxyTable;
friend class IteratorBuilder;
@@ -260,18 +262,9 @@
Iterator(Instance &aInstance, Filter aFilter);
Iterator(Instance &aInstance, IteratorType);
- bool IsDone(void) const { return (mCurrent == nullptr); }
- void Advance(void);
- void operator++(void) { Advance(); }
- void operator++(int) { Advance(); }
- const NdProxy &operator*(void)const { return *mCurrent; }
- bool operator==(const Iterator &aOther) const { return mCurrent == aOther.mCurrent; }
- bool operator!=(const Iterator &aOther) const { return !(*this == aOther); }
- NdProxy * operator->(void) { return mCurrent; }
- NdProxy & operator*(void) { return *mCurrent; }
+ void Advance(void);
- NdProxy *mCurrent;
- Filter mFilter;
+ Filter mFilter;
};
class IteratorBuilder : public InstanceLocator
diff --git a/src/core/border_router/infra_if_platform.cpp b/src/core/border_router/infra_if_platform.cpp
new file mode 100644
index 0000000..8a0d783
--- /dev/null
+++ b/src/core/border_router/infra_if_platform.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements infrastructure interface platform APIs.
+ */
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include <openthread/platform/infra_if.h>
+
+#include "border_router/routing_manager.hpp"
+#include "common/instance.hpp"
+
+using namespace ot;
+
+extern "C" void otPlatInfraIfRecvIcmp6Nd(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ const otIp6Address *aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ instance.Get<BorderRouter::RoutingManager>().RecvIcmp6Message(
+ aInfraIfIndex, static_cast<const Ip6::Address &>(*aSrcAddress), aBuffer, aBufferLength);
+}
+
+extern "C" otError otPlatInfraIfStateChanged(otInstance * aInstance,
+ uint32_t aInfraIfIndex,
+ bool aIsRunning,
+ const otIp6Address *aLinkLocalAddress)
+{
+ Instance &instance = *static_cast<Instance *>(aInstance);
+
+ return instance.Get<BorderRouter::RoutingManager>().HandleInfraIfStateChanged(
+ aInfraIfIndex, aIsRunning, static_cast<const Ip6::Address *>(aLinkLocalAddress));
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/router_advertisement.cpp b/src/core/border_router/router_advertisement.cpp
new file mode 100644
index 0000000..ea3d11a
--- /dev/null
+++ b/src/core/border_router/router_advertisement.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes implementations for ICMPv6 Router Advertisement.
+ *
+ */
+
+#include "border_router/router_advertisement.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+namespace ot {
+
+namespace BorderRouter {
+
+namespace RouterAdv {
+
+const Option *Option::GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength)
+{
+ const uint8_t *nextOption = nullptr;
+ const uint8_t *bufferEnd = aBuffer + aBufferLength;
+
+ VerifyOrExit(aBuffer != nullptr, nextOption = nullptr);
+
+ if (aCurOption == nullptr)
+ {
+ nextOption = aBuffer;
+ }
+ else
+ {
+ nextOption = reinterpret_cast<const uint8_t *>(aCurOption) + aCurOption->GetSize();
+ }
+
+ VerifyOrExit(nextOption + sizeof(Option) <= bufferEnd, nextOption = nullptr);
+ VerifyOrExit(reinterpret_cast<const Option *>(nextOption)->GetSize() > 0, nextOption = nullptr);
+ VerifyOrExit(nextOption + reinterpret_cast<const Option *>(nextOption)->GetSize() <= bufferEnd,
+ nextOption = nullptr);
+
+exit:
+ return reinterpret_cast<const Option *>(nextOption);
+}
+
+PrefixInfoOption::PrefixInfoOption(void)
+ : Option(Type::kPrefixInfo, sizeof(*this) / kLengthUnit)
+ , mPrefixLength(0)
+ , mReserved1(0)
+ , mValidLifetime(0)
+ , mPreferredLifetime(0)
+ , mReserved2(0)
+{
+ OT_UNUSED_VARIABLE(mReserved2);
+
+ mPrefix.Clear();
+}
+
+void PrefixInfoOption::SetOnLink(bool aOnLink)
+{
+ if (aOnLink)
+ {
+ mReserved1 |= kOnLinkFlagMask;
+ }
+ else
+ {
+ mReserved1 &= ~kOnLinkFlagMask;
+ }
+}
+
+void PrefixInfoOption::SetAutoAddrConfig(bool aAutoAddrConfig)
+{
+ if (aAutoAddrConfig)
+ {
+ mReserved1 |= kAutoConfigFlagMask;
+ }
+ else
+ {
+ mReserved1 &= ~kAutoConfigFlagMask;
+ }
+}
+
+void PrefixInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
+{
+ mPrefixLength = aPrefix.mLength;
+ mPrefix = static_cast<const Ip6::Address &>(aPrefix.mPrefix);
+}
+
+Ip6::Prefix PrefixInfoOption::GetPrefix(void) const
+{
+ Ip6::Prefix prefix;
+
+ prefix.Set(mPrefix.GetBytes(), mPrefixLength);
+ return prefix;
+}
+
+RouteInfoOption::RouteInfoOption(void)
+ : Option(Type::kRouteInfo, 0)
+ , mPrefixLength(0)
+ , mReserved(0)
+ , mRouteLifetime(0)
+{
+ OT_UNUSED_VARIABLE(mReserved);
+
+ mPrefix.Clear();
+}
+
+void RouteInfoOption::SetPreference(otRoutePreference aPreference)
+{
+ mReserved &= ~kPreferenceMask;
+ mReserved |= (static_cast<uint8_t>(aPreference) << kPreferenceOffset) & kPreferenceMask;
+}
+
+otRoutePreference RouteInfoOption::GetPreference(void) const
+{
+ otRoutePreference preference;
+
+ switch ((mReserved & kPreferenceMask) >> kPreferenceOffset)
+ {
+ case kPreferenceLow:
+ preference = OT_ROUTE_PREFERENCE_LOW;
+ break;
+ case kPreferenceMed:
+ preference = OT_ROUTE_PREFERENCE_MED;
+ break;
+ case kPreferenceHigh:
+ preference = OT_ROUTE_PREFERENCE_HIGH;
+ break;
+ default:
+ preference = OT_ROUTE_PREFERENCE_LOW;
+ break;
+ }
+
+ return preference;
+}
+
+void RouteInfoOption::SetPrefix(const Ip6::Prefix &aPrefix)
+{
+ // The total length (in bytes) of a Router Information Option
+ // is: (8 bytes fixed option header) + (0, 8, or 16 bytes prefix).
+ // Because the length of the option must be padded with 8 bytes,
+ // the length of the prefix (in bits) must be padded with 64 bits.
+ SetLength((aPrefix.mLength + kLengthUnit * CHAR_BIT - 1) / (kLengthUnit * CHAR_BIT) + 1);
+
+ mPrefixLength = aPrefix.mLength;
+ mPrefix = static_cast<const Ip6::Address &>(aPrefix.mPrefix);
+}
+
+Ip6::Prefix RouteInfoOption::GetPrefix(void) const
+{
+ Ip6::Prefix prefix;
+
+ prefix.Set(mPrefix.GetBytes(), mPrefixLength);
+ return prefix;
+}
+
+bool RouteInfoOption::IsValid(void) const
+{
+ otRoutePreference pref = GetPreference();
+
+ return (GetLength() == 1 || GetLength() == 2 || GetLength() == 3) &&
+ (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT) &&
+ (pref == OT_ROUTE_PREFERENCE_LOW || pref == OT_ROUTE_PREFERENCE_MED || pref == OT_ROUTE_PREFERENCE_HIGH);
+}
+
+RouterAdvMessage::RouterAdvMessage(void)
+ : mReachableTime(0)
+ , mRetransTimer(0)
+{
+ OT_UNUSED_VARIABLE(mReachableTime);
+ OT_UNUSED_VARIABLE(mRetransTimer);
+
+ mHeader.Clear();
+ mHeader.SetType(Ip6::Icmp::Header::kTypeRouterAdvert);
+}
+
+RouterSolicitMessage::RouterSolicitMessage(void)
+{
+ mHeader.Clear();
+ mHeader.SetType(Ip6::Icmp::Header::kTypeRouterSolicit);
+}
+
+} // namespace RouterAdv
+
+} // namespace BorderRouter
+
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/router_advertisement.hpp b/src/core/border_router/router_advertisement.hpp
new file mode 100644
index 0000000..e346412
--- /dev/null
+++ b/src/core/border_router/router_advertisement.hpp
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for IPv6 Router Advertisement.
+ *
+ * See RFC 4861: Neighbor Discovery for IP version 6 (https://tools.ietf.org/html/rfc4861).
+ *
+ */
+
+#ifndef ROUTER_ADVERTISEMENT_HPP_
+#define ROUTER_ADVERTISEMENT_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include <stdint.h>
+
+#include <openthread/netdata.h>
+#include <openthread/platform/toolchain.h>
+
+#include "common/encoding.hpp"
+#include "net/icmp6.hpp"
+#include "net/ip6.hpp"
+
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+namespace ot {
+
+namespace BorderRouter {
+
+namespace RouterAdv {
+
+/**
+ * This class represents the variable length options in Neighbor
+ * Discovery messages.
+ *
+ * @sa PrefixInfoOption
+ * @sa RouteInfoOption
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Option
+{
+public:
+ enum class Type : uint8_t
+ {
+ kPrefixInfo = 3, ///< Prefix Information Option.
+ kRouteInfo = 24, ///< Route Information Option.
+ };
+
+ enum : uint8_t
+ {
+ kLengthUnit = 8u, ///< The unit of length in octets.
+ };
+
+ /**
+ * This constructor initializes the option with given type and length.
+ *
+ * @param[in] aType The type of this option.
+ * @param[in] aLength The length of this option in unit of 8 octets.
+ *
+ */
+ explicit Option(Type aType, uint8_t aLength = 0)
+ : mType(aType)
+ , mLength(aLength)
+ {
+ }
+
+ /**
+ * This method returns the type of this option.
+ *
+ * @returns The option type.
+ *
+ */
+ Type GetType(void) const { return mType; }
+
+ /**
+ * This method sets the size of the option (in bytes).
+ *
+ * Since the option must end on their natural 64-bits boundaries,
+ * the actual length set to the option is padded to (aSize + 7) / 8 * 8.
+ *
+ * @param[in] aSize The size of the option in unit of 1 byte.
+ *
+ */
+ void SetSize(uint16_t aSize) { mLength = (aSize + kLengthUnit - 1) / kLengthUnit; }
+
+ /**
+ * This method returns the size of the option (in bytes).
+ *
+ * @returns The size of the option in unit of 1 byte.
+ *
+ */
+ uint16_t GetSize(void) const { return mLength * kLengthUnit; }
+
+ /**
+ * This method sets the length of the option (in unit of 8 bytes).
+ *
+ * @param[in] aLength The length of the option in unit of 8 bytes.
+ *
+ */
+ void SetLength(uint8_t aLength) { mLength = aLength; }
+
+ /**
+ * This method returns the length of the option (in unit of 8 bytes).
+ *
+ * @returns The length of the option in unit of 8 bytes.
+ *
+ */
+ uint16_t GetLength(void) const { return mLength; }
+
+ /**
+ * This helper method returns a pointer to the next valid option in the buffer.
+ *
+ * @param[in] aCurOption The current option. Use nullptr to get the first option.
+ * @param[in] aBuffer The buffer within which the options are held.
+ * @param[in] aBufferLength The length of the buffer.
+ *
+ * @returns A pointer to the next option if there are a valid one. Otherwise, nullptr.
+ *
+ */
+ static const Option *GetNextOption(const Option *aCurOption, const uint8_t *aBuffer, uint16_t aBufferLength);
+
+ /**
+ * This method tells whether this option is valid.
+ *
+ * @return A boolean that indicates whether this option is valid.
+ *
+ */
+ bool IsValid(void) const { return mLength > 0; }
+
+private:
+ Type mType; // Type of the option.
+ uint8_t mLength; // Length of the option in unit of 8 octets,
+ // including the `type` and `length` fields.
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class represents the Prefix Information Option.
+ *
+ * See section 4.6.2 of RFC 4861 for definition of this option.
+ * https://tools.ietf.org/html/rfc4861#section-4.6.2
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class PrefixInfoOption : public Option
+{
+public:
+ /**
+ * This constructor initializes this option with zero prefix
+ * length, valid lifetime and preferred lifetime.
+ *
+ */
+ PrefixInfoOption(void);
+
+ /**
+ * This method sets the on-link (L) flag.
+ *
+ * @param[in] aOnLink A boolean indicates whether the prefix is on-link or off-link.
+ *
+ */
+ void SetOnLink(bool aOnLink);
+
+ /**
+ * This method sets the autonomous address-configuration (A) flag.
+ *
+ * @param[in] aAutoAddrConfig A boolean indicates whether this prefix can be used
+ * for SLAAC.
+ *
+ */
+ void SetAutoAddrConfig(bool aAutoAddrConfig);
+
+ /**
+ * This method set the valid lifetime of the prefix in seconds.
+ *
+ * @param[in] aValidLifetime The valid lifetime in seconds.
+ *
+ */
+ void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
+
+ /**
+ * THis method returns the valid lifetime of the prefix in seconds.
+ *
+ * @returns The valid lifetime in seconds.
+ *
+ */
+ uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
+
+ /**
+ * This method sets the preferred lifetime of the prefix in seconds.
+ *
+ * @param[in] aPreferredLifetime The preferred lifetime in seconds.
+ *
+ */
+ void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
+
+ /**
+ * This method sets the prefix.
+ *
+ * @param[in] aPrefix The prefix contained in this option.
+ *
+ */
+ void SetPrefix(const Ip6::Prefix &aPrefix);
+
+ /**
+ * This method returns the prefix in this option.
+ *
+ * @returns The IPv6 prefix in this option.
+ *
+ */
+ Ip6::Prefix GetPrefix(void) const;
+
+ /**
+ * This method tells whether this option is valid.
+ *
+ * @returns A boolean indicates whether this option is valid.
+ *
+ */
+ bool IsValid(void) const
+ {
+ return (GetSize() == sizeof(*this)) && (mPrefixLength <= OT_IP6_ADDRESS_SIZE * CHAR_BIT);
+ }
+
+private:
+ enum : uint8_t
+ {
+ kAutoConfigFlagMask = 0x40u, // Bit mask of the Automatic Address Configure flag.
+ kOnLinkFlagMask = 0x80u, // Bit mask of the On-link flag.
+ };
+
+ uint8_t mPrefixLength; // The prefix length in bits.
+ uint8_t mReserved1; // The reserved field.
+ uint32_t mValidLifetime; // The valid lifetime of the prefix.
+ uint32_t mPreferredLifetime; // The preferred lifetime of the prefix.
+ uint32_t mReserved2; // The reserved field.
+ Ip6::Address mPrefix; // The prefix.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(PrefixInfoOption) == 32, "invalid PrefixInfoOption structure");
+
+/**
+ * This class represents the Route Information Option.
+ *
+ * See section 2.3 of RFC 4191 for definition of this option.
+ * https://tools.ietf.org/html/rfc4191#section-2.3
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class RouteInfoOption : public Option
+{
+public:
+ /**
+ * This constructor initializes this option with zero prefix length.
+ *
+ */
+ RouteInfoOption(void);
+
+ /**
+ * This method sets the route preference.
+ *
+ * @param[in] aPreference The route preference.
+ *
+ */
+ void SetPreference(otRoutePreference aPreference);
+
+ /**
+ * This method returns the route preference.
+ *
+ * @returns The route preference.
+ *
+ */
+ otRoutePreference GetPreference(void) const;
+
+ /**
+ * This method sets the lifetime of the route in seconds.
+ *
+ * @param[in] aLifetime The lifetime of the route in seconds.
+ *
+ */
+ void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
+
+ /**
+ * This method returns Route Lifetime in seconds.
+ *
+ * @returns The Route Lifetime in seconds.
+ *
+ */
+ uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
+
+ /**
+ * This method sets the prefix.
+ *
+ * @param[in] aPrefix The prefix contained in this option.
+ *
+ */
+ void SetPrefix(const Ip6::Prefix &aPrefix);
+
+ /**
+ * This method returns the prefix in this option.
+ *
+ * @returns The IPv6 prefix in this option.
+ *
+ */
+ Ip6::Prefix GetPrefix(void) const;
+
+ /**
+ * This method tells whether this option is valid.
+ *
+ * @returns A boolean indicates whether this option is valid.
+ *
+ */
+ bool IsValid(void) const;
+
+private:
+ enum : uint8_t
+ {
+ kPreferenceMask = 0x18u,
+ kPreferenceOffset = 3u,
+ };
+
+ enum : uint8_t
+ {
+ kPreferenceLow = 0x03,
+ kPreferenceMed = 0x00,
+ kPreferenceHigh = 0x01,
+ };
+
+ uint8_t mPrefixLength; // The prefix length in bits.
+ uint8_t mReserved; // The reserved field.
+ uint32_t mRouteLifetime; // The lifetime in seconds.
+ Ip6::Address mPrefix; // The prefix.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(RouteInfoOption) == 24, "invalid RouteInfoOption structure");
+
+/**
+ * This class implements the Router Advertisement message.
+ *
+ * See section 4.2 of RFC 4861 for definition of this message.
+ * https://tools.ietf.org/html/rfc4861#section-4.2
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class RouterAdvMessage
+{
+public:
+ /**
+ * This constructor initializes the Router Advertisement message with
+ * zero router lifetime, reachable time and retransmission timer.
+ *
+ */
+ RouterAdvMessage(void);
+
+ /**
+ * This method sets the Router Lifetime in seconds.
+ *
+ * Zero Router Lifetime means we are not a default router.
+ *
+ * @param[in] aRouterLifetime The router lifetime in seconds.
+ *
+ */
+ void SetRouterLifetime(uint16_t aRouterLifetime)
+ {
+ mHeader.mData.m16[kRouteLifetimeIdx] = HostSwap16(aRouterLifetime);
+ }
+
+private:
+ enum : uint8_t
+ {
+ kRouteLifetimeIdx = 1u, // The index of Route Lifetime in ICMPv6 Header Data. in unit of 2 octets.
+ };
+
+ Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
+ uint32_t mReachableTime; // The reachable time. In milliseconds.
+ uint32_t mRetransTimer; // The retransmission timer. In milliseconds.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(RouterAdvMessage) == 16, "invalid RouterAdvMessage structure");
+
+/**
+ * This class implements the Router Solicitation message.
+ *
+ * See section 4.1 of RFC 4861 for definition of this message.
+ * https://tools.ietf.org/html/rfc4861#section-4.1
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class RouterSolicitMessage
+{
+public:
+ /**
+ * This constructor initializes the Router Solicitation message.
+ *
+ */
+ RouterSolicitMessage(void);
+
+private:
+ Ip6::Icmp::Header mHeader; // The common ICMPv6 header.
+} OT_TOOL_PACKED_END;
+
+static_assert(sizeof(RouterSolicitMessage) == 8, "invalid RouterSolicitMessage structure");
+
+} // namespace RouterAdv
+
+} // namespace BorderRouter
+
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#endif // ROUTER_ADVERTISEMENT_HPP_
diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp
new file mode 100644
index 0000000..54459e9
--- /dev/null
+++ b/src/core/border_router/routing_manager.cpp
@@ -0,0 +1,1189 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes implementation for the RA-based routing management.
+ *
+ */
+
+#include "border_router/routing_manager.hpp"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#include <string.h>
+
+#include <openthread/platform/infra_if.h>
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
+#include "common/random.hpp"
+#include "common/settings.hpp"
+#include "net/ip6.hpp"
+#include "thread/network_data_leader.hpp"
+#include "thread/network_data_local.hpp"
+#include "thread/network_data_notifier.hpp"
+
+namespace ot {
+
+namespace BorderRouter {
+
+RoutingManager::RoutingManager(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mIsRunning(false)
+ , mIsEnabled(false)
+ , mInfraIfIsRunning(false)
+ , mInfraIfIndex(0)
+ , mAdvertisedOmrPrefixNum(0)
+ , mAdvertisedOnLinkPrefix(nullptr)
+ , mDiscoveredPrefixNum(0)
+ , mDiscoveredPrefixInvalidTimer(aInstance, HandleDiscoveredPrefixInvalidTimer)
+ , mRouterAdvertisementTimer(aInstance, HandleRouterAdvertisementTimer)
+ , mRouterAdvertisementCount(0)
+ , mRouterSolicitTimer(aInstance, HandleRouterSolicitTimer)
+ , mRouterSolicitCount(0)
+ , mRoutingPolicyTimer(aInstance, HandleRoutingPolicyTimer)
+{
+ mInfraIfLinkLocalAddress.Clear();
+
+ mLocalOmrPrefix.Clear();
+ memset(mAdvertisedOmrPrefixes, 0, sizeof(mAdvertisedOmrPrefixes));
+
+ mLocalOnLinkPrefix.Clear();
+
+ memset(mDiscoveredPrefixes, 0, sizeof(mDiscoveredPrefixes));
+}
+
+Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const Ip6::Address *aInfraIfLinkLocalAddress)
+{
+ Error error;
+
+ VerifyOrExit(!IsInitialized(), error = kErrorInvalidState);
+ VerifyOrExit(aInfraIfIndex > 0, error = kErrorInvalidArgs);
+
+ SuccessOrExit(error = LoadOrGenerateRandomOmrPrefix());
+ SuccessOrExit(error = LoadOrGenerateRandomOnLinkPrefix());
+
+ mInfraIfIndex = aInfraIfIndex;
+
+ // Initialize the infra interface status.
+ SuccessOrExit(error = HandleInfraIfStateChanged(mInfraIfIndex, aInfraIfIsRunning, aInfraIfLinkLocalAddress));
+
+exit:
+ if (error != kErrorNone)
+ {
+ mInfraIfIndex = 0;
+ }
+ return error;
+}
+
+Error RoutingManager::SetEnabled(bool aEnabled)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
+
+ VerifyOrExit(aEnabled != mIsEnabled);
+
+ mIsEnabled = aEnabled;
+ EvaluateState();
+
+exit:
+ return error;
+}
+
+Error RoutingManager::LoadOrGenerateRandomOmrPrefix(void)
+{
+ Error error = kErrorNone;
+
+ if (Get<Settings>().ReadOmrPrefix(mLocalOmrPrefix) != kErrorNone || !IsValidOmrPrefix(mLocalOmrPrefix))
+ {
+ Ip6::NetworkPrefix randomOmrPrefix;
+
+ otLogNoteBr("no valid OMR prefix found in settings, generating new one");
+
+ error = randomOmrPrefix.GenerateRandomUla();
+ if (error != kErrorNone)
+ {
+ otLogCritBr("failed to generate random OMR prefix");
+ ExitNow();
+ }
+
+ mLocalOmrPrefix.Set(randomOmrPrefix);
+ IgnoreError(Get<Settings>().SaveOmrPrefix(mLocalOmrPrefix));
+ }
+
+exit:
+ return error;
+}
+
+Error RoutingManager::LoadOrGenerateRandomOnLinkPrefix(void)
+{
+ Error error = kErrorNone;
+
+ if (Get<Settings>().ReadOnLinkPrefix(mLocalOnLinkPrefix) != kErrorNone || !IsValidOnLinkPrefix(mLocalOnLinkPrefix))
+ {
+ Ip6::NetworkPrefix randomOnLinkPrefix;
+
+ otLogNoteBr("no valid on-link prefix found in settings, generating new one");
+
+ error = randomOnLinkPrefix.GenerateRandomUla();
+ if (error != kErrorNone)
+ {
+ otLogCritBr("failed to generate random on-link prefix");
+ ExitNow();
+ }
+
+ randomOnLinkPrefix.m8[6] = 0;
+ randomOnLinkPrefix.m8[7] = 0;
+ mLocalOnLinkPrefix.Set(randomOnLinkPrefix);
+
+ IgnoreError(Get<Settings>().SaveOnLinkPrefix(mLocalOnLinkPrefix));
+ }
+
+exit:
+ return error;
+}
+
+void RoutingManager::EvaluateState(void)
+{
+ if (mIsEnabled && Get<Mle::MleRouter>().IsAttached() && mInfraIfIsRunning && mInfraIfLinkLocalAddress.IsLinkLocal())
+ {
+ Start();
+ }
+ else
+ {
+ Stop();
+ }
+}
+
+void RoutingManager::Start(void)
+{
+ if (!mIsRunning)
+ {
+ otLogInfoBr("Border Routing manager started");
+
+ mIsRunning = true;
+ StartRouterSolicitationDelay();
+ }
+}
+
+void RoutingManager::Stop(void)
+{
+ VerifyOrExit(mIsRunning);
+
+ UnpublishLocalOmrPrefix();
+ if (mAdvertisedOnLinkPrefix != nullptr)
+ {
+ RemoveExternalRoute(*mAdvertisedOnLinkPrefix);
+ }
+ InvalidateAllDiscoveredPrefixes();
+
+ // Use empty OMR & on-link prefixes to invalidate possible advertised prefixes.
+ SendRouterAdvertisement(nullptr, 0, nullptr);
+
+ memset(mAdvertisedOmrPrefixes, 0, sizeof(mAdvertisedOmrPrefixes));
+ mAdvertisedOmrPrefixNum = 0;
+
+ mAdvertisedOnLinkPrefix = nullptr;
+
+ memset(mDiscoveredPrefixes, 0, sizeof(mDiscoveredPrefixes));
+ mDiscoveredPrefixNum = 0;
+ mDiscoveredPrefixInvalidTimer.Stop();
+
+ mRouterAdvertisementTimer.Stop();
+ mRouterAdvertisementCount = 0;
+
+ mRouterSolicitTimer.Stop();
+ mRouterSolicitCount = 0;
+
+ mRoutingPolicyTimer.Stop();
+
+ otLogInfoBr("Border Routing manager stopped");
+
+ mIsRunning = false;
+
+exit:
+ return;
+}
+
+void RoutingManager::RecvIcmp6Message(uint32_t aInfraIfIndex,
+ const Ip6::Address &aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ Error error = kErrorNone;
+ const Ip6::Icmp::Header *icmp6Header;
+ const Ip6::Address * infraLinkLocalAddr;
+
+ VerifyOrExit(IsInitialized() && mIsRunning, error = kErrorDrop);
+
+ VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorDrop);
+ infraLinkLocalAddr = static_cast<const Ip6::Address *>(&mInfraIfLinkLocalAddress);
+
+ // Drop any ICMPv6 messages sent from myself.
+ VerifyOrExit(infraLinkLocalAddr != nullptr && aSrcAddress != *infraLinkLocalAddr, error = kErrorDrop);
+
+ VerifyOrExit(aBuffer != nullptr && aBufferLength >= sizeof(*icmp6Header), error = kErrorParse);
+
+ icmp6Header = reinterpret_cast<const Ip6::Icmp::Header *>(aBuffer);
+
+ switch (icmp6Header->GetType())
+ {
+ case Ip6::Icmp::Header::kTypeRouterAdvert:
+ HandleRouterAdvertisement(aSrcAddress, aBuffer, aBufferLength);
+ break;
+ case Ip6::Icmp::Header::kTypeRouterSolicit:
+ HandleRouterSolicit(aSrcAddress, aBuffer, aBufferLength);
+ break;
+ default:
+ break;
+ }
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogDebgBr("drop ICMPv6 message: %s", ErrorToString(error));
+ }
+}
+
+Error RoutingManager::HandleInfraIfStateChanged(uint32_t aInfraIfIndex,
+ bool aIsRunning,
+ const Ip6::Address *aLinkLocalAddress)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(IsInitialized(), error = kErrorInvalidState);
+ VerifyOrExit(aInfraIfIndex == mInfraIfIndex, error = kErrorInvalidArgs);
+ VerifyOrExit(aLinkLocalAddress == nullptr || aLinkLocalAddress->IsLinkLocal(), error = kErrorInvalidArgs);
+
+ otLogInfoBr("infra interface state changed: %s, link-local-addr=%s", aIsRunning ? "RUNNING" : "NOT RUNNING",
+ (aLinkLocalAddress != nullptr) ? aLinkLocalAddress->ToString().AsCString() : "(null)");
+
+ mInfraIfIsRunning = aIsRunning;
+ if (aLinkLocalAddress == nullptr)
+ {
+ mInfraIfLinkLocalAddress.Clear();
+ }
+ else
+ {
+ mInfraIfLinkLocalAddress = *aLinkLocalAddress;
+ }
+
+ EvaluateState();
+
+exit:
+ return error;
+}
+
+void RoutingManager::HandleNotifierEvents(Events aEvents)
+{
+ VerifyOrExit(IsInitialized() && IsEnabled());
+
+ if (aEvents.Contains(kEventThreadRoleChanged))
+ {
+ EvaluateState();
+ }
+
+ if (mIsRunning && aEvents.Contains(kEventThreadNetdataChanged))
+ {
+ StartRoutingPolicyEvaluationDelay();
+ }
+
+exit:
+ return;
+}
+
+uint8_t RoutingManager::EvaluateOmrPrefix(Ip6::Prefix *aNewOmrPrefixes, uint8_t aMaxOmrPrefixNum)
+{
+ uint8_t newOmrPrefixNum = 0;
+ NetworkData::Iterator iterator = NetworkData::kIteratorInit;
+ NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
+ Ip6::Prefix * smallestOmrPrefix = nullptr;
+ Ip6::Prefix * publishedLocalOmrPrefix = nullptr;
+
+ OT_ASSERT(mIsRunning);
+
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == kErrorNone)
+ {
+ uint8_t newPrefixIndex;
+
+ if (!IsValidOmrPrefix(onMeshPrefixConfig))
+ {
+ continue;
+ }
+
+ newPrefixIndex = 0;
+ while (newPrefixIndex < newOmrPrefixNum && onMeshPrefixConfig.GetPrefix() != aNewOmrPrefixes[newPrefixIndex])
+ {
+ ++newPrefixIndex;
+ }
+
+ if (newPrefixIndex != newOmrPrefixNum)
+ {
+ // Ignore duplicate prefixes.
+ continue;
+ }
+
+ if (newOmrPrefixNum >= aMaxOmrPrefixNum)
+ {
+ otLogWarnBr("EvaluateOmrPrefix: too many OMR prefixes, ignoring prefix %s",
+ onMeshPrefixConfig.GetPrefix().ToString().AsCString());
+ continue;
+ }
+
+ aNewOmrPrefixes[newOmrPrefixNum] = onMeshPrefixConfig.GetPrefix();
+ if (smallestOmrPrefix == nullptr || (onMeshPrefixConfig.GetPrefix() < *smallestOmrPrefix))
+ {
+ smallestOmrPrefix = &aNewOmrPrefixes[newOmrPrefixNum];
+ }
+ if (aNewOmrPrefixes[newOmrPrefixNum] == mLocalOmrPrefix)
+ {
+ publishedLocalOmrPrefix = &aNewOmrPrefixes[newOmrPrefixNum];
+ }
+ ++newOmrPrefixNum;
+ }
+
+ // Decide if we need to add or remove my local OMR prefix.
+ if (newOmrPrefixNum == 0)
+ {
+ otLogInfoBr("EvaluateOmrPrefix: no valid OMR prefixes found in Thread network");
+ if (PublishLocalOmrPrefix() == kErrorNone)
+ {
+ aNewOmrPrefixes[newOmrPrefixNum++] = mLocalOmrPrefix;
+ }
+
+ // The `newOmrPrefixNum` is zero when we failed to publish the local OMR prefix.
+ }
+ else if (publishedLocalOmrPrefix != nullptr && smallestOmrPrefix != publishedLocalOmrPrefix)
+ {
+ otLogInfoBr("EvaluateOmrPrefix: there is already a smaller OMR prefix %s in the Thread network",
+ smallestOmrPrefix->ToString().AsCString());
+ UnpublishLocalOmrPrefix();
+
+ // Remove the local OMR prefix from the list by overwriting it with the last one.
+ *publishedLocalOmrPrefix = aNewOmrPrefixes[--newOmrPrefixNum];
+ }
+
+ return newOmrPrefixNum;
+}
+
+Error RoutingManager::PublishLocalOmrPrefix(void)
+{
+ Error error = kErrorNone;
+ NetworkData::OnMeshPrefixConfig omrPrefixConfig;
+
+ OT_ASSERT(mIsRunning);
+
+ omrPrefixConfig.Clear();
+ omrPrefixConfig.mPrefix = mLocalOmrPrefix;
+ omrPrefixConfig.mStable = true;
+ omrPrefixConfig.mSlaac = true;
+ omrPrefixConfig.mPreferred = true;
+ omrPrefixConfig.mOnMesh = true;
+ omrPrefixConfig.mDefaultRoute = false;
+ omrPrefixConfig.mPreference = OT_ROUTE_PREFERENCE_MED;
+
+ error = Get<NetworkData::Local>().AddOnMeshPrefix(omrPrefixConfig);
+ if (error != kErrorNone)
+ {
+ otLogWarnBr("failed to publish local OMR prefix %s in Thread network: %s",
+ mLocalOmrPrefix.ToString().AsCString(), ErrorToString(error));
+ }
+ else
+ {
+ Get<NetworkData::Notifier>().HandleServerDataUpdated();
+ otLogInfoBr("published local OMR prefix %s in Thread network", mLocalOmrPrefix.ToString().AsCString());
+ }
+
+ return error;
+}
+
+void RoutingManager::UnpublishLocalOmrPrefix(void)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(mIsRunning);
+
+ SuccessOrExit(error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mLocalOmrPrefix));
+
+ Get<NetworkData::Notifier>().HandleServerDataUpdated();
+ otLogInfoBr("unpublished local OMR prefix %s from Thread network", mLocalOmrPrefix.ToString().AsCString());
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogWarnBr("failed to unpublish local OMR prefix %s from Thread network: %s",
+ mLocalOmrPrefix.ToString().AsCString(), ErrorToString(error));
+ }
+}
+
+Error RoutingManager::AddExternalRoute(const Ip6::Prefix &aPrefix, otRoutePreference aRoutePreference)
+{
+ Error error;
+ NetworkData::ExternalRouteConfig routeConfig;
+
+ OT_ASSERT(mIsRunning);
+
+ routeConfig.Clear();
+ routeConfig.SetPrefix(aPrefix);
+ routeConfig.mStable = true;
+ routeConfig.mPreference = aRoutePreference;
+
+ error = Get<NetworkData::Local>().AddHasRoutePrefix(routeConfig);
+ if (error != kErrorNone)
+ {
+ otLogWarnBr("failed to add external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
+ }
+ else
+ {
+ Get<NetworkData::Notifier>().HandleServerDataUpdated();
+ otLogInfoBr("added external route %s", aPrefix.ToString().AsCString());
+ }
+
+ return error;
+}
+
+void RoutingManager::RemoveExternalRoute(const Ip6::Prefix &aPrefix)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(mIsRunning);
+
+ SuccessOrExit(error = Get<NetworkData::Local>().RemoveHasRoutePrefix(aPrefix));
+
+ Get<NetworkData::Notifier>().HandleServerDataUpdated();
+ otLogInfoBr("removed external route %s", aPrefix.ToString().AsCString());
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogWarnBr("failed to remove external route %s: %s", aPrefix.ToString().AsCString(), ErrorToString(error));
+ }
+}
+
+bool RoutingManager::ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum)
+{
+ bool ret = false;
+
+ for (uint8_t i = 0; i < aPrefixNum; ++i)
+ {
+ if (aPrefixList[i] == aPrefix)
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+const Ip6::Prefix *RoutingManager::EvaluateOnLinkPrefix(void)
+{
+ const Ip6::Prefix *newOnLinkPrefix = nullptr;
+ const Ip6::Prefix *smallestOnLinkPrefix = nullptr;
+
+ // We don't evaluate on-link prefix if we are doing Router Solicitation.
+ VerifyOrExit(!mRouterSolicitTimer.IsRunning());
+
+ for (uint8_t i = 0; i < mDiscoveredPrefixNum; ++i)
+ {
+ ExternalPrefix &prefix = mDiscoveredPrefixes[i];
+
+ if (!prefix.mIsOnLinkPrefix)
+ {
+ continue;
+ }
+
+ if (smallestOnLinkPrefix == nullptr || (prefix.mPrefix < *smallestOnLinkPrefix))
+ {
+ smallestOnLinkPrefix = &prefix.mPrefix;
+ }
+ }
+
+ // We start advertising our local on-link prefix if there is no existing one.
+ if (smallestOnLinkPrefix == nullptr)
+ {
+ if (mAdvertisedOnLinkPrefix != nullptr)
+ {
+ newOnLinkPrefix = mAdvertisedOnLinkPrefix;
+ }
+ else if (AddExternalRoute(mLocalOnLinkPrefix, OT_ROUTE_PREFERENCE_MED) == kErrorNone)
+ {
+ newOnLinkPrefix = &mLocalOnLinkPrefix;
+ }
+ }
+ // When an application-specific on-link prefix is received and it is bigger than the
+ // advertised prefix, we will not remove the advertised prefix. In this case, there
+ // will be two on-link prefixes on the infra link. But all BRs will still converge to
+ // the same smallest on-link prefix and the application-specific prefix is not used.
+ else if (mAdvertisedOnLinkPrefix != nullptr)
+ {
+ if (*mAdvertisedOnLinkPrefix < *smallestOnLinkPrefix)
+ {
+ newOnLinkPrefix = mAdvertisedOnLinkPrefix;
+ }
+ else
+ {
+ otLogInfoBr("EvaluateOnLinkPrefix: there is already smaller on-link prefix %s on interface %u",
+ smallestOnLinkPrefix->ToString().AsCString(), mInfraIfIndex);
+
+ // TODO: we removes the advertised on-link prefix by setting valid lifetime for PIO.
+ // But SLAAC addresses configured by PIO prefix will not be removed immediately (
+ // https://tools.ietf.org/html/rfc4862#section-5.5.3). This leads to a situation that
+ // a WiFi device keeps using the old SLAAC address but a Thread device cannot reach to
+ // it. One solution is to delay removing external route until the SLAAC addresses are
+ // actually expired/deprecated.
+ RemoveExternalRoute(*mAdvertisedOnLinkPrefix);
+ }
+ }
+
+exit:
+ return newOnLinkPrefix;
+}
+
+// This method evaluate the routing policy depends on prefix and route
+// information on Thread Network and infra link. As a result, this
+// method May send RA messages on infra link and publish/unpublish
+// OMR prefix in the Thread network.
+void RoutingManager::EvaluateRoutingPolicy(void)
+{
+ OT_ASSERT(mIsRunning);
+
+ const Ip6::Prefix *newOnLinkPrefix = nullptr;
+ Ip6::Prefix newOmrPrefixes[kMaxOmrPrefixNum];
+ uint8_t newOmrPrefixNum = 0;
+
+ otLogInfoBr("evaluating routing policy");
+
+ // 0. Evaluate on-link & OMR prefixes.
+ newOnLinkPrefix = EvaluateOnLinkPrefix();
+ newOmrPrefixNum = EvaluateOmrPrefix(newOmrPrefixes, kMaxOmrPrefixNum);
+
+ // 1. Send Router Advertisement message if necessary.
+ SendRouterAdvertisement(newOmrPrefixes, newOmrPrefixNum, newOnLinkPrefix);
+ if (newOmrPrefixNum == 0)
+ {
+ // This is the very exceptional case and happens only when we failed to publish
+ // our local OMR prefix to the Thread network. We schedule the Router Advertisement
+ // timer to re-evaluate our routing policy in the future.
+ otLogWarnBr("no OMR prefix advertised! Start Router Advertisement timer for future evaluation");
+ }
+
+ // 2. Schedule Router Advertisement timer with random interval.
+ {
+ uint32_t nextSendTime;
+
+ nextSendTime = Random::NonCrypto::GetUint32InRange(kMinRtrAdvInterval, kMaxRtrAdvInterval);
+
+ if (mRouterAdvertisementCount <= kMaxInitRtrAdvertisements && nextSendTime > kMaxInitRtrAdvInterval)
+ {
+ nextSendTime = kMaxInitRtrAdvInterval;
+ }
+
+ otLogInfoBr("router advertisement scheduled in %u seconds", nextSendTime);
+ mRouterAdvertisementTimer.Start(Time::SecToMsec(nextSendTime));
+ }
+
+ // 3. Update advertised on-link & OMR prefixes information.
+ mAdvertisedOnLinkPrefix = newOnLinkPrefix;
+ static_assert(sizeof(mAdvertisedOmrPrefixes) == sizeof(newOmrPrefixes), "invalid new OMR prefix array size");
+ memcpy(mAdvertisedOmrPrefixes, newOmrPrefixes, sizeof(newOmrPrefixes[0]) * newOmrPrefixNum);
+ mAdvertisedOmrPrefixNum = newOmrPrefixNum;
+}
+
+void RoutingManager::StartRoutingPolicyEvaluationDelay(void)
+{
+ OT_ASSERT(mIsRunning);
+
+ uint32_t randomDelay;
+
+ static_assert(kMaxRoutingPolicyDelay > 0, "invalid maximum routing policy evaluation delay");
+ randomDelay = Random::NonCrypto::GetUint32InRange(0, Time::SecToMsec(kMaxRoutingPolicyDelay));
+
+ otLogInfoBr("start evaluating routing policy, scheduled in %u milliseconds", randomDelay);
+ mRoutingPolicyTimer.Start(randomDelay);
+}
+
+// starts sending Router Solicitations in random delay
+// between 0 and kMaxRtrSolicitationDelay.
+void RoutingManager::StartRouterSolicitationDelay(void)
+{
+ uint32_t randomDelay;
+
+ mRouterSolicitCount = 0;
+
+ static_assert(kMaxRtrSolicitationDelay > 0, "invalid maximum Router Solicitation delay");
+ randomDelay = Random::NonCrypto::GetUint32InRange(0, Time::SecToMsec(kMaxRtrSolicitationDelay));
+
+ otLogInfoBr("start Router Solicitation, scheduled in %u milliseconds", randomDelay);
+ mRouterSolicitTimer.Start(randomDelay);
+}
+
+Error RoutingManager::SendRouterSolicitation(void)
+{
+ Ip6::Address destAddress;
+ RouterAdv::RouterSolicitMessage routerSolicit;
+
+ OT_ASSERT(IsInitialized());
+
+ destAddress.SetToLinkLocalAllRoutersMulticast();
+ return otPlatInfraIfSendIcmp6Nd(mInfraIfIndex, &destAddress, reinterpret_cast<const uint8_t *>(&routerSolicit),
+ sizeof(routerSolicit));
+}
+
+// This method sends Router Advertisement messages to advertise on-link prefix and route for OMR prefix.
+// @param[in] aNewOmrPrefixes A pointer to an array of the new OMR prefixes to be advertised.
+// @p aNewOmrPrefixNum must be zero if this argument is nullptr.
+// @param[in] aNewOmrPrefixNum The number of the new OMR prefixes to be advertised.
+// Zero means we should stop advertising OMR prefixes.
+// @param[in] aOnLinkPrefix A pointer to the new on-link prefix to be advertised.
+// nullptr means we should stop advertising on-link prefix.
+void RoutingManager::SendRouterAdvertisement(const Ip6::Prefix *aNewOmrPrefixes,
+ uint8_t aNewOmrPrefixNum,
+ const Ip6::Prefix *aNewOnLinkPrefix)
+{
+ uint8_t buffer[kMaxRouterAdvMessageLength];
+ uint16_t bufferLength = 0;
+ RouterAdv::RouterAdvMessage routerAdv;
+
+ // Set zero Router Lifetime to indicate that the Border Router is not the default
+ // router for infra link so that hosts on infra link will not create default route
+ // to the Border Router when received RA.
+ routerAdv.SetRouterLifetime(0);
+
+ OT_ASSERT(bufferLength + sizeof(routerAdv) <= sizeof(buffer));
+ memcpy(buffer, &routerAdv, sizeof(routerAdv));
+ bufferLength += sizeof(routerAdv);
+
+ if (aNewOnLinkPrefix != nullptr)
+ {
+ RouterAdv::PrefixInfoOption pio;
+
+ pio.SetOnLink(true);
+ pio.SetAutoAddrConfig(true);
+ pio.SetValidLifetime(kDefaultOnLinkPrefixLifetime);
+ pio.SetPreferredLifetime(kDefaultOnLinkPrefixLifetime);
+ pio.SetPrefix(*aNewOnLinkPrefix);
+
+ OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
+ memcpy(buffer + bufferLength, &pio, pio.GetSize());
+ bufferLength += pio.GetSize();
+
+ if (mAdvertisedOnLinkPrefix == nullptr)
+ {
+ otLogInfoBr("start advertising new on-link prefix %s on interface %u",
+ aNewOnLinkPrefix->ToString().AsCString(), mInfraIfIndex);
+ }
+
+ otLogInfoBr("send on-link prefix %s in PIO (valid lifetime = %u seconds)",
+ aNewOnLinkPrefix->ToString().AsCString(), kDefaultOnLinkPrefixLifetime);
+ }
+ else if (mAdvertisedOnLinkPrefix != nullptr)
+ {
+ RouterAdv::PrefixInfoOption pio;
+
+ pio.SetOnLink(true);
+ pio.SetAutoAddrConfig(true);
+
+ // Set zero valid lifetime to immediately invalidate the advertised on-link prefix.
+ pio.SetValidLifetime(0);
+ pio.SetPreferredLifetime(0);
+ pio.SetPrefix(*mAdvertisedOnLinkPrefix);
+
+ OT_ASSERT(bufferLength + pio.GetSize() <= sizeof(buffer));
+ memcpy(buffer + bufferLength, &pio, pio.GetSize());
+ bufferLength += pio.GetSize();
+
+ otLogInfoBr("stop advertising on-link prefix %s on interface %u",
+ mAdvertisedOnLinkPrefix->ToString().AsCString(), mInfraIfIndex);
+ }
+
+ // Invalidate the advertised OMR prefixes if they are no longer in the new OMR prefix array.
+ for (uint8_t i = 0; i < mAdvertisedOmrPrefixNum; ++i)
+ {
+ const Ip6::Prefix &advertisedOmrPrefix = mAdvertisedOmrPrefixes[i];
+
+ if (!ContainsPrefix(advertisedOmrPrefix, aNewOmrPrefixes, aNewOmrPrefixNum))
+ {
+ RouterAdv::RouteInfoOption rio;
+
+ // Set zero route lifetime to immediately invalidate the advertised OMR prefix.
+ rio.SetRouteLifetime(0);
+ rio.SetPrefix(advertisedOmrPrefix);
+
+ OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
+ memcpy(buffer + bufferLength, &rio, rio.GetSize());
+ bufferLength += rio.GetSize();
+
+ otLogInfoBr("stop advertising OMR prefix %s on interface %u", advertisedOmrPrefix.ToString().AsCString(),
+ mInfraIfIndex);
+ }
+ }
+
+ for (uint8_t i = 0; i < aNewOmrPrefixNum; ++i)
+ {
+ const Ip6::Prefix & newOmrPrefix = aNewOmrPrefixes[i];
+ RouterAdv::RouteInfoOption rio;
+
+ rio.SetRouteLifetime(kDefaultOmrPrefixLifetime);
+ rio.SetPrefix(newOmrPrefix);
+
+ OT_ASSERT(bufferLength + rio.GetSize() <= sizeof(buffer));
+ memcpy(buffer + bufferLength, &rio, rio.GetSize());
+ bufferLength += rio.GetSize();
+
+ otLogInfoBr("send OMR prefix %s in RIO (valid lifetime = %u seconds)", newOmrPrefix.ToString().AsCString(),
+ kDefaultOmrPrefixLifetime);
+ }
+
+ // Send the message only when there are options.
+ if (bufferLength > sizeof(routerAdv))
+ {
+ Error error;
+ Ip6::Address destAddress;
+
+ ++mRouterAdvertisementCount;
+
+ destAddress.SetToLinkLocalAllNodesMulticast();
+ error = otPlatInfraIfSendIcmp6Nd(mInfraIfIndex, &destAddress, buffer, bufferLength);
+
+ if (error == kErrorNone)
+ {
+ otLogInfoBr("sent Router Advertisement on interface %u", mInfraIfIndex);
+ }
+ else
+ {
+ otLogWarnBr("failed to send Router Advertisement on interface %u: %s", mInfraIfIndex, ErrorToString(error));
+ }
+ }
+}
+
+bool RoutingManager::IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig)
+{
+ return IsValidOmrPrefix(aOnMeshPrefixConfig.GetPrefix()) && aOnMeshPrefixConfig.mSlaac && !aOnMeshPrefixConfig.mDp;
+}
+
+bool RoutingManager::IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix)
+{
+ // Accept ULA prefix with length of 64 bits and GUA prefix.
+ return (aOmrPrefix.mLength == kOmrPrefixLength && aOmrPrefix.mPrefix.mFields.m8[0] == 0xfd) ||
+ (aOmrPrefix.mLength >= 3 && (aOmrPrefix.GetBytes()[0] & 0xE0) == 0x20);
+}
+
+bool RoutingManager::IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix)
+{
+ // Accept ULA prefix with length of 64 bits and GUA prefix.
+ return (aOnLinkPrefix.mLength == kOnLinkPrefixLength && aOnLinkPrefix.mPrefix.mFields.m8[0] == 0xfd) ||
+ (aOnLinkPrefix.mLength >= 3 && (aOnLinkPrefix.GetBytes()[0] & 0xE0) == 0x20);
+}
+
+void RoutingManager::HandleRouterAdvertisementTimer(Timer &aTimer)
+{
+ aTimer.Get<RoutingManager>().HandleRouterAdvertisementTimer();
+}
+
+void RoutingManager::HandleRouterAdvertisementTimer(void)
+{
+ otLogInfoBr("router advertisement timer triggered");
+
+ EvaluateRoutingPolicy();
+}
+
+void RoutingManager::HandleRouterSolicitTimer(Timer &aTimer)
+{
+ aTimer.Get<RoutingManager>().HandleRouterSolicitTimer();
+}
+
+void RoutingManager::HandleRouterSolicitTimer(void)
+{
+ otLogInfoBr("router solicitation times out");
+
+ if (mRouterSolicitCount < kMaxRtrSolicitations)
+ {
+ uint32_t nextSolicitationDelay;
+ Error error;
+
+ error = SendRouterSolicitation();
+ ++mRouterSolicitCount;
+
+ if (error == kErrorNone)
+ {
+ otLogDebgBr("successfully sent %uth Router Solicitation", mRouterSolicitCount);
+ }
+ else
+ {
+ otLogCritBr("failed to send %uth Router Solicitation: %s", mRouterSolicitCount, ErrorToString(error));
+ }
+
+ nextSolicitationDelay =
+ (mRouterSolicitCount == kMaxRtrSolicitations) ? kMaxRtrSolicitationDelay : kRtrSolicitationInterval;
+
+ otLogDebgBr("router solicitation timer scheduled in %u seconds", nextSolicitationDelay);
+ mRouterSolicitTimer.Start(Time::SecToMsec(nextSolicitationDelay));
+ }
+ else
+ {
+ // Re-evaluate our routing policy and send Router Advertisement if necessary.
+ EvaluateRoutingPolicy();
+ }
+}
+
+void RoutingManager::HandleDiscoveredPrefixInvalidTimer(Timer &aTimer)
+{
+ aTimer.Get<RoutingManager>().HandleDiscoveredPrefixInvalidTimer();
+}
+
+void RoutingManager::HandleDiscoveredPrefixInvalidTimer(void)
+{
+ InvalidateDiscoveredPrefixes();
+}
+
+void RoutingManager::HandleRoutingPolicyTimer(Timer &aTimer)
+{
+ aTimer.Get<RoutingManager>().EvaluateRoutingPolicy();
+}
+
+void RoutingManager::HandleRouterSolicit(const Ip6::Address &aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ uint32_t randomDelay;
+
+ OT_UNUSED_VARIABLE(aSrcAddress);
+ OT_UNUSED_VARIABLE(aBuffer);
+ OT_UNUSED_VARIABLE(aBufferLength);
+
+ VerifyOrExit(!mRouterSolicitTimer.IsRunning());
+
+ otLogInfoBr("received Router Solicitation from %s on interface %u", aSrcAddress.ToString().AsCString(),
+ mInfraIfIndex);
+
+ randomDelay = Random::NonCrypto::GetUint32InRange(0, kMaxRaDelayTime);
+
+ otLogInfoBr("Router Advertisement scheduled in %u milliseconds", randomDelay);
+ mRouterAdvertisementTimer.Start(randomDelay);
+
+exit:
+ return;
+}
+
+uint32_t RoutingManager::GetPrefixExpireDelay(uint32_t aValidLifetime)
+{
+ uint32_t delay;
+
+ if (aValidLifetime * static_cast<uint64_t>(1000) > Timer::kMaxDelay)
+ {
+ delay = Timer::kMaxDelay;
+ }
+ else
+ {
+ delay = aValidLifetime * 1000;
+ }
+
+ return delay;
+}
+
+void RoutingManager::HandleRouterAdvertisement(const Ip6::Address &aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ OT_ASSERT(mIsRunning);
+ OT_UNUSED_VARIABLE(aSrcAddress);
+
+ using RouterAdv::Option;
+ using RouterAdv::PrefixInfoOption;
+ using RouterAdv::RouteInfoOption;
+ using RouterAdv::RouterAdvMessage;
+
+ bool needReevaluate = false;
+ const uint8_t *optionsBegin;
+ uint16_t optionsLength;
+ const Option * option;
+
+ VerifyOrExit(aBufferLength >= sizeof(RouterAdvMessage));
+
+ otLogInfoBr("received Router Advertisement from %s on interface %u", aSrcAddress.ToString().AsCString(),
+ mInfraIfIndex);
+
+ optionsBegin = aBuffer + sizeof(RouterAdvMessage);
+ optionsLength = aBufferLength - sizeof(RouterAdvMessage);
+
+ option = nullptr;
+ while ((option = Option::GetNextOption(option, optionsBegin, optionsLength)) != nullptr)
+ {
+ switch (option->GetType())
+ {
+ case Option::Type::kPrefixInfo:
+ {
+ const PrefixInfoOption *pio = static_cast<const PrefixInfoOption *>(option);
+
+ if (pio->IsValid())
+ {
+ needReevaluate |= UpdateDiscoveredPrefixes(*pio);
+ }
+ }
+ break;
+
+ case Option::Type::kRouteInfo:
+ {
+ const RouteInfoOption *rio = static_cast<const RouteInfoOption *>(option);
+
+ if (rio->IsValid())
+ {
+ needReevaluate |= UpdateDiscoveredPrefixes(*rio);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (needReevaluate)
+ {
+ StartRoutingPolicyEvaluationDelay();
+ }
+
+exit:
+ return;
+}
+
+bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio)
+{
+ Ip6::Prefix prefix = aPio.GetPrefix();
+ bool needReevaluate = false;
+
+ if (!IsValidOnLinkPrefix(prefix))
+ {
+ otLogInfoBr("ignore invalid prefix in PIO: %s", prefix.ToString().AsCString());
+ ExitNow();
+ }
+
+ otLogInfoBr("discovered on-link prefix (%s, %u seconds) from interface %u", prefix.ToString().AsCString(),
+ aPio.GetValidLifetime(), mInfraIfIndex);
+
+ if (aPio.GetValidLifetime() == 0)
+ {
+ needReevaluate = InvalidateDiscoveredPrefixes(&prefix, /* aIsOnLinkPrefix */ true) > 0;
+ }
+ else
+ {
+ needReevaluate = AddDiscoveredPrefix(prefix, /* aIsOnLinkPrefix */ true, aPio.GetValidLifetime());
+ }
+
+exit:
+ return needReevaluate;
+}
+
+bool RoutingManager::UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio)
+{
+ Ip6::Prefix prefix = aRio.GetPrefix();
+ bool needReevaluate = false;
+
+ if (!IsValidOmrPrefix(prefix))
+ {
+ otLogInfoBr("ignore invalid prefix in RIO: %s", prefix.ToString().AsCString());
+ ExitNow();
+ }
+
+ // Ignore the OMR prefix in current Thread Network.
+ VerifyOrExit(!NetworkDataContainsOmrPrefix(prefix));
+
+ otLogInfoBr("discovered OMR prefix (%s, %u seconds) from interface %u", prefix.ToString().AsCString(),
+ aRio.GetRouteLifetime(), mInfraIfIndex);
+
+ if (aRio.GetRouteLifetime() == 0)
+ {
+ needReevaluate = (InvalidateDiscoveredPrefixes(&prefix, /* aIsOnLinkPrefix */ false) > 0);
+ }
+ else
+ {
+ needReevaluate =
+ AddDiscoveredPrefix(prefix, /* aIsOnLinkPrefix */ false, aRio.GetRouteLifetime(), aRio.GetPreference());
+ }
+
+exit:
+ return needReevaluate;
+}
+
+bool RoutingManager::InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix, bool aIsOnLinkPrefix)
+{
+ uint8_t removedNum = 0;
+ ExternalPrefix *keptPrefix = mDiscoveredPrefixes;
+ TimeMilli now = TimerMilli::GetNow();
+ TimeMilli earliestExpireTime = now.GetDistantFuture();
+ uint8_t keptOnLinkPrefixNum = 0;
+
+ for (uint8_t i = 0; i < mDiscoveredPrefixNum; ++i)
+ {
+ ExternalPrefix &prefix = mDiscoveredPrefixes[i];
+
+ if ((aPrefix != nullptr && prefix.mPrefix == *aPrefix && prefix.mIsOnLinkPrefix == aIsOnLinkPrefix) ||
+ (prefix.mExpireTime <= now))
+ {
+ RemoveExternalRoute(prefix.mPrefix);
+ ++removedNum;
+ }
+ else
+ {
+ earliestExpireTime = OT_MIN(earliestExpireTime, prefix.mExpireTime);
+ *keptPrefix = prefix;
+ ++keptPrefix;
+ if (prefix.mIsOnLinkPrefix)
+ {
+ ++keptOnLinkPrefixNum;
+ }
+ }
+ }
+
+ mDiscoveredPrefixNum -= removedNum;
+
+ if (keptOnLinkPrefixNum == 0)
+ {
+ mDiscoveredPrefixInvalidTimer.Stop();
+
+ // There are no valid on-link prefixes on infra link now, start Router Solicitation
+ // To find out more on-link prefixes or timeout to advertise my local on-link prefix.
+ StartRouterSolicitationDelay();
+ }
+ else
+ {
+ mDiscoveredPrefixInvalidTimer.FireAt(earliestExpireTime);
+ }
+
+ return (removedNum != 0); // If anything was removed we need to reevaluate.
+}
+
+void RoutingManager::InvalidateAllDiscoveredPrefixes(void)
+{
+ TimeMilli past = TimerMilli::GetNow();
+
+ for (uint8_t i = 0; i < mDiscoveredPrefixNum; ++i)
+ {
+ mDiscoveredPrefixes[i].mExpireTime = past;
+ }
+
+ InvalidateDiscoveredPrefixes();
+
+ OT_ASSERT(mDiscoveredPrefixNum == 0);
+}
+
+// Adds a discovered prefix on infra link. If the same prefix already exists,
+// only the lifetime will be updated. Returns a boolean which indicates whether
+// a new prefix is added.
+bool RoutingManager::AddDiscoveredPrefix(const Ip6::Prefix &aPrefix,
+ bool aIsOnLinkPrefix,
+ uint32_t aLifetime,
+ otRoutePreference aRoutePreference)
+{
+ OT_ASSERT(aIsOnLinkPrefix ? IsValidOmrPrefix(aPrefix) : IsValidOnLinkPrefix(aPrefix));
+ OT_ASSERT(aLifetime > 0);
+
+ bool added = false;
+
+ for (uint8_t i = 0; i < mDiscoveredPrefixNum; ++i)
+ {
+ ExternalPrefix &prefix = mDiscoveredPrefixes[i];
+
+ if (aPrefix == prefix.mPrefix && aIsOnLinkPrefix == prefix.mIsOnLinkPrefix)
+ {
+ prefix.mExpireTime = TimerMilli::GetNow() + GetPrefixExpireDelay(aLifetime);
+ mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(prefix.mExpireTime);
+
+ otLogInfoBr("discovered prefix %s refreshed lifetime: %u seconds", aPrefix.ToString().AsCString(),
+ aLifetime);
+ ExitNow();
+ }
+ }
+
+ if (mDiscoveredPrefixNum < kMaxDiscoveredPrefixNum)
+ {
+ ExternalPrefix &newPrefix = mDiscoveredPrefixes[mDiscoveredPrefixNum];
+
+ SuccessOrExit(AddExternalRoute(aPrefix, aRoutePreference));
+
+ if (aIsOnLinkPrefix && mRouterSolicitCount > 0)
+ {
+ // Stop Router Solicitation if we discovered a valid on-link prefix.
+ // Otherwise, we wait till the Router Solicitation process times out.
+ // So the maximum delay before the Border Router starts advertising
+ // its own on-link prefix is 10 seconds = RS_DELAY (1) + RS_INTERNAL (4)
+ // + RS_INTERVAL (4) + RS_DELAY (1).
+ //
+ // Always send at least one RS message so that all BRs will respond.
+ // Consider that there are multiple BRs on the infra link, we may not learn
+ // RIOs of other BRs if the router discovery process is stopped immediately
+ // before sending any RS messages because of receiving an unsolicited RA.
+ mRouterSolicitTimer.Stop();
+ }
+
+ newPrefix.mPrefix = aPrefix;
+ newPrefix.mIsOnLinkPrefix = aIsOnLinkPrefix;
+ newPrefix.mExpireTime = TimerMilli::GetNow() + GetPrefixExpireDelay(aLifetime);
+ mDiscoveredPrefixInvalidTimer.FireAtIfEarlier(newPrefix.mExpireTime);
+
+ ++mDiscoveredPrefixNum;
+ added = true;
+ }
+ else
+ {
+ otLogWarnBr("discovered too many prefixes, ignore new prefix %s", aPrefix.ToString().AsCString());
+ }
+
+exit:
+ return added;
+}
+
+bool RoutingManager::NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const
+{
+ NetworkData::Iterator iterator = NetworkData::kIteratorInit;
+ NetworkData::OnMeshPrefixConfig onMeshPrefixConfig;
+ bool contain = false;
+
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, onMeshPrefixConfig) == OT_ERROR_NONE)
+ {
+ if (IsValidOmrPrefix(onMeshPrefixConfig) && onMeshPrefixConfig.GetPrefix() == aPrefix)
+ {
+ contain = true;
+ break;
+ }
+ }
+
+ return contain;
+}
+
+} // namespace BorderRouter
+
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp
new file mode 100644
index 0000000..c4a9e81
--- /dev/null
+++ b/src/core/border_router/routing_manager.hpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for the RA-based routing management.
+ *
+ */
+
+#ifndef ROUTING_MANAGER_HPP_
+#define ROUTING_MANAGER_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#if !OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+#error "OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE."
+#endif
+
+#if !OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
+#error "OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE is required for OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE."
+#endif
+
+#include <openthread/netdata.h>
+#include <openthread/platform/infra_if.h>
+
+#include "border_router/router_advertisement.hpp"
+#include "common/error.hpp"
+#include "common/locator.hpp"
+#include "common/notifier.hpp"
+#include "common/timer.hpp"
+#include "net/ip6.hpp"
+#include "thread/network_data.hpp"
+
+namespace ot {
+
+namespace BorderRouter {
+
+/**
+ * This class implements bi-directional routing between Thread and
+ * Infrastructure networks.
+ *
+ * The Border Routing manager works on both Thread interface and
+ * infrastructure interface. All ICMPv6 messages are sent/recv
+ * on the infrastructure interface.
+ *
+ */
+class RoutingManager : public InstanceLocator
+{
+ friend class ot::Notifier;
+
+public:
+ /**
+ * This constructor initializes the routing manager.
+ *
+ * @param[in] aInstance A OpenThread instance.
+ *
+ */
+ explicit RoutingManager(Instance &aInstance);
+
+ /**
+ * This method initializes the routing manager on given infrastructure interface.
+ *
+ * @param[in] aInfraIfIndex An infrastructure network interface index.
+ * @param[in] aInfraIfIsRunning A boolean that indicates whether the infrastructure
+ * interface is running.
+ * @param[in] aInfraIfLinkLocalAddress A pointer to the IPv6 link-local address of the infrastructure
+ * interface. NULL if the IPv6 link-local address is missing.
+ *
+ * @retval kErrorNone Successfully started the routing manager.
+ * @retval kErrorInvalidArgs The index of the infra interface is not valid.
+ *
+ */
+ Error Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning, const Ip6::Address *aInfraIfLinkLocalAddress);
+
+ /**
+ * This method enables/disables the Border Routing Manager.
+ *
+ * @note The Border Routing Manager is enabled by default.
+ *
+ * @param[in] aEnabled A boolean to enable/disable the Border Routing Manager.
+ *
+ * @retval kErrorInvalidState The Border Routing Manager is not initialized yet.
+ * @retval kErrorNone Successfully enabled/disabled the Border Routing Manager.
+ *
+ */
+ Error SetEnabled(bool aEnabled);
+
+ /**
+ * This method receives an ICMPv6 message on the infrastructure interface.
+ *
+ * Malformed or undesired messages are dropped silently.
+ *
+ * @param[in] aInfraIfIndex The infrastructure interface index.
+ * @param[in] aSrcAddress The source address this message is sent from.
+ * @param[in] aBuffer THe ICMPv6 message buffer.
+ * @param[in] aLength The length of the ICMPv6 message buffer.
+ *
+ */
+ void RecvIcmp6Message(uint32_t aInfraIfIndex,
+ const Ip6::Address &aSrcAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength);
+
+ /**
+ * This method handles infrastructure interface state changes.
+ *
+ * @param[in] aInfraIfIndex The index of the infrastructure interface.
+ * @param[in] aIsRunning A boolean that indicates whether the infrastructure
+ * interface is running.
+ * @param[in] aLinkLocalAddress A pointer to the IPv6 link local address of the infrastructure
+ * interface. NULL if the IPv6 link local address is lost.
+ *
+ * @retval kErrorNone Successfully updated the infra interface status.
+ * @retval kErrorInvalidState The Routing Manager is not initialized.
+ * @retval kErrorInvalidArgs The @p aInfraIfIndex doesn't match the infra interface the Routing Manager are
+ * initialized with, or the @p aLinkLocalAddress is not a valid IPv6 link-local
+ * address.
+ *
+ */
+ Error HandleInfraIfStateChanged(uint32_t aInfraIfIndex, bool aIsRunning, const Ip6::Address *aLinkLocalAddress);
+
+private:
+ enum : uint16_t
+ {
+ kMaxRouterAdvMessageLength = 256u, // The maximum RA message length we can handle.
+ };
+
+ enum : uint8_t
+ {
+ kMaxOmrPrefixNum =
+ OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES, // The maximum number of the OMR prefixes to advertise.
+ kMaxDiscoveredPrefixNum = 8u, // The maximum number of prefixes to discover on the infra link.
+ kOmrPrefixLength = OT_IP6_PREFIX_BITSIZE, // The length of an OMR prefix. In bits.
+ kOnLinkPrefixLength = OT_IP6_PREFIX_BITSIZE, // The length of an On-link prefix. In bits.
+ };
+
+ enum : uint32_t
+ {
+ kDefaultOmrPrefixLifetime = 1800u, // The default OMR prefix valid lifetime. In seconds.
+ kDefaultOnLinkPrefixLifetime = 1800u, // The default on-link prefix valid lifetime. In seconds.
+ kMaxRtrAdvInterval = 600, // Maximum Router Advertisement Interval. In seconds.
+ kMinRtrAdvInterval = kMaxRtrAdvInterval / 3, // Minimum Router Advertisement Interval. In seconds.
+ kMaxInitRtrAdvInterval = 16, // Maximum Initial Router Advertisement Interval. In seconds.
+ kMaxRaDelayTime = 500, // The maximum delay of sending RA after receiving RS. In milliseconds.
+ kRtrSolicitationInterval = 4, // The interval between Router Solicitations. In seconds.
+ kMaxRtrSolicitationDelay = 1, // The maximum delay for initial solicitation. In seconds.
+ kMaxRoutingPolicyDelay = 1, // The maximum delay for routing policy evaluation. In seconds.
+ };
+
+ static_assert(kMinRtrAdvInterval <= 3 * kMaxRtrAdvInterval / 4, "invalid RA intervals");
+ static_assert(kDefaultOmrPrefixLifetime >= kMaxRtrAdvInterval, "invalid default OMR prefix lifetime");
+ static_assert(kDefaultOnLinkPrefixLifetime >= kMaxRtrAdvInterval, "invalid default on-link prefix lifetime");
+
+ enum : uint32_t
+ {
+ kMaxInitRtrAdvertisements = 3, // The maximum number of initial Router Advertisements.
+ kMaxRtrSolicitations = 3, // The Maximum number of Router Solicitations before sending Router Advertisements.
+ };
+
+ // This struct represents an external prefix which is
+ // discovered on the infrastructure interface.
+ struct ExternalPrefix : public Clearable<ExternalPrefix>
+ {
+ Ip6::Prefix mPrefix;
+ TimeMilli mExpireTime;
+ bool mIsOnLinkPrefix;
+ };
+
+ void EvaluateState(void);
+ void Start(void);
+ void Stop(void);
+ void HandleNotifierEvents(Events aEvents);
+ bool IsInitialized(void) const { return mInfraIfIndex != 0; }
+ bool IsEnabled(void) const { return mIsEnabled; }
+ Error LoadOrGenerateRandomOmrPrefix(void);
+ Error LoadOrGenerateRandomOnLinkPrefix(void);
+
+ const Ip6::Prefix *EvaluateOnLinkPrefix(void);
+
+ void EvaluateRoutingPolicy(void);
+ void StartRoutingPolicyEvaluationDelay(void);
+ uint8_t EvaluateOmrPrefix(Ip6::Prefix *aNewOmrPrefixes, uint8_t aMaxOmrPrefixNum);
+ Error PublishLocalOmrPrefix(void);
+ void UnpublishLocalOmrPrefix(void);
+ Error AddExternalRoute(const Ip6::Prefix &aPrefix, otRoutePreference aRoutePreference);
+ void RemoveExternalRoute(const Ip6::Prefix &aPrefix);
+ void StartRouterSolicitationDelay(void);
+ Error SendRouterSolicitation(void);
+ void SendRouterAdvertisement(const Ip6::Prefix *aNewOmrPrefixes,
+ uint8_t aNewOmrPrefixNum,
+ const Ip6::Prefix *aNewOnLinkPrefix);
+
+ static void HandleRouterAdvertisementTimer(Timer &aTimer);
+ void HandleRouterAdvertisementTimer(void);
+
+ static void HandleRouterSolicitTimer(Timer &aTimer);
+ void HandleRouterSolicitTimer(void);
+
+ static void HandleDiscoveredPrefixInvalidTimer(Timer &aTimer);
+ void HandleDiscoveredPrefixInvalidTimer(void);
+
+ static void HandleRoutingPolicyTimer(Timer &aTimer);
+
+ void HandleRouterSolicit(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength);
+ void HandleRouterAdvertisement(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength);
+ bool UpdateDiscoveredPrefixes(const RouterAdv::PrefixInfoOption &aPio);
+ bool UpdateDiscoveredPrefixes(const RouterAdv::RouteInfoOption &aRio);
+ bool InvalidateDiscoveredPrefixes(const Ip6::Prefix *aPrefix = nullptr, bool aIsOnLinkPrefix = true);
+ void InvalidateAllDiscoveredPrefixes(void);
+ bool AddDiscoveredPrefix(const Ip6::Prefix &aPrefix,
+ bool aIsOnLinkPrefix,
+ uint32_t aLifetime,
+ otRoutePreference aRoutePreference = OT_ROUTE_PREFERENCE_MED);
+ bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
+
+ static bool IsValidOmrPrefix(const NetworkData::OnMeshPrefixConfig &aOnMeshPrefixConfig);
+ static bool IsValidOmrPrefix(const Ip6::Prefix &aOmrPrefix);
+ static bool IsValidOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
+ static bool ContainsPrefix(const Ip6::Prefix &aPrefix, const Ip6::Prefix *aPrefixList, uint8_t aPrefixNum);
+ static uint32_t GetPrefixExpireDelay(uint32_t aValidLifetime);
+
+ // Indicates whether the Routing Manager is running (started).
+ bool mIsRunning;
+
+ // Indicates whether the Routing manager is enabled.
+ // The Routing Manager will be stopped if we are
+ // disabled.
+ bool mIsEnabled;
+
+ // Indicates whether the infra interface is running.
+ // The Routing Manager will be stopped when the
+ // Infra interface is not running.
+ bool mInfraIfIsRunning;
+
+ // The index of the infra interface on which Router
+ // Advertisement messages will be sent.
+ uint32_t mInfraIfIndex;
+
+ // The IPv6 link-local address of the infra interface.
+ // It's UNSPECIFIED if no valid IPv6 link-local address
+ // is associated with the infra interface and the Routing
+ // Manager will be stopped.
+ Ip6::Address mInfraIfLinkLocalAddress;
+
+ // The OMR prefix loaded from local persistent storage or randomly generated
+ // if non is found in persistent storage.
+ Ip6::Prefix mLocalOmrPrefix;
+
+ // The advertised OMR prefixes. For a stable Thread network without
+ // manually configured OMR prefixes, there should be a single OMR prefix
+ // that is being advertised because each BRs will converge to the smallest
+ // OMR prefix sorted by method IsPrefixSmallerThan. If manually configured
+ // OMR prefixes exist, they will also be advertised on infra link.
+ Ip6::Prefix mAdvertisedOmrPrefixes[kMaxOmrPrefixNum];
+ uint8_t mAdvertisedOmrPrefixNum;
+
+ // The on-link prefix loaded from local persistent storage or randomly generated
+ // if non is found in persistent storage.
+ Ip6::Prefix mLocalOnLinkPrefix;
+
+ // Could only be nullptr or a pointer to mLocalOnLinkPrefix.
+ const Ip6::Prefix *mAdvertisedOnLinkPrefix;
+
+ // The array of prefixes discovered on the infra link. Those prefixes consist of
+ // on-link prefix(es) and OMR prefixes advertised by BRs in another Thread Network
+ // which is connected to the same infra link.
+ ExternalPrefix mDiscoveredPrefixes[kMaxDiscoveredPrefixNum];
+ uint8_t mDiscoveredPrefixNum;
+
+ TimerMilli mDiscoveredPrefixInvalidTimer;
+
+ TimerMilli mRouterAdvertisementTimer;
+ uint32_t mRouterAdvertisementCount;
+
+ TimerMilli mRouterSolicitTimer;
+ uint8_t mRouterSolicitCount;
+
+ TimerMilli mRoutingPolicyTimer;
+};
+
+} // namespace BorderRouter
+
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#endif // ROUTING_MANAGER_HPP_
diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp
index 36f4c9d..9761940 100644
--- a/src/core/coap/coap.cpp
+++ b/src/core/coap/coap.cpp
@@ -56,6 +56,9 @@
, mDefaultHandler(nullptr)
, mDefaultHandlerContext(nullptr)
, mSender(aSender)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ , mLastResponse(nullptr)
+#endif
{
}
@@ -83,11 +86,24 @@
if ((aAddress == nullptr) || (metadata.mSourceAddress == *aAddress))
{
- FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, OT_ERROR_ABORT);
+ FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorAbort);
}
}
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+void CoapBase::AddBlockWiseResource(ResourceBlockWise &aResource)
+{
+ IgnoreError(mBlockWiseResources.Add(aResource));
+}
+
+void CoapBase::RemoveBlockWiseResource(ResourceBlockWise &aResource)
+{
+ IgnoreError(mBlockWiseResources.Remove(aResource));
+ aResource.SetNext(nullptr);
+}
+#endif
+
void CoapBase::AddResource(Resource &aResource)
{
IgnoreError(mResources.Add(aResource));
@@ -122,9 +138,9 @@
return message;
}
-otError CoapBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
#if OPENTHREAD_CONFIG_OTNS_ENABLE
Get<Utils::Otns>().EmitCoapSend(static_cast<Message &>(aMessage), aMessageInfo);
@@ -133,7 +149,7 @@
error = mSender(*this, aMessage, aMessageInfo);
#if OPENTHREAD_CONFIG_OTNS_ENABLE
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
Get<Utils::Otns>().EmitCoapSendFailure(error, static_cast<Message &>(aMessage), aMessageInfo);
}
@@ -141,25 +157,76 @@
return error;
}
-otError CoapBase::SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- const TxParameters & aTxParameters,
- ResponseHandler aHandler,
- void * aContext)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+Error CoapBase::SendMessage(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const TxParameters & aTxParameters,
+ ResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
+#else
+Error CoapBase::SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const TxParameters & aTxParameters,
+ ResponseHandler aHandler,
+ void * aContext)
+#endif
{
- otError error;
+ Error error;
Message *storedCopy = nullptr;
uint16_t copyLength = 0;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint8_t buf[kMaxBlockLength] = {0};
+ uint16_t bufLen = kMaxBlockLength;
+ bool moreBlocks = false;
+#endif
switch (aMessage.GetType())
{
case kTypeAck:
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ // Check for block-wise transfer
+ if ((aTransmitHook != nullptr) && (aMessage.ReadBlockOptionValues(kOptionBlock2) == kErrorNone) &&
+ (aMessage.GetBlockWiseBlockNumber() == 0))
+ {
+ // Set payload for first block of the transfer
+ VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
+ error = kErrorNoBufs);
+ SuccessOrExit(error = aTransmitHook(aContext, buf, aMessage.GetBlockWiseBlockNumber() * bufLen, &bufLen,
+ &moreBlocks));
+ SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen));
+
+ SuccessOrExit(error = CacheLastBlockResponse(&aMessage));
+ }
+#endif
+
mResponsesQueue.EnqueueResponse(aMessage, aMessageInfo, aTxParameters);
break;
case kTypeReset:
OT_ASSERT(aMessage.GetCode() == kCodeEmpty);
break;
default:
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ // Check for block-wise transfer
+ if ((aTransmitHook != nullptr) && (aMessage.ReadBlockOptionValues(kOptionBlock1) == kErrorNone) &&
+ (aMessage.GetBlockWiseBlockNumber() == 0))
+ {
+ // Set payload for first block of the transfer
+ VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
+ error = kErrorNoBufs);
+ SuccessOrExit(error = aTransmitHook(aContext, buf, aMessage.GetBlockWiseBlockNumber() * bufLen, &bufLen,
+ &moreBlocks));
+ SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen));
+
+ // Block-Wise messages always have to be confirmable
+ if (aMessage.IsNonConfirmable())
+ {
+ aMessage.SetType(kTypeConfirmable);
+ }
+ }
+#endif
+
aMessage.SetMessageId(mMessageId++);
break;
}
@@ -208,7 +275,7 @@
Message *origRequest = FindRelatedRequest(aMessage, aMessageInfo, handlerMetadata);
if (origRequest != nullptr)
{
- FinalizeCoapTransaction(*origRequest, handlerMetadata, nullptr, nullptr, OT_ERROR_NONE);
+ FinalizeCoapTransaction(*origRequest, handlerMetadata, nullptr, nullptr, kErrorNone);
}
}
}
@@ -228,6 +295,10 @@
metadata.mHopLimit = aMessageInfo.GetHopLimit();
metadata.mIsHostInterface = aMessageInfo.IsHostInterface();
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ metadata.mBlockwiseReceiveHook = aReceiveHook;
+ metadata.mBlockwiseTransmitHook = aTransmitHook;
+#endif
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
metadata.mObserve = observe;
#endif
@@ -236,14 +307,14 @@
(metadata.mConfirmable ? metadata.mRetransmissionTimeout : aTxParameters.CalculateMaxTransmitWait());
storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, metadata);
- VerifyOrExit(storedCopy != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(storedCopy != nullptr, error = kErrorNoBufs);
}
SuccessOrExit(error = Send(aMessage, aMessageInfo));
exit:
- if (error != OT_ERROR_NONE && storedCopy != nullptr)
+ if (error != kErrorNone && storedCopy != nullptr)
{
DequeueMessage(*storedCopy);
}
@@ -251,42 +322,46 @@
return error;
}
-otError CoapBase::SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- ResponseHandler aHandler,
- void * aContext)
+Error CoapBase::SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ ResponseHandler aHandler,
+ void * aContext)
{
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ return SendMessage(aMessage, aMessageInfo, TxParameters::GetDefault(), aHandler, aContext, nullptr, nullptr);
+#else
return SendMessage(aMessage, aMessageInfo, TxParameters::GetDefault(), aHandler, aContext);
+#endif
}
-otError CoapBase::SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
return SendEmptyMessage(kTypeReset, aRequest, aMessageInfo);
}
-otError CoapBase::SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
return SendEmptyMessage(kTypeAck, aRequest, aMessageInfo);
}
-otError CoapBase::SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode)
+Error CoapBase::SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode)
{
- return (aRequest.IsConfirmable() ? SendHeaderResponse(aCode, aRequest, aMessageInfo) : OT_ERROR_INVALID_ARGS);
+ return (aRequest.IsConfirmable() ? SendHeaderResponse(aCode, aRequest, aMessageInfo) : kErrorInvalidArgs);
}
-otError CoapBase::SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
return SendHeaderResponse(kCodeNotFound, aRequest, aMessageInfo);
}
-otError CoapBase::SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = nullptr;
- VerifyOrExit(aRequest.IsConfirmable(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aRequest.IsConfirmable(), error = kErrorInvalidArgs);
- VerifyOrExit((message = NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
message->Init(aType, kCodeEmpty);
message->SetMessageId(aRequest.GetMessageId());
@@ -299,13 +374,13 @@
return error;
}
-otError CoapBase::SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+Error CoapBase::SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = nullptr;
- VerifyOrExit(aRequest.IsRequest(), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit((message = NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aRequest.IsRequest(), error = kErrorInvalidArgs);
+ VerifyOrExit((message = NewMessage()) != nullptr, error = kErrorNoBufs);
switch (aRequest.GetType())
{
@@ -319,7 +394,7 @@
break;
default:
- ExitNow(error = OT_ERROR_INVALID_ARGS);
+ ExitNow(error = kErrorInvalidArgs);
OT_UNREACHABLE_CODE(break);
}
@@ -364,7 +439,7 @@
if (!metadata.mConfirmable || (metadata.mRetransmissionsRemaining == 0))
{
// No expected response or acknowledgment.
- FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, OT_ERROR_RESPONSE_TIMEOUT);
+ FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorResponseTimeout);
continue;
}
@@ -406,7 +481,7 @@
const Metadata & aMetadata,
Message * aResponse,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
DequeueMessage(aRequest);
@@ -416,9 +491,9 @@
}
}
-otError CoapBase::AbortTransaction(ResponseHandler aHandler, void *aContext)
+Error CoapBase::AbortTransaction(ResponseHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Message *nextMessage;
Metadata metadata;
@@ -429,8 +504,8 @@
if (metadata.mResponseHandler == aHandler && metadata.mResponseContext == aContext)
{
- FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, OT_ERROR_ABORT);
- error = OT_ERROR_NONE;
+ FinalizeCoapTransaction(*message, metadata, nullptr, nullptr, kErrorAbort);
+ error = kErrorNone;
}
}
@@ -439,10 +514,10 @@
Message *CoapBase::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *messageCopy = nullptr;
- VerifyOrExit((messageCopy = aMessage.Clone(aCopyLength)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((messageCopy = aMessage.Clone(aCopyLength)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = aMetadata.AppendTo(*messageCopy));
@@ -470,22 +545,417 @@
// the timer would just shoot earlier and then it'd be setup again.
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+void CoapBase::FreeLastBlockResponse(void)
+{
+ if (mLastResponse != nullptr)
+ {
+ mLastResponse->Free();
+ mLastResponse = nullptr;
+ }
+}
+
+Error CoapBase::CacheLastBlockResponse(Message *aResponse)
+{
+ Error error = kErrorNone;
+ // Save last response for block-wise transfer
+ FreeLastBlockResponse();
+
+ if ((mLastResponse = aResponse->Clone()) == nullptr)
+ {
+ error = kErrorNoBufs;
+ }
+
+ return error;
+}
+
+Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType,
+ bool aMoreBlocks,
+ Message & aRequestOld,
+ Message & aRequest,
+ Message & aMessage)
+{
+ Error error = kErrorNone;
+ bool isOptionSet = false;
+ uint64_t optionBuf = 0;
+ uint16_t blockOption = 0;
+ Option::Iterator iterator;
+
+ blockOption = (aType == Message::kBlockType1) ? kOptionBlock1 : kOptionBlock2;
+
+ aRequest.Init(kTypeConfirmable, static_cast<ot::Coap::Code>(aRequestOld.GetCode()));
+ SuccessOrExit(error = iterator.Init(aRequestOld));
+
+ // Copy options from last response to next message
+ for (; !iterator.IsDone() && iterator.GetOption()->GetLength() != 0; error = iterator.Advance())
+ {
+ uint16_t optionNumber = iterator.GetOption()->GetNumber();
+
+ SuccessOrExit(error);
+
+ // Check if option to copy next is higher than or equal to Block1 option
+ if (optionNumber >= blockOption && !isOptionSet)
+ {
+ // Write Block1 option to next message
+ SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
+ aMessage.GetBlockWiseBlockSize()));
+ aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
+ aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
+ aRequest.SetMoreBlocksFlag(aMoreBlocks);
+
+ isOptionSet = true;
+
+ // If option to copy next is Block1 or Block2 option, option is not copied
+ if (optionNumber == kOptionBlock1 || optionNumber == kOptionBlock2)
+ {
+ continue;
+ }
+ }
+
+ // Copy option
+ SuccessOrExit(error = iterator.ReadOptionValue(&optionBuf));
+ SuccessOrExit(error = aRequest.AppendOption(optionNumber, iterator.GetOption()->GetLength(), &optionBuf));
+ }
+
+ if (!isOptionSet)
+ {
+ // Write Block1 option to next message
+ SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
+ aMessage.GetBlockWiseBlockSize()));
+ aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
+ aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
+ aRequest.SetMoreBlocksFlag(aMoreBlocks);
+
+ isOptionSet = true;
+ }
+
+exit:
+ return error;
+}
+
+Error CoapBase::SendNextBlock1Request(Message & aRequest,
+ Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const Metadata & aCoapMetadata)
+{
+ Error error = kErrorNone;
+ Message *request = nullptr;
+ bool moreBlocks = false;
+ uint8_t buf[kMaxBlockLength] = {0};
+ uint16_t bufLen = kMaxBlockLength;
+
+ SuccessOrExit(error = aRequest.ReadBlockOptionValues(kOptionBlock1));
+ SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
+
+ // Conclude block-wise transfer if last block has been received
+ if (!aRequest.IsMoreBlocksFlagSet())
+ {
+ FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
+ ExitNow();
+ }
+
+ // Get next block
+ VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
+ error = kErrorNoBufs);
+
+ SuccessOrExit(
+ error = aCoapMetadata.mBlockwiseTransmitHook(aCoapMetadata.mResponseContext, buf,
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
+ (aMessage.GetBlockWiseBlockNumber() + 1),
+ &bufLen, &moreBlocks));
+
+ // Check if block length is valid
+ VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), error = kErrorInvalidArgs);
+
+ // Init request for next block
+ VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType1, moreBlocks, aRequest, *request, aMessage));
+
+ SuccessOrExit(error = request->SetPayloadMarker());
+
+ SuccessOrExit(error = request->AppendBytes(buf, bufLen));
+
+ DequeueMessage(aRequest);
+
+ otLogInfoCoap("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet());
+
+ SuccessOrExit(error = SendMessage(*request, aMessageInfo, TxParameters::GetDefault(),
+ aCoapMetadata.mResponseHandler, aCoapMetadata.mResponseContext,
+ aCoapMetadata.mBlockwiseTransmitHook, aCoapMetadata.mBlockwiseReceiveHook));
+
+exit:
+ FreeMessageOnError(request, error);
+
+ return error;
+}
+
+Error CoapBase::SendNextBlock2Request(Message & aRequest,
+ Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const Metadata & aCoapMetadata,
+ uint32_t aTotalLength,
+ bool aBeginBlock1Transfer)
+{
+ Error error = kErrorNone;
+ Message *request = nullptr;
+ uint8_t buf[kMaxBlockLength] = {0};
+ uint16_t bufLen = kMaxBlockLength;
+
+ SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
+
+ // Check payload and block length
+ VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <=
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) &&
+ (aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength,
+ error = kErrorNoBufs);
+
+ // Read and then forward payload to receive hook function
+ bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
+ SuccessOrExit(
+ error = aCoapMetadata.mBlockwiseReceiveHook(aCoapMetadata.mResponseContext, buf,
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
+ aMessage.GetBlockWiseBlockNumber(),
+ bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
+
+ // CoAP Block-Wise Transfer continues
+ otLogInfoCoap("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet());
+
+ // Conclude block-wise transfer if last block has been received
+ if (!aMessage.IsMoreBlocksFlagSet())
+ {
+ FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
+ ExitNow();
+ }
+
+ // Init request for next block
+ VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType2, aMessage.IsMoreBlocksFlagSet(), aRequest,
+ *request, aMessage));
+
+ if (!aBeginBlock1Transfer)
+ {
+ DequeueMessage(aRequest);
+ }
+
+ otLogInfoCoap("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()));
+
+ SuccessOrExit(error =
+ SendMessage(*request, aMessageInfo, TxParameters::GetDefault(), aCoapMetadata.mResponseHandler,
+ aCoapMetadata.mResponseContext, nullptr, aCoapMetadata.mBlockwiseReceiveHook));
+
+exit:
+ FreeMessageOnError(request, error);
+
+ return error;
+}
+
+Error CoapBase::ProcessBlock1Request(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const ResourceBlockWise &aResource,
+ uint32_t aTotalLength)
+{
+ Error error = kErrorNone;
+ Message *response = nullptr;
+ uint8_t buf[kMaxBlockLength] = {0};
+ uint16_t bufLen = kMaxBlockLength;
+
+ SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
+
+ // Read and then forward payload to receive hook function
+ VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength, error = kErrorNoBufs);
+ bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
+ SuccessOrExit(error = aResource.HandleBlockReceive(buf,
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
+ aMessage.GetBlockWiseBlockNumber(),
+ bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
+
+ if (aMessage.IsMoreBlocksFlagSet())
+ {
+ // Set up next response
+ VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorFailed);
+ response->Init(kTypeAck, kCodeContinue);
+ response->SetMessageId(aMessage.GetMessageId());
+ IgnoreReturnValue(
+ response->SetToken(static_cast<const Message &>(aMessage).GetToken(), aMessage.GetTokenLength()));
+
+ response->SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber());
+ response->SetMoreBlocksFlag(aMessage.IsMoreBlocksFlagSet());
+ response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
+
+ SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType1, response->GetBlockWiseBlockNumber(),
+ response->IsMoreBlocksFlagSet(),
+ response->GetBlockWiseBlockSize()));
+
+ SuccessOrExit(error = CacheLastBlockResponse(response));
+
+ otLogInfoCoap("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()));
+
+ SuccessOrExit(error = SendMessage(*response, aMessageInfo));
+
+ error = kErrorBusy;
+ }
+ else
+ {
+ // Conclude block-wise transfer if last block has been received
+ FreeLastBlockResponse();
+ error = kErrorNone;
+ }
+
+exit:
+ if (error != kErrorNone && error != kErrorBusy && response != nullptr)
+ {
+ response->Free();
+ }
+
+ return error;
+}
+
+Error CoapBase::ProcessBlock2Request(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const ResourceBlockWise &aResource)
+{
+ Error error = kErrorNone;
+ Message * response = nullptr;
+ uint8_t buf[kMaxBlockLength] = {0};
+ uint16_t bufLen = kMaxBlockLength;
+ bool moreBlocks = false;
+ uint64_t optionBuf = 0;
+ Option::Iterator iterator;
+
+ SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
+
+ otLogInfoCoap("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()));
+
+ if (aMessage.GetBlockWiseBlockNumber() == 0)
+ {
+ aResource.HandleRequest(aMessage, aMessageInfo);
+ ExitNow();
+ }
+
+ // Set up next response
+ VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorNoBufs);
+ response->Init(kTypeAck, kCodeContent);
+ response->SetMessageId(aMessage.GetMessageId());
+
+ VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
+ error = kErrorNoBufs);
+ SuccessOrExit(error = aResource.HandleBlockTransmit(buf,
+ otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
+ aMessage.GetBlockWiseBlockNumber(),
+ &bufLen, &moreBlocks));
+
+ response->SetMoreBlocksFlag(moreBlocks);
+ if (moreBlocks)
+ {
+ switch (bufLen)
+ {
+ case 1024:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_1024);
+ break;
+ case 512:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_512);
+ break;
+ case 256:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_256);
+ break;
+ case 128:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_128);
+ break;
+ case 64:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_64);
+ break;
+ case 32:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_32);
+ break;
+ case 16:
+ response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_16);
+ break;
+ default:
+ error = kErrorInvalidArgs;
+ ExitNow();
+ break;
+ }
+ }
+ else
+ {
+ // Verify that buffer length is not larger than requested block size
+ VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()),
+ error = kErrorInvalidArgs);
+ response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
+ }
+
+ response->SetBlockWiseBlockNumber(
+ (otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber()) /
+ (otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize())));
+
+ // Copy options from last response
+ SuccessOrExit(error = iterator.Init(*mLastResponse));
+
+ while (!iterator.IsDone())
+ {
+ uint16_t optionNumber = iterator.GetOption()->GetNumber();
+
+ if (optionNumber == kOptionBlock2)
+ {
+ SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType2, response->GetBlockWiseBlockNumber(),
+ response->IsMoreBlocksFlagSet(),
+ response->GetBlockWiseBlockSize()));
+ }
+ else if (optionNumber == kOptionBlock1)
+ {
+ SuccessOrExit(error = iterator.ReadOptionValue(&optionBuf));
+ SuccessOrExit(error = response->AppendOption(optionNumber, iterator.GetOption()->GetLength(), &optionBuf));
+ }
+
+ SuccessOrExit(error = iterator.Advance());
+ }
+
+ SuccessOrExit(error = response->SetPayloadMarker());
+ SuccessOrExit(error = response->AppendBytes(buf, bufLen));
+
+ if (response->IsMoreBlocksFlagSet())
+ {
+ SuccessOrExit(error = CacheLastBlockResponse(response));
+ }
+ else
+ {
+ // Conclude block-wise transfer if last block has been received
+ FreeLastBlockResponse();
+ }
+
+ otLogInfoCoap("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(),
+ otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet());
+
+ SuccessOrExit(error = SendMessage(*response, aMessageInfo));
+
+exit:
+ FreeMessageOnError(response, error);
+
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
void CoapBase::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
Message *messageCopy = nullptr;
// Create a message copy for lower layers.
messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(Metadata));
- VerifyOrExit(messageCopy != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(messageCopy != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = Send(*messageCopy, aMessageInfo));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnCoap("Failed to send copy: %s", otThreadErrorToString(error));
+ otLogWarnCoap("Failed to send copy: %s", ErrorToString(error));
FreeMessage(messageCopy);
}
}
@@ -536,7 +1006,7 @@
{
Message &message = static_cast<Message &>(aMessage);
- if (message.ParseHeader() != OT_ERROR_NONE)
+ if (message.ParseHeader() != kErrorNone)
{
otLogDebgCoap("Failed to parse CoAP header");
@@ -563,10 +1033,14 @@
{
Metadata metadata;
Message *request = nullptr;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
bool responseObserve = false;
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ uint8_t blockOptionType = 0;
+ uint32_t totalTransfereSize = 0;
+#endif
request = FindRelatedRequest(aMessage, aMessageInfo, metadata);
VerifyOrExit(request != nullptr);
@@ -587,7 +1061,7 @@
case kTypeReset:
if (aMessage.IsEmpty())
{
- FinalizeCoapTransaction(*request, metadata, nullptr, nullptr, OT_ERROR_ABORT);
+ FinalizeCoapTransaction(*request, metadata, nullptr, nullptr, kErrorAbort);
}
// Silently ignore non-empty reset messages (RFC 7252, p. 4.2).
@@ -603,7 +1077,7 @@
// This is the ACK to our RFC7641 notification. There will be no
// "separate" response so pass it back as if it were a piggy-backed
// response so we can stop re-sending and the application can move on.
- FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, kErrorNone);
}
else
#endif
@@ -634,7 +1108,7 @@
if (metadata.mObserve && responseObserve && (metadata.mResponseHandler != nullptr))
{
// This is a RFC7641 notification. The request is *not* done!
- metadata.mResponseHandler(metadata.mResponseContext, &aMessage, &aMessageInfo, OT_ERROR_NONE);
+ metadata.mResponseHandler(metadata.mResponseContext, &aMessage, &aMessageInfo, kErrorNone);
// Consider the message acknowledged at this point.
metadata.mAcknowledged = true;
@@ -642,9 +1116,89 @@
}
else
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
{
- FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
+ if (metadata.mBlockwiseTransmitHook != nullptr || metadata.mBlockwiseReceiveHook != nullptr)
+ {
+ // Search for CoAP Block-Wise Option [RFC7959]
+ Option::Iterator iterator;
+
+ SuccessOrExit(error = iterator.Init(aMessage));
+ while (!iterator.IsDone())
+ {
+ switch (iterator.GetOption()->GetNumber())
+ {
+ case kOptionBlock1:
+ blockOptionType += 1;
+ break;
+
+ case kOptionBlock2:
+ blockOptionType += 2;
+ break;
+
+ case kOptionSize2:
+ // ToDo: wait for method to read uint option values
+ totalTransfereSize = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ SuccessOrExit(error = iterator.Advance());
+ }
+ }
+ switch (blockOptionType)
+ {
+ case 0:
+ // Piggybacked response.
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, kErrorNone);
+ break;
+ case 1: // Block1 option
+ if (aMessage.GetCode() == kCodeContinue && metadata.mBlockwiseTransmitHook != nullptr)
+ {
+ error = SendNextBlock1Request(*request, aMessage, aMessageInfo, metadata);
+ }
+
+ if (aMessage.GetCode() != kCodeContinue || metadata.mBlockwiseTransmitHook == nullptr ||
+ error != kErrorNone)
+ {
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, error);
+ }
+ break;
+ case 2: // Block2 option
+ if (aMessage.GetCode() < kCodeBadRequest && metadata.mBlockwiseReceiveHook != nullptr)
+ {
+ error = SendNextBlock2Request(*request, aMessage, aMessageInfo, metadata, totalTransfereSize,
+ false);
+ }
+
+ if (aMessage.GetCode() >= kCodeBadRequest || metadata.mBlockwiseReceiveHook == nullptr ||
+ error != kErrorNone)
+ {
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, error);
+ }
+ break;
+ case 3: // Block1 & Block2 option
+ if (aMessage.GetCode() < kCodeBadRequest && metadata.mBlockwiseReceiveHook != nullptr)
+ {
+ error =
+ SendNextBlock2Request(*request, aMessage, aMessageInfo, metadata, totalTransfereSize, true);
+ }
+
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, error);
+ break;
+ default:
+ error = kErrorAbort;
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, error);
+ break;
+ }
}
+#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ {
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, kErrorNone);
+ }
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
}
// Silently ignore acknowledgments carrying requests (RFC 7252, p. 4.2)
@@ -654,7 +1208,8 @@
case kTypeConfirmable:
// Send empty ACK if it is a CON message.
IgnoreError(SendAck(aMessage, aMessageInfo));
- // Fall through
+
+ OT_FALL_THROUGH;
// Handling of RFC7641 and multicast is below.
case kTypeNonConfirmable:
// Separate response or observation notification. If the request was to a multicast
@@ -667,11 +1222,11 @@
))
{
// If multicast non-confirmable request, allow multiple responses
- metadata.mResponseHandler(metadata.mResponseContext, &aMessage, &aMessageInfo, OT_ERROR_NONE);
+ metadata.mResponseHandler(metadata.mResponseContext, &aMessage, &aMessageInfo, kErrorNone);
}
else
{
- FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, OT_ERROR_NONE);
+ FinalizeCoapTransaction(*request, metadata, &aMessage, &aMessageInfo, kErrorNone);
}
break;
@@ -679,7 +1234,7 @@
exit:
- if (error == OT_ERROR_NONE && request == nullptr)
+ if (error == kErrorNone && request == nullptr)
{
if (aMessage.IsConfirmable() || aMessage.IsNonConfirmable())
{
@@ -694,7 +1249,13 @@
{
char uriPath[Message::kMaxReceivedUriPath + 1];
Message *cachedResponse = nullptr;
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ Option::Iterator iterator;
+ char * curUriPath = uriPath;
+ uint8_t blockOptionType = 0;
+ uint32_t totalTransfereSize = 0;
+#endif
if (mInterceptor != nullptr)
{
@@ -703,28 +1264,128 @@
switch (mResponsesQueue.GetMatchedResponseCopy(aMessage, aMessageInfo, &cachedResponse))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
cachedResponse->Finish();
error = Send(*cachedResponse, aMessageInfo);
- // fall through
+ OT_FALL_THROUGH;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
ExitNow();
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
default:
break;
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ SuccessOrExit(error = iterator.Init(aMessage));
+
+ while (!iterator.IsDone())
+ {
+ switch (iterator.GetOption()->GetNumber())
+ {
+ case kOptionUriPath:
+ if (curUriPath != uriPath)
+ {
+ *curUriPath++ = '/';
+ }
+
+ VerifyOrExit(curUriPath + iterator.GetOption()->GetLength() < OT_ARRAY_END(uriPath), error = kErrorParse);
+
+ IgnoreError(iterator.ReadOptionValue(curUriPath));
+ curUriPath += iterator.GetOption()->GetLength();
+ break;
+
+ case kOptionBlock1:
+ blockOptionType += 1;
+ break;
+
+ case kOptionBlock2:
+ blockOptionType += 2;
+ break;
+
+ case kOptionSize1:
+ // ToDo: wait for method to read uint option values
+ totalTransfereSize = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ SuccessOrExit(error = iterator.Advance());
+ }
+
+ curUriPath[0] = '\0';
+
+ for (const ResourceBlockWise *resource = mBlockWiseResources.GetHead(); resource; resource = resource->GetNext())
+ {
+ if (strcmp(resource->GetUriPath(), uriPath) != 0)
+ {
+ continue;
+ }
+
+ if ((resource->mReceiveHook != nullptr || resource->mTransmitHook != nullptr) && blockOptionType != 0)
+ {
+ switch (blockOptionType)
+ {
+ case 1:
+ if (resource->mReceiveHook != nullptr)
+ {
+ switch (ProcessBlock1Request(aMessage, aMessageInfo, *resource, totalTransfereSize))
+ {
+ case kErrorNone:
+ resource->HandleRequest(aMessage, aMessageInfo);
+ // Fall through
+ case kErrorBusy:
+ error = kErrorNone;
+ break;
+ case kErrorNoBufs:
+ IgnoreReturnValue(SendHeaderResponse(kCodeRequestTooLarge, aMessage, aMessageInfo));
+ error = kErrorDrop;
+ break;
+ case kErrorNoFrameReceived:
+ IgnoreReturnValue(SendHeaderResponse(kCodeRequestIncomplete, aMessage, aMessageInfo));
+ error = kErrorDrop;
+ break;
+ default:
+ IgnoreReturnValue(SendHeaderResponse(kCodeInternalError, aMessage, aMessageInfo));
+ error = kErrorDrop;
+ break;
+ }
+ }
+ break;
+ case 2:
+ if (resource->mTransmitHook != nullptr)
+ {
+ if ((error = ProcessBlock2Request(aMessage, aMessageInfo, *resource)) != kErrorNone)
+ {
+ IgnoreReturnValue(SendHeaderResponse(kCodeInternalError, aMessage, aMessageInfo));
+ error = kErrorDrop;
+ }
+ }
+ break;
+ }
+ ExitNow();
+ }
+ else
+ {
+ resource->HandleRequest(aMessage, aMessageInfo);
+ error = kErrorNone;
+ ExitNow();
+ }
+ }
+#else
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
for (const Resource *resource = mResources.GetHead(); resource; resource = resource->GetNext())
{
if (strcmp(resource->mUriPath, uriPath) == 0)
{
resource->HandleRequest(aMessage, aMessageInfo);
- error = OT_ERROR_NONE;
+ error = kErrorNone;
ExitNow();
}
}
@@ -732,16 +1393,16 @@
if (mDefaultHandler)
{
mDefaultHandler(mDefaultHandlerContext, &aMessage, &aMessageInfo);
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogInfoCoap("Failed to process request: %s", otThreadErrorToString(error));
+ otLogInfoCoap("Failed to process request: %s", ErrorToString(error));
- if (error == OT_ERROR_NOT_FOUND && !aMessageInfo.GetSockAddr().IsMulticast())
+ if (error == kErrorNotFound && !aMessageInfo.GetSockAddr().IsMulticast())
{
IgnoreError(SendNotFound(aMessage, aMessageInfo));
}
@@ -768,18 +1429,18 @@
{
}
-otError ResponsesQueue::GetMatchedResponseCopy(const Message & aRequest,
- const Ip6::MessageInfo &aMessageInfo,
- Message ** aResponse)
+Error ResponsesQueue::GetMatchedResponseCopy(const Message & aRequest,
+ const Ip6::MessageInfo &aMessageInfo,
+ Message ** aResponse)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const Message *cacheResponse;
cacheResponse = FindMatchedResponse(aRequest, aMessageInfo);
- VerifyOrExit(cacheResponse != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(cacheResponse != nullptr, error = kErrorNotFound);
*aResponse = cacheResponse->Clone(cacheResponse->GetLength() - sizeof(ResponseMetadata));
- VerifyOrExit(*aResponse != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(*aResponse != nullptr, error = kErrorNoBufs);
exit:
return error;
@@ -824,7 +1485,7 @@
VerifyOrExit((responseCopy = aMessage.Clone()) != nullptr);
- VerifyOrExit(metadata.AppendTo(*responseCopy) == OT_ERROR_NONE, responseCopy->Free());
+ VerifyOrExit(metadata.AppendTo(*responseCopy) == kErrorNone, responseCopy->Free());
mQueue.Enqueue(*responseCopy);
@@ -950,8 +1611,8 @@
// Calulate exchange lifetime step by step and verify no overflow.
uint32_t tmp = Multiply(mAckTimeout, (1U << (mMaxRetransmit + 1)) - 1);
- tmp /= mAckRandomFactorDenominator;
tmp = Multiply(tmp, mAckRandomFactorNumerator);
+ tmp /= mAckRandomFactorDenominator;
rval = (tmp != 0 && (tmp + mAckTimeout + 2 * kDefaultMaxLatency) > tmp);
}
@@ -995,21 +1656,20 @@
{
}
-otError Coap::Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier)
+Error Coap::Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier)
{
- otError error = OT_ERROR_NONE;
- bool socketOpened = false;
+ Error error = kErrorNone;
+ bool socketOpened = false;
VerifyOrExit(!mSocket.IsBound());
SuccessOrExit(error = mSocket.Open(&Coap::HandleUdpReceive, this));
socketOpened = true;
- SuccessOrExit(error = mSocket.BindToNetif(aNetifIdentifier));
- SuccessOrExit(error = mSocket.Bind(aPort));
+ SuccessOrExit(error = mSocket.Bind(aPort, aNetifIdentifier));
exit:
- if (error != OT_ERROR_NONE && socketOpened)
+ if (error != kErrorNone && socketOpened)
{
IgnoreError(mSocket.Close());
}
@@ -1017,9 +1677,9 @@
return error;
}
-otError Coap::Stop(void)
+Error Coap::Stop(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(mSocket.IsBound());
@@ -1036,14 +1696,14 @@
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
-otError Coap::Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Coap::Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<Coap &>(aCoapBase).Send(aMessage, aMessageInfo);
}
-otError Coap::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Coap::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- return mSocket.IsBound() ? mSocket.SendTo(aMessage, aMessageInfo) : OT_ERROR_INVALID_STATE;
+ return mSocket.IsBound() ? mSocket.SendTo(aMessage, aMessageInfo) : kErrorInvalidState;
}
} // namespace Coap
diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp
index 8a1d983..2092f3c 100644
--- a/src/core/coap/coap.hpp
+++ b/src/core/coap/coap.hpp
@@ -169,13 +169,108 @@
*/
const char *GetUriPath(void) const { return mUriPath; }
-private:
+protected:
void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+/**
+ * This class implements CoAP block-wise resource handling.
+ *
+ */
+class ResourceBlockWise : public otCoapBlockwiseResource
+{
+ friend class CoapBase;
+
+public:
+ /**
+ * This constructor initializes the resource.
+ *
+ * @param[in] aUriPath A pointer to a NULL-terminated string for the Uri-Path.
+ * @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aReceiveHook A function pointer that is called when receiving a CoAP block message for @p
+ * aUriPath.
+ * @param[in] aTransmitHook A function pointer that is called when transmitting a CoAP block message from @p
+ * aUriPath.
+ */
+ ResourceBlockWise(const char * aUriPath,
+ otCoapRequestHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseReceiveHook aReceiveHook,
+ otCoapBlockwiseTransmitHook aTransmitHook)
+ {
+ mUriPath = aUriPath;
+ mHandler = aHandler;
+ mContext = aContext;
+ mReceiveHook = aReceiveHook;
+ mTransmitHook = aTransmitHook;
+ mNext = nullptr;
+ }
+
+ Error HandleBlockReceive(const uint8_t *aBlock,
+ uint32_t aPosition,
+ uint16_t aBlockLength,
+ bool aMore,
+ uint32_t aTotalLength) const
+ {
+ return mReceiveHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore, aTotalLength);
+ }
+
+ Error HandleBlockTransmit(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore) const
+ {
+ return mTransmitHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore);
+ }
+
+ /**
+ * This method gets the next entry in the linked list.
+ *
+ * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+ *
+ */
+ const ResourceBlockWise *GetNext(void) const
+ {
+ return static_cast<const ResourceBlockWise *>(static_cast<const ResourceBlockWise *>(this)->mNext);
+ }
+
+ /**
+ * This method gets the next entry in the linked list.
+ *
+ * @returns A pointer to the next entry in the linked list or nullptr if at the end of the list.
+ *
+ */
+ ResourceBlockWise *GetNext(void)
+ {
+ return static_cast<ResourceBlockWise *>(static_cast<ResourceBlockWise *>(this)->mNext);
+ }
+
+ /**
+ * This method sets the next pointer on the entry.
+ *
+ * @param[in] aNext A pointer to the next entry.
+ *
+ */
+ void SetNext(ResourceBlockWise *aNext) { static_cast<ResourceBlockWise *>(this)->mNext = aNext; }
+
+ /**
+ * This method returns a pointer to the URI path.
+ *
+ * @returns A pointer to the URI path.
+ *
+ */
+ const char *GetUriPath(void) const { return mUriPath; }
+
+protected:
+ void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
+ {
+ mHandler(mContext, &aMessage, &aMessageInfo);
+ }
+};
+#endif
+
/**
* This class caches CoAP responses to implement message deduplication.
*
@@ -219,12 +314,12 @@
* @param[in] aMessageInfo The message info containing source endpoint address and port.
* @param[out] aResponse A pointer to return a copy of a cached CoAP response matching given arguments.
*
- * @retval OT_ERROR_NONE Matching response found and successfully created a copy.
- * @retval OT_ERROR_NO_BUFS Matching response found but there is not sufficient buffer to create a copy.
- * @retval OT_ERROR_NOT_FOUND Matching response not found.
+ * @retval kErrorNone Matching response found and successfully created a copy.
+ * @retval kErrorNoBufs Matching response found but there is not sufficient buffer to create a copy.
+ * @retval kErrorNotFound Matching response not found.
*
*/
- otError GetMatchedResponseCopy(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Message **aResponse);
+ Error GetMatchedResponseCopy(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Message **aResponse);
/**
* This method gets a reference to the cached CoAP responses queue.
@@ -242,8 +337,8 @@
struct ResponseMetadata
{
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ void ReadFrom(const Message &aMessage);
TimeMilli mDequeueTime;
Ip6::MessageInfo mMessageInfo;
@@ -269,6 +364,12 @@
friend class ResponsesQueue;
public:
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ enum {
+ kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH,
+ };
+#endif
+
/**
* This function pointer is called before CoAP server processing a CoAP message.
*
@@ -276,13 +377,12 @@
@ @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Server should continue processing this message, other
- * return values indicates the server should stop processing
- * this message.
- * @retval OT_ERROR_NOT_TMF The message is not a TMF message.
+ * @retval kErrorNone Server should continue processing this message, other return values indicates the
+ * server should stop processing this message.
+ * @retval kErrorNotTmf The message is not a TMF message.
*
*/
- typedef otError (*Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
+ typedef Error (*Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
/**
* This method clears requests and responses used by this CoAP agent.
@@ -298,6 +398,25 @@
*/
void ClearRequests(const Ip6::Address &aAddress);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+ /**
+ * This method adds a block-wise resource to the CoAP server.
+ *
+ * @param[in] aResource A reference to the resource.
+ *
+ */
+ void AddBlockWiseResource(ResourceBlockWise &aResource);
+
+ /**
+ * This method removes a block-wise resource from the CoAP server.
+ *
+ * @param[in] aResource A reference to the resource.
+ *
+ */
+ void RemoveBlockWiseResource(ResourceBlockWise &aResource);
+#endif
+
/**
* This method adds a resource to the CoAP server.
*
@@ -343,6 +462,35 @@
return NewMessage(Message::Settings(Message::kWithLinkSecurity, Message::kPriorityNet));
}
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ /**
+ * This method sends a CoAP message block-wise with custom transmission parameters.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
+ *
+ * @param[in] aMessage A reference to the message to send.
+ * @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
+ * @param[in] aTxParameters A reference to transmission parameters for this message.
+ * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
+ *
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ *
+ */
+ Error SendMessage(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const TxParameters & aTxParameters,
+ otCoapResponseHandler aHandler = nullptr,
+ void * aContext = nullptr,
+ otCoapBlockwiseTransmitHook aTransmitHook = nullptr,
+ otCoapBlockwiseReceiveHook aReceiveHook = nullptr);
+#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
/**
* This method sends a CoAP message with custom transmission parameters.
*
@@ -356,15 +504,16 @@
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully sent CoAP message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP message.
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP message.
*
*/
- otError SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- const TxParameters & aTxParameters,
- ResponseHandler aHandler = nullptr,
- void * aContext = nullptr);
+ Error SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const TxParameters & aTxParameters,
+ ResponseHandler aHandler = nullptr,
+ void * aContext = nullptr);
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a CoAP message with default transmission parameters.
@@ -378,14 +527,14 @@
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully sent CoAP message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*
*/
- otError SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- ResponseHandler aHandler = nullptr,
- void * aContext = nullptr);
+ Error SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ ResponseHandler aHandler = nullptr,
+ void * aContext = nullptr);
/**
* This method sends a CoAP reset message.
@@ -393,12 +542,12 @@
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
- * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
- * @retval OT_ERROR_INVALID_ARGS The @p aRequest is not of confirmable type.
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
+ * @retval kErrorInvalidArgs The @p aRequest is not of confirmable type.
*
*/
- otError SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+ Error SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends header-only CoAP response message.
@@ -407,12 +556,12 @@
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
- * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
- * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type.
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
+ * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
- otError SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+ Error SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends a CoAP ACK empty message which is used in Separate Response for confirmable requests.
@@ -420,12 +569,12 @@
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
- * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
- * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type.
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
+ * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
- otError SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+ Error SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends a CoAP ACK message on which a dummy CoAP response is piggybacked.
@@ -434,38 +583,56 @@
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
* @param[in] aCode The CoAP code of the dummy CoAP response.
*
- * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
- * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type.
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
+ * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
- otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode = kCodeChanged);
+ Error SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode = kCodeChanged);
/**
* This method sends a header-only CoAP message to indicate no resource matched for the request.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
- * @param[in] aMessageInfo The message info corresponding to the CoAP request.
+ * @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
- * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response.
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*
*/
- otError SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+ Error SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ /**
+ * This method sends a header-only CoAP message to indicate not all blocks have been sent or
+ * were sent out of order.
+ *
+ * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
+ * @param[in] aMessageInfo The message info corresponding to the CoAP request.
+ *
+ * @retval kErrorNone Successfully enqueued the CoAP response message.
+ * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
+ *
+ */
+ Error SendRequestEntityIncomplete(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
+ {
+ return SendHeaderResponse(kCodeRequestIncomplete, aRequest, aMessageInfo);
+ }
+#endif
/**
* This method aborts CoAP transactions associated with given handler and context.
*
- * The associated response handler will be called with OT_ERROR_ABORT.
+ * The associated response handler will be called with kErrorAbort.
*
* @param[in] aHandler A function pointer that should be called when the transaction ends.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully aborted CoAP transactions.
- * @retval OT_ERROR_NOT_FOUND CoAP transaction associated with given handler was not found.
+ * @retval kErrorNone Successfully aborted CoAP transactions.
+ * @retval kErrorNotFound CoAP transaction associated with given handler was not found.
*
*/
- otError AbortTransaction(ResponseHandler aHandler, void *aContext);
+ Error AbortTransaction(ResponseHandler aHandler, void *aContext);
/**
* This method sets interceptor to be called before processing a CoAP packet.
@@ -500,11 +667,11 @@
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
- * @retval OT_ERROR_NONE Successfully sent CoAP message.
- * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
*
*/
- typedef otError (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ typedef Error (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This constructor initializes the object.
@@ -528,9 +695,9 @@
private:
struct Metadata
{
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
- void UpdateIn(Message &aMessage) const;
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ void ReadFrom(const Message &aMessage);
+ void UpdateIn(Message &aMessage) const;
Ip6::Address mSourceAddress; // IPv6 address of the message source.
Ip6::Address mDestinationAddress; // IPv6 address of the message destination.
@@ -552,6 +719,12 @@
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
bool mObserve : 1; // Information that this request involves Observations.
#endif
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ otCoapBlockwiseReceiveHook mBlockwiseReceiveHook; // A function pointer that is called on Block2
+ // response reception.
+ otCoapBlockwiseTransmitHook mBlockwiseTransmitHook; // A function pointer that is called on Block1
+ // response reception.
+#endif
};
static void HandleRetransmissionTimer(Timer &aTimer);
@@ -565,15 +738,44 @@
const Metadata & aMetadata,
Message * aResponse,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ void FreeLastBlockResponse(void);
+ Error CacheLastBlockResponse(Message *aResponse);
+
+ Error PrepareNextBlockRequest(Message::BlockType aType,
+ bool aMoreBlocks,
+ Message & aRequestOld,
+ Message & aRequest,
+ Message & aMessage);
+ Error ProcessBlock1Request(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const ResourceBlockWise &aResource,
+ uint32_t aTotalLength);
+ Error ProcessBlock2Request(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const ResourceBlockWise &aResource);
+#endif
void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- otError SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ Error SendNextBlock1Request(Message & aRequest,
+ Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const Metadata & aCoapMetadata);
+ Error SendNextBlock2Request(Message & aRequest,
+ Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const Metadata & aCoapMetadata,
+ uint32_t aTotalLength,
+ bool aBeginBlock1Transfer);
+#endif
+ void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
- otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
MessageQueue mPendingRequests;
uint16_t mMessageId;
@@ -589,6 +791,11 @@
void * mDefaultHandlerContext;
const Sender mSender;
+
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ LinkedList<ResourceBlockWise> mBlockWiseResources;
+ Message * mLastResponse;
+#endif
};
/**
@@ -612,28 +819,28 @@
* @param[in] aPort The local UDP port to bind to.
* @param[in] aNetifIdentifier The network interface identifier to bind.
*
- * @retval OT_ERROR_NONE Successfully started the CoAP service.
- * @retval OT_ERROR_FAILED Failed to start CoAP agent.
+ * @retval kErrorNone Successfully started the CoAP service.
+ * @retval kErrorFailed Failed to start CoAP agent.
*
*/
- otError Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_UNSPECIFIED);
+ Error Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_UNSPECIFIED);
/**
* This method stops the CoAP service.
*
- * @retval OT_ERROR_NONE Successfully stopped the CoAP service.
- * @retval OT_ERROR_FAILED Failed to stop CoAP agent.
+ * @retval kErrorNone Successfully stopped the CoAP service.
+ * @retval kErrorFailed Failed to stop CoAP agent.
*
*/
- otError Stop(void);
+ Error Stop(void);
protected:
Ip6::Udp::Socket mSocket;
private:
- static otError Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
- otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static Error Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+ Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
};
} // namespace Coap
diff --git a/src/core/coap/coap_message.cpp b/src/core/coap/coap_message.cpp
index 5ca789e..41a001d 100644
--- a/src/core/coap/coap_message.cpp
+++ b/src/core/coap/coap_message.cpp
@@ -51,6 +51,11 @@
GetHelpData().mHeaderLength = kMinHeaderLength;
IgnoreError(SetLength(GetHelpData().mHeaderLength));
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ SetBlockWiseBlockNumber(0);
+ SetMoreBlocksFlag(false);
+ SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_16);
+#endif
}
void Message::Init(Type aType, Code aCode)
@@ -60,9 +65,9 @@
SetCode(aCode);
}
-otError Message::Init(Type aType, Code aCode, const char *aUriPath)
+Error Message::Init(Type aType, Code aCode, const char *aUriPath)
{
- otError error;
+ Error error;
Init(aType, aCode);
SuccessOrExit(error = GenerateRandomToken(kDefaultTokenLength));
@@ -82,17 +87,17 @@
Init(kTypeNonConfirmable, kCodePost);
}
-otError Message::InitAsConfirmablePost(const char *aUriPath)
+Error Message::InitAsConfirmablePost(const char *aUriPath)
{
return Init(kTypeConfirmable, kCodePost, aUriPath);
}
-otError Message::InitAsNonConfirmablePost(const char *aUriPath)
+Error Message::InitAsNonConfirmablePost(const char *aUriPath)
{
return Init(kTypeNonConfirmable, kCodePost, aUriPath);
}
-otError Message::InitAsPost(const Ip6::Address &aDestination, const char *aUriPath)
+Error Message::InitAsPost(const Ip6::Address &aDestination, const char *aUriPath)
{
return Init(aDestination.IsMulticast() ? kTypeNonConfirmable : kTypeConfirmable, kCodePost, aUriPath);
}
@@ -155,15 +160,15 @@
return rval;
}
-otError Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue)
+Error Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t delta;
uint8_t header[kMaxOptionHeaderSize];
uint16_t headerLength;
uint8_t *cur;
- VerifyOrExit(aNumber >= GetHelpData().mOptionLast, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aNumber >= GetHelpData().mOptionLast, error = kErrorInvalidArgs);
delta = aNumber - GetHelpData().mOptionLast;
cur = &header[1];
@@ -173,8 +178,7 @@
headerLength = static_cast<uint16_t>(cur - header);
- VerifyOrExit(static_cast<uint32_t>(GetLength()) + headerLength + aLength < kMaxHeaderLength,
- error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(static_cast<uint32_t>(GetLength()) + headerLength + aLength < kMaxHeaderLength, error = kErrorNoBufs);
SuccessOrExit(error = AppendBytes(header, headerLength));
SuccessOrExit(error = AppendBytes(aValue, aLength));
@@ -187,7 +191,7 @@
return error;
}
-otError Message::AppendUintOption(uint16_t aNumber, uint32_t aValue)
+Error Message::AppendUintOption(uint16_t aNumber, uint32_t aValue)
{
uint8_t buffer[sizeof(uint32_t)];
const uint8_t *value = &buffer[0];
@@ -195,7 +199,7 @@
Encoding::BigEndian::WriteUint32(aValue, buffer);
- while (value[0] == 0 && length > 0)
+ while ((length > 0) && (value[0] == 0))
{
value++;
length--;
@@ -204,14 +208,14 @@
return AppendOption(aNumber, length, value);
}
-otError Message::AppendStringOption(uint16_t aNumber, const char *aValue)
+Error Message::AppendStringOption(uint16_t aNumber, const char *aValue)
{
return AppendOption(aNumber, static_cast<uint16_t>(strlen(aValue)), aValue);
}
-otError Message::AppendUriPathOptions(const char *aUriPath)
+Error Message::AppendUriPathOptions(const char *aUriPath)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const char *cur = aUriPath;
const char *end;
@@ -227,10 +231,10 @@
return error;
}
-otError Message::ReadUriPathOptions(char (&aUriPath)[kMaxReceivedUriPath + 1]) const
+Error Message::ReadUriPathOptions(char (&aUriPath)[kMaxReceivedUriPath + 1]) const
{
char * curUriPath = aUriPath;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Option::Iterator iterator;
SuccessOrExit(error = iterator.Init(*this, kOptionUriPath));
@@ -244,7 +248,7 @@
*curUriPath++ = '/';
}
- VerifyOrExit(curUriPath + optionLength < OT_ARRAY_END(aUriPath), error = OT_ERROR_PARSE);
+ VerifyOrExit(curUriPath + optionLength < OT_ARRAY_END(aUriPath), error = kErrorParse);
IgnoreError(iterator.ReadOptionValue(curUriPath));
curUriPath += optionLength;
@@ -258,14 +262,14 @@
return error;
}
-otError Message::AppendBlockOption(Message::BlockType aType, uint32_t aNum, bool aMore, otCoapBlockSize aSize)
+Error Message::AppendBlockOption(Message::BlockType aType, uint32_t aNum, bool aMore, otCoapBlockSzx aSize)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint32_t encoded = aSize;
- VerifyOrExit(aType == kBlockType1 || aType == kBlockType2, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aSize <= OT_COAP_BLOCK_SIZE_1024, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aNum < kBlockNumMax, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aType == kBlockType1 || aType == kBlockType2, error = kErrorInvalidArgs);
+ VerifyOrExit(aSize <= OT_COAP_OPTION_BLOCK_SZX_1024, error = kErrorInvalidArgs);
+ VerifyOrExit(aNum < kBlockNumMax, error = kErrorInvalidArgs);
encoded |= static_cast<uint32_t>(aMore << kBlockMOffset);
encoded |= aNum << kBlockNumOffset;
@@ -276,12 +280,55 @@
return error;
}
-otError Message::SetPayloadMarker(void)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+Error Message::ReadBlockOptionValues(uint16_t aBlockType)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
+ uint8_t buf[kMaxOptionHeaderSize] = {0};
+ Option::Iterator iterator;
+
+ VerifyOrExit((aBlockType == kOptionBlock1) || (aBlockType == kOptionBlock2), error = kErrorInvalidArgs);
+
+ SuccessOrExit(error = iterator.Init(*this, aBlockType));
+ SuccessOrExit(error = iterator.ReadOptionValue(buf));
+
+ SetBlockWiseBlockNumber(0);
+ SetMoreBlocksFlag(false);
+
+ switch (iterator.GetOption()->GetLength())
+ {
+ case 0:
+ case 1:
+ SetBlockWiseBlockNumber(static_cast<uint32_t>((buf[0] & 0xf0) >> 4));
+ SetMoreBlocksFlag(static_cast<bool>((buf[0] & 0x08) >> 3 == 1));
+ SetBlockWiseBlockSize(static_cast<otCoapBlockSzx>(buf[0] & 0x07));
+ break;
+ case 2:
+ SetBlockWiseBlockNumber(static_cast<uint32_t>((buf[0] << 4) + ((buf[1] & 0xf0) >> 4)));
+ SetMoreBlocksFlag(static_cast<bool>((buf[1] & 0x08) >> 3 == 1));
+ SetBlockWiseBlockSize(static_cast<otCoapBlockSzx>(buf[1] & 0x07));
+ break;
+ case 3:
+ SetBlockWiseBlockNumber(static_cast<uint32_t>((buf[0] << 12) + (buf[1] << 4) + ((buf[2] & 0xf0) >> 4)));
+ SetMoreBlocksFlag(static_cast<bool>((buf[2] & 0x08) >> 3 == 1));
+ SetBlockWiseBlockSize(static_cast<otCoapBlockSzx>(buf[2] & 0x07));
+ break;
+ default:
+ error = kErrorInvalidArgs;
+ break;
+ }
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+Error Message::SetPayloadMarker(void)
+{
+ Error error = kErrorNone;
uint8_t marker = kPayloadMarker;
- VerifyOrExit(GetLength() < kMaxHeaderLength, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(GetLength() < kMaxHeaderLength, error = kErrorNoBufs);
SuccessOrExit(error = Append(marker));
GetHelpData().mHeaderLength = GetLength();
@@ -292,9 +339,9 @@
return error;
}
-otError Message::ParseHeader(void)
+Error Message::ParseHeader(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Option::Iterator iterator;
OT_ASSERT(mBuffer.mHead.mMetadata.mReserved >=
@@ -306,7 +353,7 @@
GetHelpData().mHeaderOffset = GetOffset();
IgnoreError(Read(GetHelpData().mHeaderOffset, GetHelpData().mHeader));
- VerifyOrExit(GetTokenLength() <= kMaxTokenLength, error = OT_ERROR_PARSE);
+ VerifyOrExit(GetTokenLength() <= kMaxTokenLength, error = kErrorParse);
SuccessOrExit(error = iterator.Init(*this));
@@ -322,7 +369,7 @@
return error;
}
-otError Message::SetToken(const uint8_t *aToken, uint8_t aTokenLength)
+Error Message::SetToken(const uint8_t *aToken, uint8_t aTokenLength)
{
OT_ASSERT(aTokenLength <= kMaxTokenLength);
@@ -333,7 +380,7 @@
return SetLength(GetHelpData().mHeaderLength);
}
-otError Message::GenerateRandomToken(uint8_t aTokenLength)
+Error Message::GenerateRandomToken(uint8_t aTokenLength)
{
uint8_t token[kMaxTokenLength];
@@ -344,7 +391,7 @@
return SetToken(token, aTokenLength);
}
-otError Message::SetTokenFromMessage(const Message &aMessage)
+Error Message::SetTokenFromMessage(const Message &aMessage)
{
return SetToken(aMessage.GetToken(), aMessage.GetTokenLength());
}
@@ -356,7 +403,7 @@
return ((tokenLength == aMessage.GetTokenLength()) && (memcmp(GetToken(), aMessage.GetToken(), tokenLength) == 0));
}
-otError Message::SetDefaultResponseHeader(const Message &aRequest)
+Error Message::SetDefaultResponseHeader(const Message &aRequest)
{
Init(kTypeAck, kCodeChanged);
@@ -477,9 +524,9 @@
}
#endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
-otError Option::Iterator::Init(const Message &aMessage)
+Error Option::Iterator::Init(const Message &aMessage)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
uint32_t offset = static_cast<uint32_t>(aMessage.GetHelpData().mHeaderOffset) + aMessage.GetOptionStart();
// Note that the case where `offset == aMessage.GetLength())` is
@@ -499,9 +546,9 @@
return error;
}
-otError Option::Iterator::Advance(void)
+Error Option::Iterator::Advance(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t headerByte;
uint16_t optionDelta;
uint16_t optionLength;
@@ -510,22 +557,22 @@
error = Read(sizeof(uint8_t), &headerByte);
- if ((error != OT_ERROR_NONE) || (headerByte == Message::kPayloadMarker))
+ if ((error != kErrorNone) || (headerByte == Message::kPayloadMarker))
{
// Payload Marker indicates end of options and start of payload.
// Absence of a Payload Marker indicates a zero-length payload.
MarkAsDone();
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
// The presence of a marker followed by a zero-length payload
// MUST be processed as a message format error.
- VerifyOrExit(mNextOptionOffset < GetMessage().GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(mNextOptionOffset < GetMessage().GetLength(), error = kErrorParse);
}
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
optionDelta = (headerByte & Message::kOptionDeltaMask) >> Message::kOptionDeltaOffset;
@@ -534,14 +581,14 @@
optionLength = (headerByte & Message::kOptionLengthMask) >> Message::kOptionLengthOffset;
SuccessOrExit(error = ReadExtendedOptionField(optionLength));
- VerifyOrExit(optionLength <= GetMessage().GetLength() - mNextOptionOffset, error = OT_ERROR_PARSE);
+ VerifyOrExit(optionLength <= GetMessage().GetLength() - mNextOptionOffset, error = kErrorParse);
mNextOptionOffset += optionLength;
mOption.mNumber += optionDelta;
mOption.mLength = optionLength;
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
MarkAsParseErrored();
}
@@ -549,25 +596,25 @@
return error;
}
-otError Option::Iterator::ReadOptionValue(void *aValue) const
+Error Option::Iterator::ReadOptionValue(void *aValue) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!IsDone(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!IsDone(), error = kErrorNotFound);
GetMessage().ReadBytes(mNextOptionOffset - mOption.mLength, aValue, mOption.mLength);
exit:
return error;
}
-otError Option::Iterator::ReadOptionValue(uint64_t &aUintValue) const
+Error Option::Iterator::ReadOptionValue(uint64_t &aUintValue) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t buffer[sizeof(uint64_t)];
- VerifyOrExit(!IsDone(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!IsDone(), error = kErrorNotFound);
- VerifyOrExit(mOption.mLength <= sizeof(uint64_t), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(mOption.mLength <= sizeof(uint64_t), error = kErrorNoBufs);
IgnoreError(ReadOptionValue(buffer));
aUintValue = 0;
@@ -582,13 +629,13 @@
return error;
}
-otError Option::Iterator::Read(uint16_t aLength, void *aBuffer)
+Error Option::Iterator::Read(uint16_t aLength, void *aBuffer)
{
// Reads `aLength` bytes from the message into `aBuffer` at
// `mNextOptionOffset` and updates the `mNextOptionOffset` on a
// successful read (i.e., when entire `aLength` bytes can be read).
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = GetMessage().Read(mNextOptionOffset, aBuffer, aLength));
mNextOptionOffset += aLength;
@@ -597,9 +644,9 @@
return error;
}
-otError Option::Iterator::ReadExtendedOptionField(uint16_t &aValue)
+Error Option::Iterator::ReadExtendedOptionField(uint16_t &aValue)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(aValue >= Message::kOption1ByteExtension);
@@ -620,18 +667,18 @@
}
else
{
- error = OT_ERROR_PARSE;
+ error = kErrorParse;
}
exit:
return error;
}
-otError Option::Iterator::InitOrAdvance(const Message *aMessage, uint16_t aNumber)
+Error Option::Iterator::InitOrAdvance(const Message *aMessage, uint16_t aNumber)
{
- otError error = (aMessage != nullptr) ? Init(*aMessage) : Advance();
+ Error error = (aMessage != nullptr) ? Init(*aMessage) : Advance();
- while ((error == OT_ERROR_NONE) && !IsDone() && (GetOption()->GetNumber() != aNumber))
+ while ((error == kErrorNone) && !IsDone() && (GetOption()->GetNumber() != aNumber))
{
error = Advance();
}
diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp
index b8580ba..2fd59da 100644
--- a/src/core/coap/coap_message.hpp
+++ b/src/core/coap/coap_message.hpp
@@ -149,6 +149,7 @@
kOptionLocationQuery = OT_COAP_OPTION_LOCATION_QUERY, ///< Location-Query
kOptionBlock2 = OT_COAP_OPTION_BLOCK2, ///< Block2 (RFC7959)
kOptionBlock1 = OT_COAP_OPTION_BLOCK1, ///< Block1 (RFC7959)
+ kOptionSize2 = OT_COAP_OPTION_SIZE2, ///< Size2 (RFC7959)
kOptionProxyUri = OT_COAP_OPTION_PROXY_URI, ///< Proxy-Uri
kOptionProxyScheme = OT_COAP_OPTION_PROXY_SCHEME, ///< Proxy-Scheme
kOptionSize1 = OT_COAP_OPTION_SIZE1, ///< Size1
@@ -222,33 +223,33 @@
* @param[in] aCode The Code value.
* @param[in] aUriPath A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError Init(Type aType, Code aCode, const char *aUriPath);
+ Error Init(Type aType, Code aCode, const char *aUriPath);
/**
* This method initializes the CoAP header as `kTypeConfirmable` and `kCodePost` with a given URI Path.
*
* @param[in] aUriPath A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError InitAsConfirmablePost(const char *aUriPath);
+ Error InitAsConfirmablePost(const char *aUriPath);
/**
* This method initializes the CoAP header as `kTypeNonConfirmable` and `kCodePost` with a given URI Path.
*
* @param[in] aUriPath A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError InitAsNonConfirmablePost(const char *aUriPath);
+ Error InitAsNonConfirmablePost(const char *aUriPath);
/**
* This method initializes the CoAP header as `kCodePost` with a given URI Path with its type determined from a
@@ -258,11 +259,11 @@
* `kTypeNonConfirmable` if multicast address, `kTypeConfirmable` otherwise.
* @param[in] aUriPath A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError InitAsPost(const Ip6::Address &aDestination, const char *aUriPath);
+ Error InitAsPost(const Ip6::Address &aDestination, const char *aUriPath);
/**
* This method writes header to the message. This must be called before sending the message.
@@ -380,33 +381,33 @@
* @param[in] aToken A pointer to the Token value.
* @param[in] aTokenLength The Length of @p aToken.
*
- * @retval OT_ERROR_NONE Successfully set the token value.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to set the token value.
+ * @retval kErrorNone Successfully set the token value.
+ * @retval kErrorNoBufs Insufficient message buffers available to set the token value.
*
*/
- otError SetToken(const uint8_t *aToken, uint8_t aTokenLength);
+ Error SetToken(const uint8_t *aToken, uint8_t aTokenLength);
/**
* This method sets the Token value and length by copying it from another given message.
*
* @param[in] aMessage The message to copy the Token from.
*
- * @retval OT_ERROR_NONE Successfully set the token value.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to set the token value.
+ * @retval kErrorNone Successfully set the token value.
+ * @retval kErrorNoBufs Insufficient message buffers available to set the token value.
*
*/
- otError SetTokenFromMessage(const Message &aMessage);
+ Error SetTokenFromMessage(const Message &aMessage);
/**
* This method sets the Token length and randomizes its value.
*
* @param[in] aTokenLength The Length of a Token to set.
*
- * @retval OT_ERROR_NONE Successfully set the token value.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to set the token value.
+ * @retval kErrorNone Successfully set the token value.
+ * @retval kErrorNoBufs Insufficient message buffers available to set the token value.
*
*/
- otError GenerateRandomToken(uint8_t aTokenLength);
+ Error GenerateRandomToken(uint8_t aTokenLength);
/**
* This method checks if Tokens in two CoAP headers are equal.
@@ -426,12 +427,12 @@
* @param[in] aLength The CoAP Option length.
* @param[in] aValue A pointer to the CoAP Option value (@p aLength bytes are used as Option value).
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue);
+ Error AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue);
/**
* This method appends an unsigned integer CoAP option as specified in RFC-7252 section-3.2
@@ -439,12 +440,12 @@
* @param[in] aNumber The CoAP Option number.
* @param[in] aValue The CoAP Option unsigned integer value.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendUintOption(uint16_t aNumber, uint32_t aValue);
+ Error AppendUintOption(uint16_t aNumber, uint32_t aValue);
/**
* This method appends a string CoAP option.
@@ -452,35 +453,35 @@
* @param[in] aNumber The CoAP Option number.
* @param[in] aValue The CoAP Option string value.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendStringOption(uint16_t aNumber, const char *aValue);
+ Error AppendStringOption(uint16_t aNumber, const char *aValue);
/**
* This method appends an Observe option.
*
* @param[in] aObserve Observe field value.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*/
- otError AppendObserveOption(uint32_t aObserve) { return AppendUintOption(kOptionObserve, aObserve & kObserveMask); }
+ Error AppendObserveOption(uint32_t aObserve) { return AppendUintOption(kOptionObserve, aObserve & kObserveMask); }
/**
* This method appends a Uri-Path option.
*
* @param[in] aUriPath A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendUriPathOptions(const char *aUriPath);
+ Error AppendUriPathOptions(const char *aUriPath);
/**
* This method reads the Uri-Path options and constructs the URI path in the buffer referenced by @p `aUriPath`.
@@ -488,11 +489,11 @@
* @param[in] aUriPath A reference to the buffer for storing URI path.
* NOTE: The buffer size must be `kMaxReceivedUriPath + 1`.
*
- * @retval OT_ERROR_NONE Successfully read the Uri-Path options.
- * @retval OT_ERROR_PARSE CoAP Option header not well-formed.
+ * @retval kErrorNone Successfully read the Uri-Path options.
+ * @retval kErrorParse CoAP Option header not well-formed.
*
*/
- otError ReadUriPathOptions(char (&aUriPath)[kMaxReceivedUriPath + 1]) const;
+ Error ReadUriPathOptions(char (&aUriPath)[kMaxReceivedUriPath + 1]) const;
/**
* This method appends a Block option
@@ -502,36 +503,36 @@
* @param[in] aMore Boolean to indicate more blocks are to be sent.
* @param[in] aSize Maximum block size.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendBlockOption(BlockType aType, uint32_t aNum, bool aMore, otCoapBlockSize aSize);
+ Error AppendBlockOption(BlockType aType, uint32_t aNum, bool aMore, otCoapBlockSzx aSize);
/**
* This method appends a Proxy-Uri option.
*
* @param[in] aProxyUri A pointer to a null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendProxyUriOption(const char *aProxyUri) { return AppendStringOption(kOptionProxyUri, aProxyUri); }
+ Error AppendProxyUriOption(const char *aProxyUri) { return AppendStringOption(kOptionProxyUri, aProxyUri); }
/**
* This method appends a Content-Format option.
*
* @param[in] aContentFormat The Content Format value.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*
*/
- otError AppendContentFormatOption(otCoapOptionContentFormat aContentFormat)
+ Error AppendContentFormatOption(otCoapOptionContentFormat aContentFormat)
{
return AppendUintOption(kOptionContentFormat, static_cast<uint32_t>(aContentFormat));
}
@@ -541,33 +542,89 @@
*
* @param[in] aMaxAge The Max-Age value.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*/
- otError AppendMaxAgeOption(uint32_t aMaxAge) { return AppendUintOption(kOptionMaxAge, aMaxAge); }
+ Error AppendMaxAgeOption(uint32_t aMaxAge) { return AppendUintOption(kOptionMaxAge, aMaxAge); }
/**
* This method appends a single Uri-Query option.
*
* @param[in] aUriQuery A pointer to null-terminated string, which should contain a single key=value pair.
*
- * @retval OT_ERROR_NONE Successfully appended the option.
- * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type.
- * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size.
+ * @retval kErrorNone Successfully appended the option.
+ * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type.
+ * @retval kErrorNoBufs The option length exceeds the buffer size.
*/
- otError AppendUriQueryOption(const char *aUriQuery) { return AppendStringOption(kOptionUriQuery, aUriQuery); }
+ Error AppendUriQueryOption(const char *aUriQuery) { return AppendStringOption(kOptionUriQuery, aUriQuery); }
+
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ /**
+ * This function reads the information contained in a Block1 or Block2 option and set it in
+ * the HelpData of the message.
+ *
+ * @param[in] aBlockType Block1 or Block2 option value.
+ *
+ * @retval kErrorNone The option has been found and is valid.
+ * @retval kErrorNotFound The option has not been found.
+ * @retval kErrorInvalidArgs The option is invalid.
+ */
+ Error ReadBlockOptionValues(uint16_t aBlockType);
+
+ /**
+ * This method returns the current header length of a message.
+ *
+ * @returns The length of the message header.
+ *
+ */
+ uint16_t GetHeaderLength(void) const { return GetHelpData().mHeaderLength; }
+
+ /**
+ * This method returns the block number of a CoAP block-wise transfer message.
+ *
+ * @returns The block number.
+ *
+ */
+ uint32_t GetBlockWiseBlockNumber(void) const { return GetHelpData().mBlockWiseData.mBlockNumber; }
+
+ /**
+ * This method checks if the More Blocks flag is set.
+ *
+ * @retval TRUE More Blocks flag is set.
+ * @retval FALSE More Blocks flag is not set.
+ *
+ */
+ bool IsMoreBlocksFlagSet(void) const { return GetHelpData().mBlockWiseData.mMoreBlocks; }
+
+ /**
+ * This method returns the block size of a CoAP block-wise transfer message.
+ *
+ * @returns The block size.
+ *
+ */
+ otCoapBlockSzx GetBlockWiseBlockSize(void) const { return GetHelpData().mBlockWiseData.mBlockSize; }
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+ /**
+ * This function reads and reassembles the URI path string and fills it into @p aUriPath.
+ *
+ * @retval kErrorNone URI path string has been reassembled.
+ * @retval kErrorNoBufs URI path string is too long.
+ *
+ */
+ Error GetUriPath(char *aUriPath) const;
/**
* This method adds Payload Marker indicating beginning of the payload to the CoAP header.
*
* It also set offset to the start of payload.
*
- * @retval OT_ERROR_NONE Payload Marker successfully added.
- * @retval OT_ERROR_NO_BUFS Message Payload Marker exceeds the buffer size.
+ * @retval kErrorNone Payload Marker successfully added.
+ * @retval kErrorNoBufs Message Payload Marker exceeds the buffer size.
*
*/
- otError SetPayloadMarker(void);
+ Error SetPayloadMarker(void);
/**
* This method returns the offset of the first CoAP option.
@@ -580,22 +637,49 @@
/**
* This method parses CoAP header and moves offset end of CoAP header.
*
- * @retval OT_ERROR_NONE Successfully parsed CoAP header from the message.
- * @retval OT_ERROR_PARSE Failed to parse the CoAP header.
+ * @retval kErrorNone Successfully parsed CoAP header from the message.
+ * @retval kErrorParse Failed to parse the CoAP header.
*
*/
- otError ParseHeader(void);
+ Error ParseHeader(void);
/**
* This method sets a default response header based on request header.
*
* @param[in] aRequest The request message.
*
- * @retval OT_ERROR_NONE Successfully set the default response header.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available to set the default response header.
+ * @retval kErrorNone Successfully set the default response header.
+ * @retval kErrorNoBufs Insufficient message buffers available to set the default response header.
*
*/
- otError SetDefaultResponseHeader(const Message &aRequest);
+ Error SetDefaultResponseHeader(const Message &aRequest);
+
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+
+ /**
+ * This method sets the block number value in the message HelpData.
+ *
+ * @param[in] aBlockNumber Block number value to set.
+ *
+ */
+ void SetBlockWiseBlockNumber(uint32_t aBlockNumber) { GetHelpData().mBlockWiseData.mBlockNumber = aBlockNumber; }
+
+ /**
+ * This method sets the More Blocks falg in the message HelpData.
+ *
+ * @param[in] aMoreBlocks TRUE or FALSE.
+ *
+ */
+ void SetMoreBlocksFlag(bool aMoreBlocks) { GetHelpData().mBlockWiseData.mMoreBlocks = aMoreBlocks; }
+
+ /**
+ * This method sets the block size value in the message HelpData.
+ *
+ * @param[in] aBlockSize Block size value to set.
+ *
+ */
+ void SetBlockWiseBlockSize(otCoapBlockSzx aBlockSize) { GetHelpData().mBlockWiseData.mBlockSize = aBlockSize; }
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method checks if a header is an empty message header.
@@ -845,6 +929,15 @@
kBlockNumMax = 0xffff,
};
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ struct BlockWiseData
+ {
+ uint32_t mBlockNumber;
+ bool mMoreBlocks;
+ otCoapBlockSzx mBlockSize;
+ };
+#endif
+
/**
* This structure represents a CoAP header excluding CoAP options.
*
@@ -868,6 +961,9 @@
uint16_t mOptionLast;
uint16_t mHeaderOffset; ///< The byte offset for the CoAP Header
uint16_t mHeaderLength;
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ BlockWiseData mBlockWiseData;
+#endif
};
const HelpData &GetHelpData(void) const
@@ -962,11 +1058,11 @@
*
* @param[in] aMessage The CoAP message.
*
- * @retval OT_ERROR_NONE Successfully initialized. Iterator is either at the first option or done.
- * @retval OT_ERROR_PARSE CoAP Option header in @p aMessage is not well-formed.
+ * @retval kErrorNone Successfully initialized. Iterator is either at the first option or done.
+ * @retval kErrorParse CoAP Option header in @p aMessage is not well-formed.
*
*/
- otError Init(const Message &aMessage);
+ Error Init(const Message &aMessage);
/**
* This method initializes the iterator to iterate over CoAP Options in a CoAP message matching a given Option
@@ -981,11 +1077,11 @@
* @param[in] aMessage The CoAP message.
* @param[in] aNumber The CoAP Option Number.
*
- * @retval OT_ERROR_NONE Successfully initialized. Iterator is either at the first matching option or done.
- * @retval OT_ERROR_PARSE CoAP Option header in @p aMessage is not well-formed.
+ * @retval kErrorNone Successfully initialized. Iterator is either at the first matching option or done.
+ * @retval kErrorParse CoAP Option header in @p aMessage is not well-formed.
*
*/
- otError Init(const Message &aMessage, uint16_t aNumber) { return InitOrAdvance(&aMessage, aNumber); }
+ Error Init(const Message &aMessage, uint16_t aNumber) { return InitOrAdvance(&aMessage, aNumber); }
/**
* This method indicates whether or not the iterator is done (i.e., has reached the end of CoAP Option Header).
@@ -1012,11 +1108,11 @@
*
* The iterator is updated to point to the next option or marked as done when there are no more options.
*
- * @retval OT_ERROR_NONE Successfully advanced the iterator.
- * @retval OT_ERROR_PARSE CoAP Option header is not well-formed.
+ * @retval kErrorNone Successfully advanced the iterator.
+ * @retval kErrorParse CoAP Option header is not well-formed.
*
*/
- otError Advance(void);
+ Error Advance(void);
/**
* This method advances the iterator to the next CoAP Option in the header matching a given Option Number value.
@@ -1026,11 +1122,11 @@
*
* @param[in] aNumber The CoAP Option Number.
*
- * @retval OT_ERROR_NONE Successfully advanced the iterator.
- * @retval OT_ERROR_PARSE CoAP Option header is not well-formed.
+ * @retval kErrorNone Successfully advanced the iterator.
+ * @retval kErrorParse CoAP Option header is not well-formed.
*
*/
- otError Advance(uint16_t aNumber) { return InitOrAdvance(nullptr, aNumber); }
+ Error Advance(uint16_t aNumber) { return InitOrAdvance(nullptr, aNumber); }
/**
* This method gets the CoAP message associated with the iterator.
@@ -1055,23 +1151,23 @@
* @param[out] aValue The pointer to a buffer to copy the Option Value. The buffer is assumed to be
* sufficiently large (i.e. at least `GetOption()->GetLength()` bytes).
*
- * @retval OT_ERROR_NONE Successfully read and copied the Option Value into given buffer.
- * @retval OT_ERROR_NOT_FOUND Iterator is done (not pointing to any option).
+ * @retval kErrorNone Successfully read and copied the Option Value into given buffer.
+ * @retval kErrorNotFound Iterator is done (not pointing to any option).
*
*/
- otError ReadOptionValue(void *aValue) const;
+ Error ReadOptionValue(void *aValue) const;
/**
* This method read the current Option Value which is assumed to be an unsigned integer.
*
* @param[out] aUintValue A reference to `uint64_t` to output the read Option Value.
*
- * @retval OT_ERROR_NONE Successfully read the Option value.
- * @retval OT_ERROR_NO_BUFS Value is too long to fit in an `uint64_t`.
- * @retval OT_ERROR_NOT_FOUND Iterator is done (not pointing to any option).
+ * @retval kErrorNone Successfully read the Option value.
+ * @retval kErrorNoBufs Value is too long to fit in an `uint64_t`.
+ * @retval kErrorNotFound Iterator is done (not pointing to any option).
*
*/
- otError ReadOptionValue(uint64_t &aUintValue) const;
+ Error ReadOptionValue(uint64_t &aUintValue) const;
/**
* This method gets the offset of beginning of the CoAP message payload (after the CoAP header).
@@ -1093,9 +1189,9 @@
void MarkAsDone(void) { mOption.mLength = kIteratorDoneLength; }
void MarkAsParseErrored(void) { MarkAsDone(), mNextOptionOffset = kNextOptionOffsetParseError; }
- otError Read(uint16_t aLength, void *aBuffer);
- otError ReadExtendedOptionField(uint16_t &aValue);
- otError InitOrAdvance(const Message *aMessage, uint16_t aNumber);
+ Error Read(uint16_t aLength, void *aBuffer);
+ Error ReadExtendedOptionField(uint16_t &aValue);
+ Error InitOrAdvance(const Message *aMessage, uint16_t aNumber);
};
/**
diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp
index 06769f8..1ab1c4f 100644
--- a/src/core/coap/coap_secure.cpp
+++ b/src/core/coap/coap_secure.cpp
@@ -54,9 +54,9 @@
{
}
-otError CoapSecure::Start(uint16_t aPort)
+Error CoapSecure::Start(uint16_t aPort)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mConnectedCallback = nullptr;
mConnectedContext = nullptr;
@@ -68,9 +68,9 @@
return error;
}
-otError CoapSecure::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext)
+Error CoapSecure::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mConnectedCallback = nullptr;
mConnectedContext = nullptr;
@@ -95,7 +95,7 @@
ClearRequestsAndResponses();
}
-otError CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext)
+Error CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext)
{
mConnectedCallback = aCallback;
mConnectedContext = aContext;
@@ -105,7 +105,7 @@
void CoapSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd)
{
- otError error;
+ Error error;
OT_UNUSED_VARIABLE(error);
@@ -115,14 +115,43 @@
error = mDtls.SetPsk(reinterpret_cast<const uint8_t *>(aPskd.GetAsCString()), aPskd.GetLength());
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
}
-otError CoapSecure::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext)
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+Error CoapSecure::SendMessage(Message & aMessage,
+ ResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsConnected(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsConnected(), error = kErrorInvalidState);
+
+ error = CoapBase::SendMessage(aMessage, mDtls.GetMessageInfo(), TxParameters::GetDefault(), aHandler, aContext,
+ aTransmitHook, aReceiveHook);
+
+exit:
+ return error;
+}
+
+Error CoapSecure::SendMessage(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ ResponseHandler aHandler,
+ void * aContext,
+ otCoapBlockwiseTransmitHook aTransmitHook,
+ otCoapBlockwiseReceiveHook aReceiveHook)
+{
+ return CoapBase::SendMessage(aMessage, aMessageInfo, TxParameters::GetDefault(), aHandler, aContext, aTransmitHook,
+ aReceiveHook);
+}
+#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+Error CoapSecure::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(IsConnected(), error = kErrorInvalidState);
error = CoapBase::SendMessage(aMessage, mDtls.GetMessageInfo(), aHandler, aContext);
@@ -130,22 +159,23 @@
return error;
}
-otError CoapSecure::SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- ResponseHandler aHandler,
- void * aContext)
+Error CoapSecure::SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ ResponseHandler aHandler,
+ void * aContext)
{
return CoapBase::SendMessage(aMessage, aMessageInfo, aHandler, aContext);
}
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
-otError CoapSecure::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error CoapSecure::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);
mTransmitQueue.Enqueue(aMessage);
mTransmitTask.Post();
- return OT_ERROR_NONE;
+ return kErrorNone;
}
void CoapSecure::HandleDtlsConnected(void *aContext, bool aConnected)
@@ -186,7 +216,7 @@
void CoapSecure::HandleTransmit(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ot::Message *message = mTransmitQueue.GetHead();
VerifyOrExit(message != nullptr);
@@ -200,14 +230,14 @@
SuccessOrExit(error = mDtls.Send(*message, message->GetLength()));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogNoteMeshCoP("CoapSecure Transmit: %s", otThreadErrorToString(error));
+ otLogNoteMeshCoP("CoapSecure Transmit: %s", ErrorToString(error));
message->Free();
}
else
{
- otLogDebgMeshCoP("CoapSecure Transmit: %s", otThreadErrorToString(error));
+ otLogDebgMeshCoP("CoapSecure Transmit: %s", ErrorToString(error));
}
}
diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp
index 889ed74..272a1d6 100644
--- a/src/core/coap/coap_secure.hpp
+++ b/src/core/coap/coap_secure.hpp
@@ -72,11 +72,11 @@
*
* @param[in] aPort The local UDP port to bind to.
*
- * @retval OT_ERROR_NONE Successfully started the CoAP agent.
- * @retval OT_ERROR_ALREADY Already started.
+ * @retval kErrorNone Successfully started the CoAP agent.
+ * @retval kErrorAlready Already started.
*
*/
- otError Start(uint16_t aPort);
+ Error Start(uint16_t aPort);
/**
* This method starts the secure CoAP agent, but do not use socket to transmit/receive messages.
@@ -84,11 +84,11 @@
* @param[in] aCallback A pointer to a function for sending messages.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully started the CoAP agent.
- * @retval OT_ERROR_ALREADY Already started.
+ * @retval kErrorNone Successfully started the CoAP agent.
+ * @retval kErrorAlready Already started.
*
*/
- otError Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext);
+ Error Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext);
/**
* This method sets connected callback of this secure CoAP agent.
@@ -116,10 +116,10 @@
* @param[in] aCallback A pointer to a function that will be called once DTLS connection is
* established.
*
- * @retval OT_ERROR_NONE Successfully started DTLS connection.
+ * @retval kErrorNone Successfully started DTLS connection.
*
*/
- otError Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext);
+ Error Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext);
/**
* This method indicates whether or not the DTLS session is active.
@@ -159,11 +159,11 @@
* @param[in] aPsk A pointer to the PSK.
* @param[in] aPskLength The PSK length.
*
- * @retval OT_ERROR_NONE Successfully set the PSK.
- * @retval OT_ERROR_INVALID_ARGS The PSK is invalid.
+ * @retval kErrorNone Successfully set the PSK.
+ * @retval kErrorInvalidArgs The PSK is invalid.
*
*/
- otError SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mDtls.SetPsk(aPsk, aPskLength); }
+ Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mDtls.SetPsk(aPsk, aPskLength); }
/**
* This method sets the PSK.
@@ -238,11 +238,11 @@
* @param[out] aCertLength The length of the base64 encoded peer certificate.
* @param[in] aCertBufferSize The buffer size of aPeerCert.
*
- * @retval OT_ERROR_NONE Successfully get the peer certificate.
- * @retval OT_ERROR_NO_BUFS Can't allocate memory for certificate.
+ * @retval kErrorNone Successfully get the peer certificate.
+ * @retval kErrorNoBufs Can't allocate memory for certificate.
*
*/
- otError GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
+ Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
return mDtls.GetPeerCertificateBase64(aPeerCert, aCertLength, aCertBufferSize);
}
@@ -272,6 +272,57 @@
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ /**
+ * This method sends a CoAP message over secure DTLS connection.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
+ *
+ * @param[in] aMessage A reference to the message to send.
+ * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
+ *
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidState DTLS connection was not initialized.
+ *
+ */
+ Error SendMessage(Message & aMessage,
+ ResponseHandler aHandler = nullptr,
+ void * aContext = nullptr,
+ otCoapBlockwiseTransmitHook aTransmitHook = nullptr,
+ otCoapBlockwiseReceiveHook aReceiveHook = nullptr);
+
+ /**
+ * This method sends a CoAP message over secure DTLS connection.
+ *
+ * If a response for a request is expected, respective function and context information should be provided.
+ * If no response is expected, these arguments should be NULL pointers.
+ * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
+ *
+ * @param[in] aMessage A reference to the message to send.
+ * @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
+ * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
+ * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
+ *
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidState DTLS connection was not initialized.
+ *
+ */
+ Error SendMessage(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ ResponseHandler aHandler = nullptr,
+ void * aContext = nullptr,
+ otCoapBlockwiseTransmitHook aTransmitHook = nullptr,
+ otCoapBlockwiseReceiveHook aReceiveHook = nullptr);
+#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a CoAP message over secure DTLS connection.
*
@@ -283,12 +334,12 @@
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully sent CoAP message.
- * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
- * @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized.
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidState DTLS connection was not initialized.
*
*/
- otError SendMessage(Message &aMessage, ResponseHandler aHandler = nullptr, void *aContext = nullptr);
+ Error SendMessage(Message &aMessage, ResponseHandler aHandler = nullptr, void *aContext = nullptr);
/**
* This method sends a CoAP message over secure DTLS connection.
@@ -302,15 +353,16 @@
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully sent CoAP message.
- * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
- * @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized.
+ * @retval kErrorNone Successfully sent CoAP message.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidState DTLS connection was not initialized.
*
*/
- otError SendMessage(Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- ResponseHandler aHandler = nullptr,
- void * aContext = nullptr);
+ Error SendMessage(Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ ResponseHandler aHandler = nullptr,
+ void * aContext = nullptr);
+#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method is used to pass UDP messages to the secure CoAP server.
@@ -333,11 +385,11 @@
const Ip6::MessageInfo &GetMessageInfo(void) const { return mDtls.GetMessageInfo(); }
private:
- static otError Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+ static Error Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<CoapSecure &>(aCoapBase).Send(aMessage, aMessageInfo);
}
- otError Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDtlsConnected(void *aContext, bool aConnected);
void HandleDtlsConnected(bool aConnected);
diff --git a/src/core/common/equatable.hpp b/src/core/common/equatable.hpp
index 83ab05b..06fdda9 100644
--- a/src/core/common/equatable.hpp
+++ b/src/core/common/equatable.hpp
@@ -41,6 +41,32 @@
namespace ot {
/**
+ * This template class defines an overload of operator `!=`.
+ *
+ * The `!=` implementation uses an existing `==` overload provided by the `Type` class.
+ *
+ * Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should publicly inherit
+ * from `Unequatable<Type>`.
+ *
+ */
+template <typename Type> class Unequatable
+{
+public:
+ /**
+ * This method overloads operator `!=` to evaluate whether or not two instances of `Type` are equal.
+ *
+ * This is implemented in terms of an existing `==` overload provided by `Type` class itself.
+ *
+ * @param[in] aOther The other `Type` instance to compare with.
+ *
+ * @retval TRUE If the two `Type` instances are not equal.
+ * @retval FALSE If the two `Type` instances are equal.
+ *
+ */
+ bool operator!=(const Type &aOther) const { return !(*static_cast<const Type *>(this) == aOther); }
+};
+
+/**
* This template class defines overloads of operators `==` and `!=`.
*
* The `==` implementation simply compares all the bytes of two `Type` instances to be equal (using `memcmp()`).
@@ -49,7 +75,7 @@
* from `Equatable<Type>`.
*
*/
-template <class Type> class Equatable
+template <typename Type> class Equatable : public Unequatable<Type>
{
public:
/**
@@ -62,17 +88,6 @@
*
*/
bool operator==(const Type &aOther) const { return memcmp(this, &aOther, sizeof(Type)) == 0; }
-
- /**
- * This method overloads operator `!=` to evaluate whether or not two instances of `Type` are equal.
- *
- * @param[in] aOther The other `Type` instance to compare with.
- *
- * @retval TRUE If the two `Type` instances are not equal.
- * @retval FALSE If the two `Type` instances are equal.
- *
- */
- bool operator!=(const Type &aOther) const { return !(*this == aOther); }
};
} // namespace ot
diff --git a/src/core/common/error.cpp b/src/core/common/error.cpp
new file mode 100644
index 0000000..3d0e4a5
--- /dev/null
+++ b/src/core/common/error.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2021, 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 error code functions used by OpenThread core modules.
+ */
+
+#include "error.hpp"
+
+#include "common/code_utils.hpp"
+
+namespace ot {
+
+const char *ErrorToString(Error aError)
+{
+ static const char *const kErrorStrings[kNumErrors] = {
+ "OK", // (0) kErrorNone
+ "Failed", // (1) kErrorFailed
+ "Drop", // (2) kErrorDrop
+ "NoBufs", // (3) kErrorNoBufs
+ "NoRoute", // (4) kErrorNoRoute
+ "Busy", // (5) kErrorBusy
+ "Parse", // (6) kErrorParse
+ "InvalidArgs", // (7) kErrorInvalidArgs
+ "Security", // (8) kErrorSecurity
+ "AddressQuery", // (9) kErrorAddressQuery
+ "NoAddress", // (10) kErrorNoAddress
+ "Abort", // (11) kErrorAbort
+ "NotImplemented", // (12) kErrorNotImplemented
+ "InvalidState", // (13) kErrorInvalidState
+ "NoAck", // (14) kErrorNoAck
+ "ChannelAccessFailure", // (15) kErrorChannelAccessFailure
+ "Detached", // (16) kErrorDetached
+ "FcsErr", // (17) kErrorFcs
+ "NoFrameReceived", // (18) kErrorNoFrameReceived
+ "UnknownNeighbor", // (19) kErrorUnknownNeighbor
+ "InvalidSourceAddress", // (20) kErrorInvalidSourceAddress
+ "AddressFiltered", // (21) kErrorAddressFiltered
+ "DestinationAddressFiltered", // (22) kErrorDestinationAddressFiltered
+ "NotFound", // (23) kErrorNotFound
+ "Already", // (24) kErrorAlready
+ "ReservedError25", // (25) Error 25 is reserved
+ "Ipv6AddressCreationFailure", // (26) kErrorIp6AddressCreationFailure
+ "NotCapable", // (27) kErrorNotCapable
+ "ResponseTimeout", // (28) kErrorResponseTimeout
+ "Duplicated", // (29) kErrorDuplicated
+ "ReassemblyTimeout", // (30) kErrorReassemblyTimeout
+ "NotTmf", // (31) kErrorNotTmf
+ "NonLowpanDataFrame", // (32) kErrorNotLowpanDataFrame
+ "ReservedError33", // (33) Error 33 is reserved
+ "LinkMarginLow", // (34) kErrorLinkMarginLow
+ "InvalidCommand", // (35) kErrorInvalidCommand
+ "Pending", // (36) kErrorPending
+ };
+
+ return aError < OT_ARRAY_LENGTH(kErrorStrings) ? kErrorStrings[aError] : "UnknownErrorType";
+}
+
+} // namespace ot
diff --git a/src/core/common/error.hpp b/src/core/common/error.hpp
new file mode 100644
index 0000000..838bbb1
--- /dev/null
+++ b/src/core/common/error.hpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021, 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 defines the errors used by OpenThread core.
+ */
+
+#ifndef ERROR_HPP_
+#define ERROR_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/error.h>
+
+#include <stdint.h>
+
+namespace ot {
+
+/**
+ * This type represents error codes used by OpenThread core modules.
+ *
+ */
+typedef otError Error;
+
+/*
+ * The `OT_ERROR_*` enumeration values are re-defined using `kError` style format.
+ * See `openthread/error.h` for more details about each error.
+ *
+ */
+constexpr Error kErrorNone = OT_ERROR_NONE;
+constexpr Error kErrorFailed = OT_ERROR_FAILED;
+constexpr Error kErrorDrop = OT_ERROR_DROP;
+constexpr Error kErrorNoBufs = OT_ERROR_NO_BUFS;
+constexpr Error kErrorNoRoute = OT_ERROR_NO_ROUTE;
+constexpr Error kErrorBusy = OT_ERROR_BUSY;
+constexpr Error kErrorParse = OT_ERROR_PARSE;
+constexpr Error kErrorInvalidArgs = OT_ERROR_INVALID_ARGS;
+constexpr Error kErrorSecurity = OT_ERROR_SECURITY;
+constexpr Error kErrorAddressQuery = OT_ERROR_ADDRESS_QUERY;
+constexpr Error kErrorNoAddress = OT_ERROR_NO_ADDRESS;
+constexpr Error kErrorAbort = OT_ERROR_ABORT;
+constexpr Error kErrorNotImplemented = OT_ERROR_NOT_IMPLEMENTED;
+constexpr Error kErrorInvalidState = OT_ERROR_INVALID_STATE;
+constexpr Error kErrorNoAck = OT_ERROR_NO_ACK;
+constexpr Error kErrorChannelAccessFailure = OT_ERROR_CHANNEL_ACCESS_FAILURE;
+constexpr Error kErrorDetached = OT_ERROR_DETACHED;
+constexpr Error kErrorFcs = OT_ERROR_FCS;
+constexpr Error kErrorNoFrameReceived = OT_ERROR_NO_FRAME_RECEIVED;
+constexpr Error kErrorUnknownNeighbor = OT_ERROR_UNKNOWN_NEIGHBOR;
+constexpr Error kErrorInvalidSourceAddress = OT_ERROR_INVALID_SOURCE_ADDRESS;
+constexpr Error kErrorAddressFiltered = OT_ERROR_ADDRESS_FILTERED;
+constexpr Error kErrorDestinationAddressFiltered = OT_ERROR_DESTINATION_ADDRESS_FILTERED;
+constexpr Error kErrorNotFound = OT_ERROR_NOT_FOUND;
+constexpr Error kErrorAlready = OT_ERROR_ALREADY;
+constexpr Error kErrorIp6AddressCreationFailure = OT_ERROR_IP6_ADDRESS_CREATION_FAILURE;
+constexpr Error kErrorNotCapable = OT_ERROR_NOT_CAPABLE;
+constexpr Error kErrorResponseTimeout = OT_ERROR_RESPONSE_TIMEOUT;
+constexpr Error kErrorDuplicated = OT_ERROR_DUPLICATED;
+constexpr Error kErrorReassemblyTimeout = OT_ERROR_REASSEMBLY_TIMEOUT;
+constexpr Error kErrorNotTmf = OT_ERROR_NOT_TMF;
+constexpr Error kErrorNotLowpanDataFrame = OT_ERROR_NOT_LOWPAN_DATA_FRAME;
+constexpr Error kErrorLinkMarginLow = OT_ERROR_LINK_MARGIN_LOW;
+constexpr Error kErrorInvalidCommand = OT_ERROR_INVALID_COMMAND;
+constexpr Error kErrorPending = OT_ERROR_PENDING;
+constexpr Error kErrorGeneric = OT_ERROR_GENERIC;
+
+constexpr uint8_t kNumErrors = OT_NUM_ERRORS;
+
+/**
+ * This function converts an `Error` into a string.
+ *
+ * @param[in] aError An error.
+ *
+ * @returns A string representation of @p aError.
+ *
+ */
+const char *ErrorToString(Error aError);
+
+} // namespace ot
+
+#endif // ERROR_HPP_
diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp
index 440dcdb..1e37ef8 100644
--- a/src/core/common/instance.cpp
+++ b/src/core/common/instance.cpp
@@ -37,6 +37,7 @@
#include "common/logging.hpp"
#include "common/new.hpp"
+#include "utils/heap.hpp"
namespace ot {
@@ -48,15 +49,10 @@
#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
-
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-
-otHeapFreeFn ot::Instance::mFree = nullptr;
-otHeapCAllocFn ot::Instance::mCAlloc = nullptr;
-
-#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
-
-#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+Utils::Heap Instance::sHeap;
+#endif
+#endif
Instance::Instance(void)
: mTimerMilliScheduler(*this)
@@ -78,6 +74,9 @@
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
, mApplicationCoapSecure(*this, /* aLayerTwoSecurity */ true)
#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ , mPingSender(*this)
+#endif
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
, mChannelMonitor(*this)
#endif
@@ -93,6 +92,9 @@
#if OPENTHREAD_CONFIG_OTNS_ENABLE
, mOtns(*this)
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ , mRoutingManager(*this)
+#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
, mLinkRaw(*this)
@@ -215,11 +217,11 @@
otPlatReset(this);
}
-otError Instance::ErasePersistentInfo(void)
+Error Instance::ErasePersistentInfo(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
Get<Settings>().Wipe();
exit:
diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp
index 2cb4324..d2997a5 100644
--- a/src/core/common/instance.hpp
+++ b/src/core/common/instance.hpp
@@ -39,13 +39,13 @@
#include <stdbool.h>
#include <stdint.h>
-#include <openthread/error.h>
#include <openthread/heap.h>
#include <openthread/platform/logging.h>
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
#include <openthread/platform/memory.h>
#endif
+#include "common/error.hpp"
#include "common/non_copyable.hpp"
#include "common/random_manager.hpp"
#include "common/tasklet.hpp"
@@ -60,27 +60,28 @@
#endif
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#include "common/code_utils.hpp"
-#include "crypto/mbedtls.hpp"
-#include "thread/tmf.hpp"
-#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-#include "utils/heap.hpp"
-#endif
#include "common/notifier.hpp"
#include "common/settings.hpp"
+#include "crypto/mbedtls.hpp"
#include "meshcop/border_agent.hpp"
+#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
+#include "meshcop/dataset_updater.hpp"
+#endif
#include "net/ip6.hpp"
#include "thread/announce_sender.hpp"
#include "thread/link_quality.hpp"
#include "thread/thread_netif.hpp"
+#include "thread/tmf.hpp"
+#include "utils/heap.hpp"
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+#include "utils/ping_sender.hpp"
+#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
#include "utils/channel_manager.hpp"
#endif
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
#include "utils/channel_monitor.hpp"
#endif
-#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
-#include "utils/dataset_updater.hpp"
-#endif
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#include "backbone_router/bbr_leader.hpp"
@@ -95,6 +96,10 @@
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#include "border_router/routing_manager.hpp"
+#endif
+
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
#include "common/extension.hpp"
@@ -236,35 +241,18 @@
*
* Erase is successful/allowed only if the device is in `disabled` state/role.
*
- * @retval OT_ERROR_NONE All persistent info/state was erased successfully.
- * @retval OT_ERROR_INVALID_STATE Device is not in `disabled` state/role.
+ * @retval kErrorNone All persistent info/state was erased successfully.
+ * @retval kErrorInvalidState Device is not in `disabled` state/role.
*
*/
- otError ErasePersistentInfo(void);
+ Error ErasePersistentInfo(void);
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
- void HeapFree(void *aPointer)
- {
- OT_ASSERT(mFree != nullptr);
-
- mFree(aPointer);
- }
-
- void *HeapCAlloc(size_t aCount, size_t aSize)
- {
- OT_ASSERT(mCAlloc != nullptr);
-
- return mCAlloc(aCount, aSize);
- }
-
- static void HeapSetCAllocFree(otHeapCAllocFn aCAlloc, otHeapFreeFn aFree)
- {
- mFree = aFree;
- mCAlloc = aCAlloc;
- }
-#elif !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- void HeapFree(void *aPointer) { mHeap.Free(aPointer); }
- void *HeapCAlloc(size_t aCount, size_t aSize) { return mHeap.CAlloc(aCount, aSize); }
+ static void HeapFree(void *aPointer) { otPlatFree(aPointer); }
+ static void *HeapCAlloc(size_t aCount, size_t aSize) { return otPlatCAlloc(aCount, aSize); }
+#else
+ static void HeapFree(void *aPointer) { sHeap.Free(aPointer); }
+ static void *HeapCAlloc(size_t aCount, size_t aSize) { return sHeap.CAlloc(aCount, aSize); }
/**
* This method returns a reference to the Heap object.
@@ -272,10 +260,7 @@
* @returns A reference to the Heap object.
*
*/
- Utils::Heap &GetHeap(void) { return mHeap; }
-#else
- void HeapFree(void *aPointer) { otPlatFree(aPointer); }
- void *HeapCAlloc(size_t aCount, size_t aSize) { return otPlatCAlloc(aCount, aSize); }
+ Utils::Heap &GetHeap(void) { return sHeap; }
#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
@@ -334,11 +319,8 @@
#if OPENTHREAD_MTD || OPENTHREAD_FTD
// RandomManager is initialized before other objects. Note that it
// requires MbedTls which itself may use Heap.
-#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
- static otHeapFreeFn mFree;
- static otHeapCAllocFn mCAlloc;
-#elif !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- Utils::Heap mHeap;
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+ static Utils::Heap sHeap;
#endif
Crypto::MbedTls mMbedTls;
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
@@ -371,6 +353,10 @@
Coap::CoapSecure mApplicationCoapSecure;
#endif
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ Utils::PingSender mPingSender;
+#endif
+
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
Utils::ChannelMonitor mChannelMonitor;
#endif
@@ -380,7 +366,7 @@
#endif
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
- Utils::DatasetUpdater mDatasetUpdater;
+ MeshCoP::DatasetUpdater mDatasetUpdater;
#endif
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
@@ -391,6 +377,10 @@
Utils::Otns mOtns;
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ BorderRouter::RoutingManager mRoutingManager;
+#endif
+
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
Mac::LinkRaw mLinkRaw;
@@ -561,7 +551,7 @@
return mThreadNetif.mMeshForwarder.mIndirectSender.mDataPollHandler;
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
template <> inline CslTxScheduler &Instance::Get(void)
{
return mThreadNetif.mMeshForwarder.mIndirectSender.mCslTxScheduler;
@@ -623,6 +613,11 @@
}
#endif
+template <> inline NetworkData::Service::Manager &Instance::Get(void)
+{
+ return mThreadNetif.mNetworkDataServiceManager;
+}
+
template <> inline Ip6::Udp &Instance::Get(void)
{
return mIp6.mUdp;
@@ -688,6 +683,20 @@
}
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+template <> inline Srp::Client &Instance::Get(void)
+{
+ return mThreadNetif.mSrpClient;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+template <> inline Dns::ServiceDiscovery::Server &Instance::Get(void)
+{
+ return mThreadNetif.mDnssdServer;
+}
+#endif
+
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
template <> inline NetworkDiagnostic::NetworkDiagnostic &Instance::Get(void)
{
@@ -740,6 +749,13 @@
return mThreadNetif.mSupervisionListener;
}
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+template <> inline Utils::PingSender &Instance::Get(void)
+{
+ return mPingSender;
+}
+#endif
+
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
template <> inline Utils::ChannelMonitor &Instance::Get(void)
{
@@ -755,7 +771,7 @@
#endif
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
-template <> inline Utils::DatasetUpdater &Instance::Get(void)
+template <> inline MeshCoP::DatasetUpdater &Instance::Get(void)
{
return mDatasetUpdater;
}
@@ -847,6 +863,20 @@
}
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+template <> inline BorderRouter::RoutingManager &Instance::Get(void)
+{
+ return mRoutingManager;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+template <> inline Srp::Server &Instance::Get(void)
+{
+ return mThreadNetif.mSrpServer;
+}
+#endif
+
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
diff --git a/src/core/common/iterator_utils.hpp b/src/core/common/iterator_utils.hpp
new file mode 100644
index 0000000..dbee0aa
--- /dev/null
+++ b/src/core/common/iterator_utils.hpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for a generic item-pointer iterator class.
+ */
+
+#ifndef ITERATOR_UTILS_HPP_
+#define ITERATOR_UTILS_HPP_
+
+namespace ot {
+
+/**
+ * @addtogroup core-iterator-utils
+ *
+ * @brief
+ * This module includes definitions for OpenThread generic item-pointer iterator class.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This template class is used as a base class for those item-pointer iterators.
+ *
+ * These iterators have common methods and operators like `Advance()` and `++` and hold a pointer to the
+ * object.
+ *
+ * Users of this class should follow CRTP-style inheritance, i.e., `IteratorType` class itself should publicly inherit
+ * from `ItemPtrIterator<ItemType, IteratorType>`.
+ *
+ * @tparam ItemType The type of the object that the iterator points to.
+ * @tparam IteratorType The Iterator class that inherits this class. The class MUST have a method `Advance()` which
+ * moves the pointer to the next. `Advance()` SHALL NOT be called when `IsDone()` is `true` and
+ * would set the pointer to `nullptr` when there's no more elements.
+ *
+ */
+template <class ItemType, class IteratorType> class ItemPtrIterator
+{
+public:
+ /**
+ * This method indicates whether there are no more items to be accessed (iterator has reached the end).
+ *
+ * @retval TRUE There are no more items to be accessed (iterator has reached the end).
+ * @retval FALSE The current item is valid.
+ *
+ */
+ bool IsDone(void) const { return mItem == nullptr; }
+
+ /**
+ * This method overloads `++` operator (pre-increment) to advance the iterator.
+ *
+ * The iterator is moved to point to the next item using IteratorType's `Advance` method.
+ * If there are no more items, the iterator becomes empty (i.e., `operator*` returns `nullptr` and `IsDone()`
+ * returns `true`).
+ *
+ */
+ void operator++(void) { static_cast<IteratorType *>(this)->Advance(); }
+
+ /**
+ * This method overloads `++` operator (post-increment) to advance the iterator.
+ *
+ * The iterator is moved to point to the next item using IteratorType's `Advance` method.
+ * If there are no more items, the iterator becomes empty (i.e., `operator*` returns `nullptr` and `IsDone()`
+ * returns `true`).
+ *
+ */
+ void operator++(int) { static_cast<IteratorType *>(this)->Advance(); }
+
+ /**
+ * This method overloads the `*` dereference operator and gets a reference to then item to which the iterator is
+ * currently pointing.
+ *
+ * This method MUST be used when the iterator is not empty/finished (i.e., `IsDone()` returns `false`).
+ *
+ * @returns A reference to the item currently pointed by the iterator.
+ *
+ */
+ ItemType &operator*(void) { return *mItem; }
+
+ /**
+ * This method overloads the `->` dereference operator and gets a pointer to the item to which the iterator is
+ * currently pointing.
+ *
+ * @returns A pointer to the item associated with the iterator, or `nullptr` if iterator is empty/done.
+ *
+ */
+ ItemType *operator->(void) { return mItem; }
+
+ /**
+ * This method overloads operator `==` to evaluate whether or not two `Iterator` instances point to the same
+ * item.
+ *
+ * @param[in] aOther The other `Iterator` to compare with.
+ *
+ * @retval TRUE If the two `Iterator` objects point to the same item or both are done.
+ * @retval FALSE If the two `Iterator` objects do not point to the same item.
+ *
+ */
+ bool operator==(const IteratorType &aOther) const { return mItem == aOther.mItem; }
+
+ /**
+ * This method overloads operator `!=` to evaluate whether or not two `Iterator` instances point to the same
+ * child entry.
+ *
+ * @param[in] aOther The other `Iterator` to compare with.
+ *
+ * @retval TRUE If the two `Iterator` objects do not point to the same item.
+ * @retval FALSE If the two `Iterator` objects point to the same item or both are done.
+ *
+ */
+ bool operator!=(const IteratorType &aOther) const { return mItem != aOther.mItem; }
+
+protected:
+ /**
+ * Default constructor
+ *
+ */
+ ItemPtrIterator(void)
+ : mItem(nullptr)
+ {
+ }
+
+ /**
+ * Contructor with an Item pointer.
+ *
+ */
+ explicit ItemPtrIterator(ItemType *item)
+ : mItem(item)
+ {
+ }
+
+ ItemType *mItem;
+};
+
+/**
+ * @}
+ *
+ */
+
+} // namespace ot
+
+#endif // ITERATOR_UTILS_HPP_
diff --git a/src/core/common/linked_list.hpp b/src/core/common/linked_list.hpp
index 08ef9a5..4e48597 100644
--- a/src/core/common/linked_list.hpp
+++ b/src/core/common/linked_list.hpp
@@ -37,7 +37,8 @@
#include "openthread-core-config.h"
#include <stdio.h>
-#include <openthread/error.h>
+
+#include "common/error.hpp"
namespace ot {
@@ -239,7 +240,7 @@
{
const Type *prev;
- return Find(aEntry, prev) == OT_ERROR_NONE;
+ return Find(aEntry, prev) == kErrorNone;
}
/**
@@ -267,17 +268,17 @@
*
* @param[in] aEntry A reference to an entry to add.
*
- * @retval OT_ERROR_NONE The entry was successfully added at the head of the list.
- * @retval OT_ERROR_ALREADY The entry is already in the list.
+ * @retval kErrorNone The entry was successfully added at the head of the list.
+ * @retval kErrorAlready The entry is already in the list.
*
*/
- otError Add(Type &aEntry)
+ Error Add(Type &aEntry)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (Contains(aEntry))
{
- error = OT_ERROR_ALREADY;
+ error = kErrorAlready;
}
else
{
@@ -295,16 +296,16 @@
*
* @param[in] aEntry A reference to an entry to remove.
*
- * @retval OT_ERROR_NONE The entry was successfully removed from the list.
- * @retval OT_ERROR_NOT_FOUND Could not find the entry in the list.
+ * @retval kErrorNone The entry was successfully removed from the list.
+ * @retval kErrorNotFound Could not find the entry in the list.
*
*/
- otError Remove(const Type &aEntry)
+ Error Remove(const Type &aEntry)
{
- Type * prev;
- otError error = Find(aEntry, prev);
+ Type *prev;
+ Error error = Find(aEntry, prev);
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
PopAfter(prev);
}
@@ -351,13 +352,13 @@
* @p aPrevEntry is set to nullptr if @p aEntry is the head of the list. Otherwise it is
* updated to point to the previous entry before @p aEntry in the list.
*
- * @retval OT_ERROR_NONE The entry was found in the list and @p aPrevEntry was updated successfully.
- * @retval OT_ERROR_NOT_FOUND The entry was not found in the list.
+ * @retval kErrorNone The entry was found in the list and @p aPrevEntry was updated successfully.
+ * @retval kErrorNotFound The entry was not found in the list.
*
*/
- otError Find(const Type &aEntry, const Type *&aPrevEntry) const
+ Error Find(const Type &aEntry, const Type *&aPrevEntry) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
aPrevEntry = nullptr;
@@ -365,7 +366,7 @@
{
if (entry == &aEntry)
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
break;
}
}
@@ -381,11 +382,11 @@
* @p aPrevEntry is set to nullptr if @p aEntry is the head of the list. Otherwise it is
* updated to point to the previous entry before @p aEntry in the list.
*
- * @retval OT_ERROR_NONE The entry was found in the list and @p aPrevEntry was updated successfully.
- * @retval OT_ERROR_NOT_FOUND The entry was not found in the list.
+ * @retval kErrorNone The entry was found in the list and @p aPrevEntry was updated successfully.
+ * @retval kErrorNotFound The entry was not found in the list.
*
*/
- otError Find(const Type &aEntry, Type *&aPrevEntry)
+ Error Find(const Type &aEntry, Type *&aPrevEntry)
{
return const_cast<const LinkedList *>(this)->Find(aEntry, const_cast<const Type *&>(aPrevEntry));
}
diff --git a/src/core/common/locator-getters.hpp b/src/core/common/locator-getters.hpp
index 43ed54c..dc87b40 100644
--- a/src/core/common/locator-getters.hpp
+++ b/src/core/common/locator-getters.hpp
@@ -63,15 +63,6 @@
return GetInstance().Get<Type>();
}
-#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-
-template <typename OwnerType> OwnerType &OwnerLocator::GetOwner(void)
-{
- return Instance::Get().Get<OwnerType>();
-}
-
-#endif
-
} // namespace ot
#endif // LOCATOR_GETTERS_HPP_
diff --git a/src/core/common/locator.hpp b/src/core/common/locator.hpp
index e2bc32b..30350c3 100644
--- a/src/core/common/locator.hpp
+++ b/src/core/common/locator.hpp
@@ -162,54 +162,6 @@
};
/**
- * This class implements a locator for owner of an object.
- *
- * This is used as the base class for objects that provide a callback (e.g., `Timer` or `Tasklet`).
- *
- */
-class OwnerLocator
-{
-public:
- /**
- * This template method returns a reference to the owner object.
- *
- * The caller needs to provide the `OwnerType` as part of the template type.
- *
- * @returns A reference to the owner of this object.
- *
- */
- template <typename OwnerType> OwnerType &GetOwner(void)
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- {
- return *static_cast<OwnerType *>(mOwner);
- }
-#else
- // Implemented in `locator-getters.hpp`
- ;
-#endif
-
-protected:
- /**
- * This constructor initializes the object.
- *
- * @param[in] aOwner A pointer to the owner object (as `void *`).
- *
- */
- explicit OwnerLocator(void *aOwner)
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
- : mOwner(aOwner)
-#endif
- {
- OT_UNUSED_VARIABLE(aOwner);
- }
-
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-private:
- void *mOwner;
-#endif
-};
-
-/**
* @}
*
*/
diff --git a/src/core/common/logging.cpp b/src/core/common/logging.cpp
index ec0fe04..42be86d 100644
--- a/src/core/common/logging.cpp
+++ b/src/core/common/logging.cpp
@@ -101,7 +101,7 @@
#endif // OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
IgnoreError(logString.Append("%s", aRegionPrefix));
- VerifyOrExit(logString.AppendVarArgs(aFormat, aArgs) != OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(logString.AppendVarArgs(aFormat, aArgs) != ot::kErrorInvalidArgs);
otPlatLog(aLogLevel, aLogRegion, "%s" OPENTHREAD_CONFIG_LOG_SUFFIX, logString.AsCString());
exit:
@@ -318,51 +318,6 @@
}
#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
-static const char *const sThreadErrorStrings[OT_NUM_ERRORS] = {
- "OK", // OT_ERROR_NONE = 0
- "Failed", // OT_ERROR_FAILED = 1
- "Drop", // OT_ERROR_DROP = 2
- "NoBufs", // OT_ERROR_NO_BUFS = 3
- "NoRoute", // OT_ERROR_NO_ROUTE = 4
- "Busy", // OT_ERROR_BUSY = 5
- "Parse", // OT_ERROR_PARSE = 6
- "InvalidArgs", // OT_ERROR_INVALID_ARGS = 7
- "Security", // OT_ERROR_SECURITY = 8
- "AddressQuery", // OT_ERROR_ADDRESS_QUERY = 9
- "NoAddress", // OT_ERROR_NO_ADDRESS = 10
- "Abort", // OT_ERROR_ABORT = 11
- "NotImplemented", // OT_ERROR_NOT_IMPLEMENTED = 12
- "InvalidState", // OT_ERROR_INVALID_STATE = 13
- "NoAck", // OT_ERROR_NO_ACK = 14
- "ChannelAccessFailure", // OT_ERROR_CHANNEL_ACCESS_FAILURE = 15
- "Detached", // OT_ERROR_DETACHED = 16
- "FcsErr", // OT_ERROR_FCS = 17
- "NoFrameReceived", // OT_ERROR_NO_FRAME_RECEIVED = 18
- "UnknownNeighbor", // OT_ERROR_UNKNOWN_NEIGHBOR = 19
- "InvalidSourceAddress", // OT_ERROR_INVALID_SOURCE_ADDRESS = 20
- "AddressFiltered", // OT_ERROR_ADDRESS_FILTERED = 21
- "DestinationAddressFiltered", // OT_ERROR_DESTINATION_ADDRESS_FILTERED = 22
- "NotFound", // OT_ERROR_NOT_FOUND = 23
- "Already", // OT_ERROR_ALREADY = 24
- "ReservedError25", // otError 25 is reserved
- "Ipv6AddressCreationFailure", // OT_ERROR_IP6_ADDRESS_CREATION_FAILURE = 26
- "NotCapable", // OT_ERROR_NOT_CAPABLE = 27
- "ResponseTimeout", // OT_ERROR_RESPONSE_TIMEOUT = 28
- "Duplicated", // OT_ERROR_DUPLICATED = 29
- "ReassemblyTimeout", // OT_ERROR_REASSEMBLY_TIMEOUT = 30
- "NotTmf", // OT_ERROR_NOT_TMF = 31
- "NonLowpanDataFrame", // OT_ERROR_NOT_LOWPAN_DATA_FRAME = 32
- "ReservedError33", // otError 33 is reserved
- "LinkMarginLow", // OT_ERROR_LINK_MARGIN_LOW = 34
- "InvalidCommand", // OT_ERROR_INVALID_COMMAND = 35
- "Pending", // OT_ERROR_PENDING = 36
-};
-
-const char *otThreadErrorToString(otError aError)
-{
- return aError < OT_ARRAY_LENGTH(sThreadErrorStrings) ? sThreadErrorStrings[aError] : "UnknownErrorType";
-}
-
#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
const char *otLogLevelToPrefixString(otLogLevel aLogLevel)
diff --git a/src/core/common/logging.hpp b/src/core/common/logging.hpp
index 2dd5a4e..89d49f4 100644
--- a/src/core/common/logging.hpp
+++ b/src/core/common/logging.hpp
@@ -94,6 +94,9 @@
#define _OT_REGION_BBR_PREFIX "-BBR-----: "
#define _OT_REGION_MLR_PREFIX "-MLR-----: "
#define _OT_REGION_DUA_PREFIX "-DUA-----: "
+#define _OT_REGION_BR_PREFIX "-BR------: "
+#define _OT_REGION_SRP_PREFIX "-SRP-----: "
+#define _OT_REGION_DNS_PREFIX "-DNS-----: "
#else
#define _OT_REGION_API_PREFIX _OT_REGION_SUFFIX
#define _OT_REGION_MLE_PREFIX _OT_REGION_SUFFIX
@@ -114,6 +117,9 @@
#define _OT_REGION_BBR_PREFIX _OT_REGION_SUFFIX
#define _OT_REGION_MLR_PREFIX _OT_REGION_SUFFIX
#define _OT_REGION_DUA_PREFIX _OT_REGION_SUFFIX
+#define _OT_REGION_BR_PREFIX _OT_REGION_SUFFIX
+#define _OT_REGION_SRP_PREFIX _OT_REGION_SUFFIX
+#define _OT_REGION_DNS_PREFIX _OT_REGION_SUFFIX
#endif
/**
@@ -330,6 +336,64 @@
#define otLogDebgMbedTls(...) otLogDebgMeshCoP(__VA_ARGS__)
/**
+ * @def otLogCritBr
+ *
+ * This function generates a log with level critical for the BR region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogWarnBr
+ *
+ * This function generates a log with level warning for the BR region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogNoteBr
+ *
+ * This function generates a log with level note for the BR region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogInfoBr
+ *
+ * This function generates a log with level info for the BR region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogDebgBr
+ *
+ * This function generates a log with level debug for the BR region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+#if OPENTHREAD_CONFIG_LOG_BR
+#define otLogCritBr(...) otLogCrit(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
+#define otLogWarnBr(...) otLogWarn(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
+#define otLogNoteBr(...) otLogNote(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
+#define otLogInfoBr(...) otLogInfo(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
+#define otLogDebgBr(...) otLogDebg(OT_LOG_REGION_BR, _OT_REGION_BR_PREFIX, __VA_ARGS__)
+#else
+#define otLogCritBr(...)
+#define otLogWarnBr(...)
+#define otLogNoteBr(...)
+#define otLogInfoBr(...)
+#define otLogDebgBr(...)
+#endif
+
+/**
* @def otLogCritMle
*
* This function generates a log with level critical for the MLE region.
@@ -1243,6 +1307,122 @@
#endif
/**
+ * @def otLogCritSrp
+ *
+ * This function generates a log with level critical for the Service Registration Protocol (SRP) region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogWarnSrp
+ *
+ * This function generates a log with level warning for the Service Registration Protocol (SRP) region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogNoteSrp
+ *
+ * This function generates a log with level note for the Service Registration Protocol (SRP) region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogInfoSrp
+ *
+ * This function generates a log with level info for the Service Registration Protocol (SRP) region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogDebgSrp
+ *
+ * This function generates a log with level debug for the Service Registration Protocol (SRP) region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+#if OPENTHREAD_CONFIG_LOG_SRP
+#define otLogCritSrp(...) otLogCrit(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
+#define otLogWarnSrp(...) otLogWarn(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
+#define otLogNoteSrp(...) otLogNote(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
+#define otLogInfoSrp(...) otLogInfo(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
+#define otLogDebgSrp(...) otLogDebg(OT_LOG_REGION_SRP, _OT_REGION_SRP_PREFIX, __VA_ARGS__)
+#else
+#define otLogCritSrp(...)
+#define otLogWarnSrp(...)
+#define otLogNoteSrp(...)
+#define otLogInfoSrp(...)
+#define otLogDebgSrp(...)
+#endif
+
+/**
+ * @def otLogCritDns
+ *
+ * This function generates a log with level critical for the DNS region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogWarnDns
+ *
+ * This function generates a log with level warning for the DNS region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogNoteDns
+ *
+ * This function generates a log with level note for the DNS region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogInfoDns
+ *
+ * This function generates a log with level info for the DNS region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+
+/**
+ * @def otLogDebgDns
+ *
+ * This function generates a log with level debug for the DNS region.
+ *
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+#if OPENTHREAD_CONFIG_LOG_DNS
+#define otLogCritDns(...) otLogCrit(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
+#define otLogWarnDns(...) otLogWarn(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
+#define otLogNoteDns(...) otLogNote(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
+#define otLogInfoDns(...) otLogInfo(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
+#define otLogDebgDns(...) otLogDebg(OT_LOG_REGION_DNS, _OT_REGION_DNS_PREFIX, __VA_ARGS__)
+#else
+#define otLogCritDns(...)
+#define otLogWarnDns(...)
+#define otLogNoteDns(...)
+#define otLogInfoDns(...)
+#define otLogDebgDns(...)
+#endif
+
+/**
* @def otLogCritPlat
*
* This function generates a log with level critical for the Platform region.
@@ -2078,6 +2258,142 @@
#endif
/**
+ * @def otDumpCritSrp
+ *
+ * This function generates a memory dump with log level critical and region Service Registration Protocol (SRP).
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpWarnSrp
+ *
+ * This function generates a memory dump with log level warning and region Service Registration Protocol (SRP).
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpNoteSrp
+ *
+ * This function generates a memory dump with log level note and region Service Registration Protocol (SRP).
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpInfoSrp
+ *
+ * This function generates a memory dump with log level info and region Service Registration Protocol (SRP).
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpDebgSrp
+ *
+ * This function generates a memory dump with log level debug and region Service Registration Protocol (SRP).
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+#if OPENTHREAD_CONFIG_LOG_SRP
+#define otDumpCritSrp(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpWarnSrp(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpNoteSrp(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpInfoSrp(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpDebgSrp(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#else
+#define otDumpCritSrp(aId, aBuf, aLength)
+#define otDumpWarnSrp(aId, aBuf, aLength)
+#define otDumpNoteSrp(aId, aBuf, aLength)
+#define otDumpInfoSrp(aId, aBuf, aLength)
+#define otDumpDebgSrp(aId, aBuf, aLength)
+#endif
+
+/**
+ * @def otDumpCritDns
+ *
+ * This function generates a memory dump with log level critical and region DNS.
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpWarnDns
+ *
+ * This function generates a memory dump with log level warning and region DNS.
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpNoteDns
+ *
+ * This function generates a memory dump with log level note and region DNS.
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpInfoDns
+ *
+ * This function generates a memory dump with log level info and region DNS.
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+
+/**
+ * @def otDumpDebgDns
+ *
+ * This function generates a memory dump with log level debug and region DNS.
+ *
+ * @param[in] aId A pointer to a NULL-terminated string that is printed before the bytes.
+ * @param[in] aBuf A pointer to the buffer.
+ * @param[in] aLength Number of bytes to print.
+ *
+ */
+#if OPENTHREAD_CONFIG_LOG_SRP
+#define otDumpCritDns(aId, aBuf, aLength) otDumpCrit(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpWarnDns(aId, aBuf, aLength) otDumpWarn(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpNoteDns(aId, aBuf, aLength) otDumpNote(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpInfoDns(aId, aBuf, aLength) otDumpInfo(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#define otDumpDebgDns(aId, aBuf, aLength) otDumpDebg(OT_LOG_REGION_SRP, aId, aBuf, aLength)
+#else
+#define otDumpCritDns(aId, aBuf, aLength)
+#define otDumpWarnDns(aId, aBuf, aLength)
+#define otDumpNoteDns(aId, aBuf, aLength)
+#define otDumpInfoDns(aId, aBuf, aLength)
+#define otDumpDebgDns(aId, aBuf, aLength)
+#endif
+
+/**
* @def otDumpCritMem
*
* This function generates a memory dump with log level debug and region memory.
@@ -2193,6 +2509,10 @@
#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#error "Dynamic log level is not supported along with multiple OT instance feature"
+#endif
+
/**
* Local/private macro to dynamically filter log level.
*/
@@ -2238,14 +2558,26 @@
/**
* @def otLogResultPlat
*
- * This function generates a log for the Plat region according to the error result. If @p aError is `OT_ERROR_NONE`, the
+ * This function generates a log for the Plat region according to the error result. If @p aError is `kErrorNone`, the
* log level is info. Otherwise the log level is warn.
*
* @param[in] aError The error result.
* @param[in] ... Arguments for the format specification.
*
*/
-#define otLogResultPlat(aError, ...) _otLogResult(Plat, aError, OT_FIRST_ARG(__VA_ARGS__) OT_REST_ARGS(__VA_ARGS__))
+#define otLogResultPlat(aError, ...) _otLogResult(Plat, aError, __VA_ARGS__)
+
+/**
+ * @def otLogResultBbr
+ *
+ * This function generates a log for the BBR region according to the error result. If @p aError is `OT_ERROR_NONE`, the
+ * log level is info. Otherwise the log level is warn.
+ *
+ * @param[in] aError The error result.
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+#define otLogResultBbr(aError, ...) _otLogResult(Bbr, aError, __VA_ARGS__)
#ifdef __cplusplus
}
diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp
index 3aeb1c8..05f2bf7 100644
--- a/src/core/common/message.cpp
+++ b/src/core/common/message.cpp
@@ -43,6 +43,10 @@
#if OPENTHREAD_MTD || OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE && OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
+#error "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE conflicts with OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT."
+#endif
+
#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE && !OPENTHREAD_CONFIG_DTLS_ENABLE
#error "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE is strongly discouraged when OPENTHREAD_CONFIG_DTLS_ENABLE is off."
#endif
@@ -62,7 +66,7 @@
Message *MessagePool::New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
VerifyOrExit((message = static_cast<Message *>(NewBuffer(aPriority))) != nullptr);
@@ -77,7 +81,7 @@
SuccessOrExit(error = message->SetLength(0));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
Free(message);
message = nullptr;
@@ -111,7 +115,7 @@
while ((
#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
- buffer = static_cast<Buffer *>(GetInstance().HeapCAlloc(sizeof(Buffer), 1))
+ buffer = static_cast<Buffer *>(Instance::HeapCAlloc(1, sizeof(Buffer)))
#elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
buffer = static_cast<Buffer *>(otPlatMessagePoolNew(&GetInstance()))
#else
@@ -143,7 +147,7 @@
{
Buffer *next = aBuffer->GetNextBuffer();
#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
- GetInstance().HeapFree(aBuffer);
+ Instance::HeapFree(aBuffer);
#elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
otPlatMessagePoolFree(&GetInstance(), aBuffer);
#else
@@ -154,7 +158,7 @@
}
}
-otError MessagePool::ReclaimBuffers(Message::Priority aPriority)
+Error MessagePool::ReclaimBuffers(Message::Priority aPriority)
{
return Get<MeshForwarder>().EvictMessage(aPriority);
}
@@ -197,9 +201,9 @@
{
}
-otError Message::ResizeMessage(uint16_t aLength)
+Error Message::ResizeMessage(uint16_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
// add buffers
Buffer * curBuffer = this;
@@ -211,7 +215,7 @@
if (curBuffer->GetNextBuffer() == nullptr)
{
curBuffer->SetNextBuffer(GetMessagePool()->NewBuffer(GetPriority()));
- VerifyOrExit(curBuffer->GetNextBuffer() != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(curBuffer->GetNextBuffer() != nullptr, error = kErrorNoBufs);
}
curBuffer = curBuffer->GetNextBuffer();
@@ -258,12 +262,12 @@
return next;
}
-otError Message::SetLength(uint16_t aLength)
+Error Message::SetLength(uint16_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t totalLengthRequest = GetReserved() + aLength;
- VerifyOrExit(totalLengthRequest >= GetReserved(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(totalLengthRequest >= GetReserved(), error = kErrorInvalidArgs);
SuccessOrExit(error = ResizeMessage(totalLengthRequest));
GetMetadata().mLength = aLength;
@@ -327,13 +331,13 @@
return rval;
}
-otError Message::SetPriority(Priority aPriority)
+Error Message::SetPriority(Priority aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t priority = static_cast<uint8_t>(aPriority);
PriorityQueue *priorityQueue = nullptr;
- VerifyOrExit(priority < kNumPriorities, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(priority < kNumPriorities, error = kErrorInvalidArgs);
VerifyOrExit(IsInAQueue(), GetMetadata().mPriority = priority);
VerifyOrExit(GetMetadata().mPriority != priority);
@@ -355,9 +359,26 @@
return error;
}
-otError Message::AppendBytes(const void *aBuf, uint16_t aLength)
+const char *Message::PriorityToString(Priority aPriority)
{
- otError error = OT_ERROR_NONE;
+ static const char *const kPriorityStrings[] = {
+ "low", // (0) kPriorityLow
+ "normal", // (1) kPriorityNormal
+ "high", // (2) kPriorityHigh
+ "net", // (3) kPriorityNet
+ };
+
+ static_assert(kPriorityLow == 0, "kPriorityLow value is incorrect");
+ static_assert(kPriorityNormal == 1, "kPriorityNormal value is incorrect");
+ static_assert(kPriorityHigh == 2, "kPriorityHigh value is incorrect");
+ static_assert(kPriorityNet == 3, "kPriorityNet value is incorrect");
+
+ return kPriorityStrings[aPriority];
+}
+
+Error Message::AppendBytes(const void *aBuf, uint16_t aLength)
+{
+ Error error = kErrorNone;
uint16_t oldLength = GetLength();
SuccessOrExit(error = SetLength(GetLength() + aLength));
@@ -367,14 +388,14 @@
return error;
}
-otError Message::PrependBytes(const void *aBuf, uint16_t aLength)
+Error Message::PrependBytes(const void *aBuf, uint16_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Buffer *newBuffer = nullptr;
while (aLength > GetReserved())
{
- VerifyOrExit((newBuffer = GetMessagePool()->NewBuffer(GetPriority())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((newBuffer = GetMessagePool()->NewBuffer(GetPriority())) != nullptr, error = kErrorNoBufs);
newBuffer->SetNextBuffer(GetNextBuffer());
SetNextBuffer(newBuffer);
@@ -520,9 +541,51 @@
return static_cast<uint16_t>(bufPtr - reinterpret_cast<uint8_t *>(aBuf));
}
-otError Message::Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const
+Error Message::Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const
{
- return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? OT_ERROR_NONE : OT_ERROR_PARSE;
+ return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? kErrorNone : kErrorParse;
+}
+
+bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const
+{
+ uint16_t bytesToCompare = aLength;
+ const uint8_t *bufPtr = reinterpret_cast<const uint8_t *>(aBuf);
+ Chunk chunk;
+
+ GetFirstChunk(aOffset, aLength, chunk);
+
+ while (chunk.GetLength() > 0)
+ {
+ VerifyOrExit(memcmp(bufPtr, chunk.GetData(), chunk.GetLength()) == 0);
+ bufPtr += chunk.GetLength();
+ bytesToCompare -= chunk.GetLength();
+ GetNextChunk(aLength, chunk);
+ }
+
+exit:
+ return (bytesToCompare == 0);
+}
+
+bool Message::CompareBytes(uint16_t aOffset,
+ const Message &aOtherMessage,
+ uint16_t aOtherOffset,
+ uint16_t aLength) const
+{
+ uint16_t bytesToCompare = aLength;
+ Chunk chunk;
+
+ GetFirstChunk(aOffset, aLength, chunk);
+
+ while (chunk.GetLength() > 0)
+ {
+ VerifyOrExit(aOtherMessage.CompareBytes(aOtherOffset, chunk.GetData(), chunk.GetLength()));
+ aOtherOffset += chunk.GetLength();
+ bytesToCompare -= chunk.GetLength();
+ GetNextChunk(aLength, chunk);
+ }
+
+exit:
+ return (bytesToCompare == 0);
}
void Message::WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength)
@@ -569,12 +632,12 @@
Message *Message::Clone(uint16_t aLength) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *messageCopy;
uint16_t offset;
VerifyOrExit((messageCopy = GetMessagePool()->New(GetType(), GetReserved(), GetPriority())) != nullptr,
- error = OT_ERROR_NO_BUFS);
+ error = kErrorNoBufs);
SuccessOrExit(error = messageCopy->SetLength(aLength));
CopyTo(0, 0, aLength, *messageCopy);
diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp
index 77a4ffa..f2a16c3 100644
--- a/src/core/common/message.hpp
+++ b/src/core/common/message.hpp
@@ -52,8 +52,23 @@
#include "thread/child_mask.hpp"
#include "thread/link_quality.hpp"
+/**
+ * This struct represents an opaque (and empty) type for an OpenThread message buffer.
+ *
+ */
+struct otMessage
+{
+};
+
namespace ot {
+namespace Crypto {
+
+class Sha256;
+class HmacSha256;
+
+} // namespace Crypto
+
/**
* @addtogroup core-message
*
@@ -85,38 +100,38 @@
} while (false)
/**
- * This macro frees a given message buffer if a given `otError` indicates an error.
+ * This macro frees a given message buffer if a given `Error` indicates an error.
*
* The parameter @p aMessage can be nullptr in which case this macro does nothing.
*
* @param[in] aMessage A pointer to a `Message` to free (can be nullptr).
- * @param[in] aError The `otError` to check.
+ * @param[in] aError The `Error` to check.
*
*/
-#define FreeMessageOnError(aMessage, aError) \
- do \
- { \
- if (((aError) != OT_ERROR_NONE) && ((aMessage) != nullptr)) \
- { \
- (aMessage)->Free(); \
- } \
+#define FreeMessageOnError(aMessage, aError) \
+ do \
+ { \
+ if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
+ { \
+ (aMessage)->Free(); \
+ } \
} while (false)
/**
- * This macro frees a given message buffer if a given `otError` indicates an error and sets the `aMessage` to `nullptr`.
+ * This macro frees a given message buffer if a given `Error` indicates an error and sets the `aMessage` to `nullptr`.
*
* @param[in] aMessage A pointer to a `Message` to free (can be nullptr).
- * @param[in] aError The `otError` to check.
+ * @param[in] aError The `Error` to check.
*
*/
-#define FreeAndNullMessageOnError(aMessage, aError) \
- do \
- { \
- if (((aError) != OT_ERROR_NONE) && ((aMessage) != nullptr)) \
- { \
- (aMessage)->Free(); \
- (aMessage) = nullptr; \
- } \
+#define FreeAndNullMessageOnError(aMessage, aError) \
+ do \
+ { \
+ if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
+ { \
+ (aMessage)->Free(); \
+ (aMessage) = nullptr; \
+ } \
} while (false)
enum
@@ -191,9 +206,10 @@
* This class represents a Message buffer.
*
*/
-class Buffer : public otMessage, public LinkedListEntry<Buffer>
+class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer>
{
friend class Message;
+ friend class LinkedListEntry<Buffer>;
public:
/**
@@ -271,7 +287,7 @@
enum
{
- kBufferDataSize = kBufferSize - sizeof(otMessage),
+ kBufferDataSize = kBufferSize - sizeof(otMessageBuffer),
kHeadBufferDataSize = kBufferDataSize - sizeof(MessageMetadata),
};
@@ -291,9 +307,11 @@
* This class represents a message.
*
*/
-class Message : public Buffer
+class Message : public otMessage, public Buffer
{
friend class Checksum;
+ friend class Crypto::HmacSha256;
+ friend class Crypto::Sha256;
friend class MessagePool;
friend class MessageQueue;
friend class PriorityQueue;
@@ -459,11 +477,11 @@
*
* @param[in] aLength Requested number of bytes in the message.
*
- * @retval OT_ERROR_NONE Successfully set the length of the message.
- * @retval OT_ERROR_NO_BUFS Failed to grow the size of the message because insufficient buffers were available.
+ * @retval kErrorNone Successfully set the length of the message.
+ * @retval kErrorNoBufs Failed to grow the size of the message because insufficient buffers were available.
*
*/
- otError SetLength(uint16_t aLength);
+ Error SetLength(uint16_t aLength);
/**
* This method returns the number of buffers in the message.
@@ -568,11 +586,21 @@
*
* @param[in] aPriority The message priority level.
*
- * @retval OT_ERROR_NONE Successfully set the priority for the message.
- * @retval OT_ERROR_INVALID_ARGS Priority level is not invalid.
+ * @retval kErrorNone Successfully set the priority for the message.
+ * @retval kErrorInvalidArgs Priority level is not invalid.
*
*/
- otError SetPriority(Priority aPriority);
+ Error SetPriority(Priority aPriority);
+
+ /**
+ * This static method convert a `Priority` to a string.
+ *
+ * @param[in] aPriority The priority level.
+ *
+ * @returns A string representation of @p aPriority.
+ *
+ */
+ static const char *PriorityToString(Priority aPriority);
/**
* This method prepends bytes to the front of the message.
@@ -582,11 +610,11 @@
* @param[in] aBuf A pointer to a data buffer (can be `nullptr` to grow message without writing bytes).
* @param[in] aLength The number of bytes to prepend.
*
- * @retval OT_ERROR_NONE Successfully prepended the bytes.
- * @retval OT_ERROR_NO_BUFS Not enough reserved bytes in the message.
+ * @retval kErrorNone Successfully prepended the bytes.
+ * @retval kErrorNoBufs Not enough reserved bytes in the message.
*
*/
- otError PrependBytes(const void *aBuf, uint16_t aLength);
+ Error PrependBytes(const void *aBuf, uint16_t aLength);
/**
* This method prepends an object to the front of the message.
@@ -597,11 +625,11 @@
*
* @param[in] aObject A reference to the object to prepend to the message.
*
- * @retval OT_ERROR_NONE Successfully prepended the object.
- * @retval OT_ERROR_NO_BUFS Not enough reserved bytes in the message.
+ * @retval kErrorNone Successfully prepended the object.
+ * @retval kErrorNoBufs Not enough reserved bytes in the message.
*
*/
- template <typename ObjectType> otError Prepend(const ObjectType &aObject)
+ template <typename ObjectType> Error Prepend(const ObjectType &aObject)
{
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
@@ -624,11 +652,11 @@
* @param[in] aBuf A pointer to a data buffer (MUST not be `nullptr`).
* @param[in] aLength The number of bytes to append.
*
- * @retval OT_ERROR_NONE Successfully appended the bytes.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the bytes.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- otError AppendBytes(const void *aBuf, uint16_t aLength);
+ Error AppendBytes(const void *aBuf, uint16_t aLength);
/**
* This method appends an object to the end of the message.
@@ -639,11 +667,11 @@
*
* @param[in] aObject A reference to the object to append to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the object.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the object.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- template <typename ObjectType> otError Append(const ObjectType &aObject)
+ template <typename ObjectType> Error Append(const ObjectType &aObject)
{
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
@@ -666,23 +694,23 @@
* This method reads a given number of bytes from the message.
*
* If there are fewer bytes available in the message than the requested read length, the available bytes will be
- * read and copied into @p aBuf. In this case `OT_ERROR_PARSE` will be returned.
+ * read and copied into @p aBuf. In this case `kErrorParse` will be returned.
*
* @param[in] aOffset Byte offset within the message to begin reading.
* @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
* @param[in] aLength Number of bytes to read.
*
- * @retval OT_ERROR_NONE @p aLength bytes were successfully read from message.
- * @retval OT_ERROR_PARSE Not enough bytes remaining in message to read the entire object.
+ * @retval kErrorNone @p aLength bytes were successfully read from message.
+ * @retval kErrorParse Not enough bytes remaining in message to read the entire object.
*
*/
- otError Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
+ Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
/**
* This method reads an object from the message.
*
* If there are fewer bytes available in the message than the requested object size, the available bytes will be
- * read and copied into @p aObject (@p aObject will be read partially). In this case `OT_ERROR_PARSE` will
+ * read and copied into @p aObject (@p aObject will be read partially). In this case `kErrorParse` will
* be returned.
*
* @tparam ObjectType The object type to read from the message.
@@ -690,11 +718,11 @@
* @param[in] aOffset Byte offset within the message to begin reading.
* @param[out] aObject A reference to the object to read into.
*
- * @retval OT_ERROR_NONE Object @p aObject was successfully read from message.
- * @retval OT_ERROR_PARSE Not enough bytes remaining in message to read the entire object.
+ * @retval kErrorNone Object @p aObject was successfully read from message.
+ * @retval kErrorParse Not enough bytes remaining in message to read the entire object.
*
*/
- template <typename ObjectType> otError Read(uint16_t aOffset, ObjectType &aObject) const
+ template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const
{
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
@@ -702,6 +730,60 @@
}
/**
+ * This method compares the bytes in the message at a given offset with a given byte array.
+ *
+ * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
+ * failure (returns FALSE).
+ *
+ * @param[in] aOffset Byte offset within the message to read from for the comparison.
+ * @param[in] aBuf A pointer to a data buffer to compare with the bytes from message.
+ * @param[in] aLength Number of bytes in @p aBuf.
+ *
+ * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
+ * FALSE otherwise.
+ *
+ */
+ bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const;
+
+ /**
+ * This method compares the bytes in the message at a given offset with bytes read from another message.
+ *
+ * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
+ * (returns FALSE).
+ *
+ * @param[in] aOffset Byte offset within the message to read from for the comparison.
+ * @param[in] aOtherMessage The other message to compare with.
+ * @param[in] aOtherOffset Byte offset within @p aOtherMessage to read from for the comparison.
+ * @param[in] aLength Number of bytes to compare.
+ *
+ * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
+ *
+ */
+ bool CompareBytes(uint16_t aOffset, const Message &aOtherMessage, uint16_t aOtherOffset, uint16_t aLength) const;
+
+ /**
+ * This method compares the bytes in the message at a given offset with an object.
+ *
+ * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
+ * message than the requested object size, it is treated as failed comparison (returns FALSE).
+ *
+ * @tparam ObjectType The object type to compare with the bytes in message.
+ *
+ * @param[in] aOffset Byte offset within the message to read from for the comparison.
+ * @param[in] aObject A reference to the object to compare with the message bytes.
+ *
+ * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
+ * FALSE otherwise.
+ *
+ */
+ template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
+ {
+ static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+
+ return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
+ }
+
+ /**
* This method writes bytes to the message.
*
* This method will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the
@@ -1251,11 +1333,11 @@
*
* @param[in] aLength The number of bytes that the message buffer needs to handle.
*
- * @retval OT_ERROR_NONE Successfully resized the message.
- * @retval OT_ERROR_NO_BUFS Could not grow the message due to insufficient available message buffers.
+ * @retval kErrorNone Successfully resized the message.
+ * @retval kErrorNoBufs Could not grow the message due to insufficient available message buffers.
*
*/
- otError ResizeMessage(uint16_t aLength);
+ Error ResizeMessage(uint16_t aLength);
private:
struct Chunk
@@ -1545,7 +1627,7 @@
private:
Buffer *NewBuffer(Message::Priority aPriority);
void FreeBuffers(Buffer *aBuffer);
- otError ReclaimBuffers(Message::Priority aPriority);
+ Error ReclaimBuffers(Message::Priority aPriority);
#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
uint16_t mNumFreeBuffers;
diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp
index 8b0be4b..34b6472 100644
--- a/src/core/common/notifier.cpp
+++ b/src/core/common/notifier.cpp
@@ -33,6 +33,7 @@
#include "notifier.hpp"
+#include "border_router/routing_manager.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/locator-getters.hpp"
@@ -42,7 +43,7 @@
Notifier::Notifier(Instance &aInstance)
: InstanceLocator(aInstance)
- , mTask(aInstance, Notifier::EmitEvents, this)
+ , mTask(aInstance, Notifier::EmitEvents)
{
for (ExternalCallback &callback : mExternalCallbacks)
{
@@ -51,9 +52,9 @@
}
}
-otError Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext)
+Error Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ExternalCallback *unusedCallback = nullptr;
VerifyOrExit(aCallback != nullptr);
@@ -70,10 +71,10 @@
continue;
}
- VerifyOrExit((callback.mHandler != aCallback) || (callback.mContext != aContext), error = OT_ERROR_ALREADY);
+ VerifyOrExit((callback.mHandler != aCallback) || (callback.mContext != aContext), error = kErrorAlready);
}
- VerifyOrExit(unusedCallback != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(unusedCallback != nullptr, error = kErrorNoBufs);
unusedCallback->mHandler = aCallback;
unusedCallback->mContext = aContext;
@@ -116,7 +117,7 @@
void Notifier::EmitEvents(Tasklet &aTasklet)
{
- aTasklet.GetOwner<Notifier>().EmitEvents();
+ aTasklet.Get<Notifier>().EmitEvents();
}
void Notifier::EmitEvents(void)
@@ -146,7 +147,7 @@
Get<Utils::ChildSupervisor>().HandleNotifierEvents(events);
#endif
#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
- Get<Utils::DatasetUpdater>().HandleNotifierEvents(events);
+ Get<MeshCoP::DatasetUpdater>().HandleNotifierEvents(events);
#endif
#endif // OPENTHREAD_FTD
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
@@ -179,6 +180,15 @@
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
Get<Extension::ExtensionBase>().HandleNotifierEvents(events);
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ Get<BorderRouter::RoutingManager>().HandleNotifierEvents(events);
+#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ Get<Srp::Server>().HandleNotifierEvents(events);
+#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ Get<Srp::Client>().HandleNotifierEvents(events);
+#endif
for (ExternalCallback &callback : mExternalCallbacks)
{
@@ -226,7 +236,7 @@
}
exit:
- otLogInfoCore("Notifier: StateChanged (0x%08x) %s%s] ", aEvents.GetAsFlags(), didLog ? "... " : "[",
+ otLogInfoCore("Notifier: StateChanged (0x%08x) %s%s]", aEvents.GetAsFlags(), didLog ? "... " : "[",
string.AsCString());
}
diff --git a/src/core/common/notifier.hpp b/src/core/common/notifier.hpp
index 8456811..77b162d 100644
--- a/src/core/common/notifier.hpp
+++ b/src/core/common/notifier.hpp
@@ -42,6 +42,7 @@
#include <openthread/instance.h>
#include <openthread/platform/toolchain.h>
+#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/tasklet.hpp"
@@ -210,12 +211,12 @@
* @param[in] aCallback A pointer to the handler function that is called to notify of the changes.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully registered the callback.
- * @retval OT_ERROR_ALREADY The callback was already registered.
- * @retval OT_ERROR_NO_BUFS Could not add the callback due to resource constraints.
+ * @retval kErrorNone Successfully registered the callback.
+ * @retval kErrorAlready The callback was already registered.
+ * @retval kErrorNoBufs Could not add the callback due to resource constraints.
*
*/
- otError RegisterCallback(otStateChangedCallback aCallback, void *aContext);
+ Error RegisterCallback(otStateChangedCallback aCallback, void *aContext);
/**
* This method removes/unregisters a previously registered `otStateChangedCallback` handler.
@@ -264,7 +265,7 @@
/**
* This template method updates a variable of a type `Type` with a new value and signals the given event.
*
- * If the variable is already set to the same value, this method returns `OT_ERROR_ALREADY` and the event is
+ * If the variable is already set to the same value, this method returns `kErrorAlready` and the event is
* signaled using `SignalIfFirst()` (i.e., signal is scheduled only if event has not been signaled before).
*
* The template `Type` should support comparison operator `==` and assignment operator `=`.
@@ -273,18 +274,18 @@
* @param[in] aNewValue The new value.
* @param[in] aEvent The event to signal.
*
- * @retval OT_ERROR_NONE The variable was update successfully and @p aEvent was signaled.
- * @retval OT_ERROR_ALREADY The variable was already set to the same value.
+ * @retval kErrorNone The variable was update successfully and @p aEvent was signaled.
+ * @retval kErrorAlready The variable was already set to the same value.
*
*/
- template <typename Type> otError Update(Type &aVariable, const Type &aNewValue, Event aEvent)
+ template <typename Type> Error Update(Type &aVariable, const Type &aNewValue, Event aEvent)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aVariable == aNewValue)
{
SignalIfFirst(aEvent);
- error = OT_ERROR_ALREADY;
+ error = kErrorAlready;
}
else
{
diff --git a/src/core/common/random.hpp b/src/core/common/random.hpp
index 3ddc1af..78deef3 100644
--- a/src/core/common/random.hpp
+++ b/src/core/common/random.hpp
@@ -38,9 +38,8 @@
#include <stdint.h>
-#include <openthread/error.h>
-
#include "common/debug.hpp"
+#include "common/error.hpp"
#include "common/random_manager.hpp"
namespace ot {
@@ -170,10 +169,10 @@
* @param[out] aBuffer A pointer to a buffer to fill with the random bytes.
* @param[in] aSize Size of buffer (number of bytes to fill).
*
- * @retval OT_ERROR_NONE Successfully filled buffer with random values.
+ * @retval kErrorNone Successfully filled buffer with random values.
*
*/
-inline otError FillBuffer(uint8_t *aBuffer, uint16_t aSize)
+inline Error FillBuffer(uint8_t *aBuffer, uint16_t aSize)
{
return RandomManager::CryptoFillBuffer(aBuffer, aSize);
}
diff --git a/src/core/common/random_manager.cpp b/src/core/common/random_manager.cpp
index de7977e..4c320c3 100644
--- a/src/core/common/random_manager.cpp
+++ b/src/core/common/random_manager.cpp
@@ -41,6 +41,7 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
+#include "common/logging.hpp"
#include "common/random.hpp"
#include "crypto/mbedtls.hpp"
@@ -57,7 +58,7 @@
RandomManager::RandomManager(void)
{
uint32_t seed;
- otError error;
+ Error error;
OT_UNUSED_VARIABLE(error);
@@ -70,10 +71,10 @@
sCtrDrbg.Init();
error = Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&seed), sizeof(seed));
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
#else
error = otPlatEntropyGet(reinterpret_cast<uint8_t *>(&seed), sizeof(seed));
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
#endif
sPrng.Init(seed);
@@ -190,8 +191,19 @@
void RandomManager::CryptoCtrDrbg::Init(void)
{
+ int rval;
+
mbedtls_ctr_drbg_init(&mCtrDrbg);
- mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, RandomManager::GetMbedTlsEntropyContext(), nullptr, 0);
+
+ rval =
+ mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, RandomManager::GetMbedTlsEntropyContext(), nullptr, 0);
+
+ if (rval != 0)
+ {
+ otLogCritMbedTls("Failed to seed the CTR DRBG");
+ }
+
+ OT_ASSERT(rval == 0);
}
void RandomManager::CryptoCtrDrbg::Deinit(void)
@@ -199,7 +211,7 @@
mbedtls_ctr_drbg_free(&mCtrDrbg);
}
-otError RandomManager::CryptoCtrDrbg::FillBuffer(uint8_t *aBuffer, uint16_t aSize)
+Error RandomManager::CryptoCtrDrbg::FillBuffer(uint8_t *aBuffer, uint16_t aSize)
{
return ot::Crypto::MbedTls::MapError(
mbedtls_ctr_drbg_random(&mCtrDrbg, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
diff --git a/src/core/common/random_manager.hpp b/src/core/common/random_manager.hpp
index 7106033..b898575 100644
--- a/src/core/common/random_manager.hpp
+++ b/src/core/common/random_manager.hpp
@@ -37,13 +37,13 @@
#include "openthread-core-config.h"
#include <stdint.h>
-#include <openthread/error.h>
#if !OPENTHREAD_RADIO
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#endif
+#include "common/error.hpp"
#include "common/non_copyable.hpp"
#if (!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) && \
@@ -94,10 +94,10 @@
* @param[out] aBuffer A pointer to a buffer to fill with the random bytes.
* @param[in] aSize Size of buffer (number of bytes to fill).
*
- * @retval OT_ERROR_NONE Successfully filled buffer with random values.
+ * @retval kErrorNone Successfully filled buffer with random values.
*
*/
- static otError CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return sCtrDrbg.FillBuffer(aBuffer, aSize); }
+ static Error CryptoFillBuffer(uint8_t *aBuffer, uint16_t aSize) { return sCtrDrbg.FillBuffer(aBuffer, aSize); }
/**
* This static method returns the initialized mbedtls_ctr_drbg_context.
@@ -139,9 +139,9 @@
class CryptoCtrDrbg
{
public:
- void Init(void);
- void Deinit(void);
- otError FillBuffer(uint8_t *aBuffer, uint16_t aSize);
+ void Init(void);
+ void Deinit(void);
+ Error FillBuffer(uint8_t *aBuffer, uint16_t aSize);
mbedtls_ctr_drbg_context *GetContext(void) { return &mCtrDrbg; }
diff --git a/src/core/common/settings.cpp b/src/core/common/settings.cpp
index 44491d8..70cd799 100644
--- a/src/core/common/settings.cpp
+++ b/src/core/common/settings.cpp
@@ -43,6 +43,9 @@
#include "thread/mle.hpp"
namespace ot {
+// This array contains critical keys that should be stored in the secure area.
+static const uint16_t kCriticalKeys[] = {SettingsBase::kKeyActiveDataset, SettingsBase::kKeyPendingDataset,
+ SettingsBase::kKeySrpEcdsaKey};
// LCOV_EXCL_START
@@ -81,16 +84,22 @@
otLogInfoCore("Non-volatile: %s DadInfo {DadCounter:%2d}", aAction, aDadInfo.GetDadCounter());
}
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+void SettingsBase::LogPrefix(const char *aAction, const char *aPrefixName, const Ip6::Prefix &aOmrPrefix) const
+{
+ otLogInfoCore("Non-volatile: %s %s %s", aAction, aPrefixName, aOmrPrefix.ToString().AsCString());
+}
+#endif
#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO)
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN)
-void SettingsBase::LogFailure(otError error, const char *aText, bool aIsDelete) const
+void SettingsBase::LogFailure(Error error, const char *aText, bool aIsDelete) const
{
- if ((error != OT_ERROR_NONE) && (!aIsDelete || (error != OT_ERROR_NOT_FOUND)))
+ if ((error != kErrorNone) && (!aIsDelete || (error != kErrorNotFound)))
{
- otLogWarnCore("Non-volatile: Error %s %s", otThreadErrorToString(error), aText);
+ otLogWarnCore("Non-volatile: Error %s %s", ErrorToString(error), aText);
}
}
@@ -116,22 +125,27 @@
otPlatSettingsDeinit(&GetInstance());
}
-otError SettingsDriver::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+void SettingsDriver::SetCriticalKeys(const uint16_t *aKeys, uint16_t aKeysLength)
+{
+ otPlatSettingsSetCriticalKeys(&GetInstance(), aKeys, aKeysLength);
+}
+
+Error SettingsDriver::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
return otPlatSettingsAdd(&GetInstance(), aKey, aValue, aValueLength);
}
-otError SettingsDriver::Delete(uint16_t aKey, int aIndex)
+Error SettingsDriver::Delete(uint16_t aKey, int aIndex)
{
return otPlatSettingsDelete(&GetInstance(), aKey, aIndex);
}
-otError SettingsDriver::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
+Error SettingsDriver::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
{
return otPlatSettingsGet(&GetInstance(), aKey, aIndex, aValue, aValueLength);
}
-otError SettingsDriver::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+Error SettingsDriver::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
return otPlatSettingsSet(&GetInstance(), aKey, aValue, aValueLength);
}
@@ -158,22 +172,28 @@
{
}
-otError SettingsDriver::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+void SettingsDriver::SetCriticalKeys(const uint16_t *aKeys, uint16_t aKeysLength)
+{
+ OT_UNUSED_VARIABLE(aKeys);
+ OT_UNUSED_VARIABLE(aKeysLength);
+}
+
+Error SettingsDriver::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
return mFlash.Add(aKey, aValue, aValueLength);
}
-otError SettingsDriver::Delete(uint16_t aKey, int aIndex)
+Error SettingsDriver::Delete(uint16_t aKey, int aIndex)
{
return mFlash.Delete(aKey, aIndex);
}
-otError SettingsDriver::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
+Error SettingsDriver::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
{
return mFlash.Get(aKey, aIndex, aValue, aValueLength);
}
-otError SettingsDriver::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+Error SettingsDriver::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
return mFlash.Set(aKey, aValue, aValueLength);
}
@@ -188,6 +208,7 @@
void Settings::Init(void)
{
Get<SettingsDriver>().Init();
+ Get<SettingsDriver>().SetCriticalKeys(kCriticalKeys, OT_ARRAY_LENGTH(kCriticalKeys));
}
void Settings::Deinit(void)
@@ -201,21 +222,21 @@
otLogInfoCore("Non-volatile: Wiped all info");
}
-otError Settings::SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset)
+Error Settings::SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset)
{
- otError error = Save(aIsActive ? kKeyActiveDataset : kKeyPendingDataset, aDataset.GetBytes(), aDataset.GetSize());
+ Error error = Save(aIsActive ? kKeyActiveDataset : kKeyPendingDataset, aDataset.GetBytes(), aDataset.GetSize());
LogFailure(error, "saving OperationalDataset", false);
return error;
}
-otError Settings::ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const
+Error Settings::ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t length = MeshCoP::Dataset::kMaxSize;
SuccessOrExit(error = Read(aIsActive ? kKeyActiveDataset : kKeyPendingDataset, aDataset.GetBytes(), length));
- VerifyOrExit(length <= MeshCoP::Dataset::kMaxSize, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(length <= MeshCoP::Dataset::kMaxSize, error = kErrorNotFound);
aDataset.SetSize(length);
@@ -223,18 +244,18 @@
return error;
}
-otError Settings::DeleteOperationalDataset(bool aIsActive)
+Error Settings::DeleteOperationalDataset(bool aIsActive)
{
- otError error = Delete(aIsActive ? kKeyActiveDataset : kKeyPendingDataset);
+ Error error = Delete(aIsActive ? kKeyActiveDataset : kKeyPendingDataset);
LogFailure(error, "deleting OperationalDataset", true);
return error;
}
-otError Settings::ReadNetworkInfo(NetworkInfo &aNetworkInfo) const
+Error Settings::ReadNetworkInfo(NetworkInfo &aNetworkInfo) const
{
- otError error;
+ Error error;
uint16_t length = sizeof(NetworkInfo);
aNetworkInfo.Init();
@@ -245,13 +266,13 @@
return error;
}
-otError Settings::SaveNetworkInfo(const NetworkInfo &aNetworkInfo)
+Error Settings::SaveNetworkInfo(const NetworkInfo &aNetworkInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetworkInfo prevNetworkInfo;
uint16_t length = sizeof(prevNetworkInfo);
- if ((Read(kKeyNetworkInfo, &prevNetworkInfo, length) == OT_ERROR_NONE) && (length == sizeof(NetworkInfo)) &&
+ if ((Read(kKeyNetworkInfo, &prevNetworkInfo, length) == kErrorNone) && (length == sizeof(NetworkInfo)) &&
(prevNetworkInfo == aNetworkInfo))
{
LogNetworkInfo("Re-saved", aNetworkInfo);
@@ -266,9 +287,9 @@
return error;
}
-otError Settings::DeleteNetworkInfo(void)
+Error Settings::DeleteNetworkInfo(void)
{
- otError error;
+ Error error;
SuccessOrExit(error = Delete(kKeyNetworkInfo));
otLogInfoCore("Non-volatile: Deleted NetworkInfo");
@@ -278,9 +299,9 @@
return error;
}
-otError Settings::ReadParentInfo(ParentInfo &aParentInfo) const
+Error Settings::ReadParentInfo(ParentInfo &aParentInfo) const
{
- otError error;
+ Error error;
uint16_t length = sizeof(ParentInfo);
aParentInfo.Init();
@@ -291,13 +312,13 @@
return error;
}
-otError Settings::SaveParentInfo(const ParentInfo &aParentInfo)
+Error Settings::SaveParentInfo(const ParentInfo &aParentInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ParentInfo prevParentInfo;
uint16_t length = sizeof(ParentInfo);
- if ((Read(kKeyParentInfo, &prevParentInfo, length) == OT_ERROR_NONE) && (length == sizeof(ParentInfo)) &&
+ if ((Read(kKeyParentInfo, &prevParentInfo, length) == kErrorNone) && (length == sizeof(ParentInfo)) &&
(prevParentInfo == aParentInfo))
{
LogParentInfo("Re-saved", aParentInfo);
@@ -312,9 +333,9 @@
return error;
}
-otError Settings::DeleteParentInfo(void)
+Error Settings::DeleteParentInfo(void)
{
- otError error;
+ Error error;
SuccessOrExit(error = Delete(kKeyParentInfo));
otLogInfoCore("Non-volatile: Deleted ParentInfo");
@@ -324,9 +345,9 @@
return error;
}
-otError Settings::AddChildInfo(const ChildInfo &aChildInfo)
+Error Settings::AddChildInfo(const ChildInfo &aChildInfo)
{
- otError error;
+ Error error;
SuccessOrExit(error = Add(kKeyChildInfo, &aChildInfo, sizeof(aChildInfo)));
LogChildInfo("Added", aChildInfo);
@@ -336,9 +357,9 @@
return error;
}
-otError Settings::DeleteAllChildInfo(void)
+Error Settings::DeleteAllChildInfo(void)
{
- otError error;
+ Error error;
SuccessOrExit(error = Delete(kKeyChildInfo));
otLogInfoCore("Non-volatile: Deleted all ChildInfo");
@@ -365,11 +386,11 @@
}
}
-otError Settings::ChildInfoIterator::Delete(void)
+Error Settings::ChildInfoIterator::Delete(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!mIsDone, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!mIsDone, error = kErrorInvalidState);
SuccessOrExit(error = Get<SettingsDriver>().Delete(kKeyChildInfo, mIndex));
LogChildInfo("Removed", mChildInfo);
@@ -381,7 +402,7 @@
void Settings::ChildInfoIterator::Read(void)
{
uint16_t length = sizeof(ChildInfo);
- otError error;
+ Error error;
mChildInfo.Init();
SuccessOrExit(
@@ -389,13 +410,13 @@
LogChildInfo("Read", mChildInfo);
exit:
- mIsDone = (error != OT_ERROR_NONE);
+ mIsDone = (error != kErrorNone);
}
#if OPENTHREAD_CONFIG_DUA_ENABLE
-otError Settings::ReadDadInfo(DadInfo &aDadInfo) const
+Error Settings::ReadDadInfo(DadInfo &aDadInfo) const
{
- otError error;
+ Error error;
uint16_t length = sizeof(DadInfo);
aDadInfo.Init();
@@ -406,13 +427,13 @@
return error;
}
-otError Settings::SaveDadInfo(const DadInfo &aDadInfo)
+Error Settings::SaveDadInfo(const DadInfo &aDadInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
DadInfo prevDadInfo;
uint16_t length = sizeof(DadInfo);
- if ((Read(kKeyDadInfo, &prevDadInfo, length) == OT_ERROR_NONE) && (length == sizeof(DadInfo)) &&
+ if ((Read(kKeyDadInfo, &prevDadInfo, length) == kErrorNone) && (length == sizeof(DadInfo)) &&
(prevDadInfo == aDadInfo))
{
LogDadInfo("Re-saved", aDadInfo);
@@ -427,9 +448,9 @@
return error;
}
-otError Settings::DeleteDadInfo(void)
+Error Settings::DeleteDadInfo(void)
{
- otError error;
+ Error error;
SuccessOrExit(error = Delete(kKeyDadInfo));
otLogInfoCore("Non-volatile: Deleted DadInfo");
@@ -440,24 +461,146 @@
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
-otError Settings::Read(Key aKey, void *aBuffer, uint16_t &aSize) const
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+Error Settings::SaveOmrPrefix(const Ip6::Prefix &aOmrPrefix)
+{
+ Error error = kErrorNone;
+ Ip6::Prefix prevOmrPrefix;
+ uint16_t length = sizeof(prevOmrPrefix);
+
+ if ((Read(kKeyOmrPrefix, &prevOmrPrefix, length) == kErrorNone) && (length == sizeof(prevOmrPrefix)) &&
+ (prevOmrPrefix == aOmrPrefix))
+ {
+ LogPrefix("Re-saved", "OMR prefix", aOmrPrefix);
+ ExitNow();
+ }
+
+ SuccessOrExit(error = Save(kKeyOmrPrefix, &aOmrPrefix, sizeof(aOmrPrefix)));
+ LogPrefix("Saved", "OMR prefix", aOmrPrefix);
+
+exit:
+ LogFailure(error, "saving OMR prefix", false);
+ return error;
+}
+
+Error Settings::ReadOmrPrefix(Ip6::Prefix &aOmrPrefix) const
+{
+ Error error;
+ uint16_t length = sizeof(aOmrPrefix);
+
+ aOmrPrefix.Clear();
+ SuccessOrExit(error = Read(kKeyOmrPrefix, &aOmrPrefix, length));
+ LogPrefix("Read", "OMR prefix", aOmrPrefix);
+
+exit:
+ return error;
+}
+
+Error Settings::SaveOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix)
+{
+ Error error = kErrorNone;
+ Ip6::Prefix prevOnLinkPrefix;
+ uint16_t length = sizeof(prevOnLinkPrefix);
+
+ if ((Read(kKeyOnLinkPrefix, &prevOnLinkPrefix, length) == kErrorNone) && (length == sizeof(prevOnLinkPrefix)) &&
+ (prevOnLinkPrefix == aOnLinkPrefix))
+ {
+ LogPrefix("Re-saved", "on-link prefix", aOnLinkPrefix);
+ ExitNow();
+ }
+
+ SuccessOrExit(error = Save(kKeyOnLinkPrefix, &aOnLinkPrefix, sizeof(aOnLinkPrefix)));
+ LogPrefix("Saved", "on-link prefix", aOnLinkPrefix);
+
+exit:
+ LogFailure(error, "saving on-link prefix", false);
+ return error;
+}
+
+Error Settings::ReadOnLinkPrefix(Ip6::Prefix &aOnLinkPrefix) const
+{
+ Error error;
+ uint16_t length = sizeof(aOnLinkPrefix);
+
+ aOnLinkPrefix.Clear();
+ SuccessOrExit(error = Read(kKeyOnLinkPrefix, &aOnLinkPrefix, length));
+ LogPrefix("Read", "on-link prefix", aOnLinkPrefix);
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+Error Settings::SaveSrpKey(const Crypto::Ecdsa::P256::KeyPair &aKeyPair)
+{
+ Error error = kErrorNone;
+
+ SuccessOrExit(error = Save(kKeySrpEcdsaKey, aKeyPair.GetDerBytes(), aKeyPair.GetDerLength()));
+ otLogInfoCore("Non-volatile: Saved SRP key");
+
+exit:
+ LogFailure(error, "saving SRP key", false);
+ return error;
+}
+
+Error Settings::ReadSrpKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair) const
+{
+ Error error;
+ uint16_t length = Crypto::Ecdsa::P256::KeyPair::kMaxDerSize;
+
+ SuccessOrExit(error = Read(kKeySrpEcdsaKey, aKeyPair.GetDerBytes(), length));
+ VerifyOrExit(length <= Crypto::Ecdsa::P256::KeyPair::kMaxDerSize, error = kErrorNotFound);
+ aKeyPair.SetDerLength(static_cast<uint8_t>(length));
+ otLogInfoCore("Non-volatile: Read SRP key");
+
+exit:
+ return error;
+}
+
+Error Settings::DeleteSrpKey(void)
+{
+ Error error;
+
+ SuccessOrExit(error = Delete(kKeySrpEcdsaKey));
+ otLogInfoCore("Non-volatile: Deleted SRP key");
+
+exit:
+ LogFailure(error, "deleting SRP key", true);
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+Error Settings::Read(Key aKey, void *aBuffer, uint16_t &aSize) const
{
return Get<SettingsDriver>().Get(aKey, 0, reinterpret_cast<uint8_t *>(aBuffer), &aSize);
}
-otError Settings::Save(Key aKey, const void *aValue, uint16_t aSize)
+Error Settings::Save(Key aKey, const void *aValue, uint16_t aSize)
{
return Get<SettingsDriver>().Set(aKey, reinterpret_cast<const uint8_t *>(aValue), aSize);
}
-otError Settings::Add(Key aKey, const void *aValue, uint16_t aSize)
+Error Settings::Add(Key aKey, const void *aValue, uint16_t aSize)
{
return Get<SettingsDriver>().Add(aKey, reinterpret_cast<const uint8_t *>(aValue), aSize);
}
-otError Settings::Delete(Key aKey)
+Error Settings::Delete(Key aKey)
{
return Get<SettingsDriver>().Delete(aKey, -1);
}
} // namespace ot
+
+//---------------------------------------------------------------------------------------------------------------------
+// Default/weak implementation of settings platform APIs
+
+OT_TOOL_WEAK void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aKeys);
+ OT_UNUSED_VARIABLE(aKeysLength);
+}
diff --git a/src/core/common/settings.hpp b/src/core/common/settings.hpp
index 2fe11c4..929fef4 100644
--- a/src/core/common/settings.hpp
+++ b/src/core/common/settings.hpp
@@ -36,6 +36,8 @@
#include "openthread-core-config.h"
+#include <openthread/platform/settings.h>
+
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
@@ -47,6 +49,9 @@
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
#include "utils/slaac_address.hpp"
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+#include "crypto/ecdsa.hpp"
+#endif
namespace ot {
@@ -75,6 +80,15 @@
void Deinit(void);
/**
+ * This method sets the critical keys that should be stored in a secure area.
+ *
+ * @param[in] aKeys A pointer to an array containing the list of critical keys.
+ * @param[in] aKeysLength The number of entries in the @p aKeys array.
+ *
+ */
+ void SetCriticalKeys(const uint16_t *aKeys, uint16_t aKeysLength);
+
+ /**
* This method adds a value to @p aKey.
*
* @param[in] aKey The key associated with the value.
@@ -82,11 +96,11 @@
* MUST NOT be nullptr if @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by @p aValue. May be zero.
*
- * @retval OT_ERROR_NONE The value was added.
- * @retval OT_ERROR_NO_BUFS Not enough space to store the value.
+ * @retval kErrorNone The value was added.
+ * @retval kErrorNoBufs Not enough space to store the value.
*
*/
- otError Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+ Error Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/**
* This method removes a value from @p aKey.
@@ -95,11 +109,11 @@
* @param[in] aIndex The index of the value to be removed.
* If set to -1, all values for @p aKey will be removed.
*
- * @retval OT_ERROR_NONE The given key and index was found and removed successfully.
- * @retval OT_ERROR_NOT_FOUND The given key or index was not found.
+ * @retval kErrorNone The given key and index was found and removed successfully.
+ * @retval kErrorNotFound The given key or index was not found.
*
*/
- otError Delete(uint16_t aKey, int aIndex);
+ Error Delete(uint16_t aKey, int aIndex);
/**
* This method fetches the value identified by @p aKey.
@@ -114,11 +128,11 @@
* At return, the actual length of the setting is written.
* May be nullptr if performing a presence check.
*
- * @retval OT_ERROR_NONE The value was fetched successfully.
- * @retval OT_ERROR_NOT_FOUND The key was not found.
+ * @retval kErrorNone The value was fetched successfully.
+ * @retval kErrorNotFound The key was not found.
*
*/
- otError Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const;
+ Error Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const;
/**
* This method sets or replaces the value identified by @p aKey.
@@ -131,11 +145,11 @@
* MUST NOT be nullptr if @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by @p aValue. May be zero.
*
- * @retval OT_ERROR_NONE The value was changed.
- * @retval OT_ERROR_NO_BUFS Not enough space to store the value.
+ * @retval kErrorNone The value was changed.
+ * @retval kErrorNoBufs Not enough space to store the value.
*
*/
- otError Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+ Error Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/**
* This method remves all values.
@@ -581,14 +595,17 @@
*/
enum Key
{
- kKeyActiveDataset = 0x0001, ///< Active Operational Dataset
- kKeyPendingDataset = 0x0002, ///< Pending Operational Dataset
- kKeyNetworkInfo = 0x0003, ///< Thread network information
- kKeyParentInfo = 0x0004, ///< Parent information
- kKeyChildInfo = 0x0005, ///< Child information
- kKeyReserved = 0x0006, ///< Reserved (previously auto-start)
- kKeySlaacIidSecretKey = 0x0007, ///< Secret key used by SLAAC module for generating semantically opaque IID
- kKeyDadInfo = 0x0008, ///< Duplicate Address Detection (DAD) information.
+ kKeyActiveDataset = OT_SETTINGS_KEY_ACTIVE_DATASET,
+ kKeyPendingDataset = OT_SETTINGS_KEY_PENDING_DATASET,
+ kKeyNetworkInfo = OT_SETTINGS_KEY_NETWORK_INFO,
+ kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO,
+ kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO,
+ kKeyReserved = OT_SETTINGS_KEY_RESERVED,
+ kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
+ kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
+ kKeyOmrPrefix = OT_SETTINGS_KEY_OMR_PREFIX,
+ kKeyOnLinkPrefix = OT_SETTINGS_KEY_ON_LINK_PREFIX,
+ kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
};
protected:
@@ -604,6 +621,9 @@
#if OPENTHREAD_CONFIG_DUA_ENABLE
void LogDadInfo(const char *aAction, const DadInfo &aDadInfo) const;
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ void LogPrefix(const char *aAction, const char *aPrefixName, const Ip6::Prefix &aOmrPrefix) const;
+#endif
#else // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_UTIL != 0)
void LogNetworkInfo(const char *, const NetworkInfo &) const {}
void LogParentInfo(const char *, const ParentInfo &) const {}
@@ -611,12 +631,15 @@
#if OPENTHREAD_CONFIG_DUA_ENABLE
void LogDadInfo(const char *, const DadInfo &) const {}
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ void LogPrefix(const char *, const char *, const Ip6::Prefix &) const {}
+#endif
#endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_UTIL != 0)
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_UTIL != 0)
- void LogFailure(otError aError, const char *aAction, bool aIsDelete) const;
+ void LogFailure(Error aError, const char *aAction, bool aIsDelete) const;
#else
- void LogFailure(otError, const char *, bool) const {}
+ void LogFailure(Error, const char *, bool) const {}
#endif
};
@@ -668,11 +691,11 @@
* @param[in] aIsActive Indicates whether Dataset is active or pending.
* @param[in] aDataset A reference to a `Dataset` object to be saved.
*
- * @retval OT_ERROR_NONE Successfully saved the Dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the Dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset);
+ Error SaveOperationalDataset(bool aIsActive, const MeshCoP::Dataset &aDataset);
/**
* This method reads the Operational Dataset (active or pending).
@@ -680,87 +703,87 @@
* @param[in] aIsActive Indicates whether Dataset is active or pending.
* @param[out] aDataset A reference to a `Dataset` object to output the read content.
*
- * @retval OT_ERROR_NONE Successfully read the Dataset.
- * @retval OT_ERROR_NOT_FOUND No corresponding value in the setting store.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully read the Dataset.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const;
+ Error ReadOperationalDataset(bool aIsActive, MeshCoP::Dataset &aDataset) const;
/**
* This method deletes the Operational Dataset (active/pending) from settings.
*
* @param[in] aIsActive Indicates whether Dataset is active or pending.
*
- * @retval OT_ERROR_NONE Successfully deleted the Dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the Dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteOperationalDataset(bool aIsActive);
+ Error DeleteOperationalDataset(bool aIsActive);
/**
* This method saves Network Info.
*
* @param[in] aNetworkInfo A reference to a `NetworkInfo` structure to be saved.
*
- * @retval OT_ERROR_NONE Successfully saved Network Info in settings.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved Network Info in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError SaveNetworkInfo(const NetworkInfo &aNetworkInfo);
+ Error SaveNetworkInfo(const NetworkInfo &aNetworkInfo);
/**
* This method reads Network Info.
*
* @param[out] aNetworkInfo A reference to a `NetworkInfo` structure to output the read content.
*
- * @retval OT_ERROR_NONE Successfully read the Network Info.
- * @retval OT_ERROR_NOT_FOUND No corresponding value in the setting store.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully read the Network Info.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError ReadNetworkInfo(NetworkInfo &aNetworkInfo) const;
+ Error ReadNetworkInfo(NetworkInfo &aNetworkInfo) const;
/**
* This method deletes Network Info from settings.
*
- * @retval OT_ERROR_NONE Successfully deleted the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteNetworkInfo(void);
+ Error DeleteNetworkInfo(void);
/**
* This method saves Parent Info.
*
* @param[in] aParentInfo A reference to a `ParentInfo` structure to be saved.
*
- * @retval OT_ERROR_NONE Successfully saved Parent Info in settings.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved Parent Info in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError SaveParentInfo(const ParentInfo &aParentInfo);
+ Error SaveParentInfo(const ParentInfo &aParentInfo);
/**
* This method reads Parent Info.
*
* @param[out] aParentInfo A reference to a `ParentInfo` structure to output the read content.
*
- * @retval OT_ERROR_NONE Successfully read the Parent Info.
- * @retval OT_ERROR_NOT_FOUND No corresponding value in the setting store.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully read the Parent Info.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError ReadParentInfo(ParentInfo &aParentInfo) const;
+ Error ReadParentInfo(ParentInfo &aParentInfo) const;
/**
* This method deletes Parent Info from settings.
*
- * @retval OT_ERROR_NONE Successfully deleted the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteParentInfo(void);
+ Error DeleteParentInfo(void);
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
@@ -769,11 +792,11 @@
*
* @param[in] aKey The SLAAC IID secret key.
*
- * @retval OT_ERROR_NONE Successfully saved the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError SaveSlaacIidSecretKey(const Utils::Slaac::IidSecretKey &aKey)
+ Error SaveSlaacIidSecretKey(const Utils::Slaac::IidSecretKey &aKey)
{
return Save(kKeySlaacIidSecretKey, &aKey, sizeof(Utils::Slaac::IidSecretKey));
}
@@ -783,12 +806,12 @@
*
* @param[out] aKey A reference to a SLAAC IID secret key to output the read value.
*
- * @retval OT_ERROR_NONE Successfully read the value.
- * @retval OT_ERROR_NOT_FOUND No corresponding value in the setting store.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully read the value.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError ReadSlaacIidSecretKey(Utils::Slaac::IidSecretKey &aKey)
+ Error ReadSlaacIidSecretKey(Utils::Slaac::IidSecretKey &aKey)
{
uint16_t length = sizeof(aKey);
@@ -798,11 +821,11 @@
/**
* This method deletes the SLAAC IID secret key value from settings.
*
- * @retval OT_ERROR_NONE Successfully deleted the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteSlaacIidSecretKey(void) { return Delete(kKeySlaacIidSecretKey); }
+ Error DeleteSlaacIidSecretKey(void) { return Delete(kKeySlaacIidSecretKey); }
#endif // OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
@@ -813,22 +836,22 @@
*
* @param[in] aChildInfo A reference to a `ChildInfo` structure to be saved/added.
*
- * @retval OT_ERROR_NONE Successfully saved the Child Info in settings.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the Child Info in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError AddChildInfo(const ChildInfo &aChildInfo);
+ Error AddChildInfo(const ChildInfo &aChildInfo);
/**
* This method deletes all Child Info entries from the settings.
*
* @note Child Info is a list-based settings property and can contain multiple entries.
*
- * @retval OT_ERROR_NONE Successfully deleted the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteAllChildInfo(void);
+ Error DeleteAllChildInfo(void);
/**
* This method enables range-based `for` loop iteration over all child info entries in the `Settings`.
@@ -847,7 +870,7 @@
* This class defines an iterator to access all Child Info entries in the settings.
*
*/
- class ChildInfoIterator : public SettingsBase
+ class ChildInfoIterator : public SettingsBase, public Unequatable<ChildInfoIterator>
{
friend class ChildInfoIteratorBuilder;
@@ -898,12 +921,12 @@
/**
* This method deletes the current Child Info entry.
*
- * @retval OT_ERROR_NONE The entry was deleted successfully.
- * @retval OT_ERROR_INVALID_STATE The entry is not valid (iterator has reached end of list).
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone The entry was deleted successfully.
+ * @retval kErrorInvalidState The entry is not valid (iterator has reached end of list).
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Delete(void);
+ Error Delete(void);
/**
* This method overloads the `*` dereference operator and gets a reference to `ChildInfo` entry to which the
@@ -932,17 +955,6 @@
return (mIsDone && aOther.mIsDone) || (!mIsDone && !aOther.mIsDone && (mIndex == aOther.mIndex));
}
- /**
- * This method overloads operator `!=` to evaluate whether or not two iterator instances are unequal.
- *
- * @param[in] aOther The other iterator to compare with.
- *
- * @retval TRUE If the two iterator objects are unequal.
- * @retval FALSE If the two iterator objects are not unequal.
- *
- */
- bool operator!=(const ChildInfoIterator &aOther) const { return !(*this == aOther); }
-
private:
enum IteratorType
{
@@ -971,35 +983,117 @@
*
* @param[in] aDadInfo A reference to a `DadInfo` structure to be saved.
*
- * @retval OT_ERROR_NONE Successfully saved duplicate address detection information in settings.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved duplicate address detection information in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError SaveDadInfo(const DadInfo &aDadInfo);
+ Error SaveDadInfo(const DadInfo &aDadInfo);
/**
* This method reads duplicate address detection information.
*
* @param[out] aDadInfo A reference to a `DadInfo` structure to output the read content.
*
- * @retval OT_ERROR_NONE Successfully read the duplicate address detection information.
- * @retval OT_ERROR_NOT_FOUND No corresponding value in the setting store.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully read the duplicate address detection information.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError ReadDadInfo(DadInfo &aDadInfo) const;
+ Error ReadDadInfo(DadInfo &aDadInfo) const;
/**
* This method deletes duplicate address detection information from settings.
*
- * @retval OT_ERROR_NONE Successfully deleted the value.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError DeleteDadInfo(void);
+ Error DeleteDadInfo(void);
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ /**
+ * This method saves OMR prefix.
+ *
+ * @param[in] aOmrPrefix An OMR prefix to be saved.
+ *
+ * @retval kErrorNone Successfully saved the OMR prefix in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error SaveOmrPrefix(const Ip6::Prefix &aOmrPrefix);
+
+ /**
+ * This method reads OMR prefix.
+ *
+ * @param[out] aOmrPrefix A reference to a `Ip6::Prefix` structure to output the OMR prefix.
+ *
+ * @retval kErrorNone Successfully read the OMR prefix.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error ReadOmrPrefix(Ip6::Prefix &aOmrPrefix) const;
+
+ /**
+ * This method saves on-link prefix.
+ *
+ * @param[in] aOnLinkPrefix An on-link prefix to be saved.
+ *
+ * @retval kErrorNone Successfully saved the on-link prefix in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error SaveOnLinkPrefix(const Ip6::Prefix &aOnLinkPrefix);
+
+ /**
+ * This method reads on-link prefix.
+ *
+ * @param[out] aOnLinkPrefix A reference to a `Ip6::Prefix` structure to output the on-link prefix.
+ *
+ * @retval kErrorNone Successfully read the on-link prefix.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error ReadOnLinkPrefix(Ip6::Prefix &aOnLinkPrefix) const;
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ /**
+ * This method saves SRP client ECDSA key pair.
+ *
+ * @param[in] aKeyPair A reference to an SRP ECDSA key-pair to save.
+ *
+ * @retval kErrorNone Successfully saved key-pair information in settings.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error SaveSrpKey(const Crypto::Ecdsa::P256::KeyPair &aKeyPair);
+
+ /**
+ * This method reads SRP client ECDSA key pair.
+ *
+ * @param[out] aKeyPair A reference to a ECDA `KeyPair` to output the read content.
+ *
+ * @retval kErrorNone Successfully read key-pair information.
+ * @retval kErrorNotFound No corresponding value in the setting store.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error ReadSrpKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair) const;
+
+ /**
+ * This method deletes SRP client ECDSA key pair from settings.
+ *
+ * @retval kErrorNone Successfully deleted the value.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
+ *
+ */
+ Error DeleteSrpKey(void);
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
private:
class ChildInfoIteratorBuilder : public InstanceLocator
{
@@ -1013,10 +1107,10 @@
ChildInfoIterator end(void) { return ChildInfoIterator(GetInstance(), ChildInfoIterator::kEndIterator); }
};
- otError Read(Key aKey, void *aBuffer, uint16_t &aSize) const;
- otError Save(Key aKey, const void *aValue, uint16_t aSize);
- otError Add(Key aKey, const void *aValue, uint16_t aSize);
- otError Delete(Key aKey);
+ Error Read(Key aKey, void *aBuffer, uint16_t &aSize) const;
+ Error Save(Key aKey, const void *aValue, uint16_t aSize);
+ Error Add(Key aKey, const void *aValue, uint16_t aSize);
+ Error Delete(Key aKey);
};
} // namespace ot
diff --git a/src/core/common/string.cpp b/src/core/common/string.cpp
index cba642b..150016b 100644
--- a/src/core/common/string.cpp
+++ b/src/core/common/string.cpp
@@ -65,10 +65,10 @@
return ret;
}
-otError StringBase::Write(char *aBuffer, uint16_t aSize, uint16_t &aLength, const char *aFormat, va_list aArgs)
+Error StringBase::Write(char *aBuffer, uint16_t aSize, uint16_t &aLength, const char *aFormat, va_list aArgs)
{
- otError error = OT_ERROR_NONE;
- int len;
+ Error error = kErrorNone;
+ int len;
len = vsnprintf(aBuffer + aLength, aSize - aLength, aFormat, aArgs);
@@ -76,12 +76,12 @@
{
aLength = 0;
aBuffer[0] = 0;
- error = OT_ERROR_INVALID_ARGS;
+ error = kErrorInvalidArgs;
}
else if (len >= aSize - aLength)
{
aLength = aSize - 1;
- error = OT_ERROR_NO_BUFS;
+ error = kErrorNoBufs;
}
else
{
diff --git a/src/core/common/string.hpp b/src/core/common/string.hpp
index 934b501..c837ca9 100644
--- a/src/core/common/string.hpp
+++ b/src/core/common/string.hpp
@@ -40,9 +40,8 @@
#include <stdint.h>
#include <stdio.h>
-#include <openthread/error.h>
-
#include "common/code_utils.hpp"
+#include "common/error.hpp"
namespace ot {
@@ -95,11 +94,11 @@
* @param[in] aFormat A pointer to the format string.
* @param[in] aArgs Arguments for the format specification.
*
- * @retval OT_ERROR_NONE Updated the string successfully.
- * @retval OT_ERROR_NO_BUFS String could not fit in the storage.
- * @retval OT_ERROR_INVALID_ARGS Arguments do not match the format string.
+ * @retval kErrorNone Updated the string successfully.
+ * @retval kErrorNoBufs String could not fit in the storage.
+ * @retval kErrorInvalidArgs Arguments do not match the format string.
*/
- static otError Write(char *aBuffer, uint16_t aSize, uint16_t &aLength, const char *aFormat, va_list aArgs);
+ static Error Write(char *aBuffer, uint16_t aSize, uint16_t &aLength, const char *aFormat, va_list aArgs);
};
/**
@@ -182,15 +181,15 @@
* @param[in] aFormat A pointer to the format string.
* @param[in] ... Arguments for the format specification.
*
- * @retval OT_ERROR_NONE Updated the string successfully.
- * @retval OT_ERROR_NO_BUFS String could not fit in the storage.
- * @retval OT_ERROR_INVALID_ARGS Arguments do not match the format string.
+ * @retval kErrorNone Updated the string successfully.
+ * @retval kErrorNoBufs String could not fit in the storage.
+ * @retval kErrorInvalidArgs Arguments do not match the format string.
*
*/
- otError Set(const char *aFormat, ...)
+ Error Set(const char *aFormat, ...)
{
va_list args;
- otError error;
+ Error error;
va_start(args, aFormat);
mLength = 0;
@@ -206,15 +205,15 @@
* @param[in] aFormat A pointer to the format string.
* @param[in] ... Arguments for the format specification.
*
- * @retval OT_ERROR_NONE Updated the string successfully.
- * @retval OT_ERROR_NO_BUFS String could not fit in the storage.
- * @retval OT_ERROR_INVALID_ARGS Arguments do not match the format string.
+ * @retval kErrorNone Updated the string successfully.
+ * @retval kErrorNoBufs String could not fit in the storage.
+ * @retval kErrorInvalidArgs Arguments do not match the format string.
*
*/
- otError Append(const char *aFormat, ...)
+ Error Append(const char *aFormat, ...)
{
va_list args;
- otError error;
+ Error error;
va_start(args, aFormat);
error = Write(mBuffer, kSize, mLength, aFormat, args);
@@ -229,12 +228,12 @@
* @param[in] aFormat A pointer to the format string.
* @param[in] aArgs Arguments for the format specification (as `va_list`).
*
- * @retval OT_ERROR_NONE Updated the string successfully.
- * @retval OT_ERROR_NO_BUFS String could not fit in the storage.
- * @retval OT_ERROR_INVALID_ARGS Arguments do not match the format string.
+ * @retval kErrorNone Updated the string successfully.
+ * @retval kErrorNoBufs String could not fit in the storage.
+ * @retval kErrorInvalidArgs Arguments do not match the format string.
*
*/
- otError AppendVarArgs(const char *aFormat, va_list aArgs) { return Write(mBuffer, kSize, mLength, aFormat, aArgs); }
+ Error AppendVarArgs(const char *aFormat, va_list aArgs) { return Write(mBuffer, kSize, mLength, aFormat, aArgs); }
/**
* This method appends an array of bytes in hex representation (using "%02x" style) to the `String` object.
@@ -242,13 +241,13 @@
* @param[in] aBytes A pointer to buffer containing the bytes to append.
* @param[in] aLength The length of @p aBytes buffer (in bytes).
*
- * @retval OT_ERROR_NONE Updated the string successfully.
- * @retval OT_ERROR_NO_BUFS String could not fit in the storage.
+ * @retval kErrorNone Updated the string successfully.
+ * @retval kErrorNoBufs String could not fit in the storage.
*
*/
- otError AppendHexBytes(const uint8_t *aBytes, uint16_t aLength)
+ Error AppendHexBytes(const uint8_t *aBytes, uint16_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
while (aLength--)
{
diff --git a/src/core/common/tasklet.cpp b/src/core/common/tasklet.cpp
index de8bab9..68ff27e 100644
--- a/src/core/common/tasklet.cpp
+++ b/src/core/common/tasklet.cpp
@@ -41,9 +41,8 @@
namespace ot {
-Tasklet::Tasklet(Instance &aInstance, Handler aHandler, void *aOwner)
+Tasklet::Tasklet(Instance &aInstance, Handler aHandler)
: InstanceLocator(aInstance)
- , OwnerLocator(aOwner)
, mHandler(aHandler)
, mNext(nullptr)
{
diff --git a/src/core/common/tasklet.hpp b/src/core/common/tasklet.hpp
index 198858c..9d9b9e5 100644
--- a/src/core/common/tasklet.hpp
+++ b/src/core/common/tasklet.hpp
@@ -61,7 +61,7 @@
* This class is used to represent a tasklet.
*
*/
-class Tasklet : public InstanceLocator, public OwnerLocator
+class Tasklet : public InstanceLocator
{
friend class TaskletScheduler;
@@ -79,10 +79,9 @@
*
* @param[in] aInstance A reference to the OpenThread instance object.
* @param[in] aHandler A pointer to a function that is called when the tasklet is run.
- * @param[in] aOwner A pointer to owner of this `Tasklet` object.
*
*/
- Tasklet(Instance &aInstance, Handler aHandler, void *aOwner);
+ Tasklet(Instance &aInstance, Handler aHandler);
/**
* This method puts the tasklet on the tasklet scheduler run queue.
@@ -129,7 +128,7 @@
*
*/
TaskletContext(Instance &aInstance, Handler aHandler, void *aContext)
- : Tasklet(aInstance, aHandler, aContext)
+ : Tasklet(aInstance, aHandler)
, mContext(aContext)
{
}
diff --git a/src/core/common/time.hpp b/src/core/common/time.hpp
index 2f63e61..98c299b 100644
--- a/src/core/common/time.hpp
+++ b/src/core/common/time.hpp
@@ -39,6 +39,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "common/equatable.hpp"
+
namespace ot {
/**
@@ -55,7 +57,7 @@
* This class represents a time instance.
*
*/
-class Time
+class Time : public Unequatable<Time>
{
public:
/**
@@ -157,17 +159,6 @@
bool operator==(const Time &aOther) const { return mValue == aOther.mValue; }
/**
- * This method indicates whether two `Time` instance are not equal.
- *
- * @param[in] aOther A `Time` instance to compare with.
- *
- * @retval TRUE The two `Time` instances are not equal.
- * @retval FALSE The two `Time` instances are equal.
- *
- */
- bool operator!=(const Time &aOther) const { return !(*this == aOther); }
-
- /**
* This method indicates whether this `Time` instance is strictly before another one.
*
* @note The comparison operators correctly take into account the wrapping of `Time` numeric value. For a given
diff --git a/src/core/common/time_ticker.cpp b/src/core/common/time_ticker.cpp
index 10461d0..28834b9 100644
--- a/src/core/common/time_ticker.cpp
+++ b/src/core/common/time_ticker.cpp
@@ -45,7 +45,7 @@
TimeTicker::TimeTicker(Instance &aInstance)
: InstanceLocator(aInstance)
, mReceivers(0)
- , mTimer(aInstance, HandleTimer, this)
+ , mTimer(aInstance, HandleTimer)
{
}
@@ -71,7 +71,7 @@
void TimeTicker::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<TimeTicker>().HandleTimer();
+ aTimer.Get<TimeTicker>().HandleTimer();
}
void TimeTicker::HandleTimer(void)
diff --git a/src/core/common/timer.hpp b/src/core/common/timer.hpp
index 751eff1..7158fb1 100644
--- a/src/core/common/timer.hpp
+++ b/src/core/common/timer.hpp
@@ -67,7 +67,7 @@
* This class implements a timer.
*
*/
-class Timer : public InstanceLocator, public OwnerLocator, public LinkedListEntry<Timer>
+class Timer : public InstanceLocator, public LinkedListEntry<Timer>
{
friend class TimerScheduler;
friend class LinkedListEntry<Timer>;
@@ -92,12 +92,10 @@
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aHandler A pointer to a function that is called when the timer expires.
- * @param[in] aOwner A pointer to owner of the `Timer` object.
*
*/
- Timer(Instance &aInstance, Handler aHandler, void *aOwner)
+ Timer(Instance &aInstance, Handler aHandler)
: InstanceLocator(aInstance)
- , OwnerLocator(aOwner)
, mHandler(aHandler)
, mFireTime()
, mNext(this)
@@ -153,11 +151,10 @@
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aHandler A pointer to a function that is called when the timer expires.
- * @param[in] aOwner A pointer to the owner of the `TimerMilli` object.
*
*/
- TimerMilli(Instance &aInstance, Handler aHandler, void *aOwner)
- : Timer(aInstance, aHandler, aOwner)
+ TimerMilli(Instance &aInstance, Handler aHandler)
+ : Timer(aInstance, aHandler)
{
}
@@ -231,7 +228,7 @@
*
*/
TimerMilliContext(Instance &aInstance, Handler aHandler, void *aContext)
- : TimerMilli(aInstance, aHandler, aContext)
+ : TimerMilli(aInstance, aHandler)
, mContext(aContext)
{
}
@@ -375,11 +372,10 @@
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aHandler A pointer to a function that is called when the timer expires.
- * @param[in] aOwner A pointer to owner of the `TimerMicro` object.
*
*/
- TimerMicro(Instance &aInstance, Handler aHandler, void *aOwner)
- : Timer(aInstance, aHandler, aOwner)
+ TimerMicro(Instance &aInstance, Handler aHandler)
+ : Timer(aInstance, aHandler)
{
}
diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp
index 46b3049..3b098e9 100644
--- a/src/core/common/tlvs.cpp
+++ b/src/core/common/tlvs.cpp
@@ -55,14 +55,14 @@
return reinterpret_cast<const uint8_t *>(this) + (IsExtended() ? sizeof(ExtendedTlv) : sizeof(Tlv));
}
-otError Tlv::AppendTo(Message &aMessage) const
+Error Tlv::AppendTo(Message &aMessage) const
{
return aMessage.AppendBytes(this, static_cast<uint16_t>(GetSize()));
}
-otError Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv)
+Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv)
{
- otError error;
+ Error error;
uint16_t offset;
uint16_t size;
@@ -79,14 +79,14 @@
return error;
}
-otError Tlv::FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset)
+Error Tlv::FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset)
{
return Find(aMessage, aType, &aOffset, nullptr, nullptr);
}
-otError Tlv::FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength)
+Error Tlv::FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength)
{
- otError error;
+ Error error;
uint16_t offset;
uint16_t size;
bool isExtendedTlv;
@@ -108,9 +108,9 @@
return error;
}
-otError Tlv::Find(const Message &aMessage, uint8_t aType, uint16_t *aOffset, uint16_t *aSize, bool *aIsExtendedTlv)
+Error Tlv::Find(const Message &aMessage, uint8_t aType, uint16_t *aOffset, uint16_t *aSize, bool *aIsExtendedTlv)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
uint16_t offset = aMessage.GetOffset();
uint16_t remainingLen = aMessage.GetLength();
Tlv tlv;
@@ -156,7 +156,7 @@
*aIsExtendedTlv = (tlv.mLength == kExtendedLength);
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
ExitNow();
}
@@ -168,9 +168,9 @@
return error;
}
-template <typename UintType> otError Tlv::ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue)
+template <typename UintType> Error Tlv::ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue)
{
- otError error;
+ Error error;
SuccessOrExit(error = ReadTlv(aMessage, aOffset, &aValue, sizeof(aValue)));
aValue = Encoding::BigEndian::HostSwap<UintType>(aValue);
@@ -180,18 +180,18 @@
}
// Explicit instantiations of `ReadUintTlv<>()`
-template otError Tlv::ReadUintTlv<uint8_t>(const Message &aMessage, uint16_t aOffset, uint8_t &aValue);
-template otError Tlv::ReadUintTlv<uint16_t>(const Message &aMessage, uint16_t aOffset, uint16_t &aValue);
-template otError Tlv::ReadUintTlv<uint32_t>(const Message &aMessage, uint16_t aOffset, uint32_t &aValue);
+template Error Tlv::ReadUintTlv<uint8_t>(const Message &aMessage, uint16_t aOffset, uint8_t &aValue);
+template Error Tlv::ReadUintTlv<uint16_t>(const Message &aMessage, uint16_t aOffset, uint16_t &aValue);
+template Error Tlv::ReadUintTlv<uint32_t>(const Message &aMessage, uint16_t aOffset, uint32_t &aValue);
-otError Tlv::ReadTlv(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength)
+Error Tlv::ReadTlv(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength)
{
- otError error = OT_ERROR_NONE;
- Tlv tlv;
+ Error error = kErrorNone;
+ Tlv tlv;
SuccessOrExit(error = aMessage.Read(aOffset, tlv));
- VerifyOrExit(!tlv.IsExtended() && (tlv.GetLength() >= aMinLength), error = OT_ERROR_PARSE);
- VerifyOrExit(tlv.GetSize() + aOffset <= aMessage.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(!tlv.IsExtended() && (tlv.GetLength() >= aMinLength), error = kErrorParse);
+ VerifyOrExit(tlv.GetSize() + aOffset <= aMessage.GetLength(), error = kErrorParse);
aMessage.ReadBytes(aOffset + sizeof(Tlv), aValue, aMinLength);
@@ -199,9 +199,9 @@
return error;
}
-template <typename UintType> otError Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue)
+template <typename UintType> Error Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t offset;
SuccessOrExit(error = FindTlvOffset(aMessage, aType, offset));
@@ -212,25 +212,25 @@
}
// Explicit instantiations of `FindUintTlv<>()`
-template otError Tlv::FindUintTlv<uint8_t>(const Message &aMessage, uint8_t aType, uint8_t &aValue);
-template otError Tlv::FindUintTlv<uint16_t>(const Message &aMessage, uint8_t aType, uint16_t &aValue);
-template otError Tlv::FindUintTlv<uint32_t>(const Message &aMessage, uint8_t aType, uint32_t &aValue);
+template Error Tlv::FindUintTlv<uint8_t>(const Message &aMessage, uint8_t aType, uint8_t &aValue);
+template Error Tlv::FindUintTlv<uint16_t>(const Message &aMessage, uint8_t aType, uint16_t &aValue);
+template Error Tlv::FindUintTlv<uint32_t>(const Message &aMessage, uint8_t aType, uint32_t &aValue);
-otError Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength)
+Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength)
{
- otError error;
+ Error error;
uint16_t offset;
uint16_t length;
SuccessOrExit(error = FindTlvValueOffset(aMessage, aType, offset, length));
- VerifyOrExit(length >= aLength, error = OT_ERROR_PARSE);
+ VerifyOrExit(length >= aLength, error = kErrorParse);
aMessage.ReadBytes(offset, aValue, aLength);
exit:
return error;
}
-template <typename UintType> otError Tlv::AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue)
+template <typename UintType> Error Tlv::AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue)
{
UintType value = Encoding::BigEndian::HostSwap<UintType>(aValue);
@@ -238,14 +238,14 @@
}
// Explicit instantiations of `AppendUintTlv<>()`
-template otError Tlv::AppendUintTlv<uint8_t>(Message &aMessage, uint8_t aType, uint8_t aValue);
-template otError Tlv::AppendUintTlv<uint16_t>(Message &aMessage, uint8_t aType, uint16_t aValue);
-template otError Tlv::AppendUintTlv<uint32_t>(Message &aMessage, uint8_t aType, uint32_t aValue);
+template Error Tlv::AppendUintTlv<uint8_t>(Message &aMessage, uint8_t aType, uint8_t aValue);
+template Error Tlv::AppendUintTlv<uint16_t>(Message &aMessage, uint8_t aType, uint16_t aValue);
+template Error Tlv::AppendUintTlv<uint32_t>(Message &aMessage, uint8_t aType, uint32_t aValue);
-otError Tlv::AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength)
+Error Tlv::AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
- Tlv tlv;
+ Error error = kErrorNone;
+ Tlv tlv;
OT_ASSERT(aLength <= Tlv::kBaseTlvMaxLength);
diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp
index b1941d4..7dfe150 100644
--- a/src/core/common/tlvs.hpp
+++ b/src/core/common/tlvs.hpp
@@ -36,11 +36,11 @@
#include "openthread-core-config.h"
-#include <openthread/error.h>
#include <openthread/thread.h>
#include <openthread/platform/toolchain.h>
#include "common/encoding.hpp"
+#include "common/error.hpp"
#include "common/type_traits.hpp"
namespace ot {
@@ -171,11 +171,11 @@
*
* @param[in] aMessage A reference to the message to append to.
*
- * @retval OT_ERROR_NONE Successfully appended the TLV to the message.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the TLV to the message.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- otError AppendTo(Message &aMessage) const;
+ Error AppendTo(Message &aMessage) const;
/**
* This static method reads a TLV in a message at a given offset expecting a minimum length for the value.
@@ -185,11 +185,11 @@
* @param[out] aValue A buffer to output the TLV's value, must contain (at least) @p aMinLength bytes.
* @param[in] aMinLength The minimum expected length of TLV and number of bytes to copy into @p aValue buffer.
*
- * @retval OT_ERROR_NONE Successfully read the TLV and copied @p aMinLength into @p aValue.
- * @retval OT_ERROR_PARSE The TLV was not well-formed and could not be parsed.
+ * @retval kErrorNone Successfully read the TLV and copied @p aMinLength into @p aValue.
+ * @retval kErrorParse The TLV was not well-formed and could not be parsed.
*
*/
- static otError ReadTlv(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength);
+ static Error ReadTlv(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength);
/**
* This static method reads a simple TLV with a single non-integral value in a message at a given offset.
@@ -200,12 +200,12 @@
* @param[in] aOffset The offset into the message pointing to the start of the TLV.
* @param[out] aValue A reference to the value object to output the read value.
*
- * @retval OT_ERROR_NONE Successfully read the TLV and updated the @p aValue.
- * @retval OT_ERROR_PARSE The TLV was not well-formed and could not be parsed.
+ * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
+ * @retval kErrorParse The TLV was not well-formed and could not be parsed.
*
*/
template <typename SimpleTlvType>
- static otError Read(const Message &aMessage, uint16_t aOffset, typename SimpleTlvType::ValueType &aValue)
+ static Error Read(const Message &aMessage, uint16_t aOffset, typename SimpleTlvType::ValueType &aValue)
{
return ReadTlv(aMessage, aOffset, &aValue, sizeof(aValue));
}
@@ -219,12 +219,12 @@
* @param[in] aOffset The offset into the message pointing to the start of the TLV.
* @param[out] aValue A reference to an unsigned int to output the read value.
*
- * @retval OT_ERROR_NONE Successfully read the TLV and updated the @p aValue.
- * @retval OT_ERROR_PARSE The TLV was not well-formed and could not be parsed.
+ * @retval kErrorNone Successfully read the TLV and updated the @p aValue.
+ * @retval kErrorParse The TLV was not well-formed and could not be parsed.
*
*/
template <typename UintTlvType>
- static otError Read(const Message &aMessage, uint16_t aOffset, typename UintTlvType::UintValueType &aValue)
+ static Error Read(const Message &aMessage, uint16_t aOffset, typename UintTlvType::UintValueType &aValue)
{
return ReadUintTlv(aMessage, aOffset, aValue);
}
@@ -239,11 +239,11 @@
* @param[in] aMaxSize Maximum number of bytes to read.
* @param[out] aTlv A reference to the TLV that will be copied to.
*
- * @retval OT_ERROR_NONE Successfully copied the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully copied the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- static otError FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv);
+ static Error FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv);
/**
* This static method searches for and reads a requested TLV out of a given message.
@@ -255,11 +255,11 @@
* @param[in] aMessage A reference to the message.
* @param[out] aTlv A reference to the TLV that will be copied to.
*
- * @retval OT_ERROR_NONE Successfully copied the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully copied the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- template <typename TlvType> static otError FindTlv(const Message &aMessage, TlvType &aTlv)
+ template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
{
return FindTlv(aMessage, TlvType::kType, sizeof(TlvType), aTlv);
}
@@ -273,11 +273,11 @@
* @param[in] aType The Type value to search for.
* @param[out] aOffset A reference to the offset of the TLV.
*
- * @retval OT_ERROR_NONE Successfully copied the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully copied the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- static otError FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset);
+ static Error FindTlvOffset(const Message &aMessage, uint8_t aType, uint16_t &aOffset);
/**
* This static method finds the offset and length of a given TLV type.
@@ -289,21 +289,18 @@
* @param[out] aValueOffset The offset where the value starts.
* @param[out] aLength The length of the value.
*
- * @retval OT_ERROR_NONE Successfully found the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully found the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- static otError FindTlvValueOffset(const Message &aMessage,
- uint8_t aType,
- uint16_t & aValueOffset,
- uint16_t & aLength);
+ static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
/**
* This static method searches for a TLV with a given type in a message, ensures its length is same or larger than
* an expected minimum value, and then reads its value into a given buffer.
*
* If the TLV length is smaller than the minimum length @p aLength, the TLV is considered invalid. In this case,
- * this method returns `OT_ERROR_PARSE` and the @p aValue buffer is not updated.
+ * this method returns `kErrorParse` and the @p aValue buffer is not updated.
*
* If the TLV length is larger than @p aLength, the TLV is considered valid, but only the first @p aLength bytes
* of the value are read and copied into the @p aValue buffer.
@@ -315,12 +312,12 @@
* @param[out] aValue A buffer to output the value (must contain at least @p aLength bytes).
* @param[in] aLength The expected (minimum) length of the TLV value.
*
- * @retval OT_ERROR_NONE The TLV was found and read successfully. @p aValue is updated.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
- * @retval OT_ERROR_PARSE TLV was found but it was not well-formed and could not be parsed.
+ * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
+ * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
*
*/
- template <typename TlvType> static otError Find(const Message &aMessage, void *aValue, uint8_t aLength)
+ template <typename TlvType> static Error Find(const Message &aMessage, void *aValue, uint8_t aLength)
{
return FindTlv(aMessage, TlvType::kType, aValue, aLength);
}
@@ -330,7 +327,7 @@
* same or larger than the expected `ValueType` object size, and then reads its value into a value object reference.
*
* If the TLV length is smaller than the size of @p aValue, the TLV is considered invalid. In this case, this
- * method returns `OT_ERROR_PARSE` and the @p aValue is not updated.
+ * method returns `kErrorParse` and the @p aValue is not updated.
*
* If the TLV length is larger than the size of @p aValue, the TLV is considered valid, but the size of
* `ValueType` bytes are read and copied into the @p aValue.
@@ -341,13 +338,13 @@
* @param[in] aType The TLV type to search for.
* @param[out] aValue A reference to the value object to output the read value.
*
- * @retval OT_ERROR_NONE The TLV was found and read successfully. @p aValue is updated.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
- * @retval OT_ERROR_PARSE TLV was found but it was not well-formed and could not be parsed.
+ * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
+ * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
*
*/
template <typename SimpleTlvType>
- static otError Find(const Message &aMessage, typename SimpleTlvType::ValueType &aValue)
+ static Error Find(const Message &aMessage, typename SimpleTlvType::ValueType &aValue)
{
return FindTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
}
@@ -357,20 +354,20 @@
* into a given `uint` reference variable.
*
* If the TLV length is smaller than size of integral value, the TLV is considered invalid. In this case, this
- * method returns `OT_ERROR_PARSE` and the @p aValue is not updated.
+ * method returns `kErrorParse` and the @p aValue is not updated.
*
* @tparam UintTlvType The simple TLV type to find (must be a sub-class of `UintTlvInfo`)
*
* @param[in] aMessage A reference to the message.
* @param[out] aValue A reference to an unsigned int value to output the TLV's value.
*
- * @retval OT_ERROR_NONE The TLV was found and read successfully. @p aValue is updated.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
- * @retval OT_ERROR_PARSE TLV was found but it was not well-formed and could not be parsed.
+ * @retval kErrorNone The TLV was found and read successfully. @p aValue is updated.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
+ * @retval kErrorParse TLV was found but it was not well-formed and could not be parsed.
*
*/
template <typename UintTlvType>
- static otError Find(const Message &aMessage, typename UintTlvType::UintValueType &aValue)
+ static Error Find(const Message &aMessage, typename UintTlvType::UintValueType &aValue)
{
return FindUintTlv(aMessage, UintTlvType::kType, aValue);
}
@@ -386,11 +383,11 @@
* @param[in] aValue A buffer containing the TLV value.
* @param[in] aLength The value length (in bytes).
*
- * @retval OT_ERROR_NONE Successfully appended the TLV to the message.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the TLV to the message.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- template <typename TlvType> static otError Append(Message &aMessage, const void *aValue, uint8_t aLength)
+ template <typename TlvType> static Error Append(Message &aMessage, const void *aValue, uint8_t aLength)
{
return AppendTlv(aMessage, TlvType::kType, aValue, aLength);
}
@@ -405,12 +402,12 @@
* @param[in] aMessage A reference to the message to append to.
* @param[in] aValue A reference to the object containing TLV's value.
*
- * @retval OT_ERROR_NONE Successfully appended the TLV to the message.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the TLV to the message.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
template <typename SimpleTlvType>
- static otError Append(Message &aMessage, const typename SimpleTlvType::ValueType &aValue)
+ static Error Append(Message &aMessage, const typename SimpleTlvType::ValueType &aValue)
{
return AppendTlv(aMessage, SimpleTlvType::kType, &aValue, sizeof(aValue));
}
@@ -425,11 +422,11 @@
* @param[in] aMessage A reference to the message to append to.
* @param[in] aValue An unsigned int value to use as TLV's value.
*
- * @retval OT_ERROR_NONE Successfully appended the TLV to the message.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the TLV to the message.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- template <typename UintTlvType> static otError Append(Message &aMessage, typename UintTlvType::UintValueType aValue)
+ template <typename UintTlvType> static Error Append(Message &aMessage, typename UintTlvType::UintValueType aValue)
{
return AppendUintTlv(aMessage, UintTlvType::kType, aValue);
}
@@ -454,22 +451,17 @@
* @param[out] aSize A pointer to a variable to output the size (total number of bytes) of the TLV.
* @param[out] aIsExtendedTlv A pointer to a boolean variable to output whether the found TLV is extended or not.
*
- * @retval OT_ERROR_NONE Successfully found the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully found the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- static otError Find(const Message &aMessage,
- uint8_t aType,
- uint16_t * aOffset,
- uint16_t * aSize,
- bool * aIsExtendedTlv);
+ static Error Find(const Message &aMessage, uint8_t aType, uint16_t *aOffset, uint16_t *aSize, bool *aIsExtendedTlv);
- static otError FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
- static otError AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
- template <typename UintType>
- static otError ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue);
- template <typename UintType> static otError FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue);
- template <typename UintType> static otError AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue);
+ static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
+ static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
+ template <typename UintType> static Error ReadUintTlv(const Message &aMessage, uint16_t aOffset, UintType &aValue);
+ template <typename UintType> static Error FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue);
+ template <typename UintType> static Error AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue);
uint8_t mType;
uint8_t mLength;
diff --git a/src/core/common/trickle_timer.cpp b/src/core/common/trickle_timer.cpp
index b8f4655..bfa3aec 100644
--- a/src/core/common/trickle_timer.cpp
+++ b/src/core/common/trickle_timer.cpp
@@ -39,40 +39,28 @@
namespace ot {
-TrickleTimer::TrickleTimer(Instance &aInstance,
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- uint32_t aRedundancyConstant,
-#endif
- Handler aTransmitHandler,
- Handler aIntervalExpiredHandler,
- void * aOwner)
- : TimerMilli(aInstance, TrickleTimer::HandleTimer, aOwner)
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- , mRedundancyConstant(aRedundancyConstant)
- , mCounter(0)
-#endif
+TrickleTimer::TrickleTimer(Instance &aInstance, Handler aHandler)
+ : TimerMilli(aInstance, TrickleTimer::HandleTimer)
, mIntervalMin(0)
, mIntervalMax(0)
, mInterval(0)
, mTimeInInterval(0)
- , mTransmitHandler(aTransmitHandler)
- , mIntervalExpiredHandler(aIntervalExpiredHandler)
- , mMode(kModeNormal)
- , mIsRunning(false)
- , mInTransmitPhase(false)
+ , mRedundancyConstant(0)
+ , mCounter(0)
+ , mHandler(aHandler)
+ , mMode(kModeTrickle)
+ , mPhase(kBeforeRandomTime)
{
- OT_ASSERT(aTransmitHandler != nullptr);
}
-void TrickleTimer::Start(uint32_t aIntervalMin, uint32_t aIntervalMax, Mode aMode)
+void TrickleTimer::Start(Mode aMode, uint32_t aIntervalMin, uint32_t aIntervalMax, uint16_t aRedundancyConstant)
{
- OT_ASSERT(aIntervalMax >= aIntervalMin);
- OT_ASSERT(aIntervalMin != 0 || aIntervalMax != 0);
+ OT_ASSERT((aIntervalMax >= aIntervalMin) && (aIntervalMin > 0));
- mIntervalMin = aIntervalMin;
- mIntervalMax = aIntervalMax;
- mMode = aMode;
- mIsRunning = true;
+ mIntervalMin = aIntervalMin;
+ mIntervalMax = aIntervalMax;
+ mRedundancyConstant = aRedundancyConstant;
+ mMode = aMode;
// Select interval randomly from range [Imin, Imax].
mInterval = Random::NonCrypto::GetUint32InRange(mIntervalMin, mIntervalMax + 1);
@@ -80,17 +68,22 @@
StartNewInterval();
}
-void TrickleTimer::Stop(void)
+void TrickleTimer::IndicateConsistent(void)
{
- mIsRunning = false;
- TimerMilli::Stop();
+ if (mCounter < kInfiniteRedundancyConstant)
+ {
+ mCounter++;
+ }
}
void TrickleTimer::IndicateInconsistent(void)
{
+ VerifyOrExit(mMode == kModeTrickle);
+
// If interval is equal to minimum when an "inconsistent" event
// is received, do nothing.
- VerifyOrExit(mIsRunning && (mInterval != mIntervalMin));
+
+ VerifyOrExit(IsRunning() && (mInterval != mIntervalMin));
mInterval = mIntervalMin;
StartNewInterval();
@@ -103,33 +96,22 @@
{
uint32_t halfInterval;
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- mCounter = 0;
-#endif
-
- mInTransmitPhase = true;
-
switch (mMode)
{
- case kModeNormal:
- halfInterval = mInterval / 2;
- VerifyOrExit(halfInterval < mInterval, mTimeInInterval = halfInterval);
-
- // Select a random point in the interval taken from the range [I/2, I).
- mTimeInInterval = Random::NonCrypto::GetUint32InRange(halfInterval, mInterval);
- break;
-
case kModePlainTimer:
mTimeInInterval = mInterval;
break;
- case kModeMPL:
- // Select a random point in interval taken from the range [0, I].
- mTimeInInterval = Random::NonCrypto::GetUint32InRange(0, mInterval + 1);
+ case kModeTrickle:
+ // Select a random point in the interval taken from the range [I/2, I).
+ halfInterval = mInterval / 2;
+ mTimeInInterval =
+ (halfInterval < mInterval) ? Random::NonCrypto::GetUint32InRange(halfInterval, mInterval) : halfInterval;
+ mCounter = 0;
+ mPhase = kBeforeRandomTime;
break;
}
-exit:
TimerMilli::Start(mTimeInInterval);
}
@@ -140,71 +122,52 @@
void TrickleTimer::HandleTimer(void)
{
- if (mInTransmitPhase)
- {
- HandleEndOfTimeInInterval();
- }
- else
- {
- HandleEndOfInterval();
- }
-}
-
-void TrickleTimer::HandleEndOfTimeInInterval(void)
-{
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- // Trickle transmits if and only if the counter `c` is less
- // than the redundancy constant `k`.
- if (mRedundancyConstant == 0 || mCounter < mRedundancyConstant)
-#endif
- {
- bool shouldContinue = mTransmitHandler(*this);
- VerifyOrExit(shouldContinue, Stop());
- }
-
switch (mMode)
{
case kModePlainTimer:
- // Select a random interval in [Imin, Imax] and restart.
mInterval = Random::NonCrypto::GetUint32InRange(mIntervalMin, mIntervalMax + 1);
StartNewInterval();
break;
- case kModeNormal:
- case kModeMPL:
- // Waiting for the rest of the interval to elapse.
- mInTransmitPhase = false;
- TimerMilli::Start(mInterval - mTimeInInterval);
+ case kModeTrickle:
+ switch (mPhase)
+ {
+ case kBeforeRandomTime:
+ // We reached end of random `mTimeInInterval` (aka `t`)
+ // within the current interval. Trickle timer invokes
+ // handler if and only if the counter is less than the
+ // redundancy constant.
+
+ mPhase = kAfterRandomTime;
+ TimerMilli::Start(mInterval - mTimeInInterval);
+ VerifyOrExit(mCounter < mRedundancyConstant);
+ break;
+
+ case kAfterRandomTime:
+ // Interval has expired. Double the interval length and
+ // ensure result is below max.
+
+ if (mInterval == 0)
+ {
+ mInterval = 1;
+ }
+ else if (mInterval <= mIntervalMax - mInterval)
+ {
+ mInterval *= 2;
+ }
+ else
+ {
+ mInterval = mIntervalMax;
+ }
+
+ StartNewInterval();
+ ExitNow(); // Exit so to not call `mHanlder`
+ }
+
break;
}
-exit:
- return;
-}
-
-void TrickleTimer::HandleEndOfInterval(void)
-{
- // Double the interval and ensure result is below max.
- if (mInterval == 0)
- {
- mInterval = 1;
- }
- else if (mInterval <= mIntervalMax - mInterval)
- {
- mInterval *= 2;
- }
- else
- {
- mInterval = mIntervalMax;
- }
-
- if (mIntervalExpiredHandler)
- {
- bool shouldContinue = mIntervalExpiredHandler(*this);
- VerifyOrExit(shouldContinue, Stop());
- }
-
- StartNewInterval();
+ mHandler(*this);
exit:
return;
diff --git a/src/core/common/trickle_timer.hpp b/src/core/common/trickle_timer.hpp
index e8ed1d0..0f65c55 100644
--- a/src/core/common/trickle_timer.hpp
+++ b/src/core/common/trickle_timer.hpp
@@ -36,6 +36,7 @@
#include "openthread-core-config.h"
+#include "common/numeric_limits.hpp"
#include "common/timer.hpp"
namespace ot {
@@ -61,41 +62,38 @@
* This enumeration defines the modes of operation for the `TrickleTimer`.
*
*/
- enum Mode
+ enum Mode : uint8_t
{
- kModeNormal, ///< Runs the normal trickle logic (as per RFC6206).
- kModePlainTimer, ///< Runs a plain timer with random interval selected between min/max intervals.
- kModeMPL, ///< Runs the trickle logic modified for MPL.
+ kModeTrickle, ///< Operate as the normal trickle logic (as per RFC 6206).
+ kModePlainTimer, ///< Operate as a plain periodic timer with random interval selected within min/max intervals.
+ };
+
+ enum : uint16_t
+ {
+ /**
+ * Special value for redundancy constant (aka `k`) to indicate infinity (when used, it disables trickle timer's
+ * suppression behavior, invoking the handler callback independent of number of "consistent" events).
+ *
+ */
+ kInfiniteRedundancyConstant = NumericLimits<uint16_t>::Max(),
};
/**
- * This function pointer is called when the timer expires.
+ * This function pointer is called when the timer expires (i.e., transmission should happen).
*
* @param[in] aTimer A reference to the trickle timer.
*
- * @retval TRUE If the trickle timer should continue running.
- * @retval FALSE If the trickle timer should stop running.
- *
*/
- typedef bool (*Handler)(TrickleTimer &aTimer);
+ typedef void (&Handler)(TrickleTimer &aTimer);
/**
* This constructor initializes a `TrickleTimer` instance.
*
- * @param[in] aInstance A reference to the OpenThread instance.
- * @param[in] aRedundancyConstant The redundancy constant for the timer, also known as `k`.
- * @param[in] aTransmitHandler A pointer to a function that is called when transmission should occur.
- * @param[in] aIntervalExpiredHandler An optional pointer to a function that is called when the interval expires.
- * @param[in] aOwner A pointer to owner of the `TrickleTimer` object.
+ * @param[in] aInstance A reference to the OpenThread instance.
+ * @param[in] aHandler A handler which is called when transmission should occur.
*
*/
- TrickleTimer(Instance &aInstance,
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- uint32_t aRedundancyConstant,
-#endif
- Handler aTransmitHandler,
- Handler aIntervalExpiredHandler,
- void * aOwner);
+ TrickleTimer(Instance &aInstance, Handler aHandler);
/**
* This method indicates whether or not the trickle timer instance is running.
@@ -104,60 +102,85 @@
* @retval FALSE If the trickle timer is not running.
*
*/
- bool IsRunning(void) const { return mIsRunning; }
+ bool IsRunning(void) const { return TimerMilli::IsRunning(); }
+
+ /**
+ * This method gets the current operation mode of the trickle timer.
+ *
+ * @returns The current operation mode of the timer.
+ *
+ */
+ Mode GetMode(void) const { return mMode; }
/**
* This method starts the trickle timer.
*
- * @param[in] aIntervalMin The minimum interval for the timer in milliseconds.
- * @param[in] aIntervalMax The maximum interval for the timer in milliseconds.
- * @param[in] aMode The operating mode for the timer.
+ * @param[in] aMode The operation mode of timer (trickle or plain periodic mode).
+ * @param[in] aIntervalMin The minimum interval for the timer in milliseconds.
+ * @param[in] aIntervalMax The maximum interval for the timer in milliseconds.
+ * @param[in] aRedundancyConstant The redundancy constant for the timer, also known as `k`. The default value
+ * is set to `kInfiniteRedundancyConstant` which disables the suppression behavior
+ * (i.e., handler is always invoked independent of number of "consistent" events).
*
*/
- void Start(uint32_t aIntervalMin, uint32_t aIntervalMax, Mode aMode);
+ void Start(Mode aMode,
+ uint32_t aIntervalMin,
+ uint32_t aIntervalMax,
+ uint16_t aRedundancyConstant = kInfiniteRedundancyConstant);
/**
* This method stops the trickle timer.
*
*/
- void Stop(void);
+ void Stop(void) { TimerMilli::Stop(); }
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
/**
- * This method indicates to the trickle timer a 'consistent' state.
+ * This method indicates to the trickle timer a 'consistent' event.
+ *
+ * The 'consistent' events are used to control suppression behavior. The trickle timer keeps track of the number of
+ * 'consistent' events in each interval. The timer handler is invoked only if the number of `consistent` events
+ * received in the interval is less than the redundancy constant.
*
*/
- void IndicateConsistent(void) { mCounter++; }
-#endif
+ void IndicateConsistent(void);
/**
- * This method indicates to the trickle timer an 'inconsistent' state.
+ * This method indicates to the trickle timer an 'inconsistent' event.
+ *
+ * Receiving an 'inconsistent' event causes the trickle timer to reset (i.e., start with interval set to the min
+ * value) unless the current interval being used is already equal to the min interval.
*
*/
void IndicateInconsistent(void);
private:
+ enum Phase : uint8_t
+ {
+ kBeforeRandomTime, // Trickle timer is before random time `t` in the current interval.
+ kAfterRandomTime, // Trickle timer is after random time `t` in the current interval.
+ };
+
void StartNewInterval(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void HandleEndOfTimeInInterval(void);
void HandleEndOfInterval(void);
- void StartAt(void) {} // Shadow base class `TimerMilli` method to ensure it is hidden.
-#ifdef ENABLE_TRICKLE_TIMER_SUPPRESSION_SUPPORT
- const uint32_t mRedundancyConstant; // Redundancy constant (aka 'k').
- uint32_t mCounter; // A counter for number of "consistent" transmissions (aka 'c').
-#endif
+ // Shadow base class `TimerMilli` methods to ensure they are hidden.
+ void StartAt(void) {}
+ void FireAt(void) {}
+ void FireAtIfEarlier(void) {}
+ void GetFireTime(void) {}
- uint32_t mIntervalMin; // Minimum interval (aka `Imin`).
- uint32_t mIntervalMax; // Maximum interval (aka `Imax`).
- uint32_t mInterval; // Current interval (aka `I`).
- uint32_t mTimeInInterval; // Time in interval (aka `t`).
- Handler mTransmitHandler; // Transmit handler callback.
- Handler mIntervalExpiredHandler; // Interval expired handler callback.
- Mode mMode; // Trickle timer mode.
- bool mIsRunning : 1; // Indicates if the trickle timer is running.
- bool mInTransmitPhase : 1; // Indicates if in transmit phase (before time `t` in current interval `I`).
+ uint32_t mIntervalMin; // Minimum interval (aka `Imin`).
+ uint32_t mIntervalMax; // Maximum interval (aka `Imax`).
+ uint32_t mInterval; // Current interval (aka `I`).
+ uint32_t mTimeInInterval; // Time in interval (aka `t`).
+ uint16_t mRedundancyConstant; // Redundancy constant (aka 'k').
+ uint16_t mCounter; // A counter for number of "consistent" transmissions (aka 'c').
+ Handler mHandler; // Handler callback.
+ Mode mMode; // Trickle timer operation mode.
+ Phase mPhase; // Trickle timer phase (before or after time `t` in the current interval).
};
/**
diff --git a/src/core/config/border_router.h b/src/core/config/border_router.h
index 2284367..bdddb0e 100644
--- a/src/core/config/border_router.h
+++ b/src/core/config/border_router.h
@@ -55,4 +55,14 @@
#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
#endif
+/**
+ * @def OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ *
+ * Define to 1 to enable (Duckhorn) Border Routing support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 0
+#endif
+
#endif // CONFIG_BORDER_ROUTER_H_
diff --git a/src/core/config/coap.h b/src/core/config/coap.h
index 712c57e..c3ee709 100644
--- a/src/core/config/coap.h
+++ b/src/core/config/coap.h
@@ -68,6 +68,26 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+ *
+ * Define to 1 to enable the CoAP Block-Wise Transfer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
+#define OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH
+ *
+ * This setting configures the maximum length of one block during a CoAP Block-Wise Transfer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH
+#define OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH 1024
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
*
* Define to 1 to enable the CoAP Secure API.
diff --git a/src/core/config/dataset_updater.h b/src/core/config/dataset_updater.h
index 1cff726..4055748 100644
--- a/src/core/config/dataset_updater.h
+++ b/src/core/config/dataset_updater.h
@@ -52,7 +52,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY
-#define OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY 1000
+#define OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY 30000
#endif
/**
diff --git a/src/core/config/dns_client.h b/src/core/config/dns_client.h
index 914bc84..e7c4d08 100644
--- a/src/core/config/dns_client.h
+++ b/src/core/config/dns_client.h
@@ -46,23 +46,68 @@
#endif
/**
- * @def OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
*
- * Maximum time that DNS Client waits for response in milliseconds.
+ * Define to 1 to enable DNS based Service Discovery (DNS-SD) client.
*
*/
-#ifndef OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT
-#define OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT 3000
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+#define OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE 1
#endif
/**
- * @def OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS
*
- * Maximum number of retransmissions for DNS client.
+ * Specifies the default DNS server IPv6 address.
+ *
+ * It MUST be a C string representation of the server IPv6 address.
+ *
+ * Default value is set to "2001:4860:4860::8888" which is the Google Public DNS IPv6 address.
*
*/
-#ifndef OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT
-#define OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT 2
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS
+#define OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS "2001:4860:4860::8888"
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_PORT
+ *
+ * Specifies the default DNS server port number.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_PORT
+#define OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_PORT 53
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT
+ *
+ * Specifies the default wait time that DNS client waits for a response from server (in milliseconds).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT
+#define OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT 6000
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS
+ *
+ * Specifies the default maximum number of DNS query tx attempts with no response before reporting failure.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS
+#define OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS 3
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_NO_RECURSION_FLAG
+ *
+ * Specifies the default "recursion desired" flag (indicates whether the server can resolve the query recursively or
+ * not).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RECURSION_DESIRED_FLAG
+#define OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RECURSION_DESIRED_FLAG 1
#endif
#endif // CONFIG_DNS_CLIENT_H_
diff --git a/src/core/config/dnssd_server.h b/src/core/config/dnssd_server.h
new file mode 100644
index 0000000..1d8c215
--- /dev/null
+++ b/src/core/config/dnssd_server.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021, 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 the DNS-SD Server.
+ *
+ */
+
+#ifndef CONFIG_DNSSD_SERVER_H_
+#define CONFIG_DNSSD_SERVER_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+ *
+ * Define to 1 to enable DNS-SD Server support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_DNSSD_SERVER_PORT
+ *
+ * Define the the DNS-SD Server port.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DNSSD_SERVER_PORT
+#define OPENTHREAD_CONFIG_DNSSD_SERVER_PORT 53
+#endif
+
+#endif // CONFIG_DNSSD_SERVER_H_
diff --git a/src/core/config/dtls.h b/src/core/config/dtls.h
new file mode 100644
index 0000000..e27918c
--- /dev/null
+++ b/src/core/config/dtls.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021, 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 DTLS.
+ *
+ */
+
+#ifndef CONFIG_DTLS_H_
+#define CONFIG_DTLS_H_
+
+#include "config/border_router.h"
+#include "config/coap.h"
+#include "config/commissioner.h"
+#include "config/joiner.h"
+
+/**
+ * @def OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN
+ *
+ * The max length of the OpenThread dtls content buffer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN
+#define OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN
+#endif
+
+#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || \
+ OPENTHREAD_CONFIG_COMMISSIONER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE
+#define OPENTHREAD_CONFIG_DTLS_ENABLE 1
+#else
+#define OPENTHREAD_CONFIG_DTLS_ENABLE 0
+#endif
+
+#endif // CONFIG_DTLS_H_
diff --git a/src/core/config/logging.h b/src/core/config/logging.h
index f8e3b0a..8649d37 100644
--- a/src/core/config/logging.h
+++ b/src/core/config/logging.h
@@ -220,7 +220,7 @@
*
*/
#ifndef OPENTHREAD_CONFIG_LOG_PLATFORM
-#define OPENTHREAD_CONFIG_LOG_PLATFORM 0
+#define OPENTHREAD_CONFIG_LOG_PLATFORM 1
#endif
/**
@@ -300,6 +300,36 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_LOG_BR
+ *
+ * Define to Border Router (BR) region logging.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_LOG_BR
+#define OPENTHREAD_CONFIG_LOG_BR 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_LOG_SRP
+ *
+ * Define to enable Service Registration Protocol (SRP) region logging.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_LOG_SRP
+#define OPENTHREAD_CONFIG_LOG_SRP 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_LOG_DNS
+ *
+ * Define to enable DNS region logging.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_LOG_DNS
+#define OPENTHREAD_CONFIG_LOG_DNS 1
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
*
* Define to prepend the log level to all log messages.
diff --git a/src/core/config/mac.h b/src/core/config/mac.h
index 7ab7b87..f733f88 100644
--- a/src/core/config/mac.h
+++ b/src/core/config/mac.h
@@ -66,11 +66,11 @@
*
* The default maximum number of retries allowed after a transmission failure for direct transmissions.
*
- * Equivalent to macMaxFrameRetries, default value is 3.
+ * Equivalent to macMaxFrameRetries, default value is 15.
*
*/
#ifndef OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT
-#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 3
+#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 15
#endif
/**
@@ -407,4 +407,14 @@
#define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD 2
#endif
+/**
+ * @def OPENTHREAD_CONFIG_MAC_SCAN_DURATION
+ *
+ * This setting configures the default scan duration in milliseconds.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SCAN_DURATION
+#define OPENTHREAD_CONFIG_MAC_SCAN_DURATION 300
+#endif
+
#endif // CONFIG_MAC_H_
diff --git a/src/core/config/mle.h b/src/core/config/mle.h
index 5c2ee78..e6131bd 100644
--- a/src/core/config/mle.h
+++ b/src/core/config/mle.h
@@ -164,6 +164,26 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL
+ *
+ * Specifies the delay wait interval (in milliseconds) used by attach backoff feature after a successful attach before
+ * it resets the current backoff interval back to the minimum value.
+ *
+ * If it is set to zero then the device resets its backoff attach interval immediately after a successful attach. With
+ * a non-zero value, if after a successful attach, the device happens to detach within the delay interval, the reattach
+ * process resumes with the previous backoff interval (as if the attach did not happen).
+ *
+ * This behavior is helpful in the situation where a battery-powered device has poor link quality to its parent and
+ * therefore attaches and detaches frequently from the parent. Using a non-zero wait interval ensures that the attach
+ * backoff interval does not reset on each attach and that the device does not drain its battery quickly trying to
+ * re-attach too frequently.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL
+#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL 20000
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_MLE_SEND_LINK_REQUEST_ON_ADV_TIMEOUT
*
* Define to 1 to send an MLE Link Request when MAX_NEIGHBOR_AGE is reached for a neighboring router.
diff --git a/src/core/config/openthread-core-config-check.h b/src/core/config/openthread-core-config-check.h
index 0b82531..6ee4eb9 100644
--- a/src/core/config/openthread-core-config-check.h
+++ b/src/core/config/openthread-core-config-check.h
@@ -28,32 +28,7 @@
/**
* @file
- * Sanity checking for configuration options.
- */
-
-#ifndef OPENTHREAD_CORE_CONFIG_CHECK_H_
-#define OPENTHREAD_CORE_CONFIG_CHECK_H_
-
-#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE && OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
-#error "OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE and OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE must not both be set."
-#endif
-
-#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT && !OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
-#error "OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT requires OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE to be also set."
-#endif
-
-#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT && OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
-#error "OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT requires DHCPv6 server on Border Router side to be enabled."
-#endif
-
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
-#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
-#error "Dynamic log level is not supported along with multiple OT instance feature"
-#endif
-#endif
-
-/*
- * Removed or replaced OPENTHREAD_CONFIG options.
+ * Checking for configuration options. Removed or replaced OPENTHREAD_CONFIG options.
*
* The checks below verify that none of the older configuration definition are
* still defined and being used. The list below is not necessarily complete and
@@ -63,6 +38,9 @@
*
*/
+#ifndef OPENTHREAD_CORE_CONFIG_CHECK_H_
+#define OPENTHREAD_CORE_CONFIG_CHECK_H_
+
#if defined(OPENTHREAD_CONFIG_DISABLE_CCA_ON_LAST_ATTEMPT) || \
defined(OPENTHREAD_CONFIG_DISABLE_CSMA_CA_ON_LAST_ATTEMPT) || \
defined(OPENTHREAD_CONFIG_MAC_DISABLE_CSMA_CA_ON_LAST_ATTEMPT)
@@ -91,14 +69,16 @@
#error "OPENTHREAD_ENABLE_CERT_LOG was replaced by OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE."
#endif
-//---------------------------------------------------------------------------------------------------------------------
-
#ifdef OPENTHREAD_ENABLE_MULTIPLE_INSTANCES
#error "OPENTHREAD_ENABLE_MULTIPLE_INSTANCES was replaced by OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE."
#endif
+#ifdef OPENTHREAD_CONFIG_NCP_UART_ENABLE
+#error "OPENTHREAD_CONFIG_NCP_UART_ENABLE was replaced by OPENTHREAD_CONFIG_NCP_HDLC_ENABLE."
+#endif
+
#ifdef OPENTHREAD_ENABLE_NCP_UART
-#error "OPENTHREAD_ENABLE_NCP_UART was replaced by OPENTHREAD_CONFIG_NCP_UART_ENABLE."
+#error "OPENTHREAD_ENABLE_NCP_UART was replaced by OPENTHREAD_CONFIG_NCP_HDLC_ENABLE."
#endif
#ifdef OPENTHREAD_ENABLE_NCP_SPI
@@ -217,8 +197,6 @@
#error "OPENTHREAD_ENABLE_SPINEL_VENDOR_SUPPORT was replaced by OPENTHREAD_ENABLE_NCP_VENDOR_HOOK."
#endif
-//---------------------------------------------------------------------------------------------------------------------
-
#ifdef OPENTHREAD_CONFIG_MAX_TX_ATTEMPTS_INDIRECT_POLLS
#error \
"OPENTHREAD_CONFIG_MAX_TX_ATTEMPTS_INDIRECT_POLLS was replaced by OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS."
@@ -496,49 +474,6 @@
"OPENTHREAD_CONFIG_COAP_ACK_TIMEOUT_MILLIS was removed. Use otCoapSendRequestWithParameters to configure CoAP transmission parameters."
#endif
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE"
-#endif
-
-#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE"
-#endif
-
-#endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-
-#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE"
-#endif
-#endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
-
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE"
-#endif
-#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-
-#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
-#if !OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-#error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE"
-#endif
-#endif
-
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
-#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE"
-#endif
-#endif
-
-#if OPENTHREAD_CONFIG_DUA_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_DUA_ENABLE"
-#endif
-
-#if OPENTHREAD_CONFIG_MLR_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
-#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLR_ENABLE"
-#endif
-
#ifdef OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL
#error "OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL is removed, use OPENTHREAD_CONFIG_LOG_OUTPUT_APP instead"
#endif
@@ -548,8 +483,12 @@
"(and OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY)"
#endif
-#if OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE && OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT
-#error "OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE conflicts with OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT."
+#ifdef OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT
+#error "OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT was replaced by OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT"
+#endif
+
+#ifdef OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT
+#error "OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT was replaced by OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS"
#endif
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_
diff --git a/src/core/config/openthread-core-default-config.h b/src/core/config/openthread-core-default-config.h
index a2076b3..5697d72 100644
--- a/src/core/config/openthread-core-default-config.h
+++ b/src/core/config/openthread-core-default-config.h
@@ -36,6 +36,7 @@
#define OPENTHREAD_CORE_DEFAULT_CONFIG_H_
#include "config/coap.h"
+#include "config/srp_server.h"
/**
* @def OPENTHREAD_CONFIG_STACK_VENDOR_OUI
@@ -265,7 +266,10 @@
*
*/
#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE
-#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+// Internal heap doesn't support size larger than 64K bytes.
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE (63 * 1024)
+#elif OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE (3072 * sizeof(void *))
#else
#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE (1568 * sizeof(void *))
@@ -279,7 +283,10 @@
*
*/
#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS
-#if OPENTHREAD_CONFIG_ECDSA_ENABLE
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+// Internal heap doesn't support size larger than 64K bytes.
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS (63 * 1024)
+#elif OPENTHREAD_CONFIG_ECDSA_ENABLE
#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 2600
#else
#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS 384
diff --git a/src/core/config/ping_sender.h b/src/core/config/ping_sender.h
new file mode 100644
index 0000000..18aba57
--- /dev/null
+++ b/src/core/config/ping_sender.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2021, 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 ping sender module.
+ *
+ */
+
+#ifndef CONFIG_PING_SENDER_H_
+#define CONFIG_PING_SENDER_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+ *
+ * Define to 1 to enable ping sender module.
+ *
+ * Ping sender module implements sending ICMPv6 Echo Request messages and processing ICMPv6 Echo Reply messages.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+#define OPENTHREAD_CONFIG_PING_SENDER_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_INTEVRAL
+ *
+ * Specifies the default ping interval (time between sending echo requests) in milliseconds.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_INTEVRAL
+#define OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_INTEVRAL 1000
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_SIZE
+ *
+ * Specifies the default ping data size in bytes. The data size specifies the Echo Request data payload which excludes
+ * the IPv6 and ICMPv6 headers.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_SIZE
+#define OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_SIZE 8
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_COUNT
+ *
+ * Specifies the default ping count (number of ping messages to send).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_COUNT
+#define OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_COUNT 1
+#endif
+
+#endif // CONFIG_PING_SENDER_H_
diff --git a/src/core/config/srp_client.h b/src/core/config/srp_client.h
new file mode 100644
index 0000000..e251151
--- /dev/null
+++ b/src/core/config/srp_client.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes compile-time configurations for the SRP (Service Registration Protocol) Client.
+ *
+ */
+
+#ifndef CONFIG_SRP_CLIENT_H_
+#define CONFIG_SRP_CLIENT_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ *
+ * Define to 1 to enable SRP Client support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ *
+ * Define to 1 to enable SRP Client auto-start feature and its APIs.
+ *
+ * When enabled, the SRP client can be configured to automatically start when it detects the presence of an SRP server
+ * (by monitoring the Thread Network Data for SRP Server Service entries).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE
+ *
+ * Define the default mode (enabled or disabled) of auto-start mode.
+ *
+ * This config is applicable/used only when `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+ *
+ * Define to 1 for the SRP client implementation to provide APIs that get/set the domain name.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE
+ *
+ * Specifies the default requested lease interval (in seconds). Set to two hours.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE (2 * 60 * 60)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE
+ *
+ * Specifies the default requested key lease interval (in seconds). Set to 14 days.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE
+#define OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE (14 * 24 * 60 * 60)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL
+ *
+ * Specifies the guard interval (in seconds) for lease renew time. The guard interval determines how much earlier
+ * (relative to the lease expiration time) the SRP client will send an SRP update for lease renewal.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL
+#define OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL 120 // two minutes in seconds
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR
+ *
+ * Specifies the numerator of early lease renewal factor.
+ *
+ * This value is used for opportunistic early refresh behave. When sending an SRP update, the services that are not yet
+ * expired but are close, are allowed to refresh early and are included in the SRP update.
+ *
+ * The "early lease renewal interval" is used to determine if a service can renew early. The interval is calculated by
+ * multiplying the accepted lease interval by the "early lease renewal factor" which is given as a fraction (numerator
+ * and denominator).
+ *
+ * If the factor is set to zero (numerator=0, denominator=1), the opportunistic early refresh behavior is disabled.
+ * If denominator is set to zero (the factor is set to infinity), then all services (including previously registered
+ * ones) are always included in SRP update message.
+ *
+ * Default value is 1/2 (i.e., services that are within half of the lease interval are allowed to refresh early).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR
+#define OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR 1
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR
+ *
+ * Specifies the denominator of early lease renewal factor.
+ *
+ * Please see OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR for more details.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR
+#define OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR 2
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY
+ *
+ * Specifies the (short) delay (in msec) after an update is required before SRP client sends the update message.
+ *
+ * When there is a change (e.g., a new service is added/removed) that requires an update, the SRP client will wait for
+ * a short delay before preparing and sending an SRP update message to server. This allows user to provide more change
+ * that are then all sent in same update message. The delay is only applied on the first change that triggers an
+ * update message transmission. Subsequent changes (API calls) while waiting for the tx to start will not reset the
+ * delay timer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY
+#define OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY 10
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL
+ *
+ * Specifies the minimum wait interval (in msec) between SRP update message retries.
+ *
+ * The update message is retransmitted if there is no response from server or if server rejects the update. The wait
+ * interval starts from the minimum value and is increased by the growth factor every failure up to the max value.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL
+#define OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL 1800
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL
+ *
+ * Specifies the maximum wait interval (in msec) between SRP update message retries.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL
+#define OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL (1 * 60 * 60 * 1000) // 1 hour in ms.
+#endif
+
+/**
+ * @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
+ * the retry interval is then randomly selected from [0, 2*300] ms).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER
+#define OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER 500
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR
+ *
+ * Specifies the numerator of the retry wait interval growth factor fraction. The growth factor is represented as
+ * a fraction (e.g., for 1.5, we can use 15 as the numerator and 10 as the denominator).
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR
+#define OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR 17
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR
+ *
+ * Specifies the denominator of the retry wait interval growth factor fraction.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR
+#define OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR 10
+#endif
+
+#endif // CONFIG_SRP_CLIENT_H_
diff --git a/src/core/config/srp_server.h b/src/core/config/srp_server.h
new file mode 100644
index 0000000..c0d9e30
--- /dev/null
+++ b/src/core/config/srp_server.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes compile-time configurations for the SRP (Service Registration Protocol) Server.
+ *
+ */
+
+#ifndef CONFIG_SRP_SERVER_H_
+#define CONFIG_SRP_SERVER_H_
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ *
+ * Define to 1 to enable SRP Server support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT
+ *
+ * Specifies the SRP Server UDP port.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT
+#define OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_NUMBER
+ *
+ * Specifies the Thread Network Data Service number for SRP Server.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_NUMBER
+#define OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_NUMBER 0x5du
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT
+ *
+ * Specifies the timeout value (in milliseconds) for the service update handler.
+ *
+ * The default timeout value is the sum of the maximum total mDNS probing delays
+ * and a loose IPC timeout of 250ms. It is recommended that this configuration should
+ * not use a value smaller than the default value here, if an Advertising Proxy is used
+ * to handle the service update events.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT
+#define OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT ((4 * 250u) + 250u)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM
+ *
+ * Specifies the maximum number of addresses the SRP server can handle for a host.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM
+#define OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM 2
+#endif
+
+#endif // CONFIG_SRP_SERVER_H_
diff --git a/src/core/crypto/aes_ccm.hpp b/src/core/crypto/aes_ccm.hpp
index 9efae0e..67744b3 100644
--- a/src/core/crypto/aes_ccm.hpp
+++ b/src/core/crypto/aes_ccm.hpp
@@ -38,8 +38,7 @@
#include <stdint.h>
-#include <openthread/error.h>
-
+#include "common/error.hpp"
#include "crypto/aes_ecb.hpp"
#include "mac/mac_types.hpp"
diff --git a/src/core/crypto/ecdsa.cpp b/src/core/crypto/ecdsa.cpp
index e46e6c2..216dfd3 100644
--- a/src/core/crypto/ecdsa.cpp
+++ b/src/core/crypto/ecdsa.cpp
@@ -50,7 +50,7 @@
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
-otError P256::KeyPair::Generate(void)
+Error P256::KeyPair::Generate(void)
{
mbedtls_pk_context pk;
int ret;
@@ -74,26 +74,26 @@
exit:
mbedtls_pk_free(&pk);
- return (ret >= 0) ? OT_ERROR_NONE : MbedTls::MapError(ret);
+ return (ret >= 0) ? kErrorNone : MbedTls::MapError(ret);
}
-otError P256::KeyPair::Parse(void *aContext) const
+Error P256::KeyPair::Parse(void *aContext) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mbedtls_pk_context *pk = reinterpret_cast<mbedtls_pk_context *>(aContext);
mbedtls_pk_init(pk);
- VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = OT_ERROR_FAILED);
- VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = OT_ERROR_PARSE);
+ VerifyOrExit(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0, error = kErrorFailed);
+ VerifyOrExit(mbedtls_pk_parse_key(pk, mDerBytes, mDerLength, nullptr, 0) == 0, error = kErrorParse);
exit:
return error;
}
-otError P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const
+Error P256::KeyPair::GetPublicKey(PublicKey &aPublicKey) const
{
- otError error;
+ Error error;
mbedtls_pk_context pk;
mbedtls_ecp_keypair *keyPair;
int ret;
@@ -113,9 +113,9 @@
return error;
}
-otError P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) const
+Error P256::KeyPair::Sign(const Sha256::Hash &aHash, Signature &aSignature) const
{
- otError error;
+ Error error;
mbedtls_pk_context pk;
mbedtls_ecp_keypair * keypair;
mbedtls_ecdsa_context ecdsa;
@@ -138,7 +138,7 @@
mbedtls_ecdsa_sign_det(&ecdsa.grp, &r, &s, &ecdsa.d, aHash.GetBytes(), Sha256::Hash::kSize, MBEDTLS_MD_SHA256);
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
- OT_ASSERT(mbedtls_mpi_size(&r) == kMpiSize);
+ OT_ASSERT(mbedtls_mpi_size(&r) <= kMpiSize);
ret = mbedtls_mpi_write_binary(&r, aSignature.mShared.mMpis.mR, kMpiSize);
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
@@ -155,9 +155,9 @@
return error;
}
-otError P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
+Error P256::PublicKey::Verify(const Sha256::Hash &aHash, const Signature &aSignature) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mbedtls_ecdsa_context ecdsa;
mbedtls_mpi r;
mbedtls_mpi s;
@@ -184,7 +184,7 @@
VerifyOrExit(ret == 0, error = MbedTls::MapError(ret));
ret = mbedtls_ecdsa_verify(&ecdsa.grp, aHash.GetBytes(), Sha256::Hash::kSize, &ecdsa.Q, &r, &s);
- VerifyOrExit(ret == 0, error = OT_ERROR_SECURITY);
+ VerifyOrExit(ret == 0, error = kErrorSecurity);
exit:
mbedtls_mpi_free(&s);
@@ -194,14 +194,14 @@
return error;
}
-otError Sign(uint8_t * aOutput,
- uint16_t & aOutputLength,
- const uint8_t *aInputHash,
- uint16_t aInputHashLength,
- const uint8_t *aPrivateKey,
- uint16_t aPrivateKeyLength)
+Error Sign(uint8_t * aOutput,
+ uint16_t & aOutputLength,
+ const uint8_t *aInputHash,
+ uint16_t aInputHashLength,
+ const uint8_t *aPrivateKey,
+ uint16_t aPrivateKeyLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mbedtls_ecdsa_context ctx;
mbedtls_pk_context pkCtx;
mbedtls_ecp_keypair * keypair;
@@ -215,26 +215,26 @@
// Parse a private key in PEM format.
VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, nullptr, 0) == 0,
- error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
+ VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = kErrorInvalidArgs);
keypair = mbedtls_pk_ec(pkCtx);
OT_ASSERT(keypair != nullptr);
- VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = OT_ERROR_FAILED);
+ VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = kErrorFailed);
// Sign using ECDSA.
VerifyOrExit(mbedtls_ecdsa_sign(&ctx.grp, &rMpi, &sMpi, &ctx.d, aInputHash, aInputHashLength,
mbedtls_ctr_drbg_random, Random::Crypto::MbedTlsContextGet()) == 0,
- error = OT_ERROR_FAILED);
- VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= aOutputLength, error = OT_ERROR_NO_BUFS);
+ error = kErrorFailed);
+ VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= aOutputLength, error = kErrorNoBufs);
// Concatenate the two octet sequences in the order R and then S.
- VerifyOrExit(mbedtls_mpi_write_binary(&rMpi, aOutput, mbedtls_mpi_size(&rMpi)) == 0, error = OT_ERROR_FAILED);
+ VerifyOrExit(mbedtls_mpi_write_binary(&rMpi, aOutput, mbedtls_mpi_size(&rMpi)) == 0, error = kErrorFailed);
aOutputLength = static_cast<uint16_t>(mbedtls_mpi_size(&rMpi));
VerifyOrExit(mbedtls_mpi_write_binary(&sMpi, aOutput + aOutputLength, mbedtls_mpi_size(&sMpi)) == 0,
- error = OT_ERROR_FAILED);
+ error = kErrorFailed);
aOutputLength += mbedtls_mpi_size(&sMpi);
exit:
diff --git a/src/core/crypto/ecdsa.hpp b/src/core/crypto/ecdsa.hpp
index 772e489..8cf3265 100644
--- a/src/core/crypto/ecdsa.hpp
+++ b/src/core/crypto/ecdsa.hpp
@@ -39,8 +39,7 @@
#include <stdint.h>
#include <stdlib.h>
-#include <openthread/error.h>
-
+#include "common/error.hpp"
#include "crypto/sha256.hpp"
namespace ot {
@@ -146,24 +145,24 @@
/**
* This method generates and populates the `KeyPair` with a new public/private keys.
*
- * @retval OT_ERROR_NONE A new key pair was generated successfully.
- * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for key generation.
- * @retval OT_ERROR_NOT_CAPABLE Feature not supported.
- * @retval OT_ERROR_FAILED Failed to generate key.
+ * @retval kErrorNone A new key pair was generated successfully.
+ * @retval kErrorNoBufs Failed to allocate buffer for key generation.
+ * @retval kErrorNotCapable Feature not supported.
+ * @retval kErrorFailed Failed to generate key.
*
*/
- otError Generate(void);
+ Error Generate(void);
/**
* This method gets the associated public key from the `KeyPair`.
*
* @param[out] aPublicKey A reference to a `PublicKey` to output the value.
*
- * @retval OT_ERROR_NONE Public key was retrieved successfully, and @p aPublicKey is updated.
- * @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format).
+ * @retval kErrorNone Public key was retrieved successfully, and @p aPublicKey is updated.
+ * @retval kErrorParse The key-pair DER format could not be parsed (invalid format).
*
*/
- otError GetPublicKey(PublicKey &aPublicKey) const;
+ Error GetPublicKey(PublicKey &aPublicKey) const;
/**
* This method gets the pointer to start of the buffer containing the key-pair info in DER format.
@@ -211,16 +210,16 @@
* @param[in] aHash The SHA-256 hash value of the message to use for signature calculation.
* @param[out] aSignature A reference to a `Signature` to output the calculated signature value.
*
- * @retval OT_ERROR_NONE The signature was calculated successfully and @p aSignature was updated.
- * @retval OT_ERROR_PARSE The key-pair DER format could not be parsed (invalid format).
- * @retval OT_ERROR_INVALID_ARGS The @p aHash is invalid.
- * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature calculation.
+ * @retval kErrorNone The signature was calculated successfully and @p aSignature was updated.
+ * @retval kErrorParse The key-pair DER format could not be parsed (invalid format).
+ * @retval kErrorInvalidArgs The @p aHash is invalid.
+ * @retval kErrorNoBufs Failed to allocate buffer for signature calculation.
*
*/
- otError Sign(const Sha256::Hash &aHash, Signature &aSignature) const;
+ Error Sign(const Sha256::Hash &aHash, Signature &aSignature) const;
private:
- otError Parse(void *aContext) const;
+ Error Parse(void *aContext) const;
uint8_t mDerBytes[kMaxDerSize];
uint8_t mDerLength;
@@ -257,13 +256,13 @@
* @param[in] aHash The SHA-256 hash value of a message to use for signature verification.
* @param[in] aSignature The signature value to verify.
*
- * @retval OT_ERROR_NONE The signature was verified successfully.
- * @retval OT_ERROR_SECURITY The signature is invalid.
- * @retval OT_ERROR_INVALID_ARGS The key or has is invalid.
- * @retval OT_ERROR_NO_BUFS Failed to allocate buffer for signature verification
+ * @retval kErrorNone The signature was verified successfully.
+ * @retval kErrorSecurity The signature is invalid.
+ * @retval kErrorInvalidArgs The key or has is invalid.
+ * @retval kErrorNoBufs Failed to allocate buffer for signature verification
*
*/
- otError Verify(const Sha256::Hash &aHash, const Signature &aSignature) const;
+ Error Verify(const Sha256::Hash &aHash, const Signature &aSignature) const;
private:
uint8_t mData[kSize];
@@ -280,18 +279,18 @@
* @param[in] aPrivateKey A private key in PEM format.
* @param[in] aPrivateKeyLength The length of the @p aPrivateKey buffer.
*
- * @retval OT_ERROR_NONE ECDSA sign has been created successfully.
- * @retval OT_ERROR_NO_BUFS Output buffer is too small.
- * @retval OT_ERROR_INVALID_ARGS Private key is not valid EC Private Key.
- * @retval OT_ERROR_FAILED Error during signing.
+ * @retval kErrorNone ECDSA sign has been created successfully.
+ * @retval kErrorNoBufs Output buffer is too small.
+ * @retval kErrorInvalidArgs Private key is not valid EC Private Key.
+ * @retval kErrorFailed Error during signing.
*
*/
-otError Sign(uint8_t * aOutput,
- uint16_t & aOutputLength,
- const uint8_t *aInputHash,
- uint16_t aInputHashLength,
- const uint8_t *aPrivateKey,
- uint16_t aPrivateKeyLength);
+Error Sign(uint8_t * aOutput,
+ uint16_t & aOutputLength,
+ const uint8_t *aInputHash,
+ uint16_t aInputHashLength,
+ const uint8_t *aPrivateKey,
+ uint16_t aPrivateKeyLength);
/**
* @}
diff --git a/src/core/crypto/hkdf_sha256.cpp b/src/core/crypto/hkdf_sha256.cpp
index fd10bef..dad7b0f 100644
--- a/src/core/crypto/hkdf_sha256.cpp
+++ b/src/core/crypto/hkdf_sha256.cpp
@@ -75,13 +75,13 @@
if (iter != 0)
{
- hmac.Update(hash.GetBytes(), sizeof(hash));
+ hmac.Update(hash);
}
hmac.Update(aInfo, aInfoLength);
iter++;
- hmac.Update(&iter, sizeof(iter));
+ hmac.Update(iter);
hmac.Finish(hash);
copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength;
diff --git a/src/core/crypto/hmac_sha256.cpp b/src/core/crypto/hmac_sha256.cpp
index e88a6c0..add3e3a 100644
--- a/src/core/crypto/hmac_sha256.cpp
+++ b/src/core/crypto/hmac_sha256.cpp
@@ -33,6 +33,8 @@
#include "hmac_sha256.hpp"
+#include "common/message.hpp"
+
namespace ot {
namespace Crypto {
@@ -54,9 +56,22 @@
mbedtls_md_hmac_starts(&mContext, aKey, aKeyLength);
}
-void HmacSha256::Update(const uint8_t *aBuf, uint16_t aBufLength)
+void HmacSha256::Update(const void *aBuf, uint16_t aBufLength)
{
- mbedtls_md_hmac_update(&mContext, aBuf, aBufLength);
+ mbedtls_md_hmac_update(&mContext, reinterpret_cast<const uint8_t *>(aBuf), aBufLength);
+}
+
+void HmacSha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
+{
+ Message::Chunk chunk;
+
+ aMessage.GetFirstChunk(aOffset, aLength, chunk);
+
+ while (chunk.GetLength() > 0)
+ {
+ Update(chunk.GetData(), chunk.GetLength());
+ aMessage.GetNextChunk(aLength, chunk);
+ }
}
void HmacSha256::Finish(Hash &aHash)
diff --git a/src/core/crypto/hmac_sha256.hpp b/src/core/crypto/hmac_sha256.hpp
index 2d0d8d9..5fcd2a0 100644
--- a/src/core/crypto/hmac_sha256.hpp
+++ b/src/core/crypto/hmac_sha256.hpp
@@ -43,6 +43,9 @@
#include "crypto/sha256.hpp"
namespace ot {
+
+class Message;
+
namespace Crypto {
/**
@@ -66,19 +69,19 @@
typedef Sha256::Hash Hash;
/**
- * Constructor for initialization of mbedtls_md_context_t.
+ * Constructor for `HmacSha256`.
*
*/
HmacSha256(void);
/**
- * Destructor for freeing of mbedtls_md_context_t.
+ * Destructor for `HmacSha256`.
*
*/
~HmacSha256(void);
/**
- * This method sets the key.
+ * This method sets the key and starts the HMAC computation.
*
* @param[in] aKey A pointer to the key.
* @param[in] aKeyLength The key length in bytes.
@@ -93,7 +96,31 @@
* @param[in] aBufLength The length of @p aBuf in bytes.
*
*/
- void Update(const uint8_t *aBuf, uint16_t aBufLength);
+ void Update(const void *aBuf, uint16_t aBufLength);
+
+ /**
+ * This method inputs an object (treated as a sequence of bytes) into the HMAC computation.
+ *
+ * @tparam ObjectType The object type.
+ *
+ * @param[in] aObject A reference to the object.
+ *
+ */
+ template <typename ObjectType> void Update(const ObjectType &aObject)
+ {
+ static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+ return Update(&aObject, sizeof(ObjectType));
+ }
+
+ /**
+ * This method inputs the bytes read from a given message into the HMAC computation.
+ *
+ * @param[in] aMessage The message to read the data from.
+ * @param[in] aOffset The offset into @p aMessage to start to read.
+ * @param[in] aLength The number of bytes to read.
+ *
+ */
+ void Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
/**
* This method finalizes the hash computation.
diff --git a/src/core/crypto/mbedtls.cpp b/src/core/crypto/mbedtls.cpp
index a5ba8c3..4b27b4a 100644
--- a/src/core/crypto/mbedtls.cpp
+++ b/src/core/crypto/mbedtls.cpp
@@ -36,7 +36,6 @@
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/debug.h>
#include <mbedtls/entropy.h>
-#include <mbedtls/error.h>
#include <mbedtls/platform.h>
#include <mbedtls/threading.h>
@@ -44,39 +43,26 @@
#include <mbedtls/pem.h>
#endif
+#include "common/error.hpp"
#include "common/instance.hpp"
namespace ot {
namespace Crypto {
-#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
-
-static void *CAlloc(size_t aCount, size_t aSize)
-{
- return Instance::Get().HeapCAlloc(aCount, aSize);
-}
-
-static void Free(void *aPointer)
-{
- Instance::Get().HeapFree(aPointer);
-}
-
-#endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
-
MbedTls::MbedTls(void)
{
-#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
+#if OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
#ifdef MBEDTLS_DEBUG_C
// mbedTLS's debug level is almost the same as OpenThread's
mbedtls_debug_set_threshold(OPENTHREAD_CONFIG_LOG_LEVEL);
#endif
- mbedtls_platform_set_calloc_free(CAlloc, Free);
-#endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
+ mbedtls_platform_set_calloc_free(Instance::HeapCAlloc, Instance::HeapFree);
+#endif // OPENTHREAD_CONFIG_ENABLE_BUILTIN_MBEDTLS_MANAGEMENT
}
-otError MbedTls::MapError(int aMbedTlsError)
+Error MbedTls::MapError(int aMbedTlsError)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
switch (aMbedTlsError)
{
@@ -116,7 +102,7 @@
case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
- error = OT_ERROR_INVALID_ARGS;
+ error = kErrorInvalidArgs;
break;
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
@@ -133,7 +119,7 @@
case MBEDTLS_ERR_SSL_ALLOC_FAILED:
case MBEDTLS_ERR_SSL_WANT_WRITE:
case MBEDTLS_ERR_ENTROPY_MAX_SOURCES:
- error = OT_ERROR_NO_BUFS;
+ error = kErrorNoBufs;
break;
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
@@ -149,29 +135,29 @@
case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED:
case MBEDTLS_ERR_THREADING_BAD_INPUT_DATA:
case MBEDTLS_ERR_THREADING_MUTEX_ERROR:
- error = OT_ERROR_SECURITY;
+ error = kErrorSecurity;
break;
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case MBEDTLS_ERR_X509_FATAL_ERROR:
- error = OT_ERROR_FAILED;
+ error = kErrorFailed;
break;
#endif
case MBEDTLS_ERR_SSL_TIMEOUT:
case MBEDTLS_ERR_SSL_WANT_READ:
- error = OT_ERROR_BUSY;
+ error = kErrorBusy;
break;
#if OPENTHREAD_CONFIG_ECDSA_ENABLE
case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:
- error = OT_ERROR_NOT_CAPABLE;
+ error = kErrorNotCapable;
break;
#endif
default:
if (aMbedTlsError < 0)
{
- error = OT_ERROR_FAILED;
+ error = kErrorFailed;
}
break;
diff --git a/src/core/crypto/mbedtls.hpp b/src/core/crypto/mbedtls.hpp
index b2df719..569815f 100644
--- a/src/core/crypto/mbedtls.hpp
+++ b/src/core/crypto/mbedtls.hpp
@@ -38,6 +38,7 @@
#include <openthread/instance.h>
+#include "common/error.hpp"
#include "common/non_copyable.hpp"
namespace ot {
@@ -68,10 +69,10 @@
*
* @param[in] aMbedTlsError The mbed TLS error.
*
- * @returns The mapped otError.
+ * @returns The mapped Error.
*
*/
- static otError MapError(int aMbedTlsError);
+ static Error MapError(int aMbedTlsError);
};
/**
diff --git a/src/core/crypto/pbkdf2_cmac.cpp b/src/core/crypto/pbkdf2_cmac.cpp
index 1af07f0..988a577 100644
--- a/src/core/crypto/pbkdf2_cmac.cpp
+++ b/src/core/crypto/pbkdf2_cmac.cpp
@@ -31,26 +31,29 @@
* This file implements PBKDF2 using AES-CMAC-PRF-128
*/
-#include "pbkdf2_cmac.h"
+#include "pbkdf2_cmac.hpp"
+#include <mbedtls/cmac.h>
#include <string.h>
#include "common/debug.hpp"
-#include <mbedtls/cmac.h>
+namespace ot {
+namespace Crypto {
+namespace Pbkdf2 {
#if OPENTHREAD_FTD
-void otPbkdf2Cmac(const uint8_t *aPassword,
- uint16_t aPasswordLen,
- const uint8_t *aSalt,
- uint16_t aSaltLen,
- uint32_t aIterationCounter,
- uint16_t aKeyLen,
- uint8_t * aKey)
+void GenerateKey(const uint8_t *aPassword,
+ uint16_t aPasswordLen,
+ const uint8_t *aSalt,
+ uint16_t aSaltLen,
+ uint32_t aIterationCounter,
+ uint16_t aKeyLen,
+ uint8_t * aKey)
{
const size_t kBlockSize = MBEDTLS_CIPHER_BLKSIZE_MAX;
- uint8_t prfInput[OT_PBKDF2_SALT_MAX_LEN + 4]; // Salt || INT(), for U1 calculation
+ uint8_t prfInput[kMaxSaltLength + 4]; // Salt || INT(), for U1 calculation
long prfOne[kBlockSize / sizeof(long)];
long prfTwo[kBlockSize / sizeof(long)];
long keyBlock[kBlockSize / sizeof(long)];
@@ -112,3 +115,7 @@
}
#endif // OPENTHREAD_FTD
+
+} // namespace Pbkdf2
+} // namespace Crypto
+} // namespace ot
diff --git a/src/core/crypto/pbkdf2_cmac.h b/src/core/crypto/pbkdf2_cmac.hpp
similarity index 71%
rename from src/core/crypto/pbkdf2_cmac.h
rename to src/core/crypto/pbkdf2_cmac.hpp
index fffb5ba..7c8559c 100644
--- a/src/core/crypto/pbkdf2_cmac.h
+++ b/src/core/crypto/pbkdf2_cmac.hpp
@@ -29,25 +29,34 @@
/**
* @file
* @brief
- * This file defines the PBKDF2 using CMAC C APIs.
+ * This file includes definitions for performing Password-Based Key Derivation Function 2 (PBKDF2) using CMAC.
*/
-#ifndef PBKDF2_CMAC_H_
-#define PBKDF2_CMAC_H_
+#ifndef PBKDF2_CMAC_HPP_
+#define PBKDF2_CMAC_HPP_
#include "openthread-core-config.h"
-#include <stdbool.h>
#include <stdint.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define OT_PBKDF2_SALT_MAX_LEN 30 // salt prefix (6) + extended panid (8) + network name (16)
+namespace ot {
+namespace Crypto {
+namespace Pbkdf2 {
/**
- * This method perform PKCS#5 PBKDF2 using CMAC (AES-CMAC-PRF-128).
+ * @addtogroup core-security
+ *
+ * @{
+ *
+ */
+
+enum : uint16_t
+{
+ kMaxSaltLength = 30, ///< Max SALT length: salt prefix (6) + extended panid (8) + network name (16)
+};
+
+/**
+ * This function performs PKCS#5 PBKDF2 using CMAC (AES-CMAC-PRF-128).
*
* @param[in] aPassword Password to use when generating key.
* @param[in] aPasswordLen Length of password.
@@ -58,16 +67,21 @@
* @param[out] aKey A pointer to the generated key.
*
*/
-void otPbkdf2Cmac(const uint8_t *aPassword,
- uint16_t aPasswordLen,
- const uint8_t *aSalt,
- uint16_t aSaltLen,
- uint32_t aIterationCounter,
- uint16_t aKeyLen,
- uint8_t * aKey);
+void GenerateKey(const uint8_t *aPassword,
+ uint16_t aPasswordLen,
+ const uint8_t *aSalt,
+ uint16_t aSaltLen,
+ uint32_t aIterationCounter,
+ uint16_t aKeyLen,
+ uint8_t * aKey);
-#ifdef __cplusplus
-} // extern "C"
-#endif
+/**
+ * @}
+ *
+ */
-#endif // PBKDF2_CMAC_H_
+} // namespace Pbkdf2
+} // namespace Crypto
+} // namespace ot
+
+#endif // PBKDF2_CMAC_HPP_
diff --git a/src/core/crypto/sha256.cpp b/src/core/crypto/sha256.cpp
index 340fe55..9721d29 100644
--- a/src/core/crypto/sha256.cpp
+++ b/src/core/crypto/sha256.cpp
@@ -33,6 +33,8 @@
#include "sha256.hpp"
+#include "common/message.hpp"
+
namespace ot {
namespace Crypto {
@@ -51,9 +53,22 @@
mbedtls_sha256_starts_ret(&mContext, 0);
}
-void Sha256::Update(const uint8_t *aBuf, uint16_t aBufLength)
+void Sha256::Update(const void *aBuf, uint16_t aBufLength)
{
- mbedtls_sha256_update_ret(&mContext, aBuf, aBufLength);
+ mbedtls_sha256_update_ret(&mContext, reinterpret_cast<const uint8_t *>(aBuf), aBufLength);
+}
+
+void Sha256::Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
+{
+ Message::Chunk chunk;
+
+ aMessage.GetFirstChunk(aOffset, aLength, chunk);
+
+ while (chunk.GetLength() > 0)
+ {
+ Update(chunk.GetData(), chunk.GetLength());
+ aMessage.GetNextChunk(aLength, chunk);
+ }
}
void Sha256::Finish(Hash &aHash)
diff --git a/src/core/crypto/sha256.hpp b/src/core/crypto/sha256.hpp
index 326f435..627a5f5 100644
--- a/src/core/crypto/sha256.hpp
+++ b/src/core/crypto/sha256.hpp
@@ -44,8 +44,12 @@
#include "common/clearable.hpp"
#include "common/equatable.hpp"
+#include "common/type_traits.hpp"
namespace ot {
+
+class Message;
+
namespace Crypto {
/**
@@ -84,13 +88,13 @@
};
/**
- * Constructor for initializing mbedtls_sha256_context.
+ * Constructor for `Sha256` object.
*
*/
Sha256(void);
/**
- * Destructor for freeing mbedtls_sha256_context.
+ * Destructor for `Sha256` object.
*
*/
~Sha256(void);
@@ -108,7 +112,31 @@
* @param[in] aBufLength The length of @p aBuf in bytes.
*
*/
- void Update(const uint8_t *aBuf, uint16_t aBufLength);
+ void Update(const void *aBuf, uint16_t aBufLength);
+
+ /**
+ * This method inputs an object (treated as a sequence of bytes) into the SHA-256 computation.
+ *
+ * @tparam ObjectType The object type.
+ *
+ * @param[in] aObject A reference to the object.
+ *
+ */
+ template <typename ObjectType> void Update(const ObjectType &aObject)
+ {
+ static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
+ return Update(&aObject, sizeof(ObjectType));
+ }
+
+ /**
+ * This method inputs the bytes read from a given message into the SHA-256 computation.
+ *
+ * @param[in] aMessage The message to read the data from.
+ * @param[in] aOffset The offset into @p aMessage to start to read.
+ * @param[in] aLength The number of bytes to read.
+ *
+ */
+ void Update(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
/**
* This method finalizes the hash computation.
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 783b845..11c9087 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -58,7 +58,7 @@
OT_UNUSED_VARIABLE(aOutput);
OT_UNUSED_VARIABLE(aOutputMaxLen);
- return OT_ERROR_INVALID_COMMAND;
+ return ot::kErrorInvalidCommand;
}
namespace ot {
@@ -79,15 +79,15 @@
{
}
-otError Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
- long value;
+ Error error = kErrorNone;
+ long value;
- VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength == 1, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
- VerifyOrExit(value >= Radio::kChannelMin && value <= Radio::kChannelMax, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value >= Radio::kChannelMin && value <= Radio::kChannelMax, error = kErrorInvalidArgs);
otPlatDiagChannelSet(static_cast<uint8_t>(value));
@@ -96,12 +96,12 @@
return error;
}
-otError Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
- long value;
+ Error error = kErrorNone;
+ long value;
- VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength == 1, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
@@ -112,7 +112,7 @@
return error;
}
-otError Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
@@ -121,10 +121,10 @@
otPlatDiagModeSet(true);
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-otError Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
@@ -133,7 +133,7 @@
otPlatDiagModeSet(false);
- return OT_ERROR_NONE;
+ return kErrorNone;
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
@@ -162,11 +162,11 @@
mStats.Clear();
}
-otError Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
if (aArgsLength == 0)
{
@@ -177,7 +177,7 @@
long value;
SuccessOrExit(error = ParseLong(aArgs[0], value));
- VerifyOrExit(value >= Radio::kChannelMin && value <= Radio::kChannelMax, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value >= Radio::kChannelMin && value <= Radio::kChannelMax, error = kErrorInvalidArgs);
mChannel = static_cast<uint8_t>(value);
IgnoreError(Get<Radio>().Receive(mChannel));
@@ -191,11 +191,11 @@
return error;
}
-otError Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
if (aArgsLength == 0)
{
@@ -219,12 +219,12 @@
return error;
}
-otError Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
+ VerifyOrExit(aArgsLength > 0, error = kErrorInvalidArgs);
if (strcmp(aArgs[0], "stop") == 0)
{
@@ -236,13 +236,13 @@
{
long value;
- VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength == 2, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
mTxPeriod = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgs[1], value));
- VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs);
mTxLen = static_cast<uint8_t>(value);
mRepeatActive = true;
@@ -257,19 +257,19 @@
return error;
}
-otError Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
- long value;
+ Error error = kErrorNone;
+ long value;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
+ VerifyOrExit(aArgsLength == 2, error = kErrorInvalidArgs);
SuccessOrExit(error = ParseLong(aArgs[0], value));
mTxPackets = static_cast<uint32_t>(value);
SuccessOrExit(error = ParseLong(aArgs[1], value));
- VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value <= OT_RADIO_FRAME_MAX_SIZE, error = kErrorInvalidArgs);
mTxLen = static_cast<uint8_t>(value);
snprintf(aOutput, aOutputMaxLen, "sending %#x packet(s), length %#x\r\nstatus 0x%02x\r\n",
@@ -281,14 +281,14 @@
return error;
}
-otError Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!Get<ThreadNetif>().IsUp(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);
@@ -307,11 +307,11 @@
return error;
}
-otError Diags::ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
if ((aArgsLength == 1) && (strcmp(aArgs[0], "clear") == 0))
{
@@ -320,7 +320,7 @@
}
else
{
- VerifyOrExit(aArgsLength == 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength == 0, error = kErrorInvalidArgs);
snprintf(aOutput, aOutputMaxLen,
"received packets: %d\r\nsent packets: %d\r\n"
"first received packet: rssi=%d, lqi=%d\r\n"
@@ -335,14 +335,14 @@
return error;
}
-otError Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
otPlatAlarmMilliStop(&GetInstance());
otPlatDiagModeSet(false);
@@ -375,12 +375,12 @@
IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
}
-otError Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_INVALID_ARGS;
+ Error error = kErrorInvalidArgs;
- VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(otPlatDiagModeGet(), error = kErrorInvalidState);
+ VerifyOrExit(aArgsLength > 0, error = kErrorInvalidArgs);
if (strcmp(aArgs[0], "sleep") == 0)
{
@@ -401,7 +401,7 @@
{
otRadioState state = Get<Radio>().GetState();
- error = OT_ERROR_NONE;
+ error = kErrorNone;
switch (state)
{
@@ -454,9 +454,9 @@
}
}
-void Diags::ReceiveDone(otRadioFrame *aFrame, otError aError)
+void Diags::ReceiveDone(otRadioFrame *aFrame, Error aError)
{
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
// for sensitivity test, only record the rssi and lqi for the first and last packet
if (mStats.mReceivedPackets == 0)
@@ -474,9 +474,9 @@
otPlatDiagRadioReceived(&GetInstance(), aFrame, aError);
}
-void Diags::TransmitDone(otError aError)
+void Diags::TransmitDone(Error aError)
{
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
mStats.mSentPackets++;
@@ -499,19 +499,19 @@
#endif // OPENTHREAD_RADIO
-void Diags::AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen)
+void Diags::AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen)
{
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
}
}
-otError Diags::ParseLong(char *aString, long &aLong)
+Error Diags::ParseLong(char *aString, long &aLong)
{
char *endptr;
aLong = strtol(aString, &endptr, 0);
- return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE;
+ return (*endptr == '\0') ? kErrorNone : kErrorParse;
}
void Diags::ProcessLine(const char *aString, char *aOutput, size_t aOutputMaxLen)
@@ -522,12 +522,12 @@
kMaxCommandBuffer = OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE,
};
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
char buffer[kMaxCommandBuffer];
char * aArgsector[kMaxArgs];
uint8_t argCount = 0;
- VerifyOrExit(StringLength(aString, kMaxCommandBuffer) < kMaxCommandBuffer, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(StringLength(aString, kMaxCommandBuffer) < kMaxCommandBuffer, error = kErrorNoBufs);
strcpy(buffer, aString);
error = ot::Utils::CmdLineParser::ParseCmd(buffer, argCount, aArgsector, kMaxArgs);
@@ -536,16 +536,16 @@
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
aOutput[0] = '\0'; // In case there is no output.
IgnoreError(ProcessCmd(argCount, &aArgsector[0], aOutput, aOutputMaxLen));
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
snprintf(aOutput, aOutputMaxLen, "failed: command string too long\r\n");
break;
- case OT_ERROR_INVALID_ARGS:
+ case kErrorInvalidArgs:
snprintf(aOutput, aOutputMaxLen, "failed: command string contains too many arguments\r\n");
break;
@@ -555,9 +555,9 @@
}
}
-otError Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
+Error Diags::ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
// 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.
@@ -594,7 +594,7 @@
exit:
// Add more platform specific diagnostics features here.
- if (error == OT_ERROR_INVALID_COMMAND && aArgsLength > 1)
+ if (error == kErrorInvalidCommand && aArgsLength > 1)
{
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", aArgs[0]);
}
diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp
index 3c3dd41..78f7814 100644
--- a/src/core/diags/factory_diags.hpp
+++ b/src/core/diags/factory_diags.hpp
@@ -40,6 +40,7 @@
#include <openthread/platform/radio.h>
+#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
@@ -77,12 +78,12 @@
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*
- * @retval OT_ERROR_INVALID_ARGS The command is supported but invalid arguments provided.
- * @retval OT_ERROR_NONE The command is successfully process.
- * @retval OT_ERROR_NOT_IMPLEMENTED The command is not supported.
+ * @retval kErrorInvalidArgs The command is supported but invalid arguments provided.
+ * @retval kErrorNone The command is successfully process.
+ * @retval kErrorNotImplemented The command is not supported.
*
*/
- otError ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessCmd(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
/**
* This method indicates whether or not the factory diagnostics mode is enabled.
@@ -103,28 +104,28 @@
* The radio driver calls this method to notify OpenThread diagnostics module of a received frame.
*
* @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received,
- * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received,
+ * kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
- void ReceiveDone(otRadioFrame *aFrame, otError aError);
+ void ReceiveDone(otRadioFrame *aFrame, Error aError);
/**
* The radio driver calls this method to notify OpenThread diagnostics module that the transmission has completed.
*
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted,
+ * kErrorChannelAccessFailure tx could not take place due to activity on channel,
+ * kErrorAbort when transmission was aborted for other reasons.
*
*/
- void TransmitDone(otError aError);
+ void TransmitDone(Error aError);
private:
struct Command
{
const char *mName;
- otError (Diags::*mCommand)(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error (Diags::*mCommand)(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
};
struct Stats
@@ -139,19 +140,19 @@
uint8_t mLastLqi;
};
- otError ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
- otError ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessChannel(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessPower(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessRadio(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessRepeat(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessSend(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessStart(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessStats(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
+ Error ProcessStop(uint8_t aArgsLength, char *aArgs[], char *aOutput, size_t aOutputMaxLen);
void TransmitPacket(void);
- static void AppendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen);
- static otError ParseLong(char *aString, long &aLong);
+ static void AppendErrorResult(Error aError, char *aOutput, size_t aOutputMaxLen);
+ static Error ParseLong(char *aString, long &aLong);
static const struct Command sCommands[];
diff --git a/src/core/mac/channel_mask.cpp b/src/core/mac/channel_mask.cpp
index 097e0c9..f10b28a 100644
--- a/src/core/mac/channel_mask.cpp
+++ b/src/core/mac/channel_mask.cpp
@@ -44,7 +44,7 @@
uint8_t num = 0;
uint8_t channel = kChannelIteratorFirst;
- while (GetNextChannel(channel) == OT_ERROR_NONE)
+ while (GetNextChannel(channel) == kErrorNone)
{
num++;
}
@@ -52,9 +52,9 @@
return num;
}
-otError ChannelMask::GetNextChannel(uint8_t &aChannel) const
+Error ChannelMask::GetNextChannel(uint8_t &aChannel) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
if (aChannel == kChannelIteratorFirst)
{
@@ -65,7 +65,7 @@
{
if (ContainsChannel(aChannel))
{
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -98,18 +98,18 @@
InfoString string;
uint8_t channel = kChannelIteratorFirst;
bool addComma = false;
- otError error;
+ Error error;
IgnoreError(string.Append("{"));
error = GetNextChannel(channel);
- while (error == OT_ERROR_NONE)
+ while (error == kErrorNone)
{
uint8_t rangeStart = channel;
uint8_t rangeEnd = channel;
- while ((error = GetNextChannel(channel)) == OT_ERROR_NONE)
+ while ((error = GetNextChannel(channel)) == kErrorNone)
{
if (channel != rangeEnd + 1)
{
diff --git a/src/core/mac/channel_mask.hpp b/src/core/mac/channel_mask.hpp
index b90ad65..e9dbbd4 100644
--- a/src/core/mac/channel_mask.hpp
+++ b/src/core/mac/channel_mask.hpp
@@ -39,6 +39,7 @@
#include <limits.h>
#include <openthread/platform/radio.h>
+#include "common/equatable.hpp"
#include "common/string.hpp"
#include "radio/radio.hpp"
@@ -61,7 +62,7 @@
* It is a wrapper class around a `uint32_t` bit vector representing a set of channels.
*
*/
-class ChannelMask
+class ChannelMask : public Unequatable<ChannelMask>
{
public:
enum
@@ -201,11 +202,11 @@
* On entry it should contain the previous channel or `kChannelIteratorFirst`.
* On exit it contains the next channel.
*
- * @retval OT_ERROR_NONE Got the next channel, @p aChannel updated successfully.
- * @retval OT_ERROR_NOT_FOUND No next channel in the channel mask (note: @p aChannel may be changed).
+ * @retval kErrorNone Got the next channel, @p aChannel updated successfully.
+ * @retval kErrorNotFound No next channel in the channel mask (note: @p aChannel may be changed).
*
*/
- otError GetNextChannel(uint8_t &aChannel) const;
+ Error GetNextChannel(uint8_t &aChannel) const;
/**
* This method randomly chooses a channel from the channel mask.
@@ -226,16 +227,6 @@
bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); }
/**
- * This method overloads `!=` operator to indicate whether two masks are different.
- *
- * @param[in] aAnother A reference to another mask to compare with the current one.
- *
- * @returns TRUE if the two masks are different, FALSE otherwise.
- *
- */
- bool operator!=(const ChannelMask &aAnother) const { return !(*this == aAnother); }
-
- /**
* This method converts the channel mask into a human-readable string.
*
* Examples of possible output:
diff --git a/src/core/mac/data_poll_handler.cpp b/src/core/mac/data_poll_handler.cpp
index cc939b6..b407479 100644
--- a/src/core/mac/data_poll_handler.cpp
+++ b/src/core/mac/data_poll_handler.cpp
@@ -47,16 +47,16 @@
{
}
-inline otError DataPollHandler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame,
- FrameContext &aContext,
- Child & aChild)
+inline Error DataPollHandler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame,
+ FrameContext &aContext,
+ Child & aChild)
{
return Get<IndirectSender>().PrepareFrameForChild(aFrame, aContext, aChild);
}
inline void DataPollHandler::Callbacks::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
- otError aError,
+ Error aError,
Child & aChild)
{
Get<IndirectSender>().HandleSentFrameToChild(aFrame, aContext, aError, aChild);
@@ -183,7 +183,7 @@
frame = &aTxFrames.GetTxFrame();
#endif
- VerifyOrExit(mCallbacks.PrepareFrameForChild(*frame, mFrameContext, *mIndirectTxChild) == OT_ERROR_NONE,
+ VerifyOrExit(mCallbacks.PrepareFrameForChild(*frame, mFrameContext, *mIndirectTxChild) == kErrorNone,
frame = nullptr);
if (mIndirectTxChild->GetIndirectTxAttempts() > 0)
@@ -210,7 +210,7 @@
return frame;
}
-void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError)
+void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError)
{
Child *child = mIndirectTxChild;
@@ -223,7 +223,7 @@
ProcessPendingPolls();
}
-void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError, Child &aChild)
+void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild)
{
if (aChild.IsFramePurgePending())
{
@@ -236,21 +236,21 @@
switch (aError)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
aChild.ResetIndirectTxAttempts();
aChild.SetFrameReplacePending(false);
break;
- case OT_ERROR_NO_ACK:
+ case kErrorNoAck:
aChild.IncrementIndirectTxAttempts();
otLogInfoMac("Indirect tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(),
aChild.GetIndirectTxAttempts(), kMaxPollTriggeredTxAttempts);
- // Fall through
+ OT_FALL_THROUGH;
- case OT_ERROR_CHANNEL_ACCESS_FAILURE:
- case OT_ERROR_ABORT:
+ case kErrorChannelAccessFailure:
+ case kErrorAbort:
if (aChild.IsFrameReplacePending())
{
diff --git a/src/core/mac/data_poll_handler.hpp b/src/core/mac/data_poll_handler.hpp
index 6d62853..1e962b0 100644
--- a/src/core/mac/data_poll_handler.hpp
+++ b/src/core/mac/data_poll_handler.hpp
@@ -90,7 +90,7 @@
class ChildInfo
{
friend class DataPollHandler;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
friend class CslTxScheduler;
#endif
@@ -171,27 +171,27 @@
* @param[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed.
* @param[in] aChild The child for which to prepare the frame.
*
- * @retval OT_ERROR_NONE Frame was prepared successfully.
- * @retval OT_ERROR_ABORT Indirect transmission to child should be aborted (no frame for the child).
+ * @retval kErrorNone Frame was prepared successfully.
+ * @retval kErrorAbort Indirect transmission to child should be aborted (no frame for the child).
*
*/
- otError PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
+ Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
/**
* This callback method notifies the end of indirect frame transmission to a child.
*
* @param[in] aFrame The transmitted frame.
* @param[in] aContext The context associated with the frame when it was prepared.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
* @param[in] aChild The child to which the frame was transmitted.
*
*/
void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
- otError aError,
+ Error aError,
Child & aChild);
/**
@@ -272,9 +272,9 @@
// Callbacks from MAC
void HandleDataPoll(Mac::RxFrame &aFrame);
Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames);
- void HandleSentFrame(const Mac::TxFrame &aFrame, otError aError);
+ void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError);
- void HandleSentFrame(const Mac::TxFrame &aFrame, otError aError, Child &aChild);
+ void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild);
void ProcessPendingPolls(void);
// In the current implementation of `DataPollHandler`, we can have a
diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp
index 0d36fd7..a92c003 100644
--- a/src/core/mac/data_poll_sender.cpp
+++ b/src/core/mac/data_poll_sender.cpp
@@ -52,7 +52,7 @@
, mPollPeriod(0)
, mExternalPollPeriod(0)
, mFastPollsUsers(0)
- , mTimer(aInstance, DataPollSender::HandlePollTimer, this)
+ , mTimer(aInstance, DataPollSender::HandlePollTimer)
, mEnabled(false)
, mAttachMode(false)
, mRetxMode(false)
@@ -94,14 +94,14 @@
mEnabled = false;
}
-otError DataPollSender::SendDataPoll(void)
+Error DataPollSender::SendDataPoll(void)
{
- otError error;
+ Error error;
- VerifyOrExit(mEnabled, error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!Get<Mac::Mac>().GetRxOnWhenIdle(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mEnabled, error = kErrorInvalidState);
+ VerifyOrExit(!Get<Mac::Mac>().GetRxOnWhenIdle(), error = kErrorInvalidState);
- VerifyOrExit(GetParent().IsStateValidOrRestoring(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(GetParent().IsStateValidOrRestoring(), error = kErrorInvalidState);
mTimer.Stop();
@@ -111,23 +111,23 @@
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
otLogDebgMac("Sending data poll");
ScheduleNextPoll(kUsePreviousPollPeriod);
break;
- case OT_ERROR_INVALID_STATE:
+ case kErrorInvalidState:
otLogWarnMac("Data poll tx requested while data polling was not enabled!");
StopPolling();
break;
- case OT_ERROR_ALREADY:
+ case kErrorAlready:
otLogDebgMac("Data poll tx requested when a previous data request still in send queue.");
ScheduleNextPoll(kUsePreviousPollPeriod);
break;
default:
- otLogWarnMac("Unexpected error %s requesting data poll", otThreadErrorToString(error));
+ otLogWarnMac("Unexpected error %s requesting data poll", ErrorToString(error));
ScheduleNextPoll(kRecalculatePollPeriod);
break;
}
@@ -136,15 +136,15 @@
}
#if OPENTHREAD_CONFIG_MULTI_RADIO
-otError DataPollSender::GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const
+Error DataPollSender::GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const
#else
-otError DataPollSender::GetPollDestinationAddress(Mac::Address &aDest) const
+Error DataPollSender::GetPollDestinationAddress(Mac::Address &aDest) const
#endif
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const Neighbor &parent = GetParent();
- VerifyOrExit(parent.IsStateValidOrRestoring(), error = OT_ERROR_ABORT);
+ VerifyOrExit(parent.IsStateValidOrRestoring(), error = kErrorAbort);
// Use extended address attaching to a new parent (i.e. parent is the parent candidate).
if ((Get<Mac::Mac>().GetShortAddress() == Mac::kShortAddrInvalid) ||
@@ -165,13 +165,13 @@
return error;
}
-otError DataPollSender::SetExternalPollPeriod(uint32_t aPeriod)
+Error DataPollSender::SetExternalPollPeriod(uint32_t aPeriod)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aPeriod != 0)
{
- VerifyOrExit(aPeriod >= OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aPeriod >= OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD, error = kErrorInvalidArgs);
// Clipped by the maximal value.
if (aPeriod > kMaxExternalPeriod)
@@ -206,7 +206,7 @@
return period;
}
-void DataPollSender::HandlePollSent(Mac::TxFrame &aFrame, otError aError)
+void DataPollSender::HandlePollSent(Mac::TxFrame &aFrame, Error aError)
{
Mac::Address macDest;
bool shouldRecalculatePollPeriod = false;
@@ -228,7 +228,7 @@
switch (aError)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
if (mRemainingFastPolls != 0)
{
@@ -250,8 +250,8 @@
break;
- case OT_ERROR_CHANNEL_ACCESS_FAILURE:
- case OT_ERROR_ABORT:
+ case kErrorChannelAccessFailure:
+ case kErrorAbort:
mRetxMode = true;
shouldRecalculatePollPeriod = true;
break;
@@ -259,8 +259,8 @@
default:
mPollTxFailureCounter++;
- otLogInfoMac("Failed to send data poll, error:%s, retx:%d/%d", otThreadErrorToString(aError),
- mPollTxFailureCounter, kMaxPollRetxAttempts);
+ otLogInfoMac("Failed to send data poll, error:%s, retx:%d/%d", ErrorToString(aError), mPollTxFailureCounter,
+ kMaxPollRetxAttempts);
if (mPollTxFailureCounter < kMaxPollRetxAttempts)
{
@@ -499,7 +499,7 @@
void DataPollSender::HandlePollTimer(Timer &aTimer)
{
- IgnoreError(aTimer.GetOwner<DataPollSender>().SendDataPoll());
+ IgnoreError(aTimer.Get<DataPollSender>().SendDataPoll());
}
uint32_t DataPollSender::GetDefaultPollPeriod(void) const
diff --git a/src/core/mac/data_poll_sender.hpp b/src/core/mac/data_poll_sender.hpp
index 8eb9f06..d37d468 100644
--- a/src/core/mac/data_poll_sender.hpp
+++ b/src/core/mac/data_poll_sender.hpp
@@ -92,13 +92,13 @@
/**
* This method enqueues a data poll (an IEEE 802.15.4 Data Request) message.
*
- * @retval OT_ERROR_NONE Successfully enqueued a data poll message
- * @retval OT_ERROR_ALREADY A data poll message is already enqueued.
- * @retval OT_ERROR_INVALID_STATE Device is not in rx-off-when-idle mode.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available.
+ * @retval kErrorNone Successfully enqueued a data poll message
+ * @retval kErrorAlready A data poll message is already enqueued.
+ * @retval kErrorInvalidState Device is not in rx-off-when-idle mode.
+ * @retval kErrorNoBufs Insufficient message buffers available.
*
*/
- otError SendDataPoll(void);
+ Error SendDataPoll(void);
/**
* This method sets/clears a user-specified/external data poll period.
@@ -111,16 +111,16 @@
* value is larger than the child timeout.
*
* A non-zero `aPeriod` should be larger than or equal to `OPENTHREAD_CONFIG_MAC_MINIMUM_POLL_PERIOD` (10ms) or
- * this method returns `OT_ERROR_INVALID_ARGS`. If a non-zero `aPeriod` is larger than maximum value of
+ * this method returns `kErrorInvalidArgs`. If a non-zero `aPeriod` is larger than maximum value of
* `0x3FFFFFF ((1 << 26) - 1)`, it would be clipped to this value.
*
* @param[in] aPeriod The data poll period in milliseconds.
*
- * @retval OT_ERROR_NONE Successfully set/cleared user-specified poll period.
- * @retval OT_ERROR_INVALID_ARGS If aPeriod is invalid.
+ * @retval kErrorNone Successfully set/cleared user-specified poll period.
+ * @retval kErrorInvalidArgs If aPeriod is invalid.
*
*/
- otError SetExternalPollPeriod(uint32_t aPeriod);
+ Error SetExternalPollPeriod(uint32_t aPeriod);
/**
* This method gets the current user-specified/external data poll period.
@@ -137,22 +137,22 @@
* @param[out] aDest Reference to a `MAC::Address` to output the poll destination address (on success).
* @param[out] aRadioType Reference to a `Mac::RadioType` to output the link type (on success).
*
- * @retval OT_ERROR_NONE @p aDest and @p aRadioType were updated successfully.
- * @retval OT_ERROR_ABORT Abort the data poll transmission (not currently attached to any parent).
+ * @retval kErrorNone @p aDest and @p aRadioType were updated successfully.
+ * @retval kErrorAbort Abort the data poll transmission (not currently attached to any parent).
*
*/
- otError GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const;
+ Error GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const;
#else
/**
* This method gets the destination MAC address for a data poll frame.
*
* @param[out] aDest Reference to a `MAC::Address` to output the poll destination address (on success).
*
- * @retval OT_ERROR_NONE @p aDest was updated successfully.
- * @retval OT_ERROR_ABORT Abort the data poll transmission (not currently attached to any parent).
+ * @retval kErrorNone @p aDest was updated successfully.
+ * @retval kErrorAbort Abort the data poll transmission (not currently attached to any parent).
*
*/
- otError GetPollDestinationAddress(Mac::Address &aDest) const;
+ Error GetPollDestinationAddress(Mac::Address &aDest) const;
#endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
/**
@@ -166,7 +166,7 @@
* @param[in] aError Error status of a data poll message transmission.
*
*/
- void HandlePollSent(Mac::TxFrame &aFrame, otError aError);
+ void HandlePollSent(Mac::TxFrame &aFrame, Error aError);
/**
* This method informs the data poll sender that a data poll timeout happened, i.e., when the ack in response to
diff --git a/src/core/mac/link_raw.cpp b/src/core/mac/link_raw.cpp
index 5f8766c..4abd372 100644
--- a/src/core/mac/link_raw.cpp
+++ b/src/core/mac/link_raw.cpp
@@ -64,23 +64,32 @@
{
}
-otError LinkRaw::SetReceiveDone(otLinkRawReceiveDone aCallback)
+Error LinkRaw::SetReceiveDone(otLinkRawReceiveDone aCallback)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
+ bool enable = aCallback != nullptr;
- otLogDebgMac("LinkRaw::Enabled(%s)", (aCallback != nullptr ? "true" : "false"));
+ otLogDebgMac("LinkRaw::Enabled(%s)", (enable ? "true" : "false"));
#if OPENTHREAD_MTD || OPENTHREAD_FTD
- VerifyOrExit(!Get<ThreadNetif>().IsUp(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
// In MTD/FTD build, `Mac` has already enabled sub-mac. We ensure to
// disable/enable MAC layer when link-raw is being enabled/disabled to
// avoid any conflict in control of radio and sub-mac between `Mac` and
// `LinkRaw`. in RADIO build, we directly enable/disable sub-mac.
- Get<Mac>().SetEnabled(aCallback == nullptr);
+ if (!enable)
+ {
+ // When disabling link-raw, make sure there is no ongoing
+ // transmit or scan operation. Otherwise Mac will attempt to
+ // handle an unexpected "done" callback.
+ VerifyOrExit(!mSubMac.IsTransmittingOrScanning(), error = kErrorBusy);
+ }
+
+ Get<Mac>().SetEnabled(!enable);
#else
- if (aCallback)
+ if (enable)
{
SuccessOrExit(error = mSubMac.Enable());
}
@@ -96,11 +105,11 @@
return error;
}
-otError LinkRaw::SetPanId(uint16_t aPanId)
+Error LinkRaw::SetPanId(uint16_t aPanId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetPanId(aPanId);
mPanId = aPanId;
@@ -108,44 +117,44 @@
return error;
}
-otError LinkRaw::SetChannel(uint8_t aChannel)
+Error LinkRaw::SetChannel(uint8_t aChannel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mReceiveChannel = aChannel;
exit:
return error;
}
-otError LinkRaw::SetExtAddress(const ExtAddress &aExtAddress)
+Error LinkRaw::SetExtAddress(const ExtAddress &aExtAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetExtAddress(aExtAddress);
exit:
return error;
}
-otError LinkRaw::SetShortAddress(ShortAddress aShortAddress)
+Error LinkRaw::SetShortAddress(ShortAddress aShortAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetShortAddress(aShortAddress);
exit:
return error;
}
-otError LinkRaw::Receive(void)
+Error LinkRaw::Receive(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
SuccessOrExit(error = mSubMac.Receive(mReceiveChannel));
@@ -153,22 +162,22 @@
return error;
}
-void LinkRaw::InvokeReceiveDone(RxFrame *aFrame, otError aError)
+void LinkRaw::InvokeReceiveDone(RxFrame *aFrame, Error aError)
{
otLogDebgMac("LinkRaw::ReceiveDone(%d bytes), error:%s", (aFrame != nullptr) ? aFrame->mLength : 0,
- otThreadErrorToString(aError));
+ ErrorToString(aError));
- if (mReceiveDoneCallback && (aError == OT_ERROR_NONE))
+ if (mReceiveDoneCallback && (aError == kErrorNone))
{
mReceiveDoneCallback(&GetInstance(), aFrame, aError);
}
}
-otError LinkRaw::Transmit(otLinkRawTransmitDone aCallback)
+Error LinkRaw::Transmit(otLinkRawTransmitDone aCallback)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
SuccessOrExit(error = mSubMac.Send());
mTransmitDoneCallback = aCallback;
@@ -177,9 +186,9 @@
return error;
}
-void LinkRaw::InvokeTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
+void LinkRaw::InvokeTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
{
- otLogDebgMac("LinkRaw::TransmitDone(%d bytes), error:%s", aFrame.mLength, otThreadErrorToString(aError));
+ otLogDebgMac("LinkRaw::TransmitDone(%d bytes), error:%s", aFrame.mLength, ErrorToString(aError));
if (mTransmitDoneCallback)
{
@@ -188,11 +197,11 @@
}
}
-otError LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback)
+Error LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
SuccessOrExit(error = mSubMac.EnergyScan(aScanChannel, aScanDuration));
mEnergyScanDoneCallback = aCallback;
@@ -210,26 +219,26 @@
}
}
-otError LinkRaw::SetMacKey(uint8_t aKeyIdMode,
- uint8_t aKeyId,
- const Key &aPrevKey,
- const Key &aCurrKey,
- const Key &aNextKey)
+Error LinkRaw::SetMacKey(uint8_t aKeyIdMode,
+ uint8_t aKeyId,
+ const Key &aPrevKey,
+ const Key &aCurrKey,
+ const Key &aNextKey)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetMacKey(aKeyIdMode, aKeyId, aPrevKey, aCurrKey, aNextKey);
exit:
return error;
}
-otError LinkRaw::SetMacFrameCounter(uint32_t aMacFrameCounter)
+Error LinkRaw::SetMacFrameCounter(uint32_t aMacFrameCounter)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetFrameCounter(aMacFrameCounter);
exit:
@@ -242,16 +251,16 @@
void LinkRaw::RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx)
{
OT_UNUSED_VARIABLE(aAckFrame);
OT_UNUSED_VARIABLE(aWillRetx);
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
- otLogInfoMac("Frame tx failed, error:%s, retries:%d/%d, %s", otThreadErrorToString(aError), aRetryCount,
+ otLogInfoMac("Frame tx failed, error:%s, retries:%d/%d, %s", ErrorToString(aError), aRetryCount,
aFrame.GetMaxFrameRetries(), aFrame.ToInfoString().AsCString());
}
}
diff --git a/src/core/mac/link_raw.hpp b/src/core/mac/link_raw.hpp
index 0f0c819..ed0fecf 100644
--- a/src/core/mac/link_raw.hpp
+++ b/src/core/mac/link_raw.hpp
@@ -80,12 +80,12 @@
* raw link-layer.
*
*
- * @retval OT_ERROR_INVALID_STATE Thread stack is enabled.
- * @retval OT_ERROR_FAILED The radio could not be enabled/disabled.
- * @retval OT_ERROR_NONE Successfully enabled/disabled raw link.
+ * @retval kErrorInvalidState Thread stack is enabled.
+ * @retval kErrorFailed The radio could not be enabled/disabled.
+ * @retval kErrorNone Successfully enabled/disabled raw link.
*
*/
- otError SetReceiveDone(otLinkRawReceiveDone aCallback);
+ Error SetReceiveDone(otLinkRawReceiveDone aCallback);
/**
* This method returns the capabilities of the raw link-layer.
@@ -98,22 +98,22 @@
/**
* This method starts a (recurring) Receive on the link-layer.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Receive.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
+ * @retval kErrorNone Successfully transitioned to Receive.
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
- otError Receive(void);
+ Error Receive(void);
/**
* This method invokes the mReceiveDoneCallback, if set.
*
* @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received,
- * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received,
+ * kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
- void InvokeReceiveDone(RxFrame *aFrame, otError aError);
+ void InvokeReceiveDone(RxFrame *aFrame, Error aError);
/**
* This method gets the radio transmit frame.
@@ -126,28 +126,28 @@
/**
* This method starts a (single) Transmit on the link-layer.
*
- * @note The callback @p aCallback will not be called if this call does not return OT_ERROR_NONE.
+ * @note The callback @p aCallback will not be called if this call does not return kErrorNone.
*
* @param[in] aCallback A pointer to a function called on completion of the transmission.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Transmit.
- * @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
+ * @retval kErrorNone Successfully transitioned to Transmit.
+ * @retval kErrorInvalidState The radio was not in the Receive state.
*
*/
- otError Transmit(otLinkRawTransmitDone aCallback);
+ Error Transmit(otLinkRawTransmitDone aCallback);
/**
* This method invokes the mTransmitDoneCallback, if set.
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
*
*/
- void InvokeTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError);
+ void InvokeTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
/**
* This method starts a (single) Energy Scan on the link-layer.
@@ -156,12 +156,12 @@
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
* @param[in] aCallback A pointer to a function called on completion of a scanned channel.
*
- * @retval OT_ERROR_NONE Successfully started scanning the channel.
- * @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone Successfully started scanning the channel.
+ * @retval kErrorNotImplemented The radio doesn't support energy scanning.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback);
+ Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback);
/**
* This method invokes the mEnergyScanDoneCallback, if set.
@@ -184,11 +184,11 @@
*
* @param[in] aShortAddress The short address.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError SetShortAddress(ShortAddress aShortAddress);
+ Error SetShortAddress(ShortAddress aShortAddress);
/**
* This function returns PANID.
@@ -203,11 +203,11 @@
*
* @param[in] aPanId The PANID.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError SetPanId(PanId aPanId);
+ Error SetPanId(PanId aPanId);
/**
* This method gets the current receiving channel.
@@ -223,7 +223,7 @@
* @param[in] aChannel The channel to use for receiving.
*
*/
- otError SetChannel(uint8_t aChannel);
+ Error SetChannel(uint8_t aChannel);
/**
* This function returns the extended address.
@@ -238,11 +238,11 @@
*
* @param[in] aExtAddress The extended address.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError SetExtAddress(const ExtAddress &aExtAddress);
+ Error SetExtAddress(const ExtAddress &aExtAddress);
/**
* This method updates MAC keys and key index.
@@ -253,26 +253,22 @@
* @param[in] aCurrKey The current MAC key.
* @param[in] aNextKey The next MAC key.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError SetMacKey(uint8_t aKeyIdMode,
- uint8_t aKeyId,
- const Key &aPrevKey,
- const Key &aCurrKey,
- const Key &aNextKey);
+ Error SetMacKey(uint8_t aKeyIdMode, uint8_t aKeyId, const Key &aPrevKey, const Key &aCurrKey, const Key &aNextKey);
/**
* This method sets the current MAC frame counter value.
*
* @param[in] aMacFrameCounter The MAC frame counter value.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
- otError SetMacFrameCounter(uint32_t aMacFrameCounter);
+ Error SetMacFrameCounter(uint32_t aMacFrameCounter);
/**
* This method records the status of a frame transmission attempt and is mainly used for logging failures.
@@ -282,10 +278,10 @@
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, or nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
* @param[in] aRetryCount Indicates number of transmission retries for this frame.
* @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only
* when there was an error in transmission (i.e., `aError` is not NONE).
@@ -294,11 +290,11 @@
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
void RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx);
#else
- void RecordFrameTransmitStatus(const TxFrame &, const RxFrame *, otError, uint8_t, bool) {}
+ void RecordFrameTransmitStatus(const TxFrame &, const RxFrame *, Error, uint8_t, bool) {}
#endif
private:
diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp
index de0a50a..6a1d6d4 100644
--- a/src/core/mac/mac.cpp
+++ b/src/core/mac/mac.cpp
@@ -70,7 +70,7 @@
const char Mac::sNetworkNameInit[] = "OpenThread";
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-const char Mac::sDomainNameInit[] = "Thread";
+const char Mac::sDomainNameInit[] = "DefaultDomain";
#endif
Mac::Mac(Instance &aInstance)
@@ -82,6 +82,9 @@
, mPendingTransmitDataDirect(false)
#if OPENTHREAD_FTD
, mPendingTransmitDataIndirect(false)
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ , mPendingTransmitDataCsl(false)
+#endif
#endif
, mPendingTransmitPoll(false)
, mPendingTransmitOobFrame(false)
@@ -108,20 +111,20 @@
, mMaxFrameRetriesDirect(kDefaultMaxFrameRetriesDirect)
#if OPENTHREAD_FTD
, mMaxFrameRetriesIndirect(kDefaultMaxFrameRetriesIndirect)
-#endif
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
, mCslTxFireTime(TimeMilli::kMaxDuration)
#endif
+#endif
, mActiveScanHandler(nullptr) // Initialize `mActiveScanHandler` and `mEnergyScanHandler` union
, mScanHandlerContext(nullptr)
, mLinks(aInstance)
- , mOperationTask(aInstance, Mac::HandleOperationTask, this)
- , mTimer(aInstance, Mac::HandleTimer, this)
+ , mOperationTask(aInstance, Mac::HandleOperationTask)
+ , mTimer(aInstance, Mac::HandleTimer)
, mOobFrame(nullptr)
, mKeyIdMode2FrameCounter(0)
, mCcaSampleCount(0)
#if OPENTHREAD_CONFIG_MULTI_RADIO
- , mTxError(OT_ERROR_NONE)
+ , mTxError(kErrorNone)
#endif
{
ExtAddress randomExtAddress;
@@ -146,12 +149,12 @@
SetShortAddress(GetShortAddress());
}
-otError Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext)
+Error Mac::ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = OT_ERROR_BUSY);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
+ VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
mActiveScanHandler = aHandler;
mScanHandlerContext = aContext;
@@ -167,12 +170,12 @@
return error;
}
-otError Mac::EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext)
+Error Mac::EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = OT_ERROR_BUSY);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
+ VerifyOrExit(!IsActiveScanInProgress() && !IsEnergyScanInProgress(), error = kErrorBusy);
mEnergyScanHandler = aHandler;
mScanHandlerContext = aContext;
@@ -207,7 +210,7 @@
case kOperationTransmitDataDirect:
#if OPENTHREAD_FTD
case kOperationTransmitDataIndirect:
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
case kOperationTransmitDataCsl:
#endif
#endif
@@ -228,9 +231,9 @@
return retval;
}
-otError Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult)
+Error Mac::ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Address address;
const Beacon * beacon = nullptr;
const BeaconPayload *beaconPayload = nullptr;
@@ -238,14 +241,14 @@
memset(&aResult, 0, sizeof(ActiveScanResult));
- VerifyOrExit(aBeaconFrame != nullptr, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aBeaconFrame != nullptr, error = kErrorInvalidArgs);
- VerifyOrExit(aBeaconFrame->GetType() == Frame::kFcfFrameBeacon, error = OT_ERROR_PARSE);
+ VerifyOrExit(aBeaconFrame->GetType() == Frame::kFcfFrameBeacon, error = kErrorParse);
SuccessOrExit(error = aBeaconFrame->GetSrcAddr(address));
- VerifyOrExit(address.IsExtended(), error = OT_ERROR_PARSE);
+ VerifyOrExit(address.IsExtended(), error = kErrorParse);
aResult.mExtAddress = address.GetExtended();
- if (OT_ERROR_NONE != aBeaconFrame->GetSrcPanId(aResult.mPanId))
+ if (kErrorNone != aBeaconFrame->GetSrcPanId(aResult.mPanId))
{
IgnoreError(aBeaconFrame->GetDstPanId(aResult.mPanId));
}
@@ -265,7 +268,7 @@
aResult.mIsJoinable = beaconPayload->IsJoiningPermitted();
aResult.mIsNative = beaconPayload->IsNative();
IgnoreError(static_cast<NetworkName &>(aResult.mNetworkName).Set(beaconPayload->GetNetworkName()));
- VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = OT_ERROR_PARSE);
+ VerifyOrExit(IsValidUtf8String(aResult.mNetworkName.m8), error = kErrorParse);
aResult.mExtendedPanId = beaconPayload->GetExtendedPanId();
}
@@ -275,11 +278,11 @@
return error;
}
-otError Mac::UpdateScanChannel(void)
+Error Mac::UpdateScanChannel(void)
{
- otError error;
+ Error error;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_ABORT);
+ VerifyOrExit(IsEnabled(), error = kErrorAbort);
error = mScanChannelMask.GetNextChannel(mScanChannel);
@@ -289,7 +292,7 @@
void Mac::PerformActiveScan(void)
{
- if (UpdateScanChannel() == OT_ERROR_NONE)
+ if (UpdateScanChannel() == kErrorNone)
{
// If there are more channels to scan, send the beacon request.
BeginTransmit();
@@ -325,7 +328,7 @@
void Mac::PerformEnergyScan(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = UpdateScanChannel());
@@ -345,7 +348,7 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FinishOperation();
@@ -417,11 +420,11 @@
return;
}
-otError Mac::SetPanChannel(uint8_t aChannel)
+Error Mac::SetPanChannel(uint8_t aChannel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = kErrorInvalidArgs);
SuccessOrExit(Get<Notifier>().Update(mPanChannel, aChannel, kEventThreadChannelChanged));
@@ -437,11 +440,11 @@
return error;
}
-otError Mac::SetTemporaryChannel(uint8_t aChannel)
+Error Mac::SetTemporaryChannel(uint8_t aChannel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = kErrorInvalidArgs);
mUsingTemporaryChannel = true;
mRadioChannel = aChannel;
@@ -470,7 +473,7 @@
IgnoreError(Get<Notifier>().Update(mSupportedChannelMask, newMask, kEventSupportedChannelMaskChanged));
}
-otError Mac::SetNetworkName(const char *aNameString)
+Error Mac::SetNetworkName(const char *aNameString)
{
// When setting Network Name from a string, we treat it as `NameData`
// with `kMaxSize + 1` chars. `NetworkName::Set(data)` will look
@@ -478,12 +481,12 @@
// the name's length and ensure that the name fits in `kMaxSize`
// chars. The `+ 1` ensures that a `aNameString` with length
// longer than `kMaxSize` is correctly rejected (returning error
- // `OT_ERROR_INVALID_ARGS`).
+ // `kErrorInvalidArgs`).
- otError error;
+ Error error;
NameData data(aNameString, NetworkName::kMaxSize + 1);
- VerifyOrExit(IsValidUtf8String(aNameString), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
error = SetNetworkName(data);
@@ -491,14 +494,14 @@
return error;
}
-otError Mac::SetNetworkName(const NameData &aNameData)
+Error Mac::SetNetworkName(const NameData &aNameData)
{
- otError error = mNetworkName.Set(aNameData);
+ Error error = mNetworkName.Set(aNameData);
- if (error == OT_ERROR_ALREADY)
+ if (error == kErrorAlready)
{
Get<Notifier>().SignalIfFirst(kEventThreadNetworkNameChanged);
- error = OT_ERROR_NONE;
+ error = kErrorNone;
ExitNow();
}
@@ -510,7 +513,7 @@
}
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-otError Mac::SetDomainName(const char *aNameString)
+Error Mac::SetDomainName(const char *aNameString)
{
// When setting Domain Name from a string, we treat it as `NameData`
// with `kMaxSize + 1` chars. `DomainName::Set(data)` will look
@@ -518,12 +521,12 @@
// the name's length and ensure that the name fits in `kMaxSize`
// chars. The `+ 1` ensures that a `aNameString` with length
// longer than `kMaxSize` is correctly rejected (returning error
- // `OT_ERROR_INVALID_ARGS`).
+ // `kErrorInvalidArgs`).
- otError error;
+ Error error;
NameData data(aNameString, DomainName::kMaxSize + 1);
- VerifyOrExit(IsValidUtf8String(aNameString), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsValidUtf8String(aNameString), error = kErrorInvalidArgs);
error = SetDomainName(data);
@@ -531,13 +534,13 @@
return error;
}
-otError Mac::SetDomainName(const NameData &aNameData)
+Error Mac::SetDomainName(const NameData &aNameData)
{
- otError error = mDomainName.Set(aNameData);
+ Error error = mDomainName.Set(aNameData);
- if (error == OT_ERROR_ALREADY)
+ if (error == kErrorAlready)
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
return error;
@@ -581,7 +584,7 @@
return;
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
void Mac::RequestCslFrameTransmission(uint32_t aDelay)
{
VerifyOrExit(mEnabled);
@@ -596,14 +599,13 @@
#endif
#endif // OPENTHREAD_FTD
-otError Mac::RequestOutOfBandFrameTransmission(otRadioFrame *aOobFrame)
+Error Mac::RequestOutOfBandFrameTransmission(otRadioFrame *aOobFrame)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aOobFrame != nullptr, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!mPendingTransmitOobFrame && (mOperation != kOperationTransmitOutOfBandFrame),
- error = OT_ERROR_ALREADY);
+ VerifyOrExit(aOobFrame != nullptr, error = kErrorInvalidArgs);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
+ VerifyOrExit(!mPendingTransmitOobFrame && (mOperation != kOperationTransmitOutOfBandFrame), error = kErrorAlready);
mOobFrame = static_cast<TxFrame *>(aOobFrame);
@@ -613,12 +615,12 @@
return error;
}
-otError Mac::RequestDataPollTransmission(void)
+Error Mac::RequestDataPollTransmission(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!mPendingTransmitPoll && (mOperation != kOperationTransmitPoll), error = OT_ERROR_ALREADY);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
+ VerifyOrExit(!mPendingTransmitPoll && (mOperation != kOperationTransmitPoll), error = kErrorAlready);
// We ensure data frame and data poll tx requests are handled in the
// order they are requested. So if we have a pending direct data frame
@@ -655,7 +657,7 @@
}
#endif
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
else if (mPendingTransmitDataCsl)
{
mTimer.FireAt(mCslTxFireTime);
@@ -727,7 +729,7 @@
mPendingTransmitDataIndirect = true;
break;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
case kOperationTransmitDataCsl:
mPendingTransmitDataCsl = true;
break;
@@ -755,7 +757,7 @@
void Mac::HandleOperationTask(Tasklet &aTasklet)
{
- aTasklet.GetOwner<Mac>().PerformNextOperation();
+ aTasklet.Get<Mac>().PerformNextOperation();
}
void Mac::PerformNextOperation(void)
@@ -772,7 +774,7 @@
mPendingTransmitDataDirect = false;
#if OPENTHREAD_FTD
mPendingTransmitDataIndirect = false;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mPendingTransmitDataCsl = false;
#endif
#endif
@@ -793,7 +795,7 @@
mPendingWaitingForData = false;
mOperation = kOperationWaitingForData;
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
else if (mPendingTransmitDataCsl && TimerMilli::GetNow() >= mCslTxFireTime)
{
mPendingTransmitDataCsl = false;
@@ -870,7 +872,7 @@
case kOperationTransmitDataDirect:
#if OPENTHREAD_FTD
case kOperationTransmitDataIndirect:
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
case kOperationTransmitDataCsl:
#endif
#endif
@@ -900,6 +902,7 @@
TxFrame *frame = nullptr;
Address src, dst;
uint16_t fcf;
+ bool iePresent = Get<MeshForwarder>().CalcIePresent(nullptr);
#if OPENTHREAD_CONFIG_MULTI_RADIO
RadioType radio;
@@ -912,7 +915,13 @@
#endif
fcf = Frame::kFcfFrameMacCmd | Frame::kFcfPanidCompression | Frame::kFcfAckRequest | Frame::kFcfSecurityEnabled;
- UpdateFrameControlField(nullptr, /* aIsTimeSync */ false, fcf);
+
+ if (iePresent)
+ {
+ fcf |= Frame::kFcfIePresent;
+ }
+
+ fcf |= Get<MeshForwarder>().CalcFrameVersion(Get<NeighborTable>().FindNeighbor(dst), iePresent);
if (dst.IsExtended())
{
@@ -935,7 +944,10 @@
frame->SetSrcAddr(src);
frame->SetDstAddr(dst);
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
- IgnoreError(AppendHeaderIe(false, *frame));
+ if (iePresent)
+ {
+ Get<MeshForwarder>().AppendHeaderIe(nullptr, *frame);
+ }
#endif
IgnoreError(frame->SetCommandId(Frame::kMacCmdDataRequest));
@@ -1136,7 +1148,7 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
mTxPendingRadioLinks.Clear();
- mTxError = OT_ERROR_ABORT;
+ mTxError = kErrorAbort;
#endif
VerifyOrExit(IsEnabled());
@@ -1198,7 +1210,7 @@
}
break;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
case kOperationTransmitDataCsl:
txFrames.SetMaxCsmaBackoffs(kMaxCsmaBackoffsCsl);
txFrames.SetMaxFrameRetries(kMaxFrameRetriesCsl);
@@ -1287,15 +1299,15 @@
mTxPendingRadioLinks = txFrames.GetSelectedRadioTypes();
// If the "required radio type set" is empty,`mTxError` starts as
- // `OT_ERROR_ABORT`. In this case, successful tx over any radio
+ // `kErrorAbort`. In this case, successful tx over any radio
// link is sufficient for overall tx to be considered successful.
// When the "required radio type set" is not empty, `mTxError`
- // starts as `OT_ERROR_NONE` and we update it if tx over any link
+ // starts as `kErrorNone` and we update it if tx over any link
// in the required set fails.
if (!txFrames.GetRequiredRadioTypes().IsEmpty())
{
- mTxError = OT_ERROR_NONE;
+ mTxError = kErrorNone;
}
#endif
@@ -1325,7 +1337,7 @@
frame = &txFrames.GetBroadcastTxFrame();
frame->SetLength(0);
- HandleTransmitDone(*frame, nullptr, OT_ERROR_ABORT);
+ HandleTransmitDone(*frame, nullptr, kErrorAbort);
}
}
@@ -1352,7 +1364,7 @@
void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx)
{
@@ -1377,12 +1389,12 @@
switch (aError)
{
- case OT_ERROR_NO_ACK:
+ case kErrorNoAck:
frameTxSuccess = false;
- // Fall through
+ OT_FALL_THROUGH;
- case OT_ERROR_NONE:
+ case kErrorNone:
neighbor->GetLinkInfo().AddFrameTxStatus(frameTxSuccess);
break;
@@ -1393,7 +1405,7 @@
// Log frame transmission failure.
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
LogFrameTxFailure(aFrame, aError, aRetryCount, aWillRetx);
otDumpDebgMac("TX ERR", aFrame.GetHeader(), 16);
@@ -1412,7 +1424,7 @@
// Update neighbor's RSSI link info from the received Ack.
- if ((aError == OT_ERROR_NONE) && ackRequested && (aAckFrame != nullptr) && (neighbor != nullptr))
+ if ((aError == kErrorNone) && ackRequested && (aAckFrame != nullptr) && (neighbor != nullptr))
{
neighbor->GetLinkInfo().AddRss(aAckFrame->GetRssi());
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
@@ -1423,7 +1435,7 @@
#if OPENTHREAD_FTD
if (aAckFrame->GetVersion() == Frame::kFcfFrameVersion2015)
{
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
ProcessCsl(*aAckFrame, dstAddr);
#endif
}
@@ -1434,12 +1446,12 @@
mCounters.mTxTotal++;
- if (aError == OT_ERROR_ABORT)
+ if (aError == kErrorAbort)
{
mCounters.mTxErrAbort++;
}
- if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE)
+ if (aError == kErrorChannelAccessFailure)
{
mCounters.mTxErrBusyChannel++;
}
@@ -1448,7 +1460,7 @@
{
mCounters.mTxAckRequested++;
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
mCounters.mTxAcked++;
}
@@ -1471,7 +1483,7 @@
return;
}
-void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
+void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
if (!aFrame.IsEmpty()
@@ -1509,10 +1521,10 @@
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
// Verify Enh-ACK integrity by checking its MIC
- if ((aError == OT_ERROR_NONE) && (aAckFrame != nullptr) &&
- (ProcessEnhAckSecurity(aFrame, *aAckFrame) != OT_ERROR_NONE))
+ if ((aError == kErrorNone) && (aAckFrame != nullptr) &&
+ (ProcessEnhAckSecurity(aFrame, *aAckFrame) != kErrorNone))
{
- aError = OT_ERROR_NO_ACK;
+ aError = kErrorNoAck;
}
#endif
}
@@ -1531,10 +1543,10 @@
// If the "required radio type set" is empty, successful
// tx over any radio link is sufficient for overall tx to
// be considered successful. In this case `mTxError`
- // starts as `OT_ERROR_ABORT` and we update it only when
- // it is not already `OT_ERROR_NONE`.
+ // starts as `kErrorAbort` and we update it only when
+ // it is not already `kErrorNone`.
- if (mTxError != OT_ERROR_NONE)
+ if (mTxError != kErrorNone)
{
mTxError = aError;
}
@@ -1544,13 +1556,13 @@
// When the "required radio type set" is not empty we
// expect the successful frame tx on all links in this set
// to consider the overall tx successful. In this case,
- // `mTxError` starts as `OT_ERROR_NONE` and we update it
+ // `mTxError` starts as `kErrorNone` and we update it
// if tx over any link in the set fails.
- if (requriedRadios.Contains(radio) && (aError != OT_ERROR_NONE))
+ if (requriedRadios.Contains(radio) && (aError != kErrorNone))
{
otLogDebgMac("Frame tx failed on required radio link %s with error %s", RadioTypeToString(radio),
- otThreadErrorToString(aError));
+ ErrorToString(aError));
mTxError = aError;
}
@@ -1584,7 +1596,7 @@
case kOperationTransmitPoll:
OT_ASSERT(aFrame.IsEmpty() || aFrame.GetAckRequest());
- if ((aError == OT_ERROR_NONE) && (aAckFrame != nullptr))
+ if ((aError == kErrorNone) && (aAckFrame != nullptr))
{
bool framePending = aAckFrame->GetFramePending();
@@ -1605,7 +1617,7 @@
case kOperationTransmitDataDirect:
mCounters.mTxData++;
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
mCounters.mTxDirectMaxRetryExpiry++;
}
@@ -1620,7 +1632,7 @@
FinishOperation();
Get<MeshForwarder>().HandleSentFrame(aFrame, aError);
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
- if (aError == OT_ERROR_NONE && Get<Mle::Mle>().GetParent().IsEnhancedKeepAliveSupported() &&
+ if (aError == kErrorNone && Get<Mle::Mle>().GetParent().IsEnhancedKeepAliveSupported() &&
aFrame.GetSecurityEnabled() && aAckFrame != nullptr)
{
Get<DataPollSender>().ProcessFrame(*aAckFrame);
@@ -1630,7 +1642,7 @@
break;
#if OPENTHREAD_FTD
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
case kOperationTransmitDataCsl:
mCounters.mTxData++;
@@ -1644,7 +1656,7 @@
case kOperationTransmitDataIndirect:
mCounters.mTxData++;
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
mCounters.mTxIndirectMaxRetryExpiry++;
}
@@ -1681,7 +1693,7 @@
void Mac::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mac>().HandleTimer();
+ aTimer.Get<Mac>().HandleTimer();
}
void Mac::HandleTimer(void)
@@ -1711,7 +1723,7 @@
}
#endif
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
else if (mPendingTransmitDataCsl)
{
PerformNextOperation();
@@ -1725,10 +1737,10 @@
}
}
-otError Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor)
+Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor)
{
KeyManager & keyManager = Get<KeyManager>();
- otError error = OT_ERROR_SECURITY;
+ Error error = kErrorSecurity;
uint8_t securityLevel;
uint8_t keyIdMode;
uint32_t frameCounter;
@@ -1737,7 +1749,7 @@
const Key * macKey;
const ExtAddress *extAddress;
- VerifyOrExit(aFrame.GetSecurityEnabled(), error = OT_ERROR_NONE);
+ VerifyOrExit(aFrame.GetSecurityEnabled(), error = kErrorNone);
IgnoreError(aFrame.GetSecurityLevel(securityLevel));
VerifyOrExit(securityLevel == Frame::kSecEncMic32);
@@ -1800,7 +1812,7 @@
#endif
// If frame counter is one off, then frame is a duplicate.
- VerifyOrExit((frameCounter + 1) != neighborFrameCounter, error = OT_ERROR_DUPLICATED);
+ VerifyOrExit((frameCounter + 1) != neighborFrameCounter, error = kErrorDuplicated);
VerifyOrExit(frameCounter >= neighborFrameCounter);
}
@@ -1854,16 +1866,16 @@
}
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-otError Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame)
+Error Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame)
{
- otError error = OT_ERROR_SECURITY;
+ Error error = kErrorSecurity;
uint8_t securityLevel;
uint8_t txKeyId;
uint8_t ackKeyId;
@@ -1875,14 +1887,14 @@
KeyManager &keyManager = Get<KeyManager>();
const Key * macKey;
- VerifyOrExit(aAckFrame.GetSecurityEnabled(), error = OT_ERROR_NONE);
+ VerifyOrExit(aAckFrame.GetSecurityEnabled(), error = kErrorNone);
VerifyOrExit(aAckFrame.IsVersion2015());
IgnoreError(aAckFrame.GetSecurityLevel(securityLevel));
VerifyOrExit(securityLevel == Frame::kSecEncMic32);
IgnoreError(aAckFrame.GetKeyIdMode(keyIdMode));
- VerifyOrExit(keyIdMode == Frame::kKeyIdMode1, error = OT_ERROR_NONE);
+ VerifyOrExit(keyIdMode == Frame::kKeyIdMode1, error = kErrorNone);
IgnoreError(aTxFrame.GetKeyId(txKeyId));
IgnoreError(aAckFrame.GetKeyId(ackKeyId));
@@ -1949,7 +1961,7 @@
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
otLogInfoMac("Frame tx attempt failed, error: Enh-ACK security check fail");
}
@@ -1958,19 +1970,19 @@
}
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-void Mac::HandleReceivedFrame(RxFrame *aFrame, otError aError)
+void Mac::HandleReceivedFrame(RxFrame *aFrame, Error aError)
{
Address srcaddr;
Address dstaddr;
PanId panid;
Neighbor *neighbor;
- otError error = aError;
+ Error error = aError;
mCounters.mRxTotal++;
SuccessOrExit(error);
- VerifyOrExit(aFrame != nullptr, error = OT_ERROR_NO_FRAME_RECEIVED);
- VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aFrame != nullptr, error = kErrorNoFrameReceived);
+ VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
// Ensure we have a valid frame before attempting to read any contents of
// the buffer received from the radio.
@@ -1988,7 +2000,7 @@
case Address::kTypeShort:
VerifyOrExit((mRxOnWhenIdle && dstaddr.IsBroadcast()) || dstaddr.GetShort() == GetShortAddress(),
- error = OT_ERROR_DESTINATION_ADDRESS_FILTERED);
+ error = kErrorDestinationAddressFiltered);
#if OPENTHREAD_FTD
// Allow multicasts from neighbor routers if FTD
@@ -2001,14 +2013,14 @@
break;
case Address::kTypeExtended:
- VerifyOrExit(dstaddr.GetExtended() == GetExtAddress(), error = OT_ERROR_DESTINATION_ADDRESS_FILTERED);
+ VerifyOrExit(dstaddr.GetExtended() == GetExtAddress(), error = kErrorDestinationAddressFiltered);
break;
}
// Verify destination PAN ID if present
- if (OT_ERROR_NONE == aFrame->GetDstPanId(panid))
+ if (kErrorNone == aFrame->GetDstPanId(panid))
{
- VerifyOrExit(panid == kShortAddrBroadcast || panid == mPanId, error = OT_ERROR_DESTINATION_ADDRESS_FILTERED);
+ VerifyOrExit(panid == kShortAddrBroadcast || panid == mPanId, error = kErrorDestinationAddressFiltered);
}
// Source Address Filtering
@@ -2020,16 +2032,16 @@
case Address::kTypeShort:
otLogDebgMac("Received frame from short address 0x%04x", srcaddr.GetShort());
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_UNKNOWN_NEIGHBOR);
+ VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
srcaddr.SetExtended(neighbor->GetExtAddress());
- // Fall through
+ OT_FALL_THROUGH;
case Address::kTypeExtended:
// Duplicate Address Protection
- VerifyOrExit(srcaddr.GetExtended() != GetExtAddress(), error = OT_ERROR_INVALID_SOURCE_ADDRESS);
+ VerifyOrExit(srcaddr.GetExtended() != GetExtAddress(), error = kErrorInvalidSourceAddress);
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
{
@@ -2067,7 +2079,7 @@
switch (error)
{
- case OT_ERROR_DUPLICATED:
+ case kErrorDuplicated:
// Allow a duplicate received frame pass, only if the
// current operation is `kOperationWaitingForData` (i.e.,
@@ -2084,16 +2096,16 @@
VerifyOrExit(mOperation == kOperationWaitingForData);
- // Fall through
+ OT_FALL_THROUGH;
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
default:
ExitNow();
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
if (aFrame->GetVersion() == Frame::kFcfFrameVersion2015)
{
ProcessCsl(*aFrame, srcaddr);
@@ -2126,11 +2138,11 @@
case Neighbor::kStateChildUpdateRequest:
// Only accept a "MAC Data Request" frame from a child being restored.
- VerifyOrExit(aFrame->IsDataRequestCommand(), error = OT_ERROR_DROP);
+ VerifyOrExit(aFrame->IsDataRequestCommand(), error = kErrorDrop);
break;
default:
- ExitNow(error = OT_ERROR_UNKNOWN_NEIGHBOR);
+ ExitNow(error = kErrorUnknownNeighbor);
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 && OPENTHREAD_FTD
@@ -2160,7 +2172,7 @@
ExitNow();
}
- // Fall through
+ OT_FALL_THROUGH;
case kOperationEnergyScan:
@@ -2201,7 +2213,7 @@
case Frame::kFcfFrameMacCmd:
if (HandleMacCommand(*aFrame)) // returns `true` when handled
{
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
break;
@@ -2226,41 +2238,41 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
LogFrameRxFailure(aFrame, error);
switch (error)
{
- case OT_ERROR_SECURITY:
+ case kErrorSecurity:
mCounters.mRxErrSec++;
break;
- case OT_ERROR_FCS:
+ case kErrorFcs:
mCounters.mRxErrFcs++;
break;
- case OT_ERROR_NO_FRAME_RECEIVED:
+ case kErrorNoFrameReceived:
mCounters.mRxErrNoFrame++;
break;
- case OT_ERROR_UNKNOWN_NEIGHBOR:
+ case kErrorUnknownNeighbor:
mCounters.mRxErrUnknownNeighbor++;
break;
- case OT_ERROR_INVALID_SOURCE_ADDRESS:
+ case kErrorInvalidSourceAddress:
mCounters.mRxErrInvalidSrcAddr++;
break;
- case OT_ERROR_ADDRESS_FILTERED:
+ case kErrorAddressFiltered:
mCounters.mRxAddressFiltered++;
break;
- case OT_ERROR_DESTINATION_ADDRESS_FILTERED:
+ case kErrorDestinationAddressFiltered:
mCounters.mRxDestAddrFiltered++;
break;
- case OT_ERROR_DUPLICATED:
+ case kErrorDuplicated:
mCounters.mRxDuplicated++;
break;
@@ -2364,67 +2376,50 @@
const char *Mac::OperationToString(Operation aOperation)
{
- const char *retval = "";
-
- switch (aOperation)
- {
- case kOperationIdle:
- retval = "Idle";
- break;
-
- case kOperationActiveScan:
- retval = "ActiveScan";
- break;
-
- case kOperationEnergyScan:
- retval = "EnergyScan";
- break;
-
- case kOperationTransmitBeacon:
- retval = "TransmitBeacon";
- break;
-
- case kOperationTransmitDataDirect:
- retval = "TransmitDataDirect";
- break;
-
+ static const char *const kOperationStrings[] = {
+ "Idle", // (0) kOperationIdle
+ "ActiveScan", // (1) kOperationActiveScan
+ "EnergyScan", // (2) kOperationEnergyScan
+ "TransmitBeacon", // (3) kOperationTransmitBeacon
+ "TransmitDataDirect", // (4) kOperationTransmitDataDirect
+ "TransmitPoll", // (5) kOperationTransmitPoll
+ "WaitingForData", // (6) kOperationWaitingForData
+ "TransmitOobFrame", // (7) kOperationTransmitOutOfBandFrame
#if OPENTHREAD_FTD
- case kOperationTransmitDataIndirect:
- retval = "TransmitDataIndirect";
- break;
+ "TransmitDataIndirect", // (8) kOperationTransmitDataIndirect
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ "TransmitDataCsl", // (9) kOperationTransmitDataCsl
+#endif
+#endif
+ };
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
- case kOperationTransmitDataCsl:
- retval = "TransmitDataCsl";
- break;
+ static_assert(kOperationIdle == 0, "kOperationIdle value is incorrect");
+ static_assert(kOperationActiveScan == 1, "kOperationActiveScan value is incorrect");
+ static_assert(kOperationEnergyScan == 2, "kOperationEnergyScan value is incorrect");
+ static_assert(kOperationTransmitBeacon == 3, "kOperationTransmitBeacon value is incorrect");
+ static_assert(kOperationTransmitDataDirect == 4, "kOperationTransmitDataDirect value is incorrect");
+ static_assert(kOperationTransmitPoll == 5, "kOperationTransmitPoll value is incorrect");
+ static_assert(kOperationWaitingForData == 6, "kOperationWaitingForData value is incorrect");
+ static_assert(kOperationTransmitOutOfBandFrame == 7, "kOperationTransmitOutOfBandFrame value is incorrect");
+#if OPENTHREAD_FTD
+ static_assert(kOperationTransmitDataIndirect == 8, "kOperationTransmitDataIndirect value is incorrect");
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ static_assert(kOperationTransmitDataCsl == 9, "TransmitDataCsl value is incorrect");
#endif
#endif
- case kOperationTransmitPoll:
- retval = "TransmitPoll";
- break;
-
- case kOperationWaitingForData:
- retval = "WaitingForData";
- break;
-
- case kOperationTransmitOutOfBandFrame:
- retval = "TransmitOobFrame";
- break;
- }
-
- return retval;
+ return kOperationStrings[aOperation];
}
-void Mac::LogFrameRxFailure(const RxFrame *aFrame, otError aError) const
+void Mac::LogFrameRxFailure(const RxFrame *aFrame, Error aError) const
{
otLogLevel logLevel;
switch (aError)
{
- case OT_ERROR_ABORT:
- case OT_ERROR_NO_FRAME_RECEIVED:
- case OT_ERROR_DESTINATION_ADDRESS_FILTERED:
+ case kErrorAbort:
+ case kErrorNoFrameReceived:
+ case kErrorDestinationAddressFiltered:
logLevel = OT_LOG_LEVEL_DEBG;
break;
@@ -2435,16 +2430,15 @@
if (aFrame == nullptr)
{
- otLogMac(logLevel, "Frame rx failed, error:%s", otThreadErrorToString(aError));
+ otLogMac(logLevel, "Frame rx failed, error:%s", ErrorToString(aError));
}
else
{
- otLogMac(logLevel, "Frame rx failed, error:%s, %s", otThreadErrorToString(aError),
- aFrame->ToInfoString().AsCString());
+ otLogMac(logLevel, "Frame rx failed, error:%s, %s", ErrorToString(aError), aFrame->ToInfoString().AsCString());
}
}
-void Mac::LogFrameTxFailure(const TxFrame &aFrame, otError aError, uint8_t aRetryCount, bool aWillRetx) const
+void Mac::LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE && OPENTHREAD_CONFIG_MULTI_RADIO
if (aFrame.GetRadioType() == kRadioTypeIeee802154)
@@ -2457,12 +2451,12 @@
uint8_t maxAttempts = aFrame.GetMaxFrameRetries() + 1;
uint8_t curAttempt = aWillRetx ? (aRetryCount + 1) : maxAttempts;
- otLogInfoMac("Frame tx attempt %d/%d failed, error:%s, %s", curAttempt, maxAttempts,
- otThreadErrorToString(aError), aFrame.ToInfoString().AsCString());
+ otLogInfoMac("Frame tx attempt %d/%d failed, error:%s, %s", curAttempt, maxAttempts, ErrorToString(aError),
+ aFrame.ToInfoString().AsCString());
}
else
{
- otLogInfoMac("Frame tx failed, error:%s, %s", otThreadErrorToString(aError), aFrame.ToInfoString().AsCString());
+ otLogInfoMac("Frame tx failed, error:%s, %s", ErrorToString(aError), aFrame.ToInfoString().AsCString());
}
}
@@ -2473,7 +2467,7 @@
#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
-void Mac::LogFrameRxFailure(const RxFrame *, otError) const
+void Mac::LogFrameRxFailure(const RxFrame *, Error) const
{
}
@@ -2481,7 +2475,7 @@
{
}
-void Mac::LogFrameTxFailure(const TxFrame &, otError, uint8_t, bool) const
+void Mac::LogFrameTxFailure(const TxFrame &, Error, uint8_t, bool) const
{
}
@@ -2559,10 +2553,10 @@
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
void Mac::ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr)
{
- const uint8_t *cur = aFrame.GetHeaderIe(Frame::kHeaderIeCsl);
+ const uint8_t *cur = aFrame.GetHeaderIe(CslIe::kHeaderIeId);
Child * child = Get<ChildTable>().FindChild(aSrcAddr, Child::kInStateAnyExceptInvalid);
const CslIe * csl;
@@ -2585,7 +2579,7 @@
exit:
return;
}
-#endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
void Mac::ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor)
@@ -2612,109 +2606,5 @@
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
-#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
-otError Mac::AppendHeaderIe(bool aIsTimeSync, TxFrame &aFrame) const
-{
- OT_UNUSED_VARIABLE(aIsTimeSync);
-
- const size_t kMaxNumHeaderIe = 3; // TimeSync + CSL + Termination2
- HeaderIe ieList[kMaxNumHeaderIe];
- otError error = OT_ERROR_NONE;
- uint8_t ieCount = 0;
-
- VerifyOrExit(aFrame.IsVersion2015() && aFrame.IsIePresent());
-
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
- if (aIsTimeSync)
- {
- ieList[ieCount].Init();
- ieList[ieCount].SetId(Frame::kHeaderIeVendor);
- ieList[ieCount].SetLength(sizeof(TimeIe));
- ieCount++;
- }
-#endif
-
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (IsCslEnabled())
- {
- OT_ASSERT(aFrame.GetSecurityEnabled());
-
- aFrame.mInfo.mTxInfo.mCslPresent = true;
- ieList[ieCount].Init();
- ieList[ieCount].SetId(Frame::kHeaderIeCsl);
- ieList[ieCount].SetLength(sizeof(CslIe));
- ieCount++;
- }
- else
-#endif
- {
- aFrame.mInfo.mTxInfo.mCslPresent = false;
- }
-
- if (ieCount > 0)
- {
- ieList[ieCount].Init();
- ieList[ieCount].SetId(Frame::kHeaderIeTermination2);
- ieList[ieCount].SetLength(0);
-
- SuccessOrExit(error = aFrame.AppendHeaderIe(ieList, ++ieCount));
- }
-
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
- if (aIsTimeSync)
- {
- uint8_t *cur = aFrame.GetHeaderIe(Frame::kHeaderIeVendor);
- TimeIe * ie = reinterpret_cast<TimeIe *>(cur + sizeof(HeaderIe));
-
- ie->Init();
- }
-#endif
-
-exit:
- return error;
-}
-#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
-
-void Mac::UpdateFrameControlField(const Neighbor *aNeighbor, bool aIsTimeSync, uint16_t &aFcf) const
-{
- OT_UNUSED_VARIABLE(aIsTimeSync);
- OT_UNUSED_VARIABLE(aNeighbor);
-
-#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
-#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
- if (aIsTimeSync)
- {
- aFcf |= Frame::kFcfFrameVersion2015 | Frame::kFcfIePresent;
- }
- else
-#endif
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (IsCslEnabled())
- {
- aFcf |= Frame::kFcfFrameVersion2015 | Frame::kFcfIePresent;
- }
- else
-#endif
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
- if (aNeighbor != nullptr && !Mle::MleRouter::IsActiveRouter(aNeighbor->GetRloc16()) &&
- static_cast<const Child *>(aNeighbor)->IsCslSynchronized())
- {
- aFcf |= Frame::kFcfFrameVersion2015;
- }
- else
-#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
- if (aNeighbor != nullptr && aNeighbor->IsEnhAckProbingActive())
- {
- aFcf |= Frame::kFcfFrameVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK.
- }
- else
-#endif
-#endif
- {
- aFcf |= Frame::kFcfFrameVersion2006;
- }
-}
-
} // namespace Mac
} // namespace ot
diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp
index caa413b..b5a6207 100644
--- a/src/core/mac/mac.hpp
+++ b/src/core/mac/mac.hpp
@@ -79,7 +79,7 @@
kDataPollTimeout = 100, ///< Timeout for receiving Data Frame (milliseconds).
kSleepDelay = 300, ///< Max sleep delay when frame is pending (milliseconds).
- kScanDurationDefault = 300, ///< Default interval between channels (milliseconds).
+ kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION, ///< Default interval between channels (milliseconds).
kMaxCsmaBackoffsDirect =
OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT, ///< macMaxCsmaBackoffs for direct transmissions
@@ -147,11 +147,11 @@
* @param[in] aHandler A pointer to a function that is called on receiving an IEEE 802.15.4 Beacon.
* @param[in] aContext A pointer to an arbitrary context (used when invoking `aHandler` callback).
*
- * @retval OT_ERROR_NONE Successfully scheduled the Active Scan request.
- * @retval OT_ERROR_BUSY Could not schedule the scan (a scan is ongoing or scheduled).
+ * @retval kErrorNone Successfully scheduled the Active Scan request.
+ * @retval kErrorBusy Could not schedule the scan (a scan is ongoing or scheduled).
*
*/
- otError ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
+ Error ActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, ActiveScanHandler aHandler, void *aContext);
/**
* This method starts an IEEE 802.15.4 Energy Scan.
@@ -162,11 +162,11 @@
* @param[in] aHandler A pointer to a function called to pass on scan result or indicate scan completion.
* @param[in] aContext A pointer to an arbitrary context (used when invoking @p aHandler callback).
*
- * @retval OT_ERROR_NONE Accepted the Energy Scan request.
- * @retval OT_ERROR_BUSY Could not start the energy scan.
+ * @retval kErrorNone Accepted the Energy Scan request.
+ * @retval kErrorBusy Could not start the energy scan.
*
*/
- otError EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext);
+ Error EnergyScan(uint32_t aScanChannels, uint16_t aScanDuration, EnergyScanHandler aHandler, void *aContext);
/**
* This method indicates the energy scan for the current channel is complete.
@@ -221,7 +221,7 @@
*/
void RequestIndirectFrameTransmission(void);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
/**
* This method requests `Mac` to start a CSL tx operation after a delay of @p aDelay time.
*
@@ -240,23 +240,23 @@
*
* @param[in] aOobFrame A pointer to the frame.
*
- * @retval OT_ERROR_NONE Successfully scheduled the frame transmission.
- * @retval OT_ERROR_ALREADY MAC layer is busy sending a previously requested frame.
- * @retval OT_ERROR_INVALID_STATE The MAC layer is not enabled.
- * @retval OT_ERROR_INVALID_ARGS The argument @p aOobFrame is nullptr.
+ * @retval kErrorNone Successfully scheduled the frame transmission.
+ * @retval kErrorAlready MAC layer is busy sending a previously requested frame.
+ * @retval kErrorInvalidState The MAC layer is not enabled.
+ * @retval kErrorInvalidArgs The argument @p aOobFrame is nullptr.
*
*/
- otError RequestOutOfBandFrameTransmission(otRadioFrame *aOobFrame);
+ Error RequestOutOfBandFrameTransmission(otRadioFrame *aOobFrame);
/**
* This method requests transmission of a data poll (MAC Data Request) frame.
*
- * @retval OT_ERROR_NONE Data poll transmission request is scheduled successfully.
- * @retval OT_ERROR_ALREADY MAC is busy sending earlier poll transmission request.
- * @retval OT_ERROR_INVALID_STATE The MAC layer is not enabled.
+ * @retval kErrorNone Data poll transmission request is scheduled successfully.
+ * @retval kErrorAlready MAC is busy sending earlier poll transmission request.
+ * @retval kErrorInvalidState The MAC layer is not enabled.
*
*/
- otError RequestDataPollTransmission(void);
+ Error RequestDataPollTransmission(void);
/**
* This method returns a reference to the IEEE 802.15.4 Extended Address.
@@ -303,11 +303,11 @@
*
* @param[in] aChannel The IEEE 802.15.4 PAN Channel.
*
- * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN Channel.
- * @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask.
+ * @retval kErrorNone Successfully set the IEEE 802.15.4 PAN Channel.
+ * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask.
*
*/
- otError SetPanChannel(uint8_t aChannel);
+ Error SetPanChannel(uint8_t aChannel);
/**
* This method sets the temporary IEEE 802.15.4 radio channel.
@@ -319,11 +319,11 @@
*
* @param[in] aChannel A IEEE 802.15.4 channel.
*
- * @retval OT_ERROR_NONE Successfully set the temporary channel
- * @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask.
+ * @retval kErrorNone Successfully set the temporary channel
+ * @retval kErrorInvalidArgs The @p aChannel is not in the supported channel mask.
*
*/
- otError SetTemporaryChannel(uint8_t aChannel);
+ Error SetTemporaryChannel(uint8_t aChannel);
/**
* This method clears the use of a previously set temporary channel and adopts the PAN channel.
@@ -360,22 +360,22 @@
*
* @param[in] aNameString A pointer to a string character array. Must be null terminated.
*
- * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError SetNetworkName(const char *aNameString);
+ Error SetNetworkName(const char *aNameString);
/**
* This method sets the IEEE 802.15.4 Network Name.
*
* @param[in] aNameData A name data (pointer to char buffer and length).
*
- * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError SetNetworkName(const NameData &aNameData);
+ Error SetNetworkName(const NameData &aNameData);
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
/**
@@ -391,22 +391,22 @@
*
* @param[in] aNameString A pointer to a string character array. Must be null terminated.
*
- * @retval OT_ERROR_NONE Successfully set the Thread Domain Name.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the Thread Domain Name.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError SetDomainName(const char *aNameString);
+ Error SetDomainName(const char *aNameString);
/**
* This method sets the Thread Domain Name.
*
* @param[in] aNameData A name data (pointer to char buffer and length).
*
- * @retval OT_ERROR_NONE Successfully set the Thread Domain Name.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the Thread Domain Name.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError SetDomainName(const NameData &aNameData);
+ Error SetDomainName(const NameData &aNameData);
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
/**
@@ -482,11 +482,11 @@
* This method is called to handle a received frame.
*
* @param[in] aFrame A pointer to the received frame, or nullptr if the receive operation was aborted.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received.
*
*/
- void HandleReceivedFrame(RxFrame *aFrame, otError aError);
+ void HandleReceivedFrame(RxFrame *aFrame, Error aError);
/**
* This method records CCA status (success/failure) for a frame transmission attempt.
@@ -505,10 +505,10 @@
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, or nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
* @param[in] aRetryCount Indicates number of transmission retries for this frame.
* @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only
* when there was an error in transmission (i.e., `aError` is not NONE).
@@ -516,7 +516,7 @@
*/
void RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx);
@@ -525,13 +525,13 @@
*
* @param[in] aFrame The frame that was transmitted.
* @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE when the tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure when the tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
*
*/
- void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError);
+ void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
/**
* This method returns if an active scan is in progress.
@@ -746,35 +746,6 @@
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
- /**
- * This method appends header IEs to a TX-frame according to its
- * frame control field and if time sync is enabled.
- *
- * @param[in] aIsTimeSync A boolean indicates if time sync is being used.
- * @param[in,out] aFrame A reference to the TX-frame to which the IEs will be appended.
- *
- * @retval OT_ERROR_NONE If append header IEs successfully.
- * @retval OT_ERROR_NOT_FOUND If cannot find header IE position in the frame.
- *
- */
- otError AppendHeaderIe(bool aIsTimeSync, TxFrame &aFrame) const;
-#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
-
- /**
- * This method updates frame control field.
- *
- * If the frame would contain header IEs, IE present field would be set.
- * If this is a CSL transmission frame or header IE is present in this frame,
- * the version should be set to 2015. Otherwise, the version would be set to 2006.
- *
- * @param[in] aNeighbor A pointer to the destination device, could be `nullptr`.
- * @param[in] aIsTimeSync A boolean indicates if time sync is being used.
- * @param[out] aFcf A reference to the frame control field to set.
- *
- */
- void UpdateFrameControlField(const Neighbor *aNeighbor, bool aIsTimeSync, uint16_t &aFcf) const;
-
private:
enum
{
@@ -783,22 +754,22 @@
kMaxAcquisitionId = 0xffff,
};
- enum Operation
+ enum Operation : uint8_t
{
kOperationIdle = 0,
kOperationActiveScan,
kOperationEnergyScan,
kOperationTransmitBeacon,
kOperationTransmitDataDirect,
-#if OPENTHREAD_FTD
- kOperationTransmitDataIndirect,
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
- kOperationTransmitDataCsl,
-#endif
-#endif
kOperationTransmitPoll,
kOperationWaitingForData,
kOperationTransmitOutOfBandFrame,
+#if OPENTHREAD_FTD
+ kOperationTransmitDataIndirect,
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ kOperationTransmitDataCsl,
+#endif
+#endif
};
#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
@@ -824,10 +795,10 @@
};
#endif // OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
- otError ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor);
- void ProcessTransmitSecurity(TxFrame &aFrame);
+ Error ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neighbor *aNeighbor);
+ void ProcessTransmitSecurity(TxFrame &aFrame);
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
- otError ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame);
+ Error ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame);
#endif
void UpdateIdleMode(void);
@@ -846,23 +817,23 @@
void HandleTimer(void);
static void HandleOperationTask(Tasklet &aTasklet);
- void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration);
- otError UpdateScanChannel(void);
- void PerformActiveScan(void);
- void ReportActiveScanResult(const RxFrame *aBeaconFrame);
- otError ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
- void PerformEnergyScan(void);
- void ReportEnergyScanResult(int8_t aRssi);
+ void Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanDuration);
+ Error UpdateScanChannel(void);
+ void PerformActiveScan(void);
+ void ReportActiveScanResult(const RxFrame *aBeaconFrame);
+ Error ConvertBeaconToActiveScanResult(const RxFrame *aBeaconFrame, ActiveScanResult &aResult);
+ void PerformEnergyScan(void);
+ void ReportEnergyScanResult(int8_t aRssi);
- void LogFrameRxFailure(const RxFrame *aFrame, otError aError) const;
- void LogFrameTxFailure(const TxFrame &aFrame, otError aError, uint8_t aRetryCount, bool aWillRetx) const;
+ void LogFrameRxFailure(const RxFrame *aFrame, Error aError) const;
+ void LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryCount, bool aWillRetx) const;
void LogBeacon(const char *aActionText, const BeaconPayload &aBeaconPayload) const;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
uint8_t GetTimeIeOffset(const Frame &aFrame);
#endif
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr);
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
@@ -883,10 +854,10 @@
bool mPendingTransmitDataDirect : 1;
#if OPENTHREAD_FTD
bool mPendingTransmitDataIndirect : 1;
-#endif
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
bool mPendingTransmitDataCsl : 1;
#endif
+#endif
bool mPendingTransmitPoll : 1;
bool mPendingTransmitOobFrame : 1;
bool mPendingWaitingForData : 1;
@@ -919,10 +890,10 @@
uint8_t mMaxFrameRetriesDirect;
#if OPENTHREAD_FTD
uint8_t mMaxFrameRetriesIndirect;
-#endif
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
TimeMilli mCslTxFireTime;
#endif
+#endif
union
{
@@ -946,7 +917,7 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
RadioTypes mTxPendingRadioLinks;
- otError mTxError;
+ Error mTxError;
#endif
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
diff --git a/src/core/mac/mac_filter.cpp b/src/core/mac/mac_filter.cpp
index f4f6f9b..568c947 100644
--- a/src/core/mac/mac_filter.cpp
+++ b/src/core/mac/mac_filter.cpp
@@ -83,14 +83,14 @@
return rval;
}
-otError Filter::AddAddress(const ExtAddress &aExtAddress)
+Error Filter::AddAddress(const ExtAddress &aExtAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
FilterEntry *entry = FindEntry(aExtAddress);
if (entry == nullptr)
{
- VerifyOrExit((entry = FindAvailableEntry()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((entry = FindAvailableEntry()) != nullptr, error = kErrorNoBufs);
entry->mExtAddress = aExtAddress;
}
@@ -118,9 +118,9 @@
}
}
-otError Filter::GetNextAddress(Iterator &aIterator, Entry &aEntry) const
+Error Filter::GetNextAddress(Iterator &aIterator, Entry &aEntry) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
{
@@ -130,7 +130,7 @@
{
aEntry.mExtAddress = entry.mExtAddress;
aEntry.mRssIn = entry.mRssIn;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
aIterator++;
break;
}
@@ -139,15 +139,15 @@
return error;
}
-otError Filter::AddRssIn(const ExtAddress &aExtAddress, int8_t aRss)
+Error Filter::AddRssIn(const ExtAddress &aExtAddress, int8_t aRss)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
FilterEntry *entry = FindEntry(aExtAddress);
if (entry == nullptr)
{
entry = FindAvailableEntry();
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
entry->mExtAddress = aExtAddress;
}
@@ -180,9 +180,9 @@
mDefaultRssIn = kFixedRssDisabled;
}
-otError Filter::GetNextRssIn(Iterator &aIterator, Entry &aEntry)
+Error Filter::GetNextRssIn(Iterator &aIterator, Entry &aEntry)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
for (; aIterator < OT_ARRAY_LENGTH(mFilterEntries); aIterator++)
{
@@ -192,7 +192,7 @@
{
aEntry.mExtAddress = entry.mExtAddress;
aEntry.mRssIn = entry.mRssIn;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
aIterator++;
ExitNow();
}
@@ -203,7 +203,7 @@
{
static_cast<ExtAddress &>(aEntry.mExtAddress).Fill(0xff);
aEntry.mRssIn = mDefaultRssIn;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
aIterator++;
}
@@ -211,9 +211,9 @@
return error;
}
-otError Filter::Apply(const ExtAddress &aExtAddress, int8_t &aRss)
+Error Filter::Apply(const ExtAddress &aExtAddress, int8_t &aRss)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
FilterEntry *entry = FindEntry(aExtAddress);
bool isInFilterList;
@@ -231,11 +231,11 @@
break;
case kModeAllowlist:
- VerifyOrExit(isInFilterList, error = OT_ERROR_ADDRESS_FILTERED);
+ VerifyOrExit(isInFilterList, error = kErrorAddressFiltered);
break;
case kModeDenylist:
- VerifyOrExit(!isInFilterList, error = OT_ERROR_ADDRESS_FILTERED);
+ VerifyOrExit(!isInFilterList, error = kErrorAddressFiltered);
break;
}
diff --git a/src/core/mac/mac_filter.hpp b/src/core/mac/mac_filter.hpp
index 4a68523..31d2e45 100644
--- a/src/core/mac/mac_filter.hpp
+++ b/src/core/mac/mac_filter.hpp
@@ -117,11 +117,11 @@
*
* @param[in] aExtAddress A reference to the Extended Address.
*
- * @retval OT_ERROR_NONE Successfully added @p aExtAddress to the filter.
- * @retval OT_ERROR_NO_BUFS No available entry exists.
+ * @retval kErrorNone Successfully added @p aExtAddress to the filter.
+ * @retval kErrorNoBufs No available entry exists.
*
*/
- otError AddAddress(const ExtAddress &aExtAddress);
+ Error AddAddress(const ExtAddress &aExtAddress);
/**
* This method removes an Extended Address from the filter.
@@ -146,11 +146,11 @@
* To get the first in-use address filter, set it to OT_MAC_FILTER_ITERATOR_INIT.
* @param[out] aEntry A reference to where the information is placed.
*
- * @retval OT_ERROR_NONE Successfully retrieved the next address filter entry.
- * @retval OT_ERROR_NOT_FOUND No subsequent entry exists.
+ * @retval kErrorNone Successfully retrieved the next address filter entry.
+ * @retval kErrorNotFound No subsequent entry exists.
*
*/
- otError GetNextAddress(Iterator &aIterator, Entry &aEntry) const;
+ Error GetNextAddress(Iterator &aIterator, Entry &aEntry) const;
/**
* This method adds a fixed received signal strength entry for the messages from a given Extended Address.
@@ -158,11 +158,11 @@
* @param[in] aExtAddress An Extended Address
* @param[in] aRss The received signal strength to set.
*
- * @retval OT_ERROR_NONE Successfully set @p aRss for @p aExtAddress.
- * @retval OT_ERROR_NO_BUFS No available entry exists.
+ * @retval kErrorNone Successfully set @p aRss for @p aExtAddress.
+ * @retval kErrorNoBufs No available entry exists.
*
*/
- otError AddRssIn(const ExtAddress &aExtAddress, int8_t aRss);
+ Error AddRssIn(const ExtAddress &aExtAddress, int8_t aRss);
/**
* This method removes a fixed received signal strength entry for a given Extended Address.
@@ -206,11 +206,11 @@
* Extended Address as all 0xff to indicate the default received signal strength
* if it was set.
*
- * @retval OT_ERROR_NONE Successfully retrieved the next RssIn filter entry.
- * @retval OT_ERROR_NOT_FOUND No subsequent entry exists.
+ * @retval kErrorNone Successfully retrieved the next RssIn filter entry.
+ * @retval kErrorNotFound No subsequent entry exists.
*
*/
- otError GetNextRssIn(Iterator &aIterator, Entry &aEntry);
+ Error GetNextRssIn(Iterator &aIterator, Entry &aEntry);
/**
* This method applies the filter rules on a given Extended Address.
@@ -218,12 +218,11 @@
* @param[in] aExtAddress A reference to the Extended Address.
* @param[out] aRss A reference to where the received signal strength to be placed.
*
- * @retval OT_ERROR_NONE Successfully applied the filter rules on @p aExtAddress.
- * @retval OT_ERROR_ADDRESS_FILTERED Address filter (allowlist or denylist) is enabled and @p aExtAddress is
- * filtered.
+ * @retval kErrorNone Successfully applied the filter rules on @p aExtAddress.
+ * @retval kErrorAddressFiltered Address filter (allowlist or denylist) is enabled and @p aExtAddress is filtered.
*
*/
- otError Apply(const ExtAddress &aExtAddress, int8_t &aRss);
+ Error Apply(const ExtAddress &aExtAddress, int8_t &aRss);
private:
enum
diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp
index bdbb030..134d8e1 100644
--- a/src/core/mac/mac_frame.cpp
+++ b/src/core/mac/mac_frame.cpp
@@ -50,6 +50,13 @@
using ot::Encoding::LittleEndian::WriteUint16;
using ot::Encoding::LittleEndian::WriteUint32;
+void HeaderIe::Init(uint16_t aId, uint8_t aLen)
+{
+ Init();
+ SetId(aId);
+ SetLength(aLen);
+}
+
void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
{
mLength = CalculateAddrFieldSize(aFcf);
@@ -79,13 +86,13 @@
return ReadUint16(mPsdu);
}
-otError Frame::ValidatePsdu(void) const
+Error Frame::ValidatePsdu(void) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindPayloadIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
- VerifyOrExit((index + GetFooterLength()) <= mLength, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
+ VerifyOrExit((index + GetFooterLength()) <= mLength, error = kErrorParse);
exit:
return error;
@@ -159,12 +166,12 @@
return present;
}
-otError Frame::GetDstPanId(PanId &aPanId) const
+Error Frame::GetDstPanId(PanId &aPanId) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindDstPanIdIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aPanId = ReadUint16(&mPsdu[index]);
exit:
@@ -184,12 +191,12 @@
return kFcfSize + kDsnSize + (IsDstPanIdPresent() ? sizeof(PanId) : 0);
}
-otError Frame::GetDstAddr(Address &aAddress) const
+Error Frame::GetDstAddr(Address &aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindDstAddrIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
switch (GetFrameControlField() & kFcfDstAddrMask)
{
@@ -297,24 +304,24 @@
return srcPanIdPresent;
}
-otError Frame::GetSrcPanId(PanId &aPanId) const
+Error Frame::GetSrcPanId(PanId &aPanId) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSrcPanIdIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aPanId = ReadUint16(&mPsdu[index]);
exit:
return error;
}
-otError Frame::SetSrcPanId(PanId aPanId)
+Error Frame::SetSrcPanId(PanId aPanId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSrcPanIdIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
WriteUint16(aPanId, &mPsdu[index]);
exit:
@@ -352,13 +359,13 @@
return index;
}
-otError Frame::GetSrcAddr(Address &aAddress) const
+Error Frame::GetSrcAddr(Address &aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSrcAddrIndex();
uint16_t fcf = GetFrameControlField();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
switch (fcf & kFcfSrcAddrMask)
{
@@ -416,12 +423,12 @@
}
}
-otError Frame::GetSecurityControlField(uint8_t &aSecurityControlField) const
+Error Frame::GetSecurityControlField(uint8_t &aSecurityControlField) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSecurityHeaderIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aSecurityControlField = mPsdu[index];
@@ -450,12 +457,12 @@
return index;
}
-otError Frame::GetSecurityLevel(uint8_t &aSecurityLevel) const
+Error Frame::GetSecurityLevel(uint8_t &aSecurityLevel) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSecurityHeaderIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aSecurityLevel = mPsdu[index] & kSecLevelMask;
@@ -463,12 +470,12 @@
return error;
}
-otError Frame::GetKeyIdMode(uint8_t &aKeyIdMode) const
+Error Frame::GetKeyIdMode(uint8_t &aKeyIdMode) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSecurityHeaderIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aKeyIdMode = mPsdu[index] & kKeyIdModeMask;
@@ -476,12 +483,12 @@
return error;
}
-otError Frame::GetFrameCounter(uint32_t &aFrameCounter) const
+Error Frame::GetFrameCounter(uint32_t &aFrameCounter) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindSecurityHeaderIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
// Security Control
index += kSecurityControlSize;
@@ -551,13 +558,13 @@
memcpy(&mPsdu[index + kSecurityControlSize + kFrameCounterSize], aKeySource, keySourceLength);
}
-otError Frame::GetKeyId(uint8_t &aKeyId) const
+Error Frame::GetKeyId(uint8_t &aKeyId) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t keySourceLength;
uint8_t index = FindSecurityHeaderIndex();
- VerifyOrExit(index != kInvalidIndex);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
keySourceLength = GetKeySourceLength(mPsdu[index] & kKeyIdModeMask);
@@ -579,11 +586,12 @@
mPsdu[index + kSecurityControlSize + kFrameCounterSize + keySourceLength] = aKeyId;
}
-otError Frame::GetCommandId(uint8_t &aCommandId) const
+Error Frame::GetCommandId(uint8_t &aCommandId) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindPayloadIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
aCommandId = mPsdu[IsVersion2015() ? index : (index - 1)];
@@ -591,12 +599,12 @@
return error;
}
-otError Frame::SetCommandId(uint8_t aCommandId)
+Error Frame::SetCommandId(uint8_t aCommandId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t index = FindPayloadIndex();
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_PARSE);
+ VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
mPsdu[IsVersion2015() ? index : (index - 1)] = aCommandId;
@@ -829,7 +837,7 @@
index += ie->GetLength();
VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
- if (ie->GetId() == kHeaderIeTermination2)
+ if (ie->GetId() == Termination2Ie::kHeaderIeId)
{
break;
}
@@ -886,25 +894,59 @@
return index;
}
-otError Frame::AppendHeaderIe(HeaderIe *aIeList, uint8_t aIeCount)
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+template <typename IeType> Error Frame::AppendHeaderIeAt(uint8_t &aIndex)
{
- otError error = OT_ERROR_NONE;
- uint16_t index = FindHeaderIeIndex();
+ Error error = kErrorNone;
- VerifyOrExit(index != kInvalidIndex, error = OT_ERROR_NOT_FOUND);
+ SuccessOrExit(error = InitIeHeaderAt(aIndex, IeType::kHeaderIeId, IeType::kIeContentSize));
- for (uint8_t i = 0; i < aIeCount; i++)
- {
- memcpy(&mPsdu[index], &aIeList[i], sizeof(HeaderIe));
-
- index += sizeof(HeaderIe) + aIeList[i].GetLength();
- mLength += sizeof(HeaderIe) + aIeList[i].GetLength();
- }
+ InitIeContentAt<IeType>(aIndex);
exit:
return error;
}
+Error Frame::InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize)
+{
+ Error error = kErrorNone;
+
+ if (aIndex == 0)
+ {
+ aIndex = FindHeaderIeIndex();
+ }
+
+ VerifyOrExit(aIndex != kInvalidIndex, error = kErrorNotFound);
+
+ reinterpret_cast<HeaderIe *>(mPsdu + aIndex)->Init(ieId, ieContentSize);
+ aIndex += sizeof(HeaderIe);
+
+ mLength += sizeof(HeaderIe) + ieContentSize;
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+template <> void Frame::InitIeContentAt<TimeIe>(uint8_t &aIndex)
+{
+ reinterpret_cast<TimeIe *>(mPsdu + aIndex)->Init();
+ aIndex += sizeof(TimeIe);
+}
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+template <> void Frame::InitIeContentAt<CslIe>(uint8_t &aIndex)
+{
+ aIndex += sizeof(CslIe);
+}
+#endif
+
+template <> void Frame::InitIeContentAt<Termination2Ie>(uint8_t &aIndex)
+{
+ OT_UNUSED_VARIABLE(aIndex);
+}
+#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+
const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
{
uint8_t index = FindHeaderIeIndex();
@@ -948,7 +990,7 @@
{
const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
- if (ie->GetId() == kHeaderIeVendor)
+ if (ie->GetId() == VendorIeHeader::kHeaderIeId)
{
const VendorIeHeader *vendorIe =
reinterpret_cast<const VendorIeHeader *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
@@ -972,7 +1014,7 @@
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
void Frame::SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase)
{
- uint8_t *cur = GetHeaderIe(Frame::kHeaderIeCsl);
+ uint8_t *cur = GetHeaderIe(CslIe::kHeaderIeId);
CslIe * csl;
VerifyOrExit(cur != nullptr);
@@ -1002,7 +1044,7 @@
const TimeIe * timeIe = nullptr;
const uint8_t *cur = nullptr;
- cur = GetHeaderIe(kHeaderIeVendor);
+ cur = GetHeaderIe(VendorIeHeader::kHeaderIeId);
VerifyOrExit(cur != nullptr);
cur += sizeof(HeaderIe);
@@ -1079,6 +1121,17 @@
}
#endif
+// Explicit instantiation
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+template Error Frame::AppendHeaderIeAt<TimeIe>(uint8_t &aIndex);
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+template Error Frame::AppendHeaderIeAt<CslIe>(uint8_t &aIndex);
+#endif
+template Error Frame::AppendHeaderIeAt<Termination2Ie>(uint8_t &aIndex);
+#endif
+
void TxFrame::CopyFrom(const TxFrame &aFromFrame)
{
uint8_t * psduBuffer = mPsdu;
@@ -1170,9 +1223,9 @@
}
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-otError TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength)
+Error TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t fcf = kFcfFrameAck | kFcfFrameVersion2015 | kFcfSrcAddrNone;
Address address;
@@ -1237,7 +1290,7 @@
}
else
{
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
SetDstPanId(panId);
@@ -1280,15 +1333,15 @@
}
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
-otError RxFrame::ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey)
+Error RxFrame::ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey)
{
#if OPENTHREAD_RADIO
OT_UNUSED_VARIABLE(aExtAddress);
OT_UNUSED_VARIABLE(aMacKey);
- return OT_ERROR_NONE;
+ return kErrorNone;
#else
- otError error = OT_ERROR_SECURITY;
+ Error error = kErrorSecurity;
uint32_t frameCounter = 0;
uint8_t securityLevel;
uint8_t nonce[Crypto::AesCcm::kNonceSize];
@@ -1296,7 +1349,7 @@
uint8_t tagLength;
Crypto::AesCcm aesCcm;
- VerifyOrExit(GetSecurityEnabled(), error = OT_ERROR_NONE);
+ VerifyOrExit(GetSecurityEnabled(), error = kErrorNone);
SuccessOrExit(GetSecurityLevel(securityLevel));
SuccessOrExit(GetFrameCounter(frameCounter));
@@ -1321,7 +1374,7 @@
VerifyOrExit(memcmp(tag, GetFooter(), tagLength) == 0);
#endif
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
@@ -1357,7 +1410,7 @@
break;
case kFcfFrameMacCmd:
- if (GetCommandId(commandId) != OT_ERROR_NONE)
+ if (GetCommandId(commandId) != kErrorNone)
{
commandId = 0xff;
}
diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp
index c8e0672..43e2047 100644
--- a/src/core/mac/mac_frame.hpp
+++ b/src/core/mac/mac_frame.hpp
@@ -72,6 +72,15 @@
void Init(void) { mFields.m16 = 0; }
/**
+ * This method initializes the Header IE with Id and Length.
+ *
+ * @param[in] aId The IE Element Id.
+ * @param[in] aLen The IE content length.
+ *
+ */
+ void Init(uint16_t aId, uint8_t aLen);
+
+ /**
* This method returns the IE Element Id.
*
* @returns the IE Element Id.
@@ -144,6 +153,12 @@
class VendorIeHeader
{
public:
+ enum : uint8_t
+ {
+ kHeaderIeId = 0x00,
+ kIeContentSize = sizeof(uint8_t) * 4,
+ };
+
/**
* This method returns the Vendor OUI.
*
@@ -205,6 +220,12 @@
kVendorIeTime = 0x01,
};
+ enum
+ {
+ kHeaderIeId = VendorIeHeader::kHeaderIeId,
+ kIeContentSize = VendorIeHeader::kIeContentSize + sizeof(uint8_t) + sizeof(uint64_t),
+ };
+
/**
* This method initializes the time IE.
*
@@ -257,6 +278,12 @@
class ThreadIe
{
public:
+ enum : uint8_t
+ {
+ kHeaderIeId = VendorIeHeader::kHeaderIeId,
+ kIeContentSize = VendorIeHeader::kIeContentSize,
+ };
+
enum : uint32_t
{
kVendorOuiThreadCompanyId = 0xeab89b,
@@ -348,10 +375,6 @@
kMacCmdCoordinatorRealignment = 8,
kMacCmdGtsRequest = 9,
- kHeaderIeVendor = 0x00,
- kHeaderIeCsl = 0x1a,
- kHeaderIeTermination2 = 0x7f,
-
kImmAckLength = kFcfSize + kDsnSize + k154FcsSize,
kInfoStringSize = 128, ///< Max chars needed for the info string representation (@sa ToInfoString()).
@@ -384,11 +407,11 @@
/**
* This method validates the frame.
*
- * @retval OT_ERROR_NONE Successfully parsed the MAC header.
- * @retval OT_ERROR_PARSE Failed to parse through the MAC header.
+ * @retval kErrorNone Successfully parsed the MAC header.
+ * @retval kErrorParse Failed to parse through the MAC header.
*
*/
- otError ValidatePsdu(void) const;
+ Error ValidatePsdu(void) const;
/**
* This method returns the IEEE 802.15.4 Frame Type.
@@ -513,11 +536,11 @@
*
* @param[out] aPanId The Destination PAN Identifier.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Destination PAN Identifier.
- * @retval OT_ERROR_PARSE Failed to parse the PAN Identifier.
+ * @retval kErrorNone Successfully retrieved the Destination PAN Identifier.
+ * @retval kErrorParse Failed to parse the PAN Identifier.
*
*/
- otError GetDstPanId(PanId &aPanId) const;
+ Error GetDstPanId(PanId &aPanId) const;
/**
* This method sets the Destination PAN Identifier.
@@ -540,10 +563,10 @@
*
* @param[out] aAddress The Destination Address.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Destination Address.
+ * @retval kErrorNone Successfully retrieved the Destination Address.
*
*/
- otError GetDstAddr(Address &aAddress) const;
+ Error GetDstAddr(Address &aAddress) const;
/**
* This method sets the Destination Address.
@@ -582,20 +605,20 @@
*
* @param[out] aPanId The Source PAN Identifier.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Source PAN Identifier.
+ * @retval kErrorNone Successfully retrieved the Source PAN Identifier.
*
*/
- otError GetSrcPanId(PanId &aPanId) const;
+ Error GetSrcPanId(PanId &aPanId) const;
/**
* This method sets the Source PAN Identifier.
*
* @param[in] aPanId The Source PAN Identifier.
*
- * @retval OT_ERROR_NONE Successfully set the Source PAN Identifier.
+ * @retval kErrorNone Successfully set the Source PAN Identifier.
*
*/
- otError SetSrcPanId(PanId aPanId);
+ Error SetSrcPanId(PanId aPanId);
/**
* This method indicates whether or not the Source Address is present for this object.
@@ -610,10 +633,10 @@
*
* @param[out] aAddress The Source Address.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Source Address.
+ * @retval kErrorNone Successfully retrieved the Source Address.
*
*/
- otError GetSrcAddr(Address &aAddress) const;
+ Error GetSrcAddr(Address &aAddress) const;
/**
* This method sets the Source Address.
@@ -644,11 +667,11 @@
*
* @param[out] aSecurityControlField The Security Control Field.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Security Level Identifier.
- * @retval OT_ERROR_PARSE Failed to find the security control field in the frame.
+ * @retval kErrorNone Successfully retrieved the Security Level Identifier.
+ * @retval kErrorParse Failed to find the security control field in the frame.
*
*/
- otError GetSecurityControlField(uint8_t &aSecurityControlField) const;
+ Error GetSecurityControlField(uint8_t &aSecurityControlField) const;
/**
* This method sets the Security Control Field.
@@ -663,30 +686,30 @@
*
* @param[out] aSecurityLevel The Security Level Identifier.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Security Level Identifier.
+ * @retval kErrorNone Successfully retrieved the Security Level Identifier.
*
*/
- otError GetSecurityLevel(uint8_t &aSecurityLevel) const;
+ Error GetSecurityLevel(uint8_t &aSecurityLevel) const;
/**
* This method gets the Key Identifier Mode.
*
* @param[out] aSecurityLevel The Key Identifier Mode.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Key Identifier Mode.
+ * @retval kErrorNone Successfully retrieved the Key Identifier Mode.
*
*/
- otError GetKeyIdMode(uint8_t &aKeyIdMode) const;
+ Error GetKeyIdMode(uint8_t &aKeyIdMode) const;
/**
* This method gets the Frame Counter.
*
* @param[out] aFrameCounter The Frame Counter.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Frame Counter.
+ * @retval kErrorNone Successfully retrieved the Frame Counter.
*
*/
- otError GetFrameCounter(uint32_t &aFrameCounter) const;
+ Error GetFrameCounter(uint32_t &aFrameCounter) const;
/**
* This method sets the Frame Counter.
@@ -717,10 +740,10 @@
*
* @param[out] aKeyId The Key Identifier.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Key Identifier.
+ * @retval kErrorNone Successfully retrieved the Key Identifier.
*
*/
- otError GetKeyId(uint8_t &aKeyId) const;
+ Error GetKeyId(uint8_t &aKeyId) const;
/**
* This method sets the Key Identifier.
@@ -735,20 +758,20 @@
*
* @param[out] aCommandId The Command ID.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Command ID.
+ * @retval kErrorNone Successfully retrieved the Command ID.
*
*/
- otError GetCommandId(uint8_t &aCommandId) const;
+ Error GetCommandId(uint8_t &aCommandId) const;
/**
* This method sets the Command ID.
*
* @param[in] aCommandId The Command ID.
*
- * @retval OT_ERROR_NONE Successfully set the Command ID.
+ * @retval kErrorNone Successfully set the Command ID.
*
*/
- otError SetCommandId(uint8_t aCommandId);
+ Error SetCommandId(uint8_t aCommandId);
/**
* This method indicates whether the frame is a MAC Data Request command (data poll).
@@ -923,16 +946,22 @@
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
/**
- * This method appends Header IEs to MAC header.
+ * This template method appends an Header IE at specified index in this frame.
*
- * @param[in] aIeList The pointer to the Header IEs array.
- * @param[in] aIeCount The number of Header IEs in the array.
+ * @param[in,out] aIndex The index to append IE. If `aIndex` is `0` on input, this method finds the index
+ * for the first IE and appends the IE at that position. If the position is not found
+ * successfully, `aIndex` will be set to `kInvalidIndex`. Otherwise the IE will be
+ * appended at `aIndex` on input. And on output, `aIndex` will be set to the end of the
+ * IE just appended.
*
- * @retval OT_ERROR_NONE Successfully appended the Header IEs.
- * @retval OT_ERROR_FAILED If IE Present bit is not set.
+ * @tparam IeType The Header IE type, it MUST contain an enum `kHeaderIeId` equal to the IE's Id
+ * and an enum `kIeContentSize` indicating the IE body's size.
+ *
+ * @retval kErrorNone Successfully appended the Header IE.
+ * @retval kErrorNotFound The position for first IE is not found.
*
*/
- otError AppendHeaderIe(HeaderIe *aIeList, uint8_t aIeCount);
+ template <typename IeType> Error AppendHeaderIeAt(uint8_t &aIndex);
/**
* This method returns a pointer to the Header IE.
@@ -1091,6 +1120,9 @@
uint8_t FindPayloadIndex(void) const;
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
uint8_t FindHeaderIeIndex(void) const;
+
+ Error InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize);
+ template <typename IeType> void InitIeContentAt(uint8_t &aIndex);
#endif
static uint8_t GetKeySourceLength(uint8_t aKeyIdMode);
@@ -1171,11 +1203,11 @@
* for AES CCM computation.
* @param[in] aMacKey A reference to the MAC key to decrypt the received frame.
*
- * @retval OT_ERROR_NONE Process of received frame AES CCM succeeded.
- * @retval OT_ERROR_SECURITY Received frame MIC check failed.
+ * @retval kErrorNone Process of received frame AES CCM succeeded.
+ * @retval kErrorSecurity Received frame MIC check failed.
*
*/
- otError ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey);
+ Error ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const Key &aMacKey);
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
@@ -1394,11 +1426,11 @@
* @param[in] aIeData A pointer to the IE data portion of the ACK to be sent.
* @param[in] aIeLength The length of IE data portion of the ACK to be sent.
*
- * @retval OT_ERROR_NONE Successfully generated Enh Ack.
- * @retval OT_ERROR_PARSE @p aFrame has incorrect format.
+ * @retval kErrorNone Successfully generated Enh Ack.
+ * @retval kErrorParse @p aFrame has incorrect format.
*
*/
- otError GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
+ Error GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength);
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
/**
@@ -1642,6 +1674,12 @@
class CslIe
{
public:
+ enum : uint8_t
+ {
+ kHeaderIeId = 0x1a,
+ kIeContentSize = sizeof(uint16_t) * 2,
+ };
+
/**
* This method returns the CSL Period.
*
@@ -1680,6 +1718,22 @@
} OT_TOOL_PACKED_END;
/**
+ * This class implements Termination2 IE.
+ *
+ * This class is empty for template specialization.
+ *
+ */
+class Termination2Ie
+{
+public:
+ enum : uint8_t
+ {
+ kHeaderIeId = 0x7f,
+ kIeContentSize = 0,
+ };
+};
+
+/**
* @}
*
*/
diff --git a/src/core/mac/mac_links.cpp b/src/core/mac/mac_links.cpp
index 5b41262..156d48d 100644
--- a/src/core/mac/mac_links.cpp
+++ b/src/core/mac/mac_links.cpp
@@ -159,9 +159,9 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
if (aRadioTypes.Contains(kRadioTypeIeee802154))
{
- otError error = mSubMac.Send();
+ Error error = mSubMac.Send();
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
}
#endif
diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp
index 4ae1fd2..0f6d835 100644
--- a/src/core/mac/mac_links.hpp
+++ b/src/core/mac/mac_links.hpp
@@ -180,7 +180,7 @@
mTxFrame802154.SetIsARetransmission(false);
mTxFrame802154.SetIsSecurityProcessed(false);
mTxFrame802154.SetCsmaCaEnabled(true); // Set to true by default, only set to `false` for CSL transmission
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mTxFrame802154.SetTxDelay(0);
mTxFrame802154.SetTxDelayBaseTime(0);
#endif
@@ -513,8 +513,8 @@
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
{
- otError error = mSubMac.Send();
- OT_ASSERT(error == OT_ERROR_NONE);
+ Error error = mSubMac.Send();
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
}
#endif
@@ -576,12 +576,12 @@
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
- * @retval OT_ERROR_NONE Successfully started scanning the channel.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
- * @retval OT_ERROR_NOT_IMPLEMENTED Energy scan is not supported by radio link.
+ * @retval kErrorNone Successfully started scanning the channel.
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
+ * @retval kErrorNotImplemented Energy scan is not supported by radio link.
*
*/
- otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
+ Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
OT_UNUSED_VARIABLE(aScanChannel);
OT_UNUSED_VARIABLE(aScanDuration);
@@ -590,7 +590,7 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
mSubMac.EnergyScan(aScanChannel, aScanDuration);
#else
- OT_ERROR_NOT_IMPLEMENTED;
+ kErrorNotImplemented;
#endif
}
@@ -654,8 +654,8 @@
*
* @param[in] TxFrame The `TxFrame` from which to get the counter value.
*
- * @retval OT_ERROR_NONE If successful.
- * @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
+ * @retval kErrorNone If successful.
+ * @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
void SetMacFrameCounter(TxFrame &aFrame);
diff --git a/src/core/mac/mac_types.cpp b/src/core/mac/mac_types.cpp
index 3ed7150..6761d35 100644
--- a/src/core/mac/mac_types.cpp
+++ b/src/core/mac/mac_types.cpp
@@ -128,15 +128,15 @@
return NameData(m8, len);
}
-otError NetworkName::Set(const NameData &aNameData)
+Error NetworkName::Set(const NameData &aNameData)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t newLen = static_cast<uint8_t>(StringLength(aNameData.GetBuffer(), aNameData.GetLength()));
- VerifyOrExit(newLen <= kMaxSize, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(newLen <= kMaxSize, error = kErrorInvalidArgs);
// Ensure the new name does not match the current one.
- VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = OT_ERROR_ALREADY);
+ VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = kErrorAlready);
memcpy(m8, aNameData.GetBuffer(), newLen);
m8[newLen] = '\0';
@@ -162,15 +162,15 @@
return NameData(m8, len);
}
-otError DomainName::Set(const NameData &aNameData)
+Error DomainName::Set(const NameData &aNameData)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t newLen = static_cast<uint8_t>(StringLength(aNameData.GetBuffer(), aNameData.GetLength()));
- VerifyOrExit(newLen <= kMaxSize, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(newLen <= kMaxSize, error = kErrorInvalidArgs);
// Ensure the new name does not match the current one.
- VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = OT_ERROR_ALREADY);
+ VerifyOrExit(memcmp(m8, aNameData.GetBuffer(), newLen) || (m8[newLen] != '\0'), error = kErrorAlready);
memcpy(m8, aNameData.GetBuffer(), newLen);
m8[newLen] = '\0';
diff --git a/src/core/mac/mac_types.hpp b/src/core/mac/mac_types.hpp
index 5cbdc63..8dac5e0 100644
--- a/src/core/mac/mac_types.hpp
+++ b/src/core/mac/mac_types.hpp
@@ -564,12 +564,12 @@
*
* @param[in] aNameData A reference to name data.
*
- * @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Network Name.
- * @retval OT_ERROR_ALREADY The name is already set to the same string.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the IEEE 802.15.4 Network Name.
+ * @retval kErrorAlready The name is already set to the same string.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError Set(const NameData &aNameData);
+ Error Set(const NameData &aNameData);
/**
* This method overloads operator `==` to evaluate whether or not two given `NetworkName` objects are equal.
@@ -623,12 +623,12 @@
*
* @param[in] aNameData A reference to name data.
*
- * @retval OT_ERROR_NONE Successfully set the Thread Domain Name.
- * @retval OT_ERROR_ALREADY The name is already set to the same string.
- * @retval OT_ERROR_INVALID_ARGS Given name is too long.
+ * @retval kErrorNone Successfully set the Thread Domain Name.
+ * @retval kErrorAlready The name is already set to the same string.
+ * @retval kErrorInvalidArgs Given name is too long.
*
*/
- otError Set(const NameData &aNameData);
+ Error Set(const NameData &aNameData);
private:
char m8[kMaxSize + 1]; ///< Byte values.
diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp
index dd27e71..dcbe4ab 100644
--- a/src/core/mac/sub_mac.cpp
+++ b/src/core/mac/sub_mac.cpp
@@ -65,14 +65,14 @@
, mPcapCallbackContext(nullptr)
, mFrameCounter(0)
, mKeyId(0)
- , mTimer(aInstance, SubMac::HandleTimer, this)
+ , mTimer(aInstance, SubMac::HandleTimer)
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
, mCslTimeout(OPENTHREAD_CONFIG_CSL_TIMEOUT)
, mCslPeriod(0)
, mCslChannel(0)
, mIsCslChannelSpecified(false)
, mCslState(kCslIdle)
- , mCslTimer(aInstance, SubMac::HandleCslTimer, this)
+ , mCslTimer(aInstance, SubMac::HandleCslTimer)
#endif
{
mExtAddress.Clear();
@@ -151,9 +151,9 @@
mPcapCallbackContext = aCallbackContext;
}
-otError SubMac::Enable(void)
+Error SubMac::Enable(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(mState == kStateDisabled);
@@ -163,13 +163,13 @@
SetState(kStateSleep);
exit:
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
return error;
}
-otError SubMac::Disable(void)
+Error SubMac::Disable(void)
{
- otError error;
+ Error error;
mTimer.Stop();
SuccessOrExit(error = Get<Radio>().Sleep());
@@ -180,13 +180,13 @@
return error;
}
-otError SubMac::Sleep(void)
+Error SubMac::Sleep(void)
{
- otError error = Get<Radio>().Sleep();
+ Error error = Get<Radio>().Sleep();
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnMac("RadioSleep() failed, error: %s", otThreadErrorToString(error));
+ otLogWarnMac("RadioSleep() failed, error: %s", ErrorToString(error));
ExitNow();
}
@@ -196,13 +196,13 @@
return error;
}
-otError SubMac::Receive(uint8_t aChannel)
+Error SubMac::Receive(uint8_t aChannel)
{
- otError error = Get<Radio>().Receive(aChannel);
+ Error error = Get<Radio>().Receive(aChannel);
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnMac("RadioReceive() failed, error: %s", otThreadErrorToString(error));
+ otLogWarnMac("RadioReceive() failed, error: %s", ErrorToString(error));
ExitNow();
}
@@ -213,9 +213,9 @@
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-otError SubMac::CslSample(uint8_t aPanChannel)
+Error SubMac::CslSample(uint8_t aPanChannel)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (!IsCslChannelSpecified())
{
@@ -233,7 +233,7 @@
#endif
break;
case kCslIdle:
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
default:
OT_ASSERT(false);
}
@@ -241,17 +241,17 @@
SetState(kStateCslSample);
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnMac("CslSample() failed, error: %s", otThreadErrorToString(error));
+ otLogWarnMac("CslSample() failed, error: %s", ErrorToString(error));
}
return error;
}
#endif
-void SubMac::HandleReceiveDone(RxFrame *aFrame, otError aError)
+void SubMac::HandleReceiveDone(RxFrame *aFrame, Error aError)
{
- if (mPcapCallback && (aFrame != nullptr) && (aError == OT_ERROR_NONE))
+ if (mPcapCallback && (aFrame != nullptr) && (aError == kErrorNone))
{
mPcapCallback(aFrame, false, mPcapCallbackContext);
}
@@ -262,7 +262,7 @@
}
#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
- if (aFrame != nullptr && aError == OT_ERROR_NONE)
+ if (aFrame != nullptr && aError == kErrorNone)
{
// Split the log into two lines for RTT to output
otLogDebgMac("Received frame in state (SubMac %s, CSL %s), timestamp %u", StateToString(mState),
@@ -275,9 +275,9 @@
mCallbacks.ReceiveDone(aFrame, aError);
}
-otError SubMac::Send(void)
+Error SubMac::Send(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
switch (mState)
{
@@ -288,7 +288,7 @@
#endif
case kStateTransmit:
case kStateEnergyScan:
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
OT_UNREACHABLE_CODE(break);
case kStateSleep:
@@ -409,7 +409,7 @@
void SubMac::BeginTransmit(void)
{
- otError error;
+ Error error;
OT_UNUSED_VARIABLE(error);
@@ -422,7 +422,7 @@
if ((mRadioCaps & OT_RADIO_CAPS_SLEEP_TO_TX) == 0)
{
error = Get<Radio>().Receive(mTransmitFrame.GetChannel());
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
}
SetState(kStateTransmit);
@@ -433,14 +433,14 @@
}
error = Get<Radio>().Transmit(mTransmitFrame);
- if (error == OT_ERROR_INVALID_STATE && mTransmitFrame.mInfo.mTxInfo.mTxDelay > 0)
+ if (error == kErrorInvalidState && mTransmitFrame.mInfo.mTxInfo.mTxDelay > 0)
{
// Platform `transmit_at` fails and we send the frame directly.
mTransmitFrame.mInfo.mTxInfo.mTxDelay = 0;
mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime = 0;
error = Get<Radio>().Transmit(mTransmitFrame);
}
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
exit:
return;
@@ -458,7 +458,7 @@
}
}
-void SubMac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
+void SubMac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
{
bool ccaSuccess = true;
bool shouldRetx;
@@ -471,18 +471,18 @@
switch (aError)
{
- case OT_ERROR_ABORT:
+ case kErrorAbort:
// Do not record CCA status in case of `ABORT` error
// since there may be no CCA check performed by radio.
break;
- case OT_ERROR_CHANNEL_ACCESS_FAILURE:
+ case kErrorChannelAccessFailure:
ccaSuccess = false;
- // fall through
+ OT_FALL_THROUGH;
- case OT_ERROR_NONE:
- case OT_ERROR_NO_ACK:
+ case kErrorNone:
+ case kErrorNoAck:
if (aFrame.IsCsmaCaEnabled())
{
mCallbacks.RecordCcaStatus(ccaSuccess, aFrame.GetChannel());
@@ -510,8 +510,7 @@
// Determine whether to re-transmit the frame.
- shouldRetx =
- ((aError != OT_ERROR_NONE) && ShouldHandleRetries() && (mTransmitRetries < aFrame.GetMaxFrameRetries()));
+ shouldRetx = ((aError != kErrorNone) && ShouldHandleRetries() && (mTransmitRetries < aFrame.GetMaxFrameRetries()));
mCallbacks.RecordFrameTransmitStatus(aFrame, aAckFrame, aError, mTransmitRetries, shouldRetx);
@@ -554,10 +553,10 @@
allowError = Get<LinkRaw>().IsEnabled();
#endif
- VerifyOrExit(aFrame.GetKeyIdMode(keyIdMode) == OT_ERROR_NONE, OT_ASSERT(allowError));
+ VerifyOrExit(aFrame.GetKeyIdMode(keyIdMode) == kErrorNone, OT_ASSERT(allowError));
VerifyOrExit(keyIdMode == Frame::kKeyIdMode1);
- VerifyOrExit(aFrame.GetFrameCounter(frameCounter) == OT_ERROR_NONE, OT_ASSERT(allowError));
+ VerifyOrExit(aFrame.GetFrameCounter(frameCounter) == kErrorNone, OT_ASSERT(allowError));
UpdateFrameCounter(frameCounter);
exit:
@@ -574,9 +573,9 @@
return Get<Radio>().GetReceiveSensitivity();
}
-otError SubMac::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
+Error SubMac::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
switch (mState)
{
@@ -587,7 +586,7 @@
case kStateCslTransmit:
#endif
case kStateEnergyScan:
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
case kStateReceive:
case kStateSleep:
@@ -605,7 +604,7 @@
else if (ShouldHandleEnergyScan())
{
error = Get<Radio>().Receive(aScanChannel);
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
SetState(kStateEnergyScan);
mEnergyScanMaxRssi = kInvalidRssiValue;
@@ -614,7 +613,7 @@
}
else
{
- error = OT_ERROR_NOT_IMPLEMENTED;
+ error = kErrorNotImplemented;
}
exit:
@@ -657,7 +656,7 @@
void SubMac::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<SubMac>().HandleTimer();
+ aTimer.Get<SubMac>().HandleTimer();
}
void SubMac::HandleTimer(void)
@@ -676,7 +675,7 @@
case kStateTransmit:
otLogDebgMac("Ack timer timed out");
IgnoreError(Get<Radio>().Receive(mTransmitFrame.GetChannel()));
- HandleTransmitDone(mTransmitFrame, nullptr, OT_ERROR_NO_ACK);
+ HandleTransmitDone(mTransmitFrame, nullptr, kErrorNoAck);
break;
case kStateEnergyScan:
@@ -859,66 +858,57 @@
const char *SubMac::StateToString(State aState)
{
- const char *str = "Unknown";
-
- switch (aState)
- {
- case kStateDisabled:
- str = "Disabled";
- break;
- case kStateSleep:
- str = "Sleep";
- break;
- case kStateReceive:
- str = "Receive";
- break;
- case kStateCsmaBackoff:
- str = "CsmaBackoff";
- break;
- case kStateTransmit:
- str = "Transmit";
- break;
- case kStateEnergyScan:
- str = "EnergyScan";
- break;
+ static const char *const kStateStrings[] = {
+ "Disabled", // (0) kStateDisabled
+ "Sleep", // (1) kStateSleep
+ "Receive", // (2) kStateReceive
+ "CsmaBackoff", // (3) kStateCsmaBackoff
+ "Transmit", // (4) kStateTransmit
+ "EnergyScan", // (5) kStateEnergyScan
#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
- case kStateCslTransmit:
- str = "CslTransmit";
- break;
+ "CslTransmit", // (6) kStateCslTransmit
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- case kStateCslSample:
- str = "CslSample";
- break;
+ "CslSample", // (7) kStateCslSample
#endif
- }
+ };
- return str;
+ static_assert(kStateDisabled == 0, "kStateDisabled value is not correct");
+ static_assert(kStateSleep == 1, "kStateSleep value is not correct");
+ static_assert(kStateReceive == 2, "kStateReceive value is not correct");
+ static_assert(kStateCsmaBackoff == 3, "kStateCsmaBackoff value is not correct");
+ static_assert(kStateTransmit == 4, "kStateTransmit value is not correct");
+ static_assert(kStateEnergyScan == 5, "kStateEnergyScan value is not correct");
+#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ static_assert(kStateCslTransmit == 6, "kStateCslTransmit value is not correct");
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ static_assert(kStateCslSample == 7, "kStateCslSample value is not correct");
+#endif
+#else
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ static_assert(kStateCslSample == 6, "kStateCslSample value is not correct");
+#endif
+#endif
+
+ return kStateStrings[aState];
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
const char *SubMac::CslStateToString(CslState aCslState)
{
- const char *str = "Unknown";
+ static const char *const kCslStateStrings[] = {
+ "CslIdle", // (0) kCslIdle
+ "CslSample", // (1) kCslSample
+ "CslSleep", // (2) kCslSleep
+ };
- switch (aCslState)
- {
- case kCslIdle:
- str = "CslIdle";
- break;
- case kCslSample:
- str = "CslSample";
- break;
- case kCslSleep:
- str = "kCslSleep";
- break;
- default:
- break;
- }
+ static_assert(kCslIdle == 0, "kCslIdle value is incorrect");
+ static_assert(kCslSample == 1, "kCslSample value is incorrect");
+ static_assert(kCslSleep == 2, "kCslSleep value is incorrect");
- return str;
+ return kCslStateStrings[aCslState];
}
-#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#endif
// LCOV_EXCL_STOP
@@ -971,7 +961,7 @@
void SubMac::HandleCslTimer(Timer &aTimer)
{
- aTimer.GetOwner<SubMac>().HandleCslTimer();
+ aTimer.Get<SubMac>().HandleCslTimer();
}
void SubMac::HandleCslTimer(void)
diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp
index b2036e3..4b79ca2 100644
--- a/src/core/mac/sub_mac.hpp
+++ b/src/core/mac/sub_mac.hpp
@@ -58,6 +58,18 @@
namespace Mac {
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE."
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE."
+#endif
+
+#if OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE && !OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE."
+#endif
+
/**
* This class implements the IEEE 802.15.4 MAC (sub-MAC).
*
@@ -104,12 +116,12 @@
* This method notifies user of `SubMac` of a received frame.
*
* @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received,
- * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received,
+ * kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
- void ReceiveDone(RxFrame *aFrame, otError aError);
+ void ReceiveDone(RxFrame *aFrame, Error aError);
/**
* This method notifies user of `SubMac` of CCA status (success/failure) for a frame transmission attempt.
@@ -132,10 +144,10 @@
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, or nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
* @param[in] aRetryCount Current retry count. This is valid only when sub-mac handles frame re-transmissions.
* @param[in] aWillRetx Indicates whether frame will be retransmitted or not. This is applicable only
* when there was an error in current transmission attempt.
@@ -143,7 +155,7 @@
*/
void RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx);
@@ -153,13 +165,13 @@
*
* @param[in] aFrame The transmitted frame.
* @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
*
*/
- void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError);
+ void TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
/**
* This method notifies user of `SubMac` that energy scan is complete.
@@ -263,40 +275,49 @@
/**
* This method enables the radio.
*
- * @retval OT_ERROR_NONE Successfully enabled.
- * @retval OT_ERROR_FAILED The radio could not be enabled.
+ * @retval kErrorNone Successfully enabled.
+ * @retval kErrorFailed The radio could not be enabled.
*
*/
- otError Enable(void);
+ Error Enable(void);
/**
* This method disables the radio.
*
- * @retval OT_ERROR_NONE Successfully disabled the radio.
+ * @retval kErrorNone Successfully disabled the radio.
*
*/
- otError Disable(void);
+ Error Disable(void);
/**
* This method transitions the radio to Sleep.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Sleep.
- * @retval OT_ERROR_BUSY The radio was transmitting.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled.
+ * @retval kErrorNone Successfully transitioned to Sleep.
+ * @retval kErrorBusy The radio was transmitting.
+ * @retval kErrorInvalidState The radio was disabled.
*
*/
- otError Sleep(void);
+ Error Sleep(void);
+
+ /**
+ * This method indicates whether the sub-mac is busy transmitting or scanning.
+ *
+ * @retval TRUE if the sub-mac is busy transmitting or scanning.
+ * @retval FALSE if the sub-mac is not busy transmitting or scanning.
+ *
+ */
+ bool IsTransmittingOrScanning(void) const { return (mState == kStateTransmit) || (mState == kStateEnergyScan); }
/**
* This method transitions the radio to Receive.
*
* @param[in] aChannel The channel to use for receiving.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Receive.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
+ * @retval kErrorNone Successfully transitioned to Receive.
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
- otError Receive(uint8_t aChannel);
+ Error Receive(uint8_t aChannel);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
@@ -309,12 +330,12 @@
* @param[in] aPanChannel The current phy channel used by the device. This param will only take effect when CSL
* channel hasn't been explicitly specified.
*
- * @retval OT_ERROR_NONE Successfully entered CSL operation (sleep or receive according to CSL timer).
- * @retval OT_ERROR_BUSY The radio was transmitting.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled.
+ * @retval kErrorNone Successfully entered CSL operation (sleep or receive according to CSL timer).
+ * @retval kErrorBusy The radio was transmitting.
+ * @retval kErrorInvalidState The radio was disabled.
*
*/
- otError CslSample(uint8_t aPanChannel);
+ Error CslSample(uint8_t aPanChannel);
#endif
/**
@@ -332,11 +353,11 @@
*
* The `SubMac` layer handles Ack timeout, CSMA backoff, and frame retransmission.
*
- * @retval OT_ERROR_NONE Successfully started the frame transmission
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
+ * @retval kErrorNone Successfully started the frame transmission
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
- otError Send(void);
+ Error Send(void);
/**
* This method gets the number of transmit retries of last transmitted frame.
@@ -360,12 +381,12 @@
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
- * @retval OT_ERROR_NONE Successfully started scanning the channel.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
- * @retval OT_ERROR_NOT_IMPLEMENTED Energy scan is not supported (applicable in link-raw/radio mode only).
+ * @retval kErrorNone Successfully started scanning the channel.
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
+ * @retval kErrorNotImplemented Energy scan is not supported (applicable in link-raw/radio mode only).
*
*/
- otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
+ Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
/**
* This method returns the noise floor value (currently use the radio receive sensitivity value).
@@ -514,7 +535,7 @@
#endif
};
- enum State
+ enum State : uint8_t
{
kStateDisabled, ///< Radio is disabled.
kStateSleep, ///< Radio is in sleep.
@@ -575,9 +596,9 @@
void BeginTransmit(void);
void SampleRssi(void);
- void HandleReceiveDone(RxFrame *aFrame, otError aError);
+ void HandleReceiveDone(RxFrame *aFrame, Error aError);
void HandleTransmitStarted(TxFrame &aFrame);
- void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError);
+ void HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError);
void UpdateFrameCounterOnTxDone(const TxFrame &aFrame);
void HandleEnergyScanDone(int8_t aMaxRssi);
diff --git a/src/core/mac/sub_mac_callbacks.cpp b/src/core/mac/sub_mac_callbacks.cpp
index 6fa84b7..6f070ec 100644
--- a/src/core/mac/sub_mac_callbacks.cpp
+++ b/src/core/mac/sub_mac_callbacks.cpp
@@ -51,7 +51,7 @@
#if OPENTHREAD_FTD || OPENTHREAD_MTD
-void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, otError aError)
+void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, Error aError)
{
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
if (Get<LinkRaw>().IsEnabled())
@@ -72,14 +72,14 @@
void SubMac::Callbacks::RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx)
{
Get<Mac>().RecordFrameTransmitStatus(aFrame, aAckFrame, aError, aRetryCount, aWillRetx);
}
-void SubMac::Callbacks::TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
+void SubMac::Callbacks::TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
{
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
if (Get<LinkRaw>().IsEnabled())
@@ -114,7 +114,7 @@
#elif OPENTHREAD_RADIO
-void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, otError aError)
+void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, Error aError)
{
Get<LinkRaw>().InvokeReceiveDone(aFrame, aError);
}
@@ -125,14 +125,14 @@
void SubMac::Callbacks::RecordFrameTransmitStatus(const TxFrame &aFrame,
const RxFrame *aAckFrame,
- otError aError,
+ Error aError,
uint8_t aRetryCount,
bool aWillRetx)
{
Get<LinkRaw>().RecordFrameTransmitStatus(aFrame, aAckFrame, aError, aRetryCount, aWillRetx);
}
-void SubMac::Callbacks::TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
+void SubMac::Callbacks::TransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
{
Get<LinkRaw>().InvokeTransmitDone(aFrame, aAckFrame, aError);
}
diff --git a/src/core/meshcop/announce_begin_client.cpp b/src/core/meshcop/announce_begin_client.cpp
index 23160f5..84ff93b 100644
--- a/src/core/meshcop/announce_begin_client.cpp
+++ b/src/core/meshcop/announce_begin_client.cpp
@@ -53,18 +53,18 @@
{
}
-otError AnnounceBeginClient::SendRequest(uint32_t aChannelMask,
- uint8_t aCount,
- uint16_t aPeriod,
- const Ip6::Address &aAddress)
+Error AnnounceBeginClient::SendRequest(uint32_t aChannelMask,
+ uint8_t aCount,
+ uint16_t aPeriod,
+ const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::ChannelMaskTlv channelMask;
Ip6::MessageInfo messageInfo;
Coap::Message * message = nullptr;
- VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kAnnounceBegin));
SuccessOrExit(error = message->SetPayloadMarker());
diff --git a/src/core/meshcop/announce_begin_client.hpp b/src/core/meshcop/announce_begin_client.hpp
index 7702e05..a351a2f 100644
--- a/src/core/meshcop/announce_begin_client.hpp
+++ b/src/core/meshcop/announce_begin_client.hpp
@@ -64,11 +64,11 @@
* @param[in] aPeriod The time between two successive MLE Announce transmissions (in milliseconds).
* @param[in] aAddress The destination address.
*
- * @retval OT_ERROR_NONE Successfully enqueued the Announce Begin message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate a Announce Begin message.
+ * @retval kErrorNone Successfully enqueued the Announce Begin message.
+ * @retval kErrorNoBufs Insufficient buffers to generate a Announce Begin message.
*
*/
- otError SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, const Ip6::Address &aAddress);
+ Error SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, const Ip6::Address &aAddress);
};
/**
diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp
index a3970f6..fb33647 100644
--- a/src/core/meshcop/border_agent.cpp
+++ b/src/core/meshcop/border_agent.cpp
@@ -62,7 +62,7 @@
memcpy(mToken, aMessage.GetToken(), mTokenLength);
}
-otError BorderAgent::ForwardContext::ToHeader(Coap::Message &aMessage, uint8_t aCode)
+Error BorderAgent::ForwardContext::ToHeader(Coap::Message &aMessage, uint8_t aCode)
{
if ((mType == Coap::kTypeNonConfirmable) || mSeparate)
{
@@ -81,17 +81,17 @@
return aMessage.SetToken(mToken, mTokenLength);
}
-Coap::Message::Code BorderAgent::CoapCodeFromError(otError aError)
+Coap::Message::Code BorderAgent::CoapCodeFromError(Error aError)
{
Coap::Message::Code code;
switch (aError)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
code = Coap::kCodeChanged;
break;
- case OT_ERROR_PARSE:
+ case kErrorParse:
code = Coap::kCodeBadRequest;
break;
@@ -103,13 +103,13 @@
return code;
}
-void BorderAgent::SendErrorMessage(ForwardContext &aForwardContext, otError aError)
+void BorderAgent::SendErrorMessage(ForwardContext &aForwardContext, Error aError)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::CoapSecure &coaps = Get<Coap::CoapSecure>();
Coap::Message * message = nullptr;
- VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = aForwardContext.ToHeader(*message, CoapCodeFromError(aError)));
SuccessOrExit(error = coaps.SendMessage(*message, coaps.GetMessageInfo()));
@@ -118,13 +118,13 @@
LogError("send error CoAP message", error);
}
-void BorderAgent::SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, otError aError)
+void BorderAgent::SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::CoapSecure &coaps = Get<Coap::CoapSecure>();
Coap::Message * message = nullptr;
- VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(coaps)) != nullptr, error = kErrorNoBufs);
if (aRequest.IsNonConfirmable() || aSeparate)
{
@@ -152,7 +152,7 @@
void BorderAgent::HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
@@ -162,13 +162,13 @@
aResult);
}
-void BorderAgent::HandleCoapResponse(ForwardContext &aForwardContext, const Coap::Message *aResponse, otError aResult)
+void BorderAgent::HandleCoapResponse(ForwardContext &aForwardContext, const Coap::Message *aResponse, Error aResult)
{
Coap::Message *message = nullptr;
- otError error;
+ Error error;
SuccessOrExit(error = aResult);
- VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
if (aForwardContext.IsPetition() && aResponse->GetCode() == Coap::kCodeChanged)
{
@@ -199,17 +199,16 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeMessage(message);
- otLogWarnMeshCoP("Commissioner request[%hu] failed: %s", aForwardContext.GetMessageId(),
- otThreadErrorToString(error));
+ otLogWarnMeshCoP("Commissioner request[%hu] failed: %s", aForwardContext.GetMessageId(), ErrorToString(error));
SendErrorMessage(aForwardContext, error);
}
- GetInstance().HeapFree(&aForwardContext);
+ Instance::HeapFree(&aForwardContext);
}
template <Coap::Resource BorderAgent::*aResource>
@@ -284,7 +283,7 @@
, mPendingSet(UriPath::kPendingSet, BorderAgent::HandleRequest<&BorderAgent::mPendingSet>, this)
, mProxyTransmit(UriPath::kProxyTx, BorderAgent::HandleRequest<&BorderAgent::mProxyTransmit>, this)
, mUdpReceiver(BorderAgent::HandleUdpReceive, this)
- , mTimer(aInstance, HandleTimeout, this)
+ , mTimer(aInstance, HandleTimeout)
, mState(kStateStopped)
{
mCommissionerAloc.InitAsThreadOriginRealmLocalScope();
@@ -316,13 +315,13 @@
Message * message = nullptr;
Ip6::MessageInfo messageInfo;
uint16_t offset;
- otError error;
+ Error error;
UdpEncapsulationTlv tlv;
SuccessOrExit(error = Tlv::FindTlvOffset(aMessage, Tlv::kUdpEncapsulation, offset));
SuccessOrExit(error = aMessage.Read(offset, tlv));
- VerifyOrExit((message = Get<Ip6::Udp>().NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Ip6::Udp>().NewMessage(0)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetLength(tlv.GetUdpLength()));
aMessage.CopyTo(offset + sizeof(tlv), 0, tlv.GetUdpLength(), *message);
@@ -342,15 +341,15 @@
bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
Coap::Message *message = nullptr;
VerifyOrExit(aMessageInfo.GetSockAddr() == mCommissionerAloc.GetAddress(),
- error = OT_ERROR_DESTINATION_ADDRESS_FILTERED);
+ error = kErrorDestinationAddressFiltered);
- VerifyOrExit(aMessage.GetLength() > 0, error = OT_ERROR_NONE);
+ VerifyOrExit(aMessage.GetLength() > 0, error = kErrorNone);
- VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
message->InitAsNonConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kProxyRx));
@@ -382,16 +381,16 @@
FreeMessageOnError(message, error);
LogError("notify commissioner on ProxyRx (c/ur)", error);
- return error != OT_ERROR_DESTINATION_ADDRESS_FILTERED;
+ return error != kErrorDestinationAddressFiltered;
}
void BorderAgent::HandleRelayReceive(const Coap::Message &aMessage)
{
Coap::Message *message = nullptr;
- otError error;
+ Error error;
- VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = OT_ERROR_DROP);
- VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
message->InitAsNonConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kRelayRx));
@@ -408,9 +407,9 @@
FreeMessageOnError(message, error);
}
-otError BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage)
+Error BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t offset = 0;
offset = aForwardMessage.GetLength();
@@ -429,11 +428,11 @@
void BorderAgent::HandleKeepAlive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
error = ForwardToLeader(aMessage, aMessageInfo, UriPath::kLeaderKeepAlive, false, true);
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
mTimer.Start(kKeepAliveTimeout);
}
@@ -441,7 +440,7 @@
void BorderAgent::HandleRelayTransmit(const Coap::Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t joinerRouterRloc;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
@@ -451,7 +450,7 @@
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRouterRloc));
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kRelayTx));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -475,27 +474,27 @@
LogError("send to joiner router request RelayTx (c/tx)", error);
}
-otError BorderAgent::ForwardToLeader(const Coap::Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- const char * aPath,
- bool aPetition,
- bool aSeparate)
+Error BorderAgent::ForwardToLeader(const Coap::Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ const char * aPath,
+ bool aPetition,
+ bool aSeparate)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ForwardContext * forwardContext = nullptr;
Ip6::MessageInfo messageInfo;
Coap::Message * message = nullptr;
uint16_t offset = 0;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
if (aSeparate)
{
SuccessOrExit(error = Get<Coap::CoapSecure>().SendAck(aMessage, aMessageInfo));
}
- forwardContext = static_cast<ForwardContext *>(GetInstance().HeapCAlloc(1, sizeof(ForwardContext)));
- VerifyOrExit(forwardContext != nullptr, error = OT_ERROR_NO_BUFS);
+ forwardContext = static_cast<ForwardContext *>(Instance::HeapCAlloc(1, sizeof(ForwardContext)));
+ VerifyOrExit(forwardContext != nullptr, error = kErrorNoBufs);
forwardContext->Init(GetInstance(), aMessage, aPetition, aSeparate);
@@ -526,11 +525,11 @@
exit:
LogError("forward to leader", error);
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
if (forwardContext != nullptr)
{
- GetInstance().HeapFree(forwardContext);
+ Instance::HeapFree(forwardContext);
}
FreeMessage(message);
@@ -562,12 +561,12 @@
}
}
-otError BorderAgent::Start(void)
+Error BorderAgent::Start(void)
{
- otError error;
+ Error error;
Coap::CoapSecure &coaps = Get<Coap::CoapSecure>();
- VerifyOrExit(mState == kStateStopped, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState == kStateStopped, error = kErrorAlready);
SuccessOrExit(error = coaps.Start(kBorderAgentUdpPort));
SuccessOrExit(error = coaps.SetPsk(Get<KeyManager>().GetPskc().m8, OT_PSKC_MAX_SIZE));
@@ -594,7 +593,7 @@
void BorderAgent::HandleTimeout(Timer &aTimer)
{
- aTimer.GetOwner<BorderAgent>().HandleTimeout();
+ aTimer.Get<BorderAgent>().HandleTimeout();
}
void BorderAgent::HandleTimeout(void)
@@ -606,12 +605,12 @@
}
}
-otError BorderAgent::Stop(void)
+Error BorderAgent::Stop(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::CoapSecure &coaps = Get<Coap::CoapSecure>();
- VerifyOrExit(mState != kStateStopped, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState != kStateStopped, error = kErrorAlready);
mTimer.Stop();
diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp
index e785bd2..43ee78f 100644
--- a/src/core/meshcop/border_agent.hpp
+++ b/src/core/meshcop/border_agent.hpp
@@ -75,20 +75,20 @@
/**
* This method starts the Border Agent service.
*
- * @retval OT_ERROR_NONE Successfully started the Border Agent service.
- * @retval OT_ERROR_ALREADY Border Agent is already started.
+ * @retval kErrorNone Successfully started the Border Agent service.
+ * @retval kErrorAlready Border Agent is already started.
*
*/
- otError Start(void);
+ Error Start(void);
/**
* This method stops the Border Agent service.
*
- * @retval OT_ERROR_NONE Successfully stopped the Border Agent service.
- * @retval OT_ERROR_ALREADY Border Agent is already stopped.
+ * @retval kErrorNone Successfully stopped the Border Agent service.
+ * @retval kErrorAlready Border Agent is already stopped.
*
*/
- otError Stop(void);
+ Error Stop(void);
/**
* This method gets the state of the Border Agent service.
@@ -111,7 +111,7 @@
void Init(Instance &aInstance, const Coap::Message &aMessage, bool aPetition, bool aSeparate);
bool IsPetition(void) const { return mPetition; }
uint16_t GetMessageId(void) const { return mMessageId; }
- otError ToHeader(Coap::Message &aMessage, uint8_t aCode);
+ Error ToHeader(Coap::Message &aMessage, uint8_t aCode);
private:
uint16_t mMessageId; // The CoAP Message ID of the original request.
@@ -124,9 +124,9 @@
void HandleNotifierEvents(Events aEvents);
- Coap::Message::Code CoapCodeFromError(otError aError);
- void SendErrorMessage(ForwardContext &aForwardContext, otError aError);
- void SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, otError aError);
+ Coap::Message::Code CoapCodeFromError(Error aError);
+ void SendErrorMessage(ForwardContext &aForwardContext, Error aError);
+ void SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError);
static void HandleConnected(bool aConnected, void *aContext);
void HandleConnected(bool aConnected);
@@ -140,15 +140,15 @@
static void HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleCoapResponse(ForwardContext &aForwardContext, const Coap::Message *aResponse, otError aResult);
+ Error aResult);
+ void HandleCoapResponse(ForwardContext &aForwardContext, const Coap::Message *aResponse, Error aResult);
- otError ForwardToLeader(const Coap::Message & aMessage,
+ Error ForwardToLeader(const Coap::Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const char * aPath,
bool aPetition,
bool aSeparate);
- otError ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage);
+ Error ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage);
void HandleKeepAlive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleRelayTransmit(const Coap::Message &aMessage);
void HandleRelayReceive(const Coap::Message &aMessage);
diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp
index b9537c0..010d5ed 100644
--- a/src/core/meshcop/commissioner.cpp
+++ b/src/core/meshcop/commissioner.cpp
@@ -41,7 +41,6 @@
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#include "common/string.hpp"
-#include "crypto/pbkdf2_cmac.h"
#include "meshcop/joiner.hpp"
#include "meshcop/joiner_router.hpp"
#include "meshcop/meshcop.hpp"
@@ -62,8 +61,8 @@
, mJoinerRloc(0)
, mSessionId(0)
, mTransmitAttempts(0)
- , mJoinerExpirationTimer(aInstance, HandleJoinerExpirationTimer, this)
- , mTimer(aInstance, HandleTimer, this)
+ , mJoinerExpirationTimer(aInstance, HandleJoinerExpirationTimer)
+ , mTimer(aInstance, HandleTimer)
, mRelayReceive(UriPath::kRelayRx, &Commissioner::HandleRelayReceive, this)
, mDatasetChanged(UriPath::kDatasetChanged, &Commissioner::HandleDatasetChanged, this)
, mJoinerFinalize(UriPath::kJoinerFinalize, &Commissioner::HandleJoinerFinalize, this)
@@ -295,18 +294,18 @@
SignalJoinerEvent(kJoinerEventRemoved, &joinerCopy);
}
-otError Commissioner::Start(otCommissionerStateCallback aStateCallback,
- otCommissionerJoinerCallback aJoinerCallback,
- void * aCallbackContext)
+Error Commissioner::Start(otCommissionerStateCallback aStateCallback,
+ otCommissionerJoinerCallback aJoinerCallback,
+ void * aCallbackContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(mState == kStateDisabled, error = OT_ERROR_ALREADY);
+ VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = kErrorInvalidState);
+ VerifyOrExit(mState == kStateDisabled, error = kErrorAlready);
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
error = Get<MeshCoP::BorderAgent>().Stop();
- VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY);
+ VerifyOrExit(error == kErrorNone || error == kErrorAlready);
#endif
SuccessOrExit(error = Get<Coap::CoapSecure>().Start(SendRelayTransmit, this));
@@ -321,7 +320,7 @@
SetState(kStatePetition);
exit:
- if ((error != OT_ERROR_NONE) && (error != OT_ERROR_ALREADY))
+ if ((error != kErrorNone) && (error != kErrorAlready))
{
Get<Coap::CoapSecure>().Stop();
}
@@ -330,12 +329,12 @@
return error;
}
-otError Commissioner::Stop(bool aResign)
+Error Commissioner::Stop(bool aResign)
{
- otError error = OT_ERROR_NONE;
- bool needResign = false;
+ Error error = kErrorNone;
+ bool needResign = false;
- VerifyOrExit(mState != kStateDisabled, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState != kStateDisabled, error = kErrorAlready);
Get<Coap::CoapSecure>().Stop();
@@ -399,10 +398,10 @@
void Commissioner::SendCommissionerSet(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
otCommissioningDataset dataset;
- VerifyOrExit(mState == kStateActive, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
memset(&dataset, 0, sizeof(dataset));
@@ -428,19 +427,19 @@
SendCommissionerSet();
}
-otError Commissioner::AddJoiner(const Mac::ExtAddress *aEui64,
- const JoinerDiscerner *aDiscerner,
- const char * aPskd,
- uint32_t aTimeout)
+Error Commissioner::AddJoiner(const Mac::ExtAddress *aEui64,
+ const JoinerDiscerner *aDiscerner,
+ const char * aPskd,
+ uint32_t aTimeout)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Joiner *joiner;
- VerifyOrExit(mState == kStateActive, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
if (aDiscerner != nullptr)
{
- VerifyOrExit(aDiscerner->IsValid(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aDiscerner->IsValid(), error = kErrorInvalidArgs);
joiner = FindJoinerEntry(*aDiscerner);
}
else
@@ -453,7 +452,7 @@
joiner = GetUnusedJoinerEntry();
}
- VerifyOrExit(joiner != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(joiner != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = joiner->mPskd.SetFrom(aPskd));
@@ -515,9 +514,9 @@
return;
}
-otError Commissioner::GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoinerInfo) const
+Error Commissioner::GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoinerInfo) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
while (aIterator < OT_ARRAY_LENGTH(mJoiners))
{
@@ -530,22 +529,22 @@
}
}
- error = OT_ERROR_NOT_FOUND;
+ error = kErrorNotFound;
exit:
return error;
}
-otError Commissioner::RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay)
+Error Commissioner::RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Joiner *joiner;
- VerifyOrExit(mState == kStateActive, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
if (aDiscerner != nullptr)
{
- VerifyOrExit(aDiscerner->IsValid(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aDiscerner->IsValid(), error = kErrorInvalidArgs);
joiner = FindJoinerEntry(*aDiscerner);
}
else
@@ -553,7 +552,7 @@
joiner = FindJoinerEntry(aEui64);
}
- VerifyOrExit(joiner != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(joiner != nullptr, error = kErrorNotFound);
RemoveJoiner(*joiner, aDelay);
@@ -579,9 +578,9 @@
}
}
-otError Commissioner::SetProvisioningUrl(const char *aProvisioningUrl)
+Error Commissioner::SetProvisioningUrl(const char *aProvisioningUrl)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t len;
if (aProvisioningUrl == nullptr)
@@ -590,11 +589,11 @@
ExitNow();
}
- VerifyOrExit(IsValidUtf8String(aProvisioningUrl), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsValidUtf8String(aProvisioningUrl), error = kErrorInvalidArgs);
len = static_cast<uint8_t>(StringLength(aProvisioningUrl, sizeof(mProvisioningUrl)));
- VerifyOrExit(len < sizeof(mProvisioningUrl), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(len < sizeof(mProvisioningUrl), error = kErrorInvalidArgs);
memcpy(mProvisioningUrl, aProvisioningUrl, len);
mProvisioningUrl[len] = '\0';
@@ -605,7 +604,7 @@
void Commissioner::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Commissioner>().HandleTimer();
+ aTimer.Get<Commissioner>().HandleTimer();
}
void Commissioner::HandleTimer(void)
@@ -627,7 +626,7 @@
void Commissioner::HandleJoinerExpirationTimer(Timer &aTimer)
{
- aTimer.GetOwner<Commissioner>().HandleJoinerExpirationTimer();
+ aTimer.Get<Commissioner>().HandleJoinerExpirationTimer();
}
void Commissioner::HandleJoinerExpirationTimer(void)
@@ -683,14 +682,14 @@
}
}
-otError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength)
+Error Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
MeshCoP::Tlv tlv;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kCommissionerGet));
@@ -723,7 +722,7 @@
void Commissioner::HandleMgmtCommissionerGetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<Commissioner *>(aContext)->HandleMgmtCommissionerGetResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -731,26 +730,26 @@
void Commissioner::HandleMgmtCommissionerGetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == Coap::kCodeChanged);
+ VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged);
otLogInfoMeshCoP("received MGMT_COMMISSIONER_GET response");
exit:
return;
}
-otError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
- const uint8_t * aTlvs,
- uint8_t aLength)
+Error Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
+ const uint8_t * aTlvs,
+ uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kCommissionerSet));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -803,7 +802,7 @@
void Commissioner::HandleMgmtCommissionerSetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<Commissioner *>(aContext)->HandleMgmtCommissionerSetResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -811,27 +810,27 @@
void Commissioner::HandleMgmtCommissionerSetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == Coap::kCodeChanged);
+ VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged);
otLogInfoMeshCoP("received MGMT_COMMISSIONER_SET response");
exit:
return;
}
-otError Commissioner::SendPetition(void)
+Error Commissioner::SendPetition(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
CommissionerIdTlv commissionerId;
mTransmitAttempts++;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kLeaderPetition));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -857,7 +856,7 @@
void Commissioner::HandleLeaderPetitionResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<Commissioner *>(aContext)->HandleLeaderPetitionResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -865,7 +864,7 @@
void Commissioner::HandleLeaderPetitionResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
@@ -873,7 +872,7 @@
bool retransmit = false;
VerifyOrExit(mState != kStateActive);
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == Coap::kCodeChanged,
+ VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
retransmit = (mState == kStatePetition));
otLogInfoMeshCoP("received Leader Petition response");
@@ -922,11 +921,11 @@
void Commissioner::SendKeepAlive(uint16_t aSessionId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kLeaderKeepAlive));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -952,7 +951,7 @@
void Commissioner::HandleLeaderKeepAliveResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<Commissioner *>(aContext)->HandleLeaderKeepAliveResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -960,14 +959,14 @@
void Commissioner::HandleLeaderKeepAliveResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
uint8_t state;
VerifyOrExit(mState == kStateActive);
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == Coap::kCodeChanged,
+ VerifyOrExit(aResult == kErrorNone && aMessage->GetCode() == Coap::kCodeChanged,
IgnoreError(Stop(/* aResign */ false)));
otLogInfoMeshCoP("received Leader keep-alive response");
@@ -991,7 +990,7 @@
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error;
+ Error error;
uint16_t joinerPort;
Ip6::InterfaceIdentifier joinerIid;
uint16_t joinerRloc;
@@ -999,7 +998,7 @@
uint16_t offset;
uint16_t length;
- VerifyOrExit(mState == kStateActive, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
VerifyOrExit(aMessage.IsNonConfirmablePostRequest());
@@ -1008,7 +1007,7 @@
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRloc));
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
- VerifyOrExit(length <= aMessage.GetLength() - offset, error = OT_ERROR_PARSE);
+ VerifyOrExit(length <= aMessage.GetLength() - offset, error = kErrorParse);
if (!Get<Coap::CoapSecure>().IsConnectionActive())
{
@@ -1085,7 +1084,7 @@
otLogInfoMeshCoP("received joiner finalize");
- if (Tlv::FindTlv(aMessage, provisioningUrl) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, provisioningUrl) == kErrorNone)
{
uint8_t len = static_cast<uint8_t>(StringLength(mProvisioningUrl, sizeof(mProvisioningUrl)));
@@ -1112,11 +1111,11 @@
void Commissioner::SendJoinFinalizeResponse(const Coap::Message &aRequest, StateTlv::State aState)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::MessageInfo joinerMessageInfo;
Coap::Message * message;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -1153,22 +1152,22 @@
FreeMessageOnError(message, error);
}
-otError Commissioner::SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Commissioner::SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<Commissioner *>(aContext)->SendRelayTransmit(aMessage, aMessageInfo);
}
-otError Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ExtendedTlv tlv;
Coap::Message * message;
uint16_t offset;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
message->InitAsNonConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kRelayTx));
@@ -1222,22 +1221,17 @@
const char *Commissioner::StateToString(State aState)
{
- const char *str = "Unknown";
+ static const char *const kStateStrings[] = {
+ "disabled", // (0) kStateDisabled
+ "petition", // (1) kStatePetition
+ "active", // (2) kStateActive
+ };
- switch (aState)
- {
- case kStateDisabled:
- str = "disabled";
- break;
- case kStatePetition:
- str = "petition";
- break;
- case kStateActive:
- str = "active";
- break;
- }
+ static_assert(kStateDisabled == 0, "kStateDisabled value is incorrect");
+ static_assert(kStatePetition == 1, "kStatePetition value is incorrect");
+ static_assert(kStateActive == 2, "kStateActive value is incorrect");
- return str;
+ return kStateStrings[aState];
}
void Commissioner::LogJoinerEntry(const char *aAction, const Joiner &aJoiner) const
diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp
index 4bfde65..8a21c43 100644
--- a/src/core/meshcop/commissioner.hpp
+++ b/src/core/meshcop/commissioner.hpp
@@ -86,25 +86,25 @@
* @param[in] aJoinerCallback A pointer to a function that is called when a joiner event occurs.
* @param[in] aCallbackContext A pointer to application-specific context.
*
- * @retval OT_ERROR_NONE Successfully started the Commissioner service.
- * @retval OT_ERROR_ALREADY Commissioner is already started.
- * @retval OT_ERROR_INVALID_STATE Device is not currently attached to a network.
+ * @retval kErrorNone Successfully started the Commissioner service.
+ * @retval kErrorAlready Commissioner is already started.
+ * @retval kErrorInvalidState Device is not currently attached to a network.
*
*/
- otError Start(otCommissionerStateCallback aStateCallback,
- otCommissionerJoinerCallback aJoinerCallback,
- void * aCallbackContext);
+ Error Start(otCommissionerStateCallback aStateCallback,
+ otCommissionerJoinerCallback aJoinerCallback,
+ void * aCallbackContext);
/**
* This method stops the Commissioner service.
*
* @param[in] aResign Whether send LEAD_KA.req to resign as Commissioner
*
- * @retval OT_ERROR_NONE Successfully stopped the Commissioner service.
- * @retval OT_ERROR_ALREADY Commissioner is already stopped.
+ * @retval kErrorNone Successfully stopped the Commissioner service.
+ * @retval kErrorAlready Commissioner is already stopped.
*
*/
- otError Stop(bool aResign);
+ Error Stop(bool aResign);
/**
* This method clears all Joiner entries.
@@ -118,12 +118,12 @@
* @param[in] aPskd A pointer to the PSKd.
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NO_BUFS No buffers available to add the Joiner.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNoBufs No buffers available to add the Joiner.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError AddJoinerAny(const char *aPskd, uint32_t aTimeout) { return AddJoiner(nullptr, nullptr, aPskd, aTimeout); }
+ Error AddJoinerAny(const char *aPskd, uint32_t aTimeout) { return AddJoiner(nullptr, nullptr, aPskd, aTimeout); }
/**
* This method adds a Joiner entry.
@@ -132,12 +132,12 @@
* @param[in] aPskd A pointer to the PSKd.
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NO_BUFS No buffers available to add the Joiner.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNoBufs No buffers available to add the Joiner.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError AddJoiner(const Mac::ExtAddress &aEui64, const char *aPskd, uint32_t aTimeout)
+ Error AddJoiner(const Mac::ExtAddress &aEui64, const char *aPskd, uint32_t aTimeout)
{
return AddJoiner(&aEui64, nullptr, aPskd, aTimeout);
}
@@ -149,12 +149,12 @@
* @param[in] aPskd A pointer to the PSKd.
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NO_BUFS No buffers available to add the Joiner.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNoBufs No buffers available to add the Joiner.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError AddJoiner(const JoinerDiscerner &aDiscerner, const char *aPskd, uint32_t aTimeout)
+ Error AddJoiner(const JoinerDiscerner &aDiscerner, const char *aPskd, uint32_t aTimeout)
{
return AddJoiner(nullptr, &aDiscerner, aPskd, aTimeout);
}
@@ -165,23 +165,23 @@
* @param[inout] aIterator A iterator to the index of the joiner.
* @param[out] aJoiner A reference to Joiner info.
*
- * @retval OT_ERROR_NONE Successfully get the Joiner info.
- * @retval OT_ERROR_NOT_FOUND Not found next Joiner.
+ * @retval kErrorNone Successfully get the Joiner info.
+ * @retval kErrorNotFound Not found next Joiner.
*
*/
- otError GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoiner) const;
+ Error GetNextJoinerInfo(uint16_t &aIterator, otJoinerInfo &aJoiner) const;
/**
* This method removes a Joiner entry accepting any Joiner.
*
* @param[in] aDelay The delay to remove Joiner (in seconds).
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NOT_FOUND The Joiner entry accepting any Joiner was not found.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNotFound The Joiner entry accepting any Joiner was not found.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError RemoveJoinerAny(uint32_t aDelay) { return RemoveJoiner(nullptr, nullptr, aDelay); }
+ Error RemoveJoinerAny(uint32_t aDelay) { return RemoveJoiner(nullptr, nullptr, aDelay); }
/**
* This method removes a Joiner entry.
@@ -189,12 +189,12 @@
* @param[in] aEui64 The Joiner's IEEE EUI-64.
* @param[in] aDelay The delay to remove Joiner (in seconds).
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NOT_FOUND The Joiner specified by @p aEui64 was not found.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNotFound The Joiner specified by @p aEui64 was not found.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError RemoveJoiner(const Mac::ExtAddress &aEui64, uint32_t aDelay)
+ Error RemoveJoiner(const Mac::ExtAddress &aEui64, uint32_t aDelay)
{
return RemoveJoiner(&aEui64, nullptr, aDelay);
}
@@ -205,12 +205,12 @@
* @param[in] aDiscerner A Joiner Discerner.
* @param[in] aDelay The delay to remove Joiner (in seconds).
*
- * @retval OT_ERROR_NONE Successfully added the Joiner.
- * @retval OT_ERROR_NOT_FOUND The Joiner specified by @p aEui64 was not found.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Successfully added the Joiner.
+ * @retval kErrorNotFound The Joiner specified by @p aEui64 was not found.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError RemoveJoiner(const JoinerDiscerner &aDiscerner, uint32_t aDelay)
+ Error RemoveJoiner(const JoinerDiscerner &aDiscerner, uint32_t aDelay)
{
return RemoveJoiner(nullptr, &aDiscerner, aDelay);
}
@@ -228,11 +228,11 @@
*
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be nullptr to set URL to empty string).
*
- * @retval OT_ERROR_NONE Successfully set the Provisioning URL.
- * @retval OT_ERROR_INVALID_ARGS @p aProvisioningUrl is invalid (too long).
+ * @retval kErrorNone Successfully set the Provisioning URL.
+ * @retval kErrorInvalidArgs @p aProvisioningUrl is invalid (too long).
*
*/
- otError SetProvisioningUrl(const char *aProvisioningUrl);
+ Error SetProvisioningUrl(const char *aProvisioningUrl);
/**
* This method returns the Commissioner Session ID.
@@ -272,12 +272,12 @@
* @param[in] aTlvs A pointer to Commissioning Data TLVs.
* @param[in] aLength The length of requested TLVs in bytes.
*
- * @retval OT_ERROR_NONE Send MGMT_COMMISSIONER_GET successfully.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Send MGMT_COMMISSIONER_GET successfully.
+ * @retval kErrorNoBufs Insufficient buffer space to send.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
+ Error SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
/**
* This method sends MGMT_COMMISSIONER_SET.
@@ -286,14 +286,12 @@
* @param[in] aTlvs A pointer to user specific Commissioning Data TLVs.
* @param[in] aLength The length of user specific TLVs in bytes.
*
- * @retval OT_ERROR_NONE Send MGMT_COMMISSIONER_SET successfully.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
- * @retval OT_ERROR_INVALID_STATE Commissioner service is not started.
+ * @retval kErrorNone Send MGMT_COMMISSIONER_SET successfully.
+ * @retval kErrorNoBufs Insufficient buffer space to send.
+ * @retval kErrorInvalidState Commissioner service is not started.
*
*/
- otError SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
- const uint8_t * aTlvs,
- uint8_t aLength);
+ Error SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
/**
* This method returns a reference to the AnnounceBeginClient instance.
@@ -374,12 +372,12 @@
Joiner *FindBestMatchingJoinerEntry(const Mac::ExtAddress &aReceivedJoinerId);
void RemoveJoinerEntry(Joiner &aJoiner);
- otError AddJoiner(const Mac::ExtAddress *aEui64,
- const JoinerDiscerner *aDiscerner,
- const char * aPskd,
- uint32_t aTimeout);
- otError RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay);
- void RemoveJoiner(Joiner &aJoiner, uint32_t aDelay);
+ Error AddJoiner(const Mac::ExtAddress *aEui64,
+ const JoinerDiscerner *aDiscerner,
+ const char * aPskd,
+ uint32_t aTimeout);
+ Error RemoveJoiner(const Mac::ExtAddress *aEui64, const JoinerDiscerner *aDiscerner, uint32_t aDelay);
+ void RemoveJoiner(Joiner &aJoiner, uint32_t aDelay);
void AddCoapResources(void);
void RemoveCoapResources(void);
@@ -395,27 +393,27 @@
static void HandleMgmtCommissionerSetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
void HandleMgmtCommissionerSetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
static void HandleMgmtCommissionerGetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
void HandleMgmtCommissionerGetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
static void HandleLeaderPetitionResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleLeaderPetitionResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleLeaderPetitionResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleLeaderKeepAliveResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleCoapsConnected(bool aConnected, void *aContext);
void HandleCoapsConnected(bool aConnected);
@@ -431,14 +429,14 @@
void SendJoinFinalizeResponse(const Coap::Message &aRequest, StateTlv::State aState);
- static otError SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- otError SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static Error SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- void ComputeBloomFilter(SteeringData &aSteeringData) const;
- void SendCommissionerSet(void);
- otError SendPetition(void);
- void SendKeepAlive(void);
- void SendKeepAlive(uint16_t aSessionId);
+ void ComputeBloomFilter(SteeringData &aSteeringData) const;
+ void SendCommissionerSet(void);
+ Error SendPetition(void);
+ void SendKeepAlive(void);
+ void SendKeepAlive(uint16_t aSessionId);
void SetState(State aState);
void SignalJoinerEvent(JoinerEvent aEvent, const Joiner *aJoiner) const;
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index 2a7f05b..e9216e2 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -48,9 +48,9 @@
namespace ot {
namespace MeshCoP {
-otError Dataset::Info::GenerateRandom(Instance &aInstance)
+Error Dataset::Info::GenerateRandom(Instance &aInstance)
{
- otError error;
+ Error error;
Mac::ChannelMask supportedChannels = aInstance.Get<Mac::Mac>().GetSupportedChannelMask();
Mac::ChannelMask preferredChannels(aInstance.Get<Radio>().GetPreferredChannelMask());
@@ -285,9 +285,9 @@
memcpy(mTlvs, aDataset.mTlvs, mLength);
}
-otError Dataset::SetFrom(const Info &aDatasetInfo)
+Error Dataset::SetFrom(const Info &aDatasetInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aDatasetInfo.IsActiveTimestampPresent())
{
@@ -400,9 +400,9 @@
IgnoreError(SetTlv((mType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp, aTimestamp));
}
-otError Dataset::SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength)
+Error Dataset::SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t bytesAvailable = sizeof(mTlvs) - mLength;
Tlv * old = GetTlv(aType);
Tlv tlv;
@@ -412,7 +412,7 @@
bytesAvailable += sizeof(Tlv) + old->GetLength();
}
- VerifyOrExit(sizeof(Tlv) + aLength <= bytesAvailable, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(sizeof(Tlv) + aLength <= bytesAvailable, error = kErrorNoBufs);
if (old != nullptr)
{
@@ -433,20 +433,20 @@
return error;
}
-otError Dataset::SetTlv(const Tlv &aTlv)
+Error Dataset::SetTlv(const Tlv &aTlv)
{
return SetTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength());
}
-otError Dataset::Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error Dataset::Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength)
{
- otError error = OT_ERROR_INVALID_ARGS;
+ Error error = kErrorInvalidArgs;
SuccessOrExit(aMessage.Read(aOffset, mTlvs, aLength));
mLength = aLength;
mUpdateTime = TimerMilli::GetNow();
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
@@ -463,9 +463,9 @@
return;
}
-otError Dataset::AppendMleDatasetTlv(Message &aMessage) const
+Error Dataset::AppendMleDatasetTlv(Message &aMessage) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mle::Tlv tlv;
Mle::Tlv::Type type;
@@ -519,13 +519,13 @@
mLength -= length;
}
-otError Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdated) const
+Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdated) const
{
Mac::Mac & mac = aInstance.Get<Mac::Mac>();
KeyManager &keyManager = aInstance.Get<KeyManager>();
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(IsValid(), error = kErrorParse);
if (aIsMasterKeyUpdated)
{
@@ -542,10 +542,10 @@
error = mac.SetPanChannel(channel);
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
otLogWarnMeshCoP("DatasetManager::ApplyConfiguration() Failed to set channel to %d (%s)", channel,
- otThreadErrorToString(error));
+ ErrorToString(error));
ExitNow();
}
diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp
index 3aa3ec9..b258e01 100644
--- a/src/core/meshcop/dataset.hpp
+++ b/src/core/meshcop/dataset.hpp
@@ -603,10 +603,10 @@
*
* @param[in] aInstance The OpenThread instance.
*
- * @retval OT_ERROR_NONE If the Dataset was generated successfully.
+ * @retval kErrorNone If the Dataset was generated successfully.
*
*/
- otError GenerateRandom(Instance &aInstance);
+ Error GenerateRandom(Instance &aInstance);
/**
* This method checks whether the Dataset is a subset of another one, i.e., all the components in the current
@@ -764,11 +764,11 @@
*
* @param[in] aTlv A reference to the TLV.
*
- * @retval OT_ERROR_NONE Successfully set the TLV.
- * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space.
+ * @retval kErrorNone Successfully set the TLV.
+ * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
*
*/
- otError SetTlv(const Tlv &aTlv);
+ Error SetTlv(const Tlv &aTlv);
/**
* This method sets a TLV with a given TLV Type and Value.
@@ -777,11 +777,11 @@
* @param[in] aValue A pointer to TLV Value.
* @param[in] aLength The TLV Length in bytes (length of @p aValue).
*
- * @retval OT_ERROR_NONE Successfully set the TLV.
- * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space.
+ * @retval kErrorNone Successfully set the TLV.
+ * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
*
*/
- otError SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
+ Error SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
/**
* This template method sets a TLV with a given TLV Type and Value.
@@ -791,11 +791,11 @@
* @param[in] aType The TLV Type.
* @param[in] aValue The TLV Value (of type `ValueType`).
*
- * @retval OT_ERROR_NONE Successfully set the TLV.
- * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space.
+ * @retval kErrorNone Successfully set the TLV.
+ * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
*
*/
- template <typename ValueType> otError SetTlv(Tlv::Type aType, const ValueType &aValue)
+ template <typename ValueType> Error SetTlv(Tlv::Type aType, const ValueType &aValue)
{
static_assert(!TypeTraits::IsPointer<ValueType>::kValue, "ValueType must not be a pointer");
@@ -809,11 +809,11 @@
* @param[in] aOffset The message buffer offset where the dataset starts.
* @param[in] aLength The TLVs length in the message buffer in bytes.
*
- * @retval OT_ERROR_NONE Successfully set the Dataset.
- * @retval OT_ERROR_INVALID_ARGS The values of @p aOffset and @p aLength are not valid for @p aMessage.
+ * @retval kErrorNone Successfully set the Dataset.
+ * @retval kErrorInvalidArgs The values of @p aOffset and @p aLength are not valid for @p aMessage.
*
*/
- otError Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+ Error Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength);
/**
* This method sets the Dataset using an existing Dataset.
@@ -831,11 +831,11 @@
*
* @param[in] aDatasetInfo The input Dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully set the Dataset.
- * @retval OT_ERROR_INVALID_ARGS Dataset is missing Active and/or Pending Timestamp.
+ * @retval kErrorNone Successfully set the Dataset.
+ * @retval kErrorInvalidArgs Dataset is missing Active and/or Pending Timestamp.
*
*/
- otError SetFrom(const Info &aDatasetInfo);
+ Error SetFrom(const Info &aDatasetInfo);
/**
* This method sets the Dataset using @p aDataset.
@@ -858,11 +858,11 @@
*
* @param[in] aMessage A message to append to.
*
- * @retval OT_ERROR_NONE Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to append the message with MLE Dataset TLV.
+ * @retval kErrorNone Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
+ * @retval kErrorNoBufs Insufficient available buffers to append the message with MLE Dataset TLV.
*
*/
- otError AppendMleDatasetTlv(Message &aMessage) const;
+ Error AppendMleDatasetTlv(Message &aMessage) const;
/**
* This method applies the Active or Pending Dataset to the Thread interface.
@@ -870,11 +870,11 @@
* @param[in] aInstance A reference to the OpenThread instance.
* @param[out] aIsMasterKeyUpdated A pointer to where to place whether master key was updated.
*
- * @retval OT_ERROR_NONE Successfully applied configuration.
- * @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
+ * @retval kErrorNone Successfully applied configuration.
+ * @retval kErrorParse The dataset has at least one TLV with invalid format.
*
*/
- otError ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdated = nullptr) const;
+ Error ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdated = nullptr) const;
/**
* This method converts a Pending Dataset to an Active Dataset.
@@ -943,11 +943,11 @@
* @param[in] aType The TLV Type.
* @param[in] aValue The TLV value (as `uint16_t`).
*
- * @retval OT_ERROR_NONE Successfully set the TLV.
- * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space.
+ * @retval kErrorNone Successfully set the TLV.
+ * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
*
*/
-template <> inline otError Dataset::SetTlv(Tlv::Type aType, const uint16_t &aValue)
+template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint16_t &aValue)
{
uint16_t value = Encoding::BigEndian::HostSwap16(aValue);
@@ -960,11 +960,11 @@
* @param[in] aType The TLV Type.
* @param[in] aValue The TLV value (as `uint32_t`).
*
- * @retval OT_ERROR_NONE Successfully set the TLV.
- * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space.
+ * @retval kErrorNone Successfully set the TLV.
+ * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
*
*/
-template <> inline otError Dataset::SetTlv(Tlv::Type aType, const uint32_t &aValue)
+template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint32_t &aValue)
{
uint32_t value = Encoding::BigEndian::HostSwap32(aValue);
diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp
index a733a6d..f6391e6 100644
--- a/src/core/meshcop/dataset_local.cpp
+++ b/src/core/meshcop/dataset_local.cpp
@@ -66,10 +66,10 @@
mSaved = false;
}
-otError DatasetLocal::Restore(Dataset &aDataset)
+Error DatasetLocal::Restore(Dataset &aDataset)
{
const Timestamp *timestamp;
- otError error;
+ Error error;
mTimestampPresent = false;
@@ -89,14 +89,14 @@
return error;
}
-otError DatasetLocal::Read(Dataset &aDataset) const
+Error DatasetLocal::Read(Dataset &aDataset) const
{
DelayTimerTlv *delayTimer;
uint32_t elapsed;
- otError error;
+ Error error;
error = Get<Settings>().ReadOperationalDataset(IsActive(), aDataset);
- VerifyOrExit(error == OT_ERROR_NONE, aDataset.mLength = 0);
+ VerifyOrExit(error == kErrorNone, aDataset.mLength = 0);
if (mType == Dataset::kActive)
{
@@ -126,10 +126,10 @@
return error;
}
-otError DatasetLocal::Read(Dataset::Info &aDatasetInfo) const
+Error DatasetLocal::Read(Dataset::Info &aDatasetInfo) const
{
Dataset dataset(mType);
- otError error;
+ Error error;
aDatasetInfo.Clear();
@@ -140,10 +140,10 @@
return error;
}
-otError DatasetLocal::Read(otOperationalDatasetTlvs &aDataset) const
+Error DatasetLocal::Read(otOperationalDatasetTlvs &aDataset) const
{
Dataset dataset(mType);
- otError error;
+ Error error;
memset(&aDataset, 0, sizeof(aDataset));
@@ -154,9 +154,9 @@
return error;
}
-otError DatasetLocal::Save(const Dataset::Info &aDatasetInfo)
+Error DatasetLocal::Save(const Dataset::Info &aDatasetInfo)
{
- otError error;
+ Error error;
Dataset dataset(mType);
SuccessOrExit(error = dataset.SetFrom(aDatasetInfo));
@@ -166,7 +166,7 @@
return error;
}
-otError DatasetLocal::Save(const otOperationalDatasetTlvs &aDataset)
+Error DatasetLocal::Save(const otOperationalDatasetTlvs &aDataset)
{
Dataset dataset(mType);
@@ -175,10 +175,10 @@
return Save(dataset);
}
-otError DatasetLocal::Save(const Dataset &aDataset)
+Error DatasetLocal::Save(const Dataset &aDataset)
{
const Timestamp *timestamp;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aDataset.GetSize() == 0)
{
diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp
index e5d4464..66c4d3f 100644
--- a/src/core/meshcop/dataset_local.hpp
+++ b/src/core/meshcop/dataset_local.hpp
@@ -95,44 +95,44 @@
*
* @param[out] aDataset Where to place the dataset.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Restore(Dataset &aDataset);
+ Error Restore(Dataset &aDataset);
/**
* This method retrieves the dataset from non-volatile memory.
*
* @param[out] aDataset Where to place the dataset.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(Dataset &aDataset) const;
+ Error Read(Dataset &aDataset) const;
/**
* This method retrieves the dataset from non-volatile memory.
*
* @param[out] aDatasetInfo Where to place the dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(Dataset::Info &aDatasetInfo) const;
+ Error Read(Dataset::Info &aDatasetInfo) const;
/**
* This method retrieves the dataset from non-volatile memory.
*
* @param[out] aDataset Where to place the dataset.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(otOperationalDatasetTlvs &aDataset) const;
+ Error Read(otOperationalDatasetTlvs &aDataset) const;
/**
* This method returns the local time this dataset was last updated or restored.
@@ -147,33 +147,33 @@
*
* @param[in] aDatasetInfo The Dataset to save as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const Dataset::Info &aDatasetInfo);
+ Error Save(const Dataset::Info &aDatasetInfo);
/**
* This method stores the dataset into non-volatile memory.
*
* @param[in] aDataset The Dataset to save as `otOperationalDatasetTlvs`.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const otOperationalDatasetTlvs &aDataset);
+ Error Save(const otOperationalDatasetTlvs &aDataset);
/**
* This method stores the dataset into non-volatile memory.
*
* @param[in] aDataset The Dataset to save.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const Dataset &aDataset);
+ Error Save(const Dataset &aDataset);
/**
* This method compares this dataset to another based on the timestamp.
diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp
index 5403cf2..ae94d2e 100644
--- a/src/core/meshcop/dataset_manager.cpp
+++ b/src/core/meshcop/dataset_manager.cpp
@@ -55,7 +55,7 @@
, mLocal(aInstance, aType)
, mTimestampValid(false)
, mCoapPending(false)
- , mTimer(aInstance, aTimerHandler, this)
+ , mTimer(aInstance, aTimerHandler)
{
mTimestamp.Init();
}
@@ -78,9 +78,9 @@
return rval;
}
-otError DatasetManager::Restore(void)
+Error DatasetManager::Restore(void)
{
- otError error;
+ Error error;
Dataset dataset(GetType());
const Timestamp *timestamp;
@@ -109,9 +109,9 @@
return error;
}
-otError DatasetManager::ApplyConfiguration(void) const
+Error DatasetManager::ApplyConfiguration(void) const
{
- otError error;
+ Error error;
Dataset dataset(GetType());
SuccessOrExit(error = Read(dataset));
@@ -135,9 +135,9 @@
IgnoreError(Restore());
}
-otError DatasetManager::Save(const Dataset &aDataset)
+Error DatasetManager::Save(const Dataset &aDataset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const Timestamp *timestamp;
int compare;
bool isMasterkeyUpdated = false;
@@ -167,7 +167,7 @@
}
else if (compare < 0)
{
- VerifyOrExit(!Get<Mle::MleRouter>().IsLeader(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!Get<Mle::MleRouter>().IsLeader(), error = kErrorInvalidState);
SendSet();
}
@@ -177,9 +177,9 @@
return error;
}
-otError DatasetManager::Save(const Dataset::Info &aDatasetInfo)
+Error DatasetManager::Save(const Dataset::Info &aDatasetInfo)
{
- otError error;
+ Error error;
SuccessOrExit(error = mLocal.Save(aDatasetInfo));
HandleDatasetUpdated();
@@ -188,9 +188,20 @@
return error;
}
-otError DatasetManager::Save(const otOperationalDatasetTlvs &aDataset)
+Error DatasetManager::Save(const otOperationalDatasetTlvs &aDataset)
{
- otError error;
+ Error error;
+
+ SuccessOrExit(error = mLocal.Save(aDataset));
+ HandleDatasetUpdated();
+
+exit:
+ return error;
+}
+
+Error DatasetManager::SaveLocal(const Dataset &aDataset)
+{
+ Error error;
SuccessOrExit(error = mLocal.Save(aDataset));
HandleDatasetUpdated();
@@ -234,9 +245,9 @@
: kEventPendingDatasetChanged);
}
-otError DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
+Error DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
{
- otError error;
+ Error error;
const MeshCoP::ChannelMaskTlv *channelMaskTlv;
uint32_t mask;
Dataset dataset(GetType());
@@ -244,12 +255,12 @@
SuccessOrExit(error = Read(dataset));
channelMaskTlv = dataset.GetTlv<ChannelMaskTlv>();
- VerifyOrExit(channelMaskTlv != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(channelMaskTlv != nullptr, error = kErrorNotFound);
VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0);
aChannelMask.SetMask(mask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
- VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!aChannelMask.IsEmpty(), error = kErrorNotFound);
exit:
return error;
@@ -262,14 +273,14 @@
void DatasetManager::SendSet(void)
{
- otError error;
+ Error error;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
Dataset dataset(GetType());
- VerifyOrExit(!mCoapPending, error = OT_ERROR_BUSY);
- VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!mCoapPending, error = kErrorBusy);
+ VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = kErrorInvalidState);
+ VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, error = kErrorInvalidState);
if (IsActiveDataset())
{
@@ -282,11 +293,11 @@
if (pendingActiveTimestamp != nullptr && mLocal.Compare(pendingActiveTimestamp) == 0)
{
// stop registration attempts during dataset transition
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
}
}
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error =
message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveSet : UriPath::kPendingSet));
@@ -307,13 +318,13 @@
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
mCoapPending = true;
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
mTimer.Start(kDelayNoBufs);
- // fall through
+ OT_FALL_THROUGH;
default:
LogError("send Dataset set to leader", error);
@@ -325,7 +336,7 @@
void DatasetManager::HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aError)
+ Error aError)
{
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
@@ -390,13 +401,13 @@
uint8_t * aTlvs,
uint8_t aLength) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
Dataset dataset(GetType());
IgnoreError(Read(dataset));
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -443,9 +454,9 @@
FreeMessageOnError(message, error);
}
-otError DatasetManager::AppendDatasetToMessage(const Dataset::Info &aDatasetInfo, Message &aMessage) const
+Error DatasetManager::AppendDatasetToMessage(const Dataset::Info &aDatasetInfo, Message &aMessage) const
{
- otError error;
+ Error error;
Dataset dataset(GetType());
SuccessOrExit(error = dataset.SetFrom(aDatasetInfo));
@@ -455,13 +466,13 @@
return error;
}
-otError DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength)
+Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error =
message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveSet : UriPath::kPendingSet));
@@ -476,7 +487,7 @@
for (const Tlv *cur = reinterpret_cast<const Tlv *>(aTlvs); cur < end; cur = cur->GetNext())
{
- VerifyOrExit((cur + 1) <= end, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((cur + 1) <= end, error = kErrorInvalidArgs);
if (cur->GetType() == Tlv::kCommissionerSessionId)
{
@@ -518,12 +529,12 @@
return error;
}
-otError DatasetManager::SendGetRequest(const Dataset::Components &aDatasetComponents,
- const uint8_t * aTlvTypes,
- uint8_t aLength,
- const otIp6Address * aAddress) const
+Error DatasetManager::SendGetRequest(const Dataset::Components &aDatasetComponents,
+ const uint8_t * aTlvTypes,
+ uint8_t aLength,
+ const otIp6Address * aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
Tlv tlv;
@@ -592,7 +603,7 @@
datasetTlvs[length++] = Tlv::kChannelMask;
}
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error =
message->InitAsConfirmablePost(IsActiveDataset() ? UriPath::kActiveGet : UriPath::kPendingGet));
@@ -668,9 +679,9 @@
return isValid;
}
-otError ActiveDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error ActiveDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Dataset dataset(GetType());
SuccessOrExit(error = dataset.Set(aMessage, aOffset, aLength));
@@ -694,12 +705,12 @@
void ActiveDataset::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<ActiveDataset>().HandleTimer();
+ aTimer.Get<ActiveDataset>().HandleTimer();
}
PendingDataset::PendingDataset(Instance &aInstance)
: DatasetManager(aInstance, Dataset::kPending, PendingDataset::HandleTimer)
- , mDelayTimer(aInstance, PendingDataset::HandleDelayTimer, this)
+ , mDelayTimer(aInstance, PendingDataset::HandleDelayTimer)
, mResourceGet(UriPath::kPendingGet, &PendingDataset::HandleGet, this)
#if OPENTHREAD_FTD
, mResourceSet(UriPath::kPendingSet, &PendingDataset::HandleSet, this)
@@ -723,9 +734,9 @@
IgnoreError(DatasetManager::Save(dataset));
}
-otError PendingDataset::Save(const Dataset::Info &aDatasetInfo)
+Error PendingDataset::Save(const Dataset::Info &aDatasetInfo)
{
- otError error;
+ Error error;
SuccessOrExit(error = DatasetManager::Save(aDatasetInfo));
StartDelayTimer();
@@ -734,9 +745,9 @@
return error;
}
-otError PendingDataset::Save(const otOperationalDatasetTlvs &aDataset)
+Error PendingDataset::Save(const otOperationalDatasetTlvs &aDataset)
{
- otError error;
+ Error error;
SuccessOrExit(error = DatasetManager::Save(aDataset));
StartDelayTimer();
@@ -745,9 +756,20 @@
return error;
}
-otError PendingDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+Error PendingDataset::Save(const Dataset &aDataset)
{
- otError error = OT_ERROR_NONE;
+ Error error;
+
+ SuccessOrExit(error = DatasetManager::SaveLocal(aDataset));
+ StartDelayTimer();
+
+exit:
+ return error;
+}
+
+Error PendingDataset::Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength)
+{
+ Error error = kErrorNone;
Dataset dataset(GetType());
SuccessOrExit(error = dataset.Set(aMessage, aOffset, aLength));
@@ -785,7 +807,7 @@
void PendingDataset::HandleDelayTimer(Timer &aTimer)
{
- aTimer.GetOwner<PendingDataset>().HandleDelayTimer();
+ aTimer.Get<PendingDataset>().HandleDelayTimer();
}
void PendingDataset::HandleDelayTimer(void)
@@ -834,7 +856,7 @@
void PendingDataset::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<PendingDataset>().HandleTimer();
+ aTimer.Get<PendingDataset>().HandleTimer();
}
} // namespace MeshCoP
diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp
index 98d08a7..5fbcd94 100644
--- a/src/core/meshcop/dataset_manager.hpp
+++ b/src/core/meshcop/dataset_manager.hpp
@@ -64,11 +64,11 @@
/**
* This method restores the Operational Dataset from non-volatile memory.
*
- * @retval OT_ERROR_NONE Successfully restore the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully restore the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Restore(void);
+ Error Restore(void);
/**
* This method compares @p aTimestamp to the dataset's timestamp value.
@@ -87,53 +87,53 @@
*
* @param[out] aDataset Where to place the dataset.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(Dataset &aDataset) const { return mLocal.Read(aDataset); }
+ Error Read(Dataset &aDataset) const { return mLocal.Read(aDataset); }
/**
* This method retrieves the dataset from non-volatile memory.
*
* @param[out] aDatasetInfo Where to place the dataset (as `Dataset::Info`).
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(Dataset::Info &aDatasetInfo) const { return mLocal.Read(aDatasetInfo); }
+ Error Read(Dataset::Info &aDatasetInfo) const { return mLocal.Read(aDatasetInfo); }
/**
* This method retrieves the dataset from non-volatile memory.
*
* @param[out] aDataset Where to place the dataset.
*
- * @retval OT_ERROR_NONE Successfully retrieved the dataset.
- * @retval OT_ERROR_NOT_FOUND There is no corresponding dataset stored in non-volatile memory.
+ * @retval kErrorNone Successfully retrieved the dataset.
+ * @retval kErrorNotFound There is no corresponding dataset stored in non-volatile memory.
*
*/
- otError Read(otOperationalDatasetTlvs &aDataset) const { return mLocal.Read(aDataset); }
+ Error Read(otOperationalDatasetTlvs &aDataset) const { return mLocal.Read(aDataset); }
/**
* This method retrieves the channel mask from local dataset.
*
* @param[out] aChannelMask A reference to the channel mask.
*
- * @retval OT_ERROR_NONE Successfully retrieved the channel mask.
- * @retval OT_ERROR_NOT_FOUND There is no valid channel mask stored in local dataset.
+ * @retval kErrorNone Successfully retrieved the channel mask.
+ * @retval kErrorNotFound There is no valid channel mask stored in local dataset.
*
*/
- otError GetChannelMask(Mac::ChannelMask &aChannelMask) const;
+ Error GetChannelMask(Mac::ChannelMask &aChannelMask) const;
/**
* This method applies the Active or Pending Dataset to the Thread interface.
*
- * @retval OT_ERROR_NONE Successfully applied configuration.
- * @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
+ * @retval kErrorNone Successfully applied configuration.
+ * @retval kErrorParse The dataset has at least one TLV with invalid format.
*
*/
- otError ApplyConfiguration(void) const;
+ Error ApplyConfiguration(void) const;
/**
* This method updates the Operational Dataset when detaching from the network.
@@ -150,11 +150,11 @@
* @param[in] aTlvs Any additional raw TLVs to include.
* @param[in] aLength Number of bytes in @p aTlvs.
*
- * @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
+ * @retval kErrorNone Successfully send the meshcop dataset command.
+ * @retval kErrorNoBufs Insufficient buffer space to send.
*
*/
- otError SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength);
+ Error SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength);
/**
* This method sends a MGMT_GET request.
@@ -164,25 +164,25 @@
* @param[in] aLength Number of bytes in @p aTlvTypes.
* @param[in] aAddress The IPv6 destination address for the MGMT_GET request.
*
- * @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
+ * @retval kErrorNone Successfully send the meshcop dataset command.
+ * @retval kErrorNoBufs Insufficient buffer space to send.
*
*/
- otError SendGetRequest(const Dataset::Components &aDatasetComponents,
- const uint8_t * aTlvTypes,
- uint8_t aLength,
- const otIp6Address * aAddress) const;
+ Error SendGetRequest(const Dataset::Components &aDatasetComponents,
+ const uint8_t * aTlvTypes,
+ uint8_t aLength,
+ const otIp6Address * aAddress) const;
#if OPENTHREAD_FTD
/**
* This method appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
*
* @param[in] aMessage The message to append the TLV to.
*
- * @retval OT_ERROR_NONE Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to append the message with MLE Dataset TLV.
+ * @retval kErrorNone Successfully append MLE Dataset TLV without MeshCoP Sub Timestamp TLV.
+ * @retval kErrorNoBufs Insufficient available buffers to append the message with MLE Dataset TLV.
*
*/
- otError AppendMleDatasetTlv(Message &aMessage) const;
+ Error AppendMleDatasetTlv(Message &aMessage) const;
#endif
protected:
@@ -200,11 +200,11 @@
* @param[in] aMessage A message to read the TLV from.
* @param[in] aOffset An offset into the message to read from.
*
- * @retval OT_ERROR_NONE The TLV was read successfully.
- * @retval OT_ERROR_PARSE The TLV was not well-formed and could not be parsed.
+ * @retval kErrorNone The TLV was read successfully.
+ * @retval kErrorParse The TLV was not well-formed and could not be parsed.
*
*/
- otError ReadFromMessage(const Message &aMessage, uint16_t aOffset);
+ Error ReadFromMessage(const Message &aMessage, uint16_t aOffset);
private:
enum
@@ -244,33 +244,33 @@
*
* @param[in] aDataset The Operational Dataset.
*
- * @retval OT_ERROR_NONE Successfully applied configuration.
- * @retval OT_ERROR_PARSE The dataset has at least one TLV with invalid format.
+ * @retval kErrorNone Successfully applied configuration.
+ * @retval kErrorParse The dataset has at least one TLV with invalid format.
*
*/
- otError Save(const Dataset &aDataset);
+ Error Save(const Dataset &aDataset);
/**
* This method saves the Operational Dataset in non-volatile memory.
*
* @param[in] aDatasetInfo The Operational Dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const Dataset::Info &aDatasetInfo);
+ Error Save(const Dataset::Info &aDatasetInfo);
/**
* This method saves the Operational Dataset in non-volatile memory.
*
* @param[in] aDataset The Operational Dataset.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const otOperationalDatasetTlvs &aDataset);
+ Error Save(const otOperationalDatasetTlvs &aDataset);
/**
* This method sets the Operational Dataset for the partition.
@@ -283,7 +283,18 @@
* @param[in] aLength The length of the Operational Dataset.
*
*/
- otError Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+ Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+
+ /**
+ * This method saves the Operational Dataset in non-volatile memory.
+ *
+ * @param[in] aDataset The Operational Dataset.
+ *
+ * @retval kErrorNone Successfully applied configuration.
+ * @retval kErrorParse The dataset has at least one TLV with invalid format.
+ *
+ */
+ Error SaveLocal(const Dataset &aDataset);
/**
* This method handles a MGMT_GET request message.
@@ -316,11 +327,11 @@
* @param[in] aMessage The CoAP message buffer.
* @param[in] aMessageInfo The message info.
*
- * @retval OT_ERROR_NONE The MGMT_SET request message was handled successfully.
- * @retval OT_ERROR_DROP The MGMT_SET request message was dropped.
+ * @retval kErrorNone The MGMT_SET request message was handled successfully.
+ * @retval kErrorDrop The MGMT_SET request message was dropped.
*
*/
- otError HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#endif
DatasetLocal mLocal;
@@ -331,19 +342,19 @@
static void HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aError);
+ Error aError);
void HandleCoapResponse(void);
- bool IsActiveDataset(void) const { return GetType() == Dataset::kActive; }
- bool IsPendingDataset(void) const { return GetType() == Dataset::kPending; }
- void SignalDatasetChange(void) const;
- void HandleDatasetUpdated(void);
- otError AppendDatasetToMessage(const Dataset::Info &aDatasetInfo, Message &aMessage) const;
- void SendSet(void);
- void SendGetResponse(const Coap::Message & aRequest,
- const Ip6::MessageInfo &aMessageInfo,
- uint8_t * aTlvs,
- uint8_t aLength) const;
+ bool IsActiveDataset(void) const { return GetType() == Dataset::kActive; }
+ bool IsPendingDataset(void) const { return GetType() == Dataset::kPending; }
+ void SignalDatasetChange(void) const;
+ void HandleDatasetUpdated(void);
+ Error AppendDatasetToMessage(const Dataset::Info &aDatasetInfo, Message &aMessage) const;
+ void SendSet(void);
+ void SendGetResponse(const Coap::Message & aRequest,
+ const Ip6::MessageInfo &aMessageInfo,
+ uint8_t * aTlvs,
+ uint8_t aLength) const;
#if OPENTHREAD_FTD
void SendSetResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aMessageInfo, StateTlv::State aState);
@@ -419,29 +430,29 @@
* @param[in] aLength The length of the Operational Dataset.
*
*/
- otError Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+ Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
/**
* This method sets the Operational Dataset in non-volatile memory.
*
* @param[in] aDatasetInfo The Operational Dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const Dataset::Info &aDatasetInfo) { return DatasetManager::Save(aDatasetInfo); }
+ Error Save(const Dataset::Info &aDatasetInfo) { return DatasetManager::Save(aDatasetInfo); }
/**
* This method sets the Operational Dataset in non-volatile memory.
*
* @param[in] aDataset The Operational Dataset.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const otOperationalDatasetTlvs &aDataset) { return DatasetManager::Save(aDataset); }
+ Error Save(const otOperationalDatasetTlvs &aDataset) { return DatasetManager::Save(aDataset); }
#if OPENTHREAD_FTD
@@ -450,11 +461,11 @@
*
* @param[out] aDatasetInfo The Operational Dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully created a new Operational Dataset.
- * @retval OT_ERROR_FAILED Failed to generate random values for new parameters.
+ * @retval kErrorNone Successfully created a new Operational Dataset.
+ * @retval kErrorFailed Failed to generate random values for new parameters.
*
*/
- otError CreateNewNetwork(Dataset::Info &aDatasetInfo) { return aDatasetInfo.GenerateRandom(GetInstance()); }
+ Error CreateNewNetwork(Dataset::Info &aDatasetInfo) { return aDatasetInfo.GenerateRandom(GetInstance()); }
/**
* This method starts the Leader functions for maintaining the Active Operational Dataset.
@@ -471,12 +482,12 @@
/**
* This method generate a default Active Operational Dataset.
*
- * @retval OT_ERROR_NONE Successfully generated an Active Operational Dataset.
- * @retval OT_ERROR_ALREADY A valid Active Operational Dataset already exists.
- * @retval OT_ERROR_INVALID_STATE Device is not currently attached to a network.
+ * @retval kErrorNone Successfully generated an Active Operational Dataset.
+ * @retval kErrorAlready A valid Active Operational Dataset already exists.
+ * @retval kErrorInvalidState Device is not currently attached to a network.
*
*/
- otError GenerateLocal(void);
+ Error GenerateLocal(void);
#endif
private:
@@ -532,11 +543,11 @@
*
* @param[in] aDatasetInfo The Operational Dataset as `Dataset::Info`.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const Dataset::Info &aDatasetInfo);
+ Error Save(const Dataset::Info &aDatasetInfo);
/**
* This method saves the Operational Dataset in non-volatile memory.
@@ -545,11 +556,11 @@
*
* @param[in] aDataset The Operational Dataset.
*
- * @retval OT_ERROR_NONE Successfully saved the dataset.
- * @retval OT_ERROR_NOT_IMPLEMENTED The platform does not implement settings functionality.
+ * @retval kErrorNone Successfully saved the dataset.
+ * @retval kErrorNotImplemented The platform does not implement settings functionality.
*
*/
- otError Save(const otOperationalDatasetTlvs &aDataset);
+ Error Save(const otOperationalDatasetTlvs &aDataset);
/**
* This method sets the Operational Dataset for the partition.
@@ -564,7 +575,18 @@
* @param[in] aLength The length of the Operational Dataset.
*
*/
- otError Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+ Error Save(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
+
+ /**
+ * This method saves the Operational Dataset in non-volatile memory.
+ *
+ * @param[in] aDataset The Operational Dataset.
+ *
+ * @retval kErrorNone Successfully applied configuration.
+ * @retval kErrorParse The dataset has at least one TLV with invalid format.
+ *
+ */
+ Error Save(const Dataset &aDataset);
#if OPENTHREAD_FTD
/**
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index 02affdd..e8e5ffb 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -57,7 +57,7 @@
namespace ot {
namespace MeshCoP {
-otError DatasetManager::AppendMleDatasetTlv(Message &aMessage) const
+Error DatasetManager::AppendMleDatasetTlv(Message &aMessage) const
{
Dataset dataset(GetType());
@@ -66,7 +66,7 @@
return dataset.AppendMleDatasetTlv(aMessage);
}
-otError DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Tlv tlv;
Timestamp * timestamp;
@@ -107,14 +107,14 @@
type = (GetType() == Dataset::kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp;
- if (Tlv::FindTlv(aMessage, activeTimestamp) != OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, activeTimestamp) != kErrorNone)
{
ExitNow();
}
VerifyOrExit(activeTimestamp.IsValid());
- if (Tlv::FindTlv(aMessage, pendingTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone)
{
VerifyOrExit(pendingTimestamp.IsValid());
}
@@ -126,7 +126,7 @@
VerifyOrExit(mLocal.Compare(timestamp) > 0);
// check channel
- if (Tlv::FindTlv(aMessage, channel) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, channel) == kErrorNone)
{
VerifyOrExit(channel.IsValid());
@@ -137,20 +137,20 @@
}
// check PAN ID
- if (Tlv::Find<PanIdTlv>(aMessage, panId) == OT_ERROR_NONE && panId != Get<Mac::Mac>().GetPanId())
+ if (Tlv::Find<PanIdTlv>(aMessage, panId) == kErrorNone && panId != Get<Mac::Mac>().GetPanId())
{
doesAffectConnectivity = true;
}
// check mesh local prefix
- if (Tlv::Find<MeshLocalPrefixTlv>(aMessage, meshLocalPrefix) == OT_ERROR_NONE &&
+ if (Tlv::Find<MeshLocalPrefixTlv>(aMessage, meshLocalPrefix) == kErrorNone &&
meshLocalPrefix != Get<Mle::MleRouter>().GetMeshLocalPrefix())
{
doesAffectConnectivity = true;
}
// check network master key
- if (Tlv::Find<NetworkMasterKeyTlv>(aMessage, masterKey) == OT_ERROR_NONE)
+ if (Tlv::Find<NetworkMasterKeyTlv>(aMessage, masterKey) == kErrorNone)
{
hasMasterKey = true;
@@ -171,7 +171,7 @@
}
// check commissioner session id
- if (Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId) == OT_ERROR_NONE)
+ if (Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId) == kErrorNone)
{
const CommissionerSessionIdTlv *localId;
@@ -223,7 +223,7 @@
}
}
- // fall through
+ OT_FALL_THROUGH;
default:
SuccessOrExit(dataset.SetTlv(datasetTlv));
@@ -266,17 +266,17 @@
SendSetResponse(aMessage, aMessageInfo, state);
}
- return (state == StateTlv::kAccept) ? OT_ERROR_NONE : OT_ERROR_DROP;
+ return (state == StateTlv::kAccept) ? kErrorNone : kErrorDrop;
}
void DatasetManager::SendSetResponse(const Coap::Message & aRequest,
const Ip6::MessageInfo &aMessageInfo,
StateTlv::State aState)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -291,26 +291,26 @@
FreeMessageOnError(message, error);
}
-otError DatasetManager::DatasetTlv::ReadFromMessage(const Message &aMessage, uint16_t aOffset)
+Error DatasetManager::DatasetTlv::ReadFromMessage(const Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = aMessage.Read(aOffset, this, sizeof(Tlv)));
- VerifyOrExit(GetLength() <= kMaxValueSize, error = OT_ERROR_PARSE);
+ VerifyOrExit(GetLength() <= kMaxValueSize, error = kErrorParse);
SuccessOrExit(error = aMessage.Read(aOffset + sizeof(Tlv), mValue, GetLength()));
- VerifyOrExit(Tlv::IsValid(*this), error = OT_ERROR_PARSE);
+ VerifyOrExit(Tlv::IsValid(*this), error = kErrorParse);
exit:
return error;
}
-otError ActiveDataset::GenerateLocal(void)
+Error ActiveDataset::GenerateLocal(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Dataset dataset(GetType());
- VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!mLocal.IsTimestampPresent(), error = OT_ERROR_ALREADY);
+ VerifyOrExit(Get<Mle::MleRouter>().IsAttached(), error = kErrorInvalidState);
+ VerifyOrExit(!mLocal.IsTimestampPresent(), error = kErrorAlready);
IgnoreError(Read(dataset));
diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp
new file mode 100644
index 0000000..9c70e45
--- /dev/null
+++ b/src/core/meshcop/dataset_updater.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements Dataset Updater.
+ *
+ */
+
+#include "dataset_updater.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
+#include "common/random.hpp"
+
+#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
+
+namespace ot {
+namespace MeshCoP {
+
+DatasetUpdater::DatasetUpdater(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mCallback(nullptr)
+ , mCallbackContext(nullptr)
+ , mTimer(aInstance, DatasetUpdater::HandleTimer)
+ , mDataset(nullptr)
+{
+}
+
+Error DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext)
+{
+ Error error = kErrorNone;
+ Message *message = nullptr;
+
+ VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = kErrorInvalidState);
+ VerifyOrExit(mDataset == nullptr, error = kErrorBusy);
+
+ VerifyOrExit(!aDataset.IsActiveTimestampPresent() && !aDataset.IsPendingTimestampPresent(),
+ error = kErrorInvalidArgs);
+
+ message = Get<MessagePool>().New(Message::kTypeOther, 0);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+
+ SuccessOrExit(error = message->Append(aDataset));
+
+ mCallback = aCallback;
+ mCallbackContext = aContext;
+ mDataset = message;
+
+ mTimer.Start(1);
+
+exit:
+ FreeMessageOnError(message, error);
+ return error;
+}
+
+void DatasetUpdater::CancelUpdate(void)
+{
+ VerifyOrExit(mDataset != nullptr);
+
+ FreeMessage(mDataset);
+ mDataset = nullptr;
+ mTimer.Stop();
+
+exit:
+ return;
+}
+
+void DatasetUpdater::HandleTimer(Timer &aTimer)
+{
+ aTimer.Get<DatasetUpdater>().HandleTimer();
+}
+
+void DatasetUpdater::HandleTimer(void)
+{
+ PreparePendingDataset();
+}
+
+void DatasetUpdater::PreparePendingDataset(void)
+{
+ Dataset dataset(Dataset::kPending);
+ MeshCoP::Dataset::Info requestedDataset;
+ Error error;
+
+ VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = kErrorInvalidState);
+
+ IgnoreError(mDataset->Read(0, requestedDataset));
+
+ error = Get<ActiveDataset>().Read(dataset);
+
+ if (error != kErrorNone)
+ {
+ // If there is no valid Active Dataset but MLE is not disabled,
+ // set the timer to try again after the retry interval. This
+ // handles the situation where a dataset update request comes
+ // right after the network is formed but before the active
+ // dataset is created.
+
+ mTimer.Start(kRetryInterval);
+ ExitNow(error = kErrorNone);
+ }
+
+ IgnoreError(dataset.SetFrom(requestedDataset));
+
+ if (!requestedDataset.IsDelayPresent())
+ {
+ uint32_t delay = kDefaultDelay;
+
+ SuccessOrExit(error = dataset.SetTlv(Tlv::kDelayTimer, delay));
+ }
+
+ {
+ Timestamp timestamp;
+
+ if (Get<PendingDataset>().GetTimestamp() != nullptr)
+ {
+ timestamp = *Get<PendingDataset>().GetTimestamp();
+ }
+
+ timestamp.AdvanceRandomTicks();
+ dataset.SetTimestamp(timestamp);
+ }
+
+ {
+ ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
+ tlv->AdvanceRandomTicks();
+ }
+
+ SuccessOrExit(error = Get<PendingDataset>().Save(dataset));
+
+exit:
+ if (error != kErrorNone)
+ {
+ Finish(error);
+ }
+}
+
+void DatasetUpdater::Finish(Error aError)
+{
+ OT_ASSERT(mDataset != nullptr);
+
+ FreeMessage(mDataset);
+ mDataset = nullptr;
+
+ if (mCallback != nullptr)
+ {
+ mCallback(aError, mCallbackContext);
+ }
+}
+
+void DatasetUpdater::HandleNotifierEvents(Events aEvents)
+{
+ MeshCoP::Dataset::Info requestedDataset;
+ MeshCoP::Dataset::Info dataset;
+
+ VerifyOrExit(mDataset != nullptr);
+
+ VerifyOrExit(aEvents.ContainsAny(kEventActiveDatasetChanged | kEventPendingDatasetChanged));
+
+ IgnoreError(mDataset->Read(0, requestedDataset));
+
+ if (aEvents.Contains(kEventActiveDatasetChanged) && Get<MeshCoP::ActiveDataset>().Read(dataset) == kErrorNone)
+ {
+ if (requestedDataset.IsSubsetOf(dataset))
+ {
+ Finish(kErrorNone);
+ }
+ else if (requestedDataset.GetActiveTimestamp() <= dataset.GetActiveTimestamp())
+ {
+ Finish(kErrorAlready);
+ }
+ }
+
+ if (aEvents.Contains(kEventPendingDatasetChanged) && Get<MeshCoP::PendingDataset>().Read(dataset) == kErrorNone)
+ {
+ if (!requestedDataset.IsSubsetOf(dataset))
+ {
+ Finish(kErrorAlready);
+ }
+ }
+
+exit:
+ return;
+}
+
+} // namespace MeshCoP
+} // namespace ot
+
+#endif // #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
diff --git a/src/core/utils/dataset_updater.hpp b/src/core/meshcop/dataset_updater.hpp
similarity index 66%
rename from src/core/utils/dataset_updater.hpp
rename to src/core/meshcop/dataset_updater.hpp
index 63f13d3..7d77196 100644
--- a/src/core/utils/dataset_updater.hpp
+++ b/src/core/meshcop/dataset_updater.hpp
@@ -47,7 +47,7 @@
#include "meshcop/meshcop_tlvs.hpp"
namespace ot {
-namespace Utils {
+namespace MeshCoP {
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
@@ -72,13 +72,13 @@
* This type represents the callback function pointer which is called when a Dataset update request finishes,
* reporting success or failure status of the request.
*
- * The function pointer has the syntax `void (*Callback)(otError aError, void *aContext)`.
+ * The function pointer has the syntax `void (*Callback)(Error aError, void *aContext)`.
*
* @param[in] aError The error status.
- * OT_ERROR_NONE indicates Dataset update successfully finished.
- * OT_ERROR_INVALID_STATE indicates failure due invalid state (MLE being disabled).
- * OT_ERROR_ALREADY indicates failure due to another device within network requesting
- * a conflicting Dataset update.
+ * kErrorNone indicates Dataset update successfully finished.
+ * kErrorInvalidState indicates failure due invalid state (MLE being disabled).
+ * kErrorAlready indicates failure due to another device within network requesting a
+ * conflicting Dataset update.
* @param[in] aContext A pointer to the arbitrary context provided by the user.
*
*/
@@ -93,19 +93,15 @@
* @param[in] aDataset Dataset info containing fields to change.
* @param[in] aCallback A callback to indicate when Dataset update request finishes.
* @param[in] aContext An arbitrary context passed to callback.
- * @param[in] aRetryWaitInterval The wait time after sending Pending dataset before retrying (interval in ms).
*
- * @retval OT_ERROR_NONE Dataset update started successfully (@p aCallback will be invoked on completion).
- * @retval OT_ERROR_INVALID_STATE Device is disabled (MLE is disabled).
- * @retval OT_ERROR_INVALID_ARGS The @p aDataset is not valid (contains Active or Pending Timestamp).
- * @retval OT_ERROR_BUSY Cannot start update, a previous one is ongoing.
- * @retval OT_ERROR_NO_BUFS Could not allocated buffer to save Dataset.
+ * @retval kErrorNone Dataset update started successfully (@p aCallback will be invoked on completion).
+ * @retval kErrorInvalidState Device is disabled (MLE is disabled).
+ * @retval kErrorInvalidArgs The @p aDataset is not valid (contains Active or Pending Timestamp).
+ * @retval kErrorBusy Cannot start update, a previous one is ongoing.
+ * @retval kErrorNoBufs Could not allocated buffer to save Dataset.
*
*/
- otError RequestUpdate(const MeshCoP::Dataset::Info &aDataset,
- Callback aCallback,
- void * aContext,
- uint32_t aReryWaitInterval = kWaitInterval);
+ Error RequestUpdate(const MeshCoP::Dataset::Info &aDataset, Callback aCallback, void *aContext);
/**
* This method cancels an ongoing (if any) Operational Dataset update request.
@@ -120,36 +116,22 @@
* @retval FALSE There is no ongoing update.
*
*/
- bool IsUpdateOngoing(void) const { return (mState != kStateIdle); }
+ bool IsUpdateOngoing(void) const { return mDataset != nullptr; }
private:
- enum State : uint8_t
- {
- kStateIdle,
- kStateUpdateRequested,
- kStateSentMgmtPendingDataset,
- };
-
enum : uint32_t
{
- // Default delay (in ms) in Pending Dataset.
- kDefaultDelay = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY,
+ kDefaultDelay = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_DELAY, // Default delay (in ms) in Pending Dataset.
- // Default wait interval (in ms) after sending Pending Dataset to retry (in addition Dataset Delay)
- kWaitInterval = OPENTHREAD_CONFIG_DATASET_UPDATER_DEFAULT_RETRY_WAIT_INTERVAL,
-
- kRetryInterval = 1000, // In ms. Retry interval when preparing and/or sending Pending Dataset fails.
- kMaxTimestampIncrease = 128, // Maximum increase of Pending/Active Timestamp during Dataset Update.
+ kRetryInterval = 1000, // In ms. Retry interval when preparing and/or sending Pending Dataset fails.
};
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void PreparePendingDataset(void);
- void Finish(otError aError);
+ void Finish(Error aError);
void HandleNotifierEvents(Events aEvents);
- State mState;
- uint32_t mWaitInterval;
Callback mCallback;
void * mCallbackContext;
TimerMilli mTimer;
@@ -158,7 +140,7 @@
#endif // (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
-} // namespace Utils
+} // namespace MeshCoP
} // namespace ot
#endif // DATASET_UPDATER_HPP_
diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp
index e10096a..57ab274 100644
--- a/src/core/meshcop/dtls.cpp
+++ b/src/core/meshcop/dtls.cpp
@@ -56,8 +56,8 @@
namespace MeshCoP {
const mbedtls_ecp_group_id Dtls::sCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
-#ifdef MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED
-const int Dtls::sHashes[] = {MBEDTLS_MD_NONE};
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+const int Dtls::sHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
#endif
Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
@@ -126,11 +126,11 @@
mbedtls_ssl_free(&mSsl);
}
-otError Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
+Error Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
{
- otError error;
+ Error error;
- VerifyOrExit(mState == kStateClosed, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState == kStateClosed, error = kErrorAlready);
SuccessOrExit(error = mSocket.Open(&Dtls::HandleUdpReceive, this));
@@ -143,11 +143,11 @@
return error;
}
-otError Dtls::Connect(const Ip6::SockAddr &aSockAddr)
+Error Dtls::Connect(const Ip6::SockAddr &aSockAddr)
{
- otError error;
+ Error error;
- VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
mMessageInfo.SetPeerAddr(aSockAddr.GetAddress());
mMessageInfo.SetPeerPort(aSockAddr.mPort);
@@ -208,26 +208,26 @@
return;
}
-otError Dtls::Bind(uint16_t aPort)
+Error Dtls::Bind(uint16_t aPort)
{
- otError error;
+ Error error;
- VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(mTransportCallback == nullptr, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
+ VerifyOrExit(mTransportCallback == nullptr, error = kErrorAlready);
- SuccessOrExit(error = mSocket.Bind(aPort));
+ SuccessOrExit(error = mSocket.Bind(aPort, OT_NETIF_UNSPECIFIED));
exit:
return error;
}
-otError Dtls::Bind(TransportCallback aCallback, void *aContext)
+Error Dtls::Bind(TransportCallback aCallback, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mState == kStateOpen, error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!mSocket.IsBound(), error = OT_ERROR_ALREADY);
- VerifyOrExit(mTransportCallback == nullptr, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
+ VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready);
+ VerifyOrExit(mTransportCallback == nullptr, error = kErrorAlready);
mTransportCallback = aCallback;
mTransportContext = aContext;
@@ -236,7 +236,7 @@
return error;
}
-otError Dtls::Setup(bool aClient)
+Error Dtls::Setup(bool aClient)
{
int rval;
@@ -284,7 +284,7 @@
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{
mbedtls_ssl_conf_curves(&mConf, sCurves);
-#ifdef MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
mbedtls_ssl_conf_sig_hashes(&mConf, sHashes);
#endif
}
@@ -431,11 +431,11 @@
return;
}
-otError Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
+Error Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aPskLength <= sizeof(mPsk), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aPskLength <= sizeof(mPsk), error = kErrorInvalidArgs);
memcpy(mPsk, aPsk, aPskLength);
mPskLength = aPskLength;
@@ -500,15 +500,15 @@
#ifdef MBEDTLS_BASE64_C
-otError Dtls::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
+Error Dtls::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mState == kStateConnected, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateConnected, error = kErrorInvalidState);
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength, mSsl.session->peer_cert->raw.p,
mSsl.session->peer_cert->raw.len) == 0,
- error = OT_ERROR_NO_BUFS);
+ error = kErrorNoBufs);
exit:
return error;
@@ -518,19 +518,19 @@
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
#ifdef MBEDTLS_SSL_SRV_C
-otError Dtls::SetClientId(const uint8_t *aClientId, uint8_t aLength)
+Error Dtls::SetClientId(const uint8_t *aClientId, uint8_t aLength)
{
int rval = mbedtls_ssl_set_client_transport_id(&mSsl, aClientId, aLength);
return Crypto::MbedTls::MapError(rval);
}
#endif
-otError Dtls::Send(Message &aMessage, uint16_t aLength)
+Error Dtls::Send(Message &aMessage, uint16_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t buffer[kApplicationDataMaxLength];
- VerifyOrExit(aLength <= kApplicationDataMaxLength, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aLength <= kApplicationDataMaxLength, error = kErrorNoBufs);
// Store message specific sub type.
if (aMessage.GetSubType() != Message::kSubTypeNone)
@@ -564,8 +564,8 @@
int Dtls::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
{
- otError error;
- int rval = 0;
+ Error error;
+ int rval = 0;
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{
@@ -585,16 +585,16 @@
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
rval = static_cast<int>(aLength);
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
rval = MBEDTLS_ERR_SSL_WANT_WRITE;
break;
default:
- otLogWarnMeshCoP("Dtls::HandleMbedtlsTransmit: %s error", otThreadErrorToString(error));
+ otLogWarnMeshCoP("Dtls::HandleMbedtlsTransmit: %s error", ErrorToString(error));
rval = MBEDTLS_ERR_NET_SEND_FAILED;
break;
}
@@ -781,7 +781,7 @@
void Dtls::Process(void)
{
- uint8_t buf[MBEDTLS_SSL_MAX_CONTENT_LEN];
+ uint8_t buf[OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN];
bool shouldDisconnect = false;
int rval;
@@ -904,12 +904,12 @@
}
}
-otError Dtls::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType)
+Error Dtls::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ot::Message *message = nullptr;
- VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = kErrorNoBufs);
message->SetSubType(aMessageSubType);
message->SetLinkSecurityEnabled(mLayerTwoSecurity);
diff --git a/src/core/meshcop/dtls.hpp b/src/core/meshcop/dtls.hpp
index a3cc414..0e507d0 100644
--- a/src/core/meshcop/dtls.hpp
+++ b/src/core/meshcop/dtls.hpp
@@ -108,7 +108,7 @@
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
- typedef otError (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ typedef Error (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This method opens the DTLS socket.
@@ -117,23 +117,23 @@
* @param[in] aConnectedHandler A pointer to a function that is called when connected or disconnected.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully opened the socket.
- * @retval OT_ERROR_ALREADY The DTLS is already open.
+ * @retval kErrorNone Successfully opened the socket.
+ * @retval kErrorAlready The DTLS is already open.
*
*/
- otError Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
+ Error Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
/**
* This method binds this DTLS to a UDP port.
*
* @param[in] aPort The port to bind.
*
- * @retval OT_ERROR_NONE Successfully bound the DTLS socket.
- * @retval OT_ERROR_INVALID_STATE The DTLS socket is not open.
- * @retval OT_ERROR_ALREADY Already bound.
+ * @retval kErrorNone Successfully bound the DTLS socket.
+ * @retval kErrorInvalidState The DTLS socket is not open.
+ * @retval kErrorAlready Already bound.
*
*/
- otError Bind(uint16_t aPort);
+ Error Bind(uint16_t aPort);
/**
* This method binds this DTLS with a transport callback.
@@ -141,12 +141,12 @@
* @param[in] aCallback A pointer to a function for sending messages.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully bound the DTLS socket.
- * @retval OT_ERROR_INVALID_STATE The DTLS socket is not open.
- * @retval OT_ERROR_ALREADY Already bound.
+ * @retval kErrorNone Successfully bound the DTLS socket.
+ * @retval kErrorInvalidState The DTLS socket is not open.
+ * @retval kErrorAlready Already bound.
*
*/
- otError Bind(TransportCallback aCallback, void *aContext);
+ Error Bind(TransportCallback aCallback, void *aContext);
/**
* This method establishes a DTLS session.
@@ -157,11 +157,11 @@
*
* @param[in] aSockAddr A reference to the remote sockaddr.
*
- * @retval OT_ERROR_NONE Successfully started DTLS handshake.
- * @retval OT_ERROR_INVALID_STATE The DTLS socket is not open.
+ * @retval kErrorNone Successfully started DTLS handshake.
+ * @retval kErrorInvalidState The DTLS socket is not open.
*
*/
- otError Connect(const Ip6::SockAddr &aSockAddr);
+ Error Connect(const Ip6::SockAddr &aSockAddr);
/**
* This method indicates whether or not the DTLS session is active.
@@ -198,11 +198,11 @@
*
* @param[in] aPsk A pointer to the PSK.
*
- * @retval OT_ERROR_NONE Successfully set the PSK.
- * @retval OT_ERROR_INVALID_ARGS The PSK is invalid.
+ * @retval kErrorNone Successfully set the PSK.
+ * @retval kErrorInvalidArgs The PSK is invalid.
*
*/
- otError SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
+ Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
@@ -217,7 +217,7 @@
* @param[in] aPskIdentity The Identity Name for the PSK.
* @param[in] aPskIdLength The PSK Identity Length.
*
- * @retval OT_ERROR_NONE Successfully set the PSK.
+ * @retval kErrorNone Successfully set the PSK.
*
*/
void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength);
@@ -264,12 +264,12 @@
* @param[out] aCertLength The length of the base64 encoded peer certificate.
* @param[in] aCertBufferSize The buffer size of aPeerCert.
*
- * @retval OT_ERROR_INVALID_STATE Not connected yet.
- * @retval OT_ERROR_NONE Successfully get the peer certificate.
- * @retval OT_ERROR_NO_BUFS Can't allocate memory for certificate.
+ * @retval kErrorInvalidState Not connected yet.
+ * @retval kErrorNone Successfully get the peer certificate.
+ * @retval kErrorNoBufs Can't allocate memory for certificate.
*
*/
- otError GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);
+ Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);
#endif
/**
@@ -291,10 +291,10 @@
* @param[in] aClientId A pointer to the Client ID.
* @param[in] aLength Number of bytes in the Client ID.
*
- * @retval OT_ERROR_NONE Successfully set the Client ID.
+ * @retval kErrorNone Successfully set the Client ID.
*
*/
- otError SetClientId(const uint8_t *aClientId, uint8_t aLength);
+ Error SetClientId(const uint8_t *aClientId, uint8_t aLength);
#endif
/**
@@ -303,11 +303,11 @@
* @param[in] aMessage A message to send via DTLS.
* @param[in] aLength Number of bytes in the data buffer.
*
- * @retval OT_ERROR_NONE Successfully sent the data via the DTLS session.
- * @retval OT_ERROR_NO_BUFS A message is too long.
+ * @retval kErrorNone Successfully sent the data via the DTLS session.
+ * @retval kErrorNoBufs A message is too long.
*
*/
- otError Send(Message &aMessage, uint16_t aLength);
+ Error Send(Message &aMessage, uint16_t aLength);
/**
* This method provides a received DTLS message to the DTLS object.
@@ -357,8 +357,8 @@
#endif
};
- void FreeMbedtls(void);
- otError Setup(bool aClient);
+ void FreeMbedtls(void);
+ Error Setup(bool aClient);
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
/**
@@ -402,8 +402,8 @@
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
- void HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
- otError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
+ void HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
+ Error HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
void Process(void);
@@ -414,7 +414,7 @@
uint8_t mPskLength;
static const mbedtls_ecp_group_id sCurves[];
-#ifdef MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
static const int sHashes[];
#endif
diff --git a/src/core/meshcop/energy_scan_client.cpp b/src/core/meshcop/energy_scan_client.cpp
index f279878..f40e5ab 100644
--- a/src/core/meshcop/energy_scan_client.cpp
+++ b/src/core/meshcop/energy_scan_client.cpp
@@ -58,21 +58,21 @@
Get<Tmf::TmfAgent>().AddResource(mEnergyScan);
}
-otError EnergyScanClient::SendQuery(uint32_t aChannelMask,
- uint8_t aCount,
- uint16_t aPeriod,
- uint16_t aScanDuration,
- const Ip6::Address & aAddress,
- otCommissionerEnergyReportCallback aCallback,
- void * aContext)
+Error EnergyScanClient::SendQuery(uint32_t aChannelMask,
+ uint8_t aCount,
+ uint16_t aPeriod,
+ uint16_t aScanDuration,
+ const Ip6::Address & aAddress,
+ otCommissionerEnergyReportCallback aCallback,
+ void * aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::ChannelMaskTlv channelMask;
Ip6::MessageInfo messageInfo;
Coap::Message * message = nullptr;
- VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kEnergyScan));
SuccessOrExit(error = message->SetPayloadMarker());
diff --git a/src/core/meshcop/energy_scan_client.hpp b/src/core/meshcop/energy_scan_client.hpp
index ae0074e..6e14842 100644
--- a/src/core/meshcop/energy_scan_client.hpp
+++ b/src/core/meshcop/energy_scan_client.hpp
@@ -69,17 +69,17 @@
* @param[in] aCallback A pointer to a function called on receiving an Energy Report message.
* @param[in] aContext A pointer to application-specific context.
*
- * @retval OT_ERROR_NONE Successfully enqueued the Energy Scan Query message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate an Energy Scan Query message.
+ * @retval kErrorNone Successfully enqueued the Energy Scan Query message.
+ * @retval kErrorNoBufs Insufficient buffers to generate an Energy Scan Query message.
*
*/
- otError SendQuery(uint32_t aChannelMask,
- uint8_t aCount,
- uint16_t aPeriod,
- uint16_t aScanDuration,
- const Ip6::Address & aAddress,
- otCommissionerEnergyReportCallback aCallback,
- void * aContext);
+ Error SendQuery(uint32_t aChannelMask,
+ uint8_t aCount,
+ uint16_t aPeriod,
+ uint16_t aScanDuration,
+ const Ip6::Address & aAddress,
+ otCommissionerEnergyReportCallback aCallback,
+ void * aContext);
private:
static void HandleReport(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp
index 349a4c6..176bbdd 100644
--- a/src/core/meshcop/joiner.cpp
+++ b/src/core/meshcop/joiner.cpp
@@ -62,7 +62,7 @@
, mContext(nullptr)
, mJoinerRouterIndex(0)
, mFinalizeMessage(nullptr)
- , mTimer(aInstance, Joiner::HandleTimer, this)
+ , mTimer(aInstance, Joiner::HandleTimer)
, mJoinerEntrust(UriPath::kJoinerEntrust, &Joiner::HandleJoinerEntrust, this)
{
SetIdFromIeeeEui64();
@@ -84,12 +84,12 @@
return mDiscerner.IsEmpty() ? nullptr : &mDiscerner;
}
-otError Joiner::SetDiscerner(const JoinerDiscerner &aDiscerner)
+Error Joiner::SetDiscerner(const JoinerDiscerner &aDiscerner)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aDiscerner.IsValid(), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(mState == kStateIdle, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aDiscerner.IsValid(), error = kErrorInvalidArgs);
+ VerifyOrExit(mState == kStateIdle, error = kErrorInvalidState);
mDiscerner = aDiscerner;
mDiscerner.GenerateJoinerId(mId);
@@ -98,11 +98,11 @@
return error;
}
-otError Joiner::ClearDiscerner(void)
+Error Joiner::ClearDiscerner(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mState == kStateIdle, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mState == kStateIdle, error = kErrorInvalidState);
VerifyOrExit(!mDiscerner.IsEmpty());
mDiscerner.Clear();
@@ -124,29 +124,29 @@
return;
}
-otError Joiner::Start(const char * aPskd,
- const char * aProvisioningUrl,
- const char * aVendorName,
- const char * aVendorModel,
- const char * aVendorSwVersion,
- const char * aVendorData,
- otJoinerCallback aCallback,
- void * aContext)
+Error Joiner::Start(const char * aPskd,
+ const char * aProvisioningUrl,
+ const char * aVendorName,
+ const char * aVendorModel,
+ const char * aVendorSwVersion,
+ const char * aVendorData,
+ otJoinerCallback aCallback,
+ void * aContext)
{
- otError error;
+ Error error;
JoinerPskd joinerPskd;
Mac::ExtAddress randomAddress;
SteeringData::HashBitIndexes filterIndexes;
otLogInfoMeshCoP("Joiner starting");
- VerifyOrExit(aProvisioningUrl == nullptr || IsValidUtf8String(aProvisioningUrl), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aVendorName == nullptr || IsValidUtf8String(aVendorName), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aVendorSwVersion == nullptr || IsValidUtf8String(aVendorSwVersion), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aProvisioningUrl == nullptr || IsValidUtf8String(aProvisioningUrl), error = kErrorInvalidArgs);
+ VerifyOrExit(aVendorName == nullptr || IsValidUtf8String(aVendorName), error = kErrorInvalidArgs);
+ VerifyOrExit(aVendorSwVersion == nullptr || IsValidUtf8String(aVendorSwVersion), error = kErrorInvalidArgs);
- VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
+ VerifyOrExit(mState == kStateIdle, error = kErrorBusy);
VerifyOrExit(Get<ThreadNetif>().IsUp() && Get<Mle::Mle>().GetRole() == Mle::kRoleDisabled,
- error = OT_ERROR_INVALID_STATE);
+ error = kErrorInvalidState);
SuccessOrExit(error = joinerPskd.SetFrom(aPskd));
@@ -184,7 +184,7 @@
SetState(kStateDiscover);
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeJoinerFinalizeMessage();
}
@@ -199,10 +199,10 @@
// Callback is set to `nullptr` to skip calling it from `Finish()`
mCallback = nullptr;
- Finish(OT_ERROR_ABORT);
+ Finish(kErrorAbort);
}
-void Joiner::Finish(otError aError)
+void Joiner::Finish(Error aError)
{
switch (mState)
{
@@ -217,7 +217,7 @@
IgnoreError(Get<Ip6::Filter>().RemoveUnsecurePort(kJoinerUdpPort));
mTimer.Stop();
- // Fall through
+ OT_FALL_THROUGH;
case kStateDiscover:
Get<Coap::CoapSecure>().Stop();
@@ -290,7 +290,7 @@
Get<Mle::MleRouter>().UpdateLinkLocalAddress();
mJoinerRouterIndex = 0;
- TryNextJoinerRouter(OT_ERROR_NONE);
+ TryNextJoinerRouter(kErrorNone);
}
exit:
@@ -339,12 +339,12 @@
return;
}
-void Joiner::TryNextJoinerRouter(otError aPrevError)
+void Joiner::TryNextJoinerRouter(Error aPrevError)
{
for (; mJoinerRouterIndex < OT_ARRAY_LENGTH(mJoinerRouters); mJoinerRouterIndex++)
{
JoinerRouter &router = mJoinerRouters[mJoinerRouterIndex];
- otError error;
+ Error error;
if (router.mPriority == 0)
{
@@ -352,7 +352,7 @@
}
error = Connect(router);
- VerifyOrExit(error != OT_ERROR_NONE, mJoinerRouterIndex++);
+ VerifyOrExit(error != kErrorNone, mJoinerRouterIndex++);
// Save the error from `Connect` only if there is no previous
// error from earlier attempts. This ensures that if there has
@@ -361,15 +361,15 @@
// emitted from `Finish()` call corresponds to the error from
// that attempt.
- if (aPrevError == OT_ERROR_NONE)
+ if (aPrevError == kErrorNone)
{
aPrevError = error;
}
}
- if (aPrevError == OT_ERROR_NONE)
+ if (aPrevError == kErrorNone)
{
- aPrevError = OT_ERROR_NOT_FOUND;
+ aPrevError = kErrorNotFound;
}
Finish(aPrevError);
@@ -378,9 +378,9 @@
return;
}
-otError Joiner::Connect(JoinerRouter &aRouter)
+Error Joiner::Connect(JoinerRouter &aRouter)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Ip6::SockAddr sockAddr(aRouter.mJoinerUdpPort);
otLogInfoMeshCoP("Joiner connecting to %s, pan:0x%04x, chan:%d", aRouter.mExtAddr.ToString().AsCString(),
@@ -418,27 +418,27 @@
}
else
{
- TryNextJoinerRouter(OT_ERROR_SECURITY);
+ TryNextJoinerRouter(kErrorSecurity);
}
exit:
return;
}
-otError Joiner::PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
- const char *aVendorName,
- const char *aVendorModel,
- const char *aVendorSwVersion,
- const char *aVendorData)
+Error Joiner::PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
+ const char *aVendorName,
+ const char *aVendorModel,
+ const char *aVendorSwVersion,
+ const char *aVendorData)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VendorNameTlv vendorNameTlv;
VendorModelTlv vendorModelTlv;
VendorSwVersionTlv vendorSwVersionTlv;
VendorStackVersionTlv vendorStackVersionTlv;
ProvisioningUrlTlv provisioningUrlTlv;
- VerifyOrExit((mFinalizeMessage = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((mFinalizeMessage = NewMeshCoPMessage(Get<Coap::CoapSecure>())) != nullptr, error = kErrorNoBufs);
mFinalizeMessage->InitAsConfirmablePost();
SuccessOrExit(error = mFinalizeMessage->AppendUriPathOptions(UriPath::kJoinerFinalize));
@@ -483,7 +483,7 @@
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeJoinerFinalizeMessage();
}
@@ -522,21 +522,19 @@
void Joiner::HandleJoinerFinalizeResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<Joiner *>(aContext)->HandleJoinerFinalizeResponse(
*static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
}
-void Joiner::HandleJoinerFinalizeResponse(Coap::Message & aMessage,
- const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+void Joiner::HandleJoinerFinalizeResponse(Coap::Message &aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
uint8_t state;
- VerifyOrExit(mState == kStateConnected && aResult == OT_ERROR_NONE && aMessage.IsAck() &&
+ VerifyOrExit(mState == kStateConnected && aResult == kErrorNone && aMessage.IsAck() &&
aMessage.GetCode() == Coap::kCodeChanged);
SuccessOrExit(Tlv::Find<StateTlv>(aMessage, state));
@@ -563,10 +561,10 @@
void Joiner::HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
Dataset::Info datasetInfo;
- VerifyOrExit(mState == kStateEntrust && aMessage.IsConfirmablePostRequest(), error = OT_ERROR_DROP);
+ VerifyOrExit(mState == kStateEntrust && aMessage.IsConfirmablePostRequest(), error = kErrorDrop);
otLogInfoMeshCoP("Joiner received entrust");
otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_ENT.ntf");
@@ -593,11 +591,11 @@
void Joiner::SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
Ip6::MessageInfo responseInfo(aRequestInfo);
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
message->SetSubType(Message::kSubTypeJoinerEntrust);
@@ -615,12 +613,12 @@
void Joiner::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Joiner>().HandleTimer();
+ aTimer.Get<Joiner>().HandleTimer();
}
void Joiner::HandleTimer(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
switch (mState)
{
@@ -632,7 +630,7 @@
case kStateConnected:
case kStateEntrust:
- error = OT_ERROR_RESPONSE_TIMEOUT;
+ error = kErrorResponseTimeout;
break;
case kStateJoined:
@@ -642,7 +640,7 @@
Get<Mac::Mac>().SetExtAddress(extAddress);
Get<Mle::MleRouter>().UpdateLinkLocalAddress();
- error = OT_ERROR_NONE;
+ error = kErrorNone;
break;
}
@@ -653,31 +651,23 @@
const char *Joiner::StateToString(State aState)
{
- const char *str = "Unknown";
+ static const char *const kStateStrings[] = {
+ "Idle", // (0) kStateIdle
+ "Discover", // (1) kStateDiscover
+ "Connecting", // (2) kStateConnect
+ "Connected", // (3) kStateConnected
+ "Entrust", // (4) kStateEntrust
+ "Joined", // (5) kStateJoined
+ };
- switch (aState)
- {
- case kStateIdle:
- str = "Idle";
- break;
- case kStateDiscover:
- str = "Discover";
- break;
- case kStateConnect:
- str = "Connecting";
- break;
- case kStateConnected:
- str = "Connected";
- break;
- case kStateEntrust:
- str = "Entrust";
- break;
- case kStateJoined:
- str = "Joined";
- break;
- }
+ static_assert(kStateIdle == 0, "kStateIdle value is incorrect");
+ static_assert(kStateDiscover == 1, "kStateDiscover value is incorrect");
+ static_assert(kStateConnect == 2, "kStateConnect value is incorrect");
+ static_assert(kStateConnected == 3, "kStateConnected value is incorrect");
+ static_assert(kStateEntrust == 4, "kStateEntrust value is incorrect");
+ static_assert(kStateJoined == 5, "kStateJoined value is incorrect");
- return str;
+ return kStateStrings[aState];
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
diff --git a/src/core/meshcop/joiner.hpp b/src/core/meshcop/joiner.hpp
index 176ad33..904a3ed 100644
--- a/src/core/meshcop/joiner.hpp
+++ b/src/core/meshcop/joiner.hpp
@@ -92,19 +92,19 @@
* @param[in] aCallback A pointer to a function that is called when the join operation completes.
* @param[in] aContext A pointer to application-specific context.
*
- * @retval OT_ERROR_NONE Successfully started the Joiner service.
- * @retval OT_ERROR_BUSY The previous attempt is still on-going.
- * @retval OT_ERROR_INVALID_STATE The IPv6 stack is not enabled or Thread stack is fully enabled.
+ * @retval kErrorNone Successfully started the Joiner service.
+ * @retval kErrorBusy The previous attempt is still on-going.
+ * @retval kErrorInvalidState The IPv6 stack is not enabled or Thread stack is fully enabled.
*
*/
- otError Start(const char * aPskd,
- const char * aProvisioningUrl,
- const char * aVendorName,
- const char * aVendorModel,
- const char * aVendorSwVersion,
- const char * aVendorData,
- otJoinerCallback aCallback,
- void * aContext);
+ Error Start(const char * aPskd,
+ const char * aProvisioningUrl,
+ const char * aVendorName,
+ const char * aVendorModel,
+ const char * aVendorSwVersion,
+ const char * aVendorData,
+ otJoinerCallback aCallback,
+ void * aContext);
/**
* This method stops the Joiner service.
@@ -147,23 +147,23 @@
*
* @param[in] aDiscerner A Joiner Discerner
*
- * @retval OT_ERROR_NONE The Joiner Discerner updated successfully.
- * @retval OT_ERROR_INVALID_ARGS @p aDiscerner is not valid (specified length is not within valid range).
- * @retval OT_ERROR_INVALID_STATE There is an ongoing Joining process so Joiner Discerner could not be changed.
+ * @retval kErrorNone The Joiner Discerner updated successfully.
+ * @retval kErrorInvalidArgs @p aDiscerner is not valid (specified length is not within valid range).
+ * @retval kErrorInvalidState There is an ongoing Joining process so Joiner Discerner could not be changed.
*
*/
- otError SetDiscerner(const JoinerDiscerner &aDiscerner);
+ Error SetDiscerner(const JoinerDiscerner &aDiscerner);
/**
* This method clears any previously set Joiner Discerner.
*
* When cleared, Joiner ID is derived as first 64 bits of SHA-256 of factory-assigned IEEE EUI-64.
*
- * @retval OT_ERROR_NONE The Joiner Discerner cleared and Joiner ID updated.
- * @retval OT_ERROR_INVALID_STATE There is an ongoing Joining process so Joiner Discerner could not be changed.
+ * @retval kErrorNone The Joiner Discerner cleared and Joiner ID updated.
+ * @retval kErrorInvalidState There is an ongoing Joining process so Joiner Discerner could not be changed.
*
*/
- otError ClearDiscerner(void);
+ Error ClearDiscerner(void);
private:
enum
@@ -191,8 +191,8 @@
static void HandleJoinerFinalizeResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleJoinerFinalizeResponse(Coap::Message &aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleJoinerFinalizeResponse(Coap::Message &aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleJoinerEntrust(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleJoinerEntrust(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
@@ -205,19 +205,19 @@
void SetState(State aState);
void SetIdFromIeeeEui64(void);
void SaveDiscoveredJoinerRouter(const Mle::DiscoverScanner::ScanResult &aResult);
- void TryNextJoinerRouter(otError aPrevError);
- otError Connect(JoinerRouter &aRouter);
- void Finish(otError aError);
+ void TryNextJoinerRouter(Error aPrevError);
+ Error Connect(JoinerRouter &aRouter);
+ void Finish(Error aError);
uint8_t CalculatePriority(int8_t aRssi, bool aSteeringDataAllowsAny);
- otError PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
- const char *aVendorName,
- const char *aVendorModel,
- const char *aVendorSwVersion,
- const char *aVendorData);
- void FreeJoinerFinalizeMessage(void);
- void SendJoinerFinalize(void);
- void SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo);
+ Error PrepareJoinerFinalizeMessage(const char *aProvisioningUrl,
+ const char *aVendorName,
+ const char *aVendorModel,
+ const char *aVendorSwVersion,
+ const char *aVendorData);
+ void FreeJoinerFinalizeMessage(void);
+ void SendJoinerFinalize(void);
+ void SendJoinerEntrustResponse(const Coap::Message &aRequest, const Ip6::MessageInfo &aRequestInfo);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
void LogCertMessage(const char *aText, const Coap::Message &aMessage) const;
diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp
index 7ceb9be..7216ad6 100644
--- a/src/core/meshcop/joiner_router.cpp
+++ b/src/core/meshcop/joiner_router.cpp
@@ -55,7 +55,7 @@
: InstanceLocator(aInstance)
, mSocket(aInstance)
, mRelayTransmit(UriPath::kRelayTx, &JoinerRouter::HandleRelayTransmit, this)
- , mTimer(aInstance, JoinerRouter::HandleTimer, this)
+ , mTimer(aInstance, JoinerRouter::HandleTimer)
, mJoinerUdpPort(0)
, mIsJoinerPortConfigured(false)
{
@@ -130,7 +130,7 @@
void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
ExtendedTlv tlv;
@@ -141,7 +141,7 @@
SuccessOrExit(error = GetBorderAgentRloc(Get<ThreadNetif>(), borderAgentRloc));
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kRelayRx));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -180,7 +180,7 @@
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error;
+ Error error;
uint16_t joinerPort;
Ip6::InterfaceIdentifier joinerIid;
Kek kek;
@@ -190,7 +190,7 @@
Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
Ip6::MessageInfo messageInfo;
- VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);
otLogInfoMeshCoP("Received relay transmit");
@@ -199,7 +199,7 @@
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
- VerifyOrExit((message = mSocket.NewMessage(0, settings)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mSocket.NewMessage(0, settings)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetLength(length));
aMessage.CopyTo(offset, 0, length, *message);
@@ -209,7 +209,7 @@
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
- if (Tlv::Find<JoinerRouterKekTlv>(aMessage, kek) == OT_ERROR_NONE)
+ if (Tlv::Find<JoinerRouterKekTlv>(aMessage, kek) == kErrorNone)
{
otLogInfoMeshCoP("Received kek");
@@ -222,11 +222,11 @@
void JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessageInfo, const Kek &aKek)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message = Get<MessagePool>().New(Message::kTypeOther, 0);
JoinerEntrustMetadata metadata;
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
metadata.mMessageInfo = aMessageInfo;
metadata.mMessageInfo.SetPeerPort(Tmf::kUdpPort);
@@ -249,7 +249,7 @@
void JoinerRouter::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<JoinerRouter>().HandleTimer();
+ aTimer.Get<JoinerRouter>().HandleTimer();
}
void JoinerRouter::HandleTimer(void)
@@ -278,7 +278,7 @@
Get<KeyManager>().SetKek(metadata.mKek);
- if (SendJoinerEntrust(metadata.mMessageInfo) != OT_ERROR_NONE)
+ if (SendJoinerEntrust(metadata.mMessageInfo) != kErrorNone)
{
mTimer.Start(0);
}
@@ -288,13 +288,13 @@
return;
}
-otError JoinerRouter::SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo)
+Error JoinerRouter::SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
message = PrepareJoinerEntrustMessage();
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
IgnoreError(Get<Tmf::TmfAgent>().AbortTransaction(&JoinerRouter::HandleJoinerEntrustResponse, this));
@@ -312,14 +312,14 @@
Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void)
{
- otError error;
+ Error error;
Coap::Message *message = nullptr;
Dataset dataset(Dataset::kActive);
NetworkNameTlv networkName;
const Tlv * tlv;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
message->InitAsConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kJoinerEntrust));
@@ -390,7 +390,7 @@
void JoinerRouter::HandleJoinerEntrustResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<JoinerRouter *>(aContext)->HandleJoinerEntrustResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -398,13 +398,13 @@
void JoinerRouter::HandleJoinerEntrustResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
SendDelayedJoinerEntrust();
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage != nullptr);
+ VerifyOrExit(aResult == kErrorNone && aMessage != nullptr);
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp
index 42b3fb1..47323f7 100644
--- a/src/core/meshcop/joiner_router.hpp
+++ b/src/core/meshcop/joiner_router.hpp
@@ -89,8 +89,8 @@
struct JoinerEntrustMetadata
{
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ void ReadFrom(const Message &aMessage);
Ip6::MessageInfo mMessageInfo; // Message info of the message to send.
TimeMilli mSendTime; // Time when the message shall be sent.
@@ -108,8 +108,8 @@
static void HandleJoinerEntrustResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleJoinerEntrustResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleJoinerEntrustResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
@@ -117,7 +117,7 @@
void Start(void);
void DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessageInfo, const Kek &aKek);
void SendDelayedJoinerEntrust(void);
- otError SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo);
+ Error SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo);
Coap::Message *PrepareJoinerEntrustMessage(void);
Ip6::Udp::Socket mSocket;
diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp
index 24e4c1f..4866e96 100644
--- a/src/core/meshcop/meshcop.cpp
+++ b/src/core/meshcop/meshcop.cpp
@@ -38,7 +38,7 @@
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#include "common/string.hpp"
-#include "crypto/pbkdf2_cmac.h"
+#include "crypto/pbkdf2_cmac.hpp"
#include "crypto/sha256.hpp"
#include "mac/mac_types.hpp"
#include "thread/thread_netif.hpp"
@@ -46,11 +46,11 @@
namespace ot {
namespace MeshCoP {
-otError JoinerPskd::SetFrom(const char *aPskdString)
+Error JoinerPskd::SetFrom(const char *aPskdString)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsPskdValid(aPskdString), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsPskdValid(aPskdString), error = kErrorInvalidArgs);
Clear();
memcpy(m8, aPskdString, StringLength(aPskdString, sizeof(m8)));
@@ -291,21 +291,21 @@
Crypto::Sha256::Hash hash;
sha256.Start();
- sha256.Update(aEui64.m8, sizeof(aEui64));
+ sha256.Update(aEui64);
sha256.Finish(hash);
memcpy(&aJoinerId, hash.GetBytes(), sizeof(aJoinerId));
aJoinerId.SetLocal(true);
}
-otError GetBorderAgentRloc(ThreadNetif &aNetif, uint16_t &aRloc)
+Error GetBorderAgentRloc(ThreadNetif &aNetif, uint16_t &aRloc)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const BorderAgentLocatorTlv *borderAgentLocator;
borderAgentLocator = static_cast<const BorderAgentLocatorTlv *>(
aNetif.Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
- VerifyOrExit(borderAgentLocator != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(borderAgentLocator != nullptr, error = kErrorNotFound);
aRloc = borderAgentLocator->GetBorderAgentLocator();
@@ -314,19 +314,19 @@
}
#if OPENTHREAD_FTD
-otError GeneratePskc(const char * aPassPhrase,
- const Mac::NetworkName & aNetworkName,
- const Mac::ExtendedPanId &aExtPanId,
- Pskc & aPskc)
+Error GeneratePskc(const char * aPassPhrase,
+ const Mac::NetworkName & aNetworkName,
+ const Mac::ExtendedPanId &aExtPanId,
+ Pskc & aPskc)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const char saltPrefix[] = "Thread";
- uint8_t salt[OT_PBKDF2_SALT_MAX_LEN];
+ uint8_t salt[Crypto::Pbkdf2::kMaxSaltLength];
uint16_t saltLen = 0;
uint16_t passphraseLen;
uint8_t networkNameLen;
- VerifyOrExit(IsValidUtf8String(aPassPhrase), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsValidUtf8String(aPassPhrase), error = kErrorInvalidArgs);
passphraseLen = static_cast<uint16_t>(StringLength(aPassPhrase, OT_COMMISSIONING_PASSPHRASE_MAX_SIZE + 1));
networkNameLen = static_cast<uint8_t>(StringLength(aNetworkName.GetAsCString(), OT_NETWORK_NAME_MAX_SIZE + 1));
@@ -334,7 +334,7 @@
VerifyOrExit((passphraseLen >= OT_COMMISSIONING_PASSPHRASE_MIN_SIZE) &&
(passphraseLen <= OT_COMMISSIONING_PASSPHRASE_MAX_SIZE) &&
(networkNameLen <= OT_NETWORK_NAME_MAX_SIZE),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
memset(salt, 0, sizeof(salt));
memcpy(salt, saltPrefix, sizeof(saltPrefix) - 1);
@@ -346,8 +346,8 @@
memcpy(salt + saltLen, aNetworkName.GetAsCString(), networkNameLen);
saltLen += networkNameLen;
- otPbkdf2Cmac(reinterpret_cast<const uint8_t *>(aPassPhrase), passphraseLen, reinterpret_cast<const uint8_t *>(salt),
- saltLen, 16384, OT_PSKC_MAX_SIZE, aPskc.m8);
+ Crypto::Pbkdf2::GenerateKey(reinterpret_cast<const uint8_t *>(aPassPhrase), passphraseLen, salt, saltLen, 16384,
+ OT_PSKC_MAX_SIZE, aPskc.m8);
exit:
return error;
@@ -355,11 +355,11 @@
#endif // OPENTHREAD_FTD
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
-void LogError(const char *aActionText, otError aError)
+void LogError(const char *aActionText, Error aError)
{
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
- otLogWarnMeshCoP("Failed to %s: %s", aActionText, otThreadErrorToString(aError));
+ otLogWarnMeshCoP("Failed to %s: %s", aActionText, ErrorToString(aError));
}
}
#endif
diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp
index 2f1c1a0..f5e8d3a 100644
--- a/src/core/meshcop/meshcop.hpp
+++ b/src/core/meshcop/meshcop.hpp
@@ -45,6 +45,7 @@
#include "coap/coap.hpp"
#include "common/clearable.hpp"
+#include "common/equatable.hpp"
#include "common/message.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
@@ -65,7 +66,7 @@
* This type represents a Joiner PSKd.
*
*/
-class JoinerPskd : public otJoinerPskd, public Clearable<JoinerPskd>
+class JoinerPskd : public otJoinerPskd, public Clearable<JoinerPskd>, public Unequatable<JoinerPskd>
{
public:
enum
@@ -91,11 +92,11 @@
*
* @param[in] aPskdString A pointer to the PSKd C string array.
*
- * @retval OT_ERROR_NONE The PSKd was updated successfully.
- * @retval OT_ERROR_INVALID_ARGS The given PSKd C string is not valid.
+ * @retval kErrorNone The PSKd was updated successfully.
+ * @retval kErrorInvalidArgs The given PSKd C string is not valid.
*
*/
- otError SetFrom(const char *aPskdString);
+ Error SetFrom(const char *aPskdString);
/**
* This method gets the PSKd as a null terminated C string.
@@ -129,17 +130,6 @@
bool operator==(const JoinerPskd &aOther) const;
/**
- * This method overloads operator `!=` to evaluate whether or not two PSKds are unequal.
- *
- * @param[in] aOther The other PSKd to compare with.
- *
- * @retval TRUE If the two are not equal.
- * @retval FALSE If the two are equal.
- *
- */
- bool operator!=(const JoinerPskd &aOther) const { return !(*this == aOther); }
-
- /**
* This static method indicates whether a given PSKd string if well-formed and valid.
*
* @param[in] aPskdString A pointer to a PSKd string array.
@@ -156,7 +146,7 @@
* This type represents a Joiner Discerner.
*
*/
-class JoinerDiscerner : public otJoinerDiscerner
+class JoinerDiscerner : public otJoinerDiscerner, public Unequatable<JoinerDiscerner>
{
friend class SteeringData;
@@ -242,17 +232,6 @@
bool operator==(const JoinerDiscerner &aOther) const;
/**
- * This method overloads operator `!=` to evaluate whether or not two Joiner Discerner instances are equal.
- *
- * @param[in] aOther The other Joiner Discerner to compare with.
- *
- * @retval TRUE If the two are not equal.
- * @retval FALSE If the two are equal.
- *
- */
- bool operator!=(const JoinerDiscerner &aOther) const { return !(*this == aOther); }
-
- /**
* This method converts the Joiner Discerner to a string.
*
* @returns An `InfoString` representation of Joiner Discerner.
@@ -463,14 +442,14 @@
* @param[in] aExtPanId The extended PAN ID for PSKc computation.
* @param[out] aPskc A reference to a PSKc where the generated PSKc will be placed.
*
- * @retval OT_ERROR_NONE Successfully generate PSKc.
- * @retval OT_ERROR_INVALID_ARGS If the length of passphrase is out of range.
+ * @retval kErrorNone Successfully generate PSKc.
+ * @retval kErrorInvalidArgs If the length of passphrase is out of range.
*
*/
-otError GeneratePskc(const char * aPassPhrase,
- const Mac::NetworkName & aNetworkName,
- const Mac::ExtendedPanId &aExtPanId,
- Pskc & aPskc);
+Error GeneratePskc(const char * aPassPhrase,
+ const Mac::NetworkName & aNetworkName,
+ const Mac::ExtendedPanId &aExtPanId,
+ Pskc & aPskc);
/**
* This function computes the Joiner ID from a factory-assigned IEEE EUI-64.
@@ -487,26 +466,26 @@
* @param[in] aNetif A reference to the thread interface.
* @param[out] aRloc Border agent RLOC.
*
- * @retval OT_ERROR_NONE Successfully got the Border Agent Rloc.
- * @retval OT_ERROR_NOT_FOUND Border agent is not available.
+ * @retval kErrorNone Successfully got the Border Agent Rloc.
+ * @retval kErrorNotFound Border agent is not available.
*
*/
-otError GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
+Error GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MESHCOP == 1)
/**
* This function emits a log message indicating an error during a MeshCoP action.
*
- * Note that log message is emitted only if there is an error, i.e. @p aError is not `OT_ERROR_NONE`. The log
+ * Note that log message is emitted only if there is an error, i.e. @p aError is not `kErrorNone`. The log
* message will have the format "Failed to {aActionText} : {ErrorString}".
*
* @param[in] aActionText A string representing the failed action.
* @param[in] aError The error in sending the message.
*
*/
-void LogError(const char *aActionText, otError aError);
+void LogError(const char *aActionText, Error aError);
#else
-inline void LogError(const char *, otError)
+inline void LogError(const char *, Error)
{
}
#endif
diff --git a/src/core/meshcop/meshcop_leader.cpp b/src/core/meshcop/meshcop_leader.cpp
index 9822afd..8ef8731 100644
--- a/src/core/meshcop/meshcop_leader.cpp
+++ b/src/core/meshcop/meshcop_leader.cpp
@@ -56,7 +56,7 @@
: InstanceLocator(aInstance)
, mPetition(UriPath::kLeaderPetition, Leader::HandlePetition, this)
, mKeepAlive(UriPath::kLeaderKeepAlive, Leader::HandleKeepAlive, this)
- , mTimer(aInstance, HandleTimer, this)
+ , mTimer(aInstance, HandleTimer)
, mDelayTimerMinimal(DelayTimerTlv::kDelayTimerMinimal)
, mSessionId(Random::NonCrypto::GetUint16())
{
@@ -123,10 +123,10 @@
const Ip6::MessageInfo &aMessageInfo,
StateTlv::State aState)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -207,10 +207,10 @@
const Ip6::MessageInfo &aMessageInfo,
StateTlv::State aState)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -228,11 +228,11 @@
void Leader::SendDatasetChanged(const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::MessageInfo messageInfo;
Coap::Message * message;
- VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDatasetChanged));
@@ -248,11 +248,11 @@
LogError("send dataset changed", error);
}
-otError Leader::SetDelayTimerMinimal(uint32_t aDelayTimerMinimal)
+Error Leader::SetDelayTimerMinimal(uint32_t aDelayTimerMinimal)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit((aDelayTimerMinimal != 0 && aDelayTimerMinimal < DelayTimerTlv::kDelayTimerDefault),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
mDelayTimerMinimal = aDelayTimerMinimal;
exit:
@@ -266,7 +266,7 @@
void Leader::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Leader>().HandleTimer();
+ aTimer.Get<Leader>().HandleTimer();
}
void Leader::HandleTimer(void)
diff --git a/src/core/meshcop/meshcop_leader.hpp b/src/core/meshcop/meshcop_leader.hpp
index d074039..47e2393 100644
--- a/src/core/meshcop/meshcop_leader.hpp
+++ b/src/core/meshcop/meshcop_leader.hpp
@@ -86,11 +86,11 @@
*
* @param[in] aDelayTimerMinimal The value of minimal delay timer (in ms).
*
- * @retval OT_ERROR_NONE Successfully set the minimal delay timer.
- * @retval OT_ERROR_INVALID_ARGS If @p aDelayTimerMinimal is not valid.
+ * @retval kErrorNone Successfully set the minimal delay timer.
+ * @retval kErrorInvalidArgs If @p aDelayTimerMinimal is not valid.
*
*/
- otError SetDelayTimerMinimal(uint32_t aDelayTimerMinimal);
+ Error SetDelayTimerMinimal(uint32_t aDelayTimerMinimal);
/**
* This method gets minimal delay timer.
diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp
index f85c351..96d6215 100644
--- a/src/core/meshcop/meshcop_tlvs.hpp
+++ b/src/core/meshcop/meshcop_tlvs.hpp
@@ -156,11 +156,11 @@
* @param[in] aMaxLength Maximum number of bytes to read.
* @param[out] aTlv A reference to the TLV that will be copied to.
*
- * @retval OT_ERROR_NONE Successfully copied the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully copied the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- static otError FindTlv(const Message &aMessage, Type aType, uint16_t aMaxLength, Tlv &aTlv)
+ static Error FindTlv(const Message &aMessage, Type aType, uint16_t aMaxLength, Tlv &aTlv)
{
return ot::Tlv::FindTlv(aMessage, static_cast<uint8_t>(aType), aMaxLength, aTlv);
}
@@ -175,12 +175,12 @@
* @param[in] aMessage A reference to the message.
* @param[out] aTlv A reference to the TLV that will be copied to.
*
- * @retval OT_ERROR_NONE Successfully copied the TLV.
- * @retval OT_ERROR_NOT_FOUND Could not find the TLV with Type @p aType.
+ * @retval kErrorNone Successfully copied the TLV.
+ * @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
- template <typename TlvType> static otError FindTlv(const Message &aMessage, TlvType &aTlv)
+ template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
{
return ot::Tlv::FindTlv(aMessage, aTlv);
}
diff --git a/src/core/meshcop/panid_query_client.cpp b/src/core/meshcop/panid_query_client.cpp
index 4598d0f..47b49b1 100644
--- a/src/core/meshcop/panid_query_client.cpp
+++ b/src/core/meshcop/panid_query_client.cpp
@@ -57,19 +57,19 @@
Get<Tmf::TmfAgent>().AddResource(mPanIdQuery);
}
-otError PanIdQueryClient::SendQuery(uint16_t aPanId,
- uint32_t aChannelMask,
- const Ip6::Address & aAddress,
- otCommissionerPanIdConflictCallback aCallback,
- void * aContext)
+Error PanIdQueryClient::SendQuery(uint16_t aPanId,
+ uint32_t aChannelMask,
+ const Ip6::Address & aAddress,
+ otCommissionerPanIdConflictCallback aCallback,
+ void * aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::ChannelMaskTlv channelMask;
Ip6::MessageInfo messageInfo;
Coap::Message * message = nullptr;
- VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsPost(aAddress, UriPath::kPanIdQuery));
SuccessOrExit(error = message->SetPayloadMarker());
diff --git a/src/core/meshcop/panid_query_client.hpp b/src/core/meshcop/panid_query_client.hpp
index 7fe58f2..4ad1b43 100644
--- a/src/core/meshcop/panid_query_client.hpp
+++ b/src/core/meshcop/panid_query_client.hpp
@@ -67,15 +67,15 @@
* @param[in] aCallback A pointer to a function called on receiving an Energy Report message.
* @param[in] aContext A pointer to application-specific context.
*
- * @retval OT_ERROR_NONE Successfully enqueued the PAN ID Query message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate a PAN ID Query message.
+ * @retval kErrorNone Successfully enqueued the PAN ID Query message.
+ * @retval kErrorNoBufs Insufficient buffers to generate a PAN ID Query message.
*
*/
- otError SendQuery(uint16_t aPanId,
- uint32_t aChannelMask,
- const Ip6::Address & aAddress,
- otCommissionerPanIdConflictCallback aCallback,
- void * aContext);
+ Error SendQuery(uint16_t aPanId,
+ uint32_t aChannelMask,
+ const Ip6::Address & aAddress,
+ otCommissionerPanIdConflictCallback aCallback,
+ void * aContext);
private:
static void HandleConflict(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
diff --git a/src/core/meshcop/timestamp.cpp b/src/core/meshcop/timestamp.cpp
index 47eef75..9a523d1 100644
--- a/src/core/meshcop/timestamp.cpp
+++ b/src/core/meshcop/timestamp.cpp
@@ -68,5 +68,19 @@
return rval;
}
+void Timestamp::AdvanceRandomTicks(void)
+{
+ uint16_t ticks = GetTicks();
+
+ ticks += Random::NonCrypto::GetUint32InRange(1, kMaxRandomTicks);
+
+ if (ticks & (kTicksMask >> kTicksOffset))
+ {
+ SetSeconds(GetSeconds() + 1);
+ }
+
+ SetTicks(ticks);
+}
+
} // namespace MeshCoP
} // namespace ot
diff --git a/src/core/meshcop/timestamp.hpp b/src/core/meshcop/timestamp.hpp
index 4149cd6..b8888b9 100644
--- a/src/core/meshcop/timestamp.hpp
+++ b/src/core/meshcop/timestamp.hpp
@@ -42,6 +42,7 @@
#include <openthread/platform/toolchain.h>
#include "common/encoding.hpp"
+#include "common/random.hpp"
namespace ot {
namespace MeshCoP {
@@ -137,11 +138,18 @@
((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask));
}
+ /**
+ * This method increments the timestamp by a random number of ticks [0, 32767].
+ *
+ */
+ void AdvanceRandomTicks(void);
+
private:
enum
{
kTicksOffset = 1,
kTicksMask = 0x7fff << kTicksOffset,
+ kMaxRandomTicks = 0x7fff,
kAuthoritativeOffset = 0,
kAuthoritativeMask = 1 << kAuthoritativeOffset,
};
diff --git a/src/core/net/checksum.cpp b/src/core/net/checksum.cpp
index 8dfa694..db600e6 100644
--- a/src/core/net/checksum.cpp
+++ b/src/core/net/checksum.cpp
@@ -114,13 +114,13 @@
}
}
-otError Checksum::VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto)
+Error Checksum::VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto)
{
Checksum checksum;
checksum.Calculate(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), aIpProto, aMessage);
- return (checksum.GetValue() == kValidRxChecksum) ? OT_ERROR_NONE : OT_ERROR_DROP;
+ return (checksum.GetValue() == kValidRxChecksum) ? kErrorNone : kErrorDrop;
}
void Checksum::UpdateMessageChecksum(Message & aMessage,
diff --git a/src/core/net/checksum.hpp b/src/core/net/checksum.hpp
index f61cbaf..fa8e1ae 100644
--- a/src/core/net/checksum.hpp
+++ b/src/core/net/checksum.hpp
@@ -62,13 +62,11 @@
* @param[in] aMessageInfo The message info associated with @p aMessage.
* @param[in] aIpProto The Internet Protocol value.
*
- * @retval OT_ERROR_NONE The checksum is valid if UDP/ICMP6 protocol, or not a UDP/ICMP6 protocol.
- * @retval OT_ERROR_DROP The check is not valid and message should be dropped.
+ * @retval kErrorNone The checksum is valid if UDP/ICMP6 protocol, or not a UDP/ICMP6 protocol.
+ * @retval kErrorDrop The check is not valid and message should be dropped.
*
*/
- static otError VerifyMessageChecksum(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- uint8_t aIpProto);
+ static Error VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto);
/**
* This static method calculates and then updates the checksum in a given message (if UDP/ICMP6).
diff --git a/src/core/net/dhcp6.hpp b/src/core/net/dhcp6.hpp
index 4988e58..ac4bf82 100644
--- a/src/core/net/dhcp6.hpp
+++ b/src/core/net/dhcp6.hpp
@@ -112,11 +112,11 @@
/**
* This method generates a cryptographically secure random sequence to populate the transaction identifier.
*
- * @retval OT_ERROR_NONE Successfully generated a random transaction identifier.
- * @retval OT_ERROR_FAILED Failed to generate random sequence.
+ * @retval kErrorNone Successfully generated a random transaction identifier.
+ * @retval kErrorFailed Failed to generate random sequence.
*
*/
- otError GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, kSize); }
+ Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, kSize); }
private:
uint8_t m8[kSize];
diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp
index 6fe9c83..4a61703 100644
--- a/src/core/net/dhcp6_client.cpp
+++ b/src/core/net/dhcp6_client.cpp
@@ -50,7 +50,7 @@
Client::Client(Instance &aInstance)
: InstanceLocator(aInstance)
, mSocket(aInstance)
- , mTrickleTimer(aInstance, Client::HandleTrickleTimer, nullptr, this)
+ , mTrickleTimer(aInstance, Client::HandleTrickleTimer)
, mStartTime(0)
, mIdentityAssociationCurrent(nullptr)
{
@@ -80,7 +80,7 @@
found = false;
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
if (!config.mDhcp)
{
@@ -104,7 +104,7 @@
// add IdentityAssociation for new configured prefix
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
IdentityAssociation *idAssociation = nullptr;
@@ -178,6 +178,7 @@
void Client::Stop(void)
{
+ mTrickleTimer.Stop();
IgnoreError(mSocket.Close());
}
@@ -202,8 +203,8 @@
mIdentityAssociationCurrent = &idAssociation;
- mTrickleTimer.Start(Time::SecToMsec(kTrickleTimerImin), Time::SecToMsec(kTrickleTimerImax),
- TrickleTimer::kModeNormal);
+ mTrickleTimer.Start(TrickleTimer::kModeTrickle, Time::SecToMsec(kTrickleTimerImin),
+ Time::SecToMsec(kTrickleTimerImax));
mTrickleTimer.IndicateInconsistent();
@@ -214,16 +215,16 @@
return rval;
}
-bool Client::HandleTrickleTimer(TrickleTimer &aTrickleTimer)
+void Client::HandleTrickleTimer(TrickleTimer &aTrickleTimer)
{
- return aTrickleTimer.GetOwner<Client>().HandleTrickleTimer();
+ aTrickleTimer.Get<Client>().HandleTrickleTimer();
}
-bool Client::HandleTrickleTimer(void)
+void Client::HandleTrickleTimer(void)
{
- bool rval = true;
+ OT_ASSERT(mSocket.IsBound());
- VerifyOrExit(mIdentityAssociationCurrent != nullptr, rval = false);
+ VerifyOrExit(mIdentityAssociationCurrent != nullptr, mTrickleTimer.Stop());
switch (mIdentityAssociationCurrent->mStatus)
{
@@ -231,7 +232,7 @@
mStartTime = TimerMilli::GetNow();
mIdentityAssociationCurrent->mStatus = kIaStatusSoliciting;
- // fall through
+ OT_FALL_THROUGH;
case kIaStatusSoliciting:
Solicit(mIdentityAssociationCurrent->mPrefixAgentRloc);
@@ -242,9 +243,8 @@
if (!ProcessNextIdentityAssociation())
{
- mTrickleTimer.Stop();
Stop();
- rval = false;
+ mTrickleTimer.Stop();
}
break;
@@ -254,16 +254,16 @@
}
exit:
- return rval;
+ return;
}
void Client::Solicit(uint16_t aRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message));
SuccessOrExit(error = AppendElapsedTime(*message));
@@ -285,14 +285,14 @@
otLogInfoIp6("solicit");
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeMessage(message);
- otLogWarnIp6("Failed to send DHCPv6 Solicit: %s", otThreadErrorToString(error));
+ otLogWarnIp6("Failed to send DHCPv6 Solicit: %s", ErrorToString(error));
}
}
-otError Client::AppendHeader(Message &aMessage)
+Error Client::AppendHeader(Message &aMessage)
{
Header header;
@@ -302,7 +302,7 @@
return aMessage.Append(header);
}
-otError Client::AppendElapsedTime(Message &aMessage)
+Error Client::AppendElapsedTime(Message &aMessage)
{
ElapsedTime option;
@@ -311,7 +311,7 @@
return aMessage.Append(option);
}
-otError Client::AppendClientIdentifier(Message &aMessage)
+Error Client::AppendClientIdentifier(Message &aMessage)
{
ClientIdentifier option;
Mac::ExtAddress eui64;
@@ -326,14 +326,14 @@
return aMessage.Append(option);
}
-otError Client::AppendIaNa(Message &aMessage, uint16_t aRloc16)
+Error Client::AppendIaNa(Message &aMessage, uint16_t aRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t count = 0;
uint16_t length = 0;
IaNa option;
- VerifyOrExit(mIdentityAssociationCurrent != nullptr, error = OT_ERROR_DROP);
+ VerifyOrExit(mIdentityAssociationCurrent != nullptr, error = kErrorDrop);
for (IdentityAssociation &idAssociation : mIdentityAssociations)
{
@@ -362,12 +362,12 @@
return error;
}
-otError Client::AppendIaAddress(Message &aMessage, uint16_t aRloc16)
+Error Client::AppendIaAddress(Message &aMessage, uint16_t aRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
IaAddress option;
- VerifyOrExit(mIdentityAssociationCurrent, error = OT_ERROR_DROP);
+ VerifyOrExit(mIdentityAssociationCurrent, error = kErrorDrop);
option.Init();
@@ -387,7 +387,7 @@
return error;
}
-otError Client::AppendRapidCommit(Message &aMessage)
+Error Client::AppendRapidCommit(Message &aMessage)
{
RapidCommit option;
@@ -475,9 +475,9 @@
return rval;
}
-otError Client::ProcessServerIdentifier(Message &aMessage, uint16_t aOffset)
+Error Client::ProcessServerIdentifier(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServerIdentifier option;
SuccessOrExit(aMessage.Read(aOffset, option));
@@ -486,14 +486,14 @@
((option.GetLength() == (sizeof(option) - sizeof(Option))) &&
(option.GetDuidType() == kDuidLinkLayerAddress) &&
(option.GetDuidHardwareType() == kHardwareTypeEui64)),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
exit:
return error;
}
-otError Client::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset)
+Error Client::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ClientIdentifier option;
Mac::ExtAddress eui64;
@@ -503,14 +503,14 @@
VerifyOrExit(
(option.GetLength() == (sizeof(option) - sizeof(Option))) && (option.GetDuidType() == kDuidLinkLayerAddress) &&
(option.GetDuidHardwareType() == kHardwareTypeEui64) && (option.GetDuidLinkLayerAddress() == eui64),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
exit:
return error;
}
-otError Client::ProcessIaNa(Message &aMessage, uint16_t aOffset)
+Error Client::ProcessIaNa(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
IaNa option;
uint16_t optionOffset;
uint16_t length;
@@ -520,7 +520,7 @@
aOffset += sizeof(option);
length = option.GetLength() - (sizeof(option) - sizeof(Option));
- VerifyOrExit(length <= aMessage.GetLength() - aOffset, error = OT_ERROR_PARSE);
+ VerifyOrExit(length <= aMessage.GetLength() - aOffset, error = kErrorParse);
if ((optionOffset = FindOption(aMessage, aOffset, length, kOptionStatusCode)) > 0)
{
@@ -544,26 +544,26 @@
return error;
}
-otError Client::ProcessStatusCode(Message &aMessage, uint16_t aOffset)
+Error Client::ProcessStatusCode(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
StatusCode option;
SuccessOrExit(error = aMessage.Read(aOffset, option));
VerifyOrExit((option.GetLength() >= sizeof(option) - sizeof(Option)) && (option.GetStatusCode() == kStatusSuccess),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
exit:
return error;
}
-otError Client::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
+Error Client::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
{
- otError error;
+ Error error;
IaAddress option;
SuccessOrExit(error = aMessage.Read(aOffset, option));
- VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = OT_ERROR_PARSE);
+ VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = kErrorParse);
for (IdentityAssociation &idAssociation : mIdentityAssociations)
{
@@ -583,11 +583,11 @@
idAssociation.mNetifAddress.mValid = option.GetValidLifetime() != 0;
idAssociation.mStatus = kIaStatusSolicitReplied;
Get<ThreadNetif>().AddUnicastAddress(idAssociation.mNetifAddress);
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
- error = OT_ERROR_NOT_FOUND;
+ error = kErrorNotFound;
exit:
return error;
diff --git a/src/core/net/dhcp6_client.hpp b/src/core/net/dhcp6_client.hpp
index 0f40b8e..cb29880 100644
--- a/src/core/net/dhcp6_client.hpp
+++ b/src/core/net/dhcp6_client.hpp
@@ -51,6 +51,8 @@
namespace Dhcp6 {
+#if OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+
/**
* @addtogroup core-dhcp6
*
@@ -120,26 +122,26 @@
bool ProcessNextIdentityAssociation(void);
- otError AppendHeader(Message &aMessage);
- otError AppendClientIdentifier(Message &aMessage);
- otError AppendIaNa(Message &aMessage, uint16_t aRloc16);
- otError AppendIaAddress(Message &aMessage, uint16_t aRloc16);
- otError AppendElapsedTime(Message &aMessage);
- otError AppendRapidCommit(Message &aMessage);
+ Error AppendHeader(Message &aMessage);
+ Error AppendClientIdentifier(Message &aMessage);
+ Error AppendIaNa(Message &aMessage, uint16_t aRloc16);
+ Error AppendIaAddress(Message &aMessage, uint16_t aRloc16);
+ Error AppendElapsedTime(Message &aMessage);
+ Error AppendRapidCommit(Message &aMessage);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReply(Message &aMessage);
uint16_t FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode);
- otError ProcessServerIdentifier(Message &aMessage, uint16_t aOffset);
- otError ProcessClientIdentifier(Message &aMessage, uint16_t aOffset);
- otError ProcessIaNa(Message &aMessage, uint16_t aOffset);
- otError ProcessStatusCode(Message &aMessage, uint16_t aOffset);
- otError ProcessIaAddress(Message &aMessage, uint16_t aOffset);
+ Error ProcessServerIdentifier(Message &aMessage, uint16_t aOffset);
+ Error ProcessClientIdentifier(Message &aMessage, uint16_t aOffset);
+ Error ProcessIaNa(Message &aMessage, uint16_t aOffset);
+ Error ProcessStatusCode(Message &aMessage, uint16_t aOffset);
+ Error ProcessIaAddress(Message &aMessage, uint16_t aOffset);
- static bool HandleTrickleTimer(TrickleTimer &aTrickleTimer);
- bool HandleTrickleTimer(void);
+ static void HandleTrickleTimer(TrickleTimer &aTrickleTimer);
+ void HandleTrickleTimer(void);
Ip6::Udp::Socket mSocket;
@@ -152,6 +154,19 @@
IdentityAssociation *mIdentityAssociationCurrent;
};
+/**
+ * @}
+ *
+ */
+
+#else // OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+
+#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT
+#error "OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT requires OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE to be also set."
+#endif
+
+#endif // OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
+
} // namespace Dhcp6
} // namespace ot
diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp
index 1d24c97..f441ada 100644
--- a/src/core/net/dhcp6_server.cpp
+++ b/src/core/net/dhcp6_server.cpp
@@ -55,9 +55,9 @@
memset(mPrefixAgents, 0, sizeof(mPrefixAgents));
}
-otError Server::UpdateService(void)
+Error Server::UpdateService(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
NetworkData::Iterator iterator;
NetworkData::OnMeshPrefixConfig config;
@@ -75,7 +75,7 @@
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == kErrorNone)
{
if (!config.mDhcp)
{
@@ -84,7 +84,7 @@
error = Get<NetworkData::Leader>().GetContext(prefixAgent.GetPrefixAsAddress(), lowpanContext);
- if ((error == OT_ERROR_NONE) && (prefixAgent.GetContextId() == lowpanContext.mContextId))
+ if ((error == kErrorNone) && (prefixAgent.GetContextId() == lowpanContext.mContextId))
{
// still in network data
found = true;
@@ -102,7 +102,7 @@
// add dhcp agent aloc and prefix delegation
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, rloc16, config) == kErrorNone)
{
if (!config.mDhcp)
{
@@ -112,7 +112,7 @@
error = Get<NetworkData::Leader>().GetContext(static_cast<const Ip6::Address &>(config.mPrefix.mPrefix),
lowpanContext);
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
AddPrefixAgent(config.GetPrefix(), lowpanContext);
}
@@ -143,7 +143,7 @@
void Server::AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
PrefixAgent *newEntry = nullptr;
for (PrefixAgent &prefixAgent : mPrefixAgents)
@@ -159,7 +159,7 @@
}
}
- VerifyOrExit(newEntry != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(newEntry != nullptr, error = kErrorNoBufs);
newEntry->Set(aIp6Prefix, Get<Mle::MleRouter>().GetMeshLocalPrefix(), aContext.mContextId);
Get<ThreadNetif>().AddUnicastAddress(newEntry->GetAloc());
@@ -167,9 +167,9 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogNoteIp6("Failed to add DHCPv6 prefix agent: %s", otThreadErrorToString(error));
+ otLogNoteIp6("Failed to add DHCPv6 prefix agent: %s", ErrorToString(error));
}
}
@@ -251,33 +251,33 @@
exit:
return rval;
}
-otError Server::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClientId)
+Error Server::ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClientId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = aMessage.Read(aOffset, aClientId));
VerifyOrExit((aClientId.GetLength() == sizeof(aClientId) - sizeof(Option)) &&
(aClientId.GetDuidType() == kDuidLinkLayerAddress) &&
(aClientId.GetDuidHardwareType() == kHardwareTypeEui64),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
exit:
return error;
}
-otError Server::ProcessElapsedTime(Message &aMessage, uint16_t aOffset)
+Error Server::ProcessElapsedTime(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ElapsedTime option;
SuccessOrExit(error = aMessage.Read(aOffset, option));
- VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = OT_ERROR_PARSE);
+ VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = kErrorParse);
exit:
return error;
}
-otError Server::ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa)
+Error Server::ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t optionOffset;
uint16_t length;
@@ -286,7 +286,7 @@
aOffset += sizeof(aIaNa);
length = aIaNa.GetLength() + sizeof(Option) - sizeof(IaNa);
- VerifyOrExit(length <= aMessage.GetLength() - aOffset, error = OT_ERROR_PARSE);
+ VerifyOrExit(length <= aMessage.GetLength() - aOffset, error = kErrorParse);
mPrefixAgentsMask = 0;
@@ -303,13 +303,13 @@
return error;
}
-otError Server::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
+Error Server::ProcessIaAddress(Message &aMessage, uint16_t aOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
IaAddress option;
SuccessOrExit(error = aMessage.Read(aOffset, option));
- VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = OT_ERROR_PARSE);
+ VerifyOrExit(option.GetLength() == sizeof(option) - sizeof(Option), error = kErrorParse);
// mask matching prefix
for (uint16_t i = 0; i < OT_ARRAY_LENGTH(mPrefixAgents); i++)
@@ -325,16 +325,16 @@
return error;
}
-otError Server::SendReply(const Ip6::Address & aDst,
- const TransactionId &aTransactionId,
- ClientIdentifier & aClientId,
- IaNa & aIaNa)
+Error Server::SendReply(const Ip6::Address & aDst,
+ const TransactionId &aTransactionId,
+ ClientIdentifier & aClientId,
+ IaNa & aIaNa)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::MessageInfo messageInfo;
Message * message;
- VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, aTransactionId));
SuccessOrExit(error = AppendServerIdentifier(*message));
SuccessOrExit(error = AppendClientIdentifier(*message, aClientId));
@@ -352,7 +352,7 @@
return error;
}
-otError Server::AppendHeader(Message &aMessage, const TransactionId &aTransactionId)
+Error Server::AppendHeader(Message &aMessage, const TransactionId &aTransactionId)
{
Header header;
@@ -362,14 +362,14 @@
return aMessage.Append(header);
}
-otError Server::AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClientId)
+Error Server::AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClientId)
{
return aMessage.Append(aClientId);
}
-otError Server::AppendServerIdentifier(Message &aMessage)
+Error Server::AppendServerIdentifier(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServerIdentifier option;
Mac::ExtAddress eui64;
@@ -385,9 +385,9 @@
return error;
}
-otError Server::AppendIaNa(Message &aMessage, IaNa &aIaNa)
+Error Server::AppendIaNa(Message &aMessage, IaNa &aIaNa)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t length = 0;
if (mPrefixAgentsMask)
@@ -416,7 +416,7 @@
return error;
}
-otError Server::AppendStatusCode(Message &aMessage, Status aStatusCode)
+Error Server::AppendStatusCode(Message &aMessage, Status aStatusCode)
{
StatusCode option;
@@ -425,9 +425,9 @@
return aMessage.Append(option);
}
-otError Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId)
+Error Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (mPrefixAgentsMask)
{
@@ -456,9 +456,9 @@
return error;
}
-otError Server::AddIaAddress(Message &aMessage, const Ip6::Address &aPrefix, ClientIdentifier &aClientId)
+Error Server::AddIaAddress(Message &aMessage, const Ip6::Address &aPrefix, ClientIdentifier &aClientId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
IaAddress option;
option.Init();
@@ -472,7 +472,7 @@
return error;
}
-otError Server::AppendRapidCommit(Message &aMessage)
+Error Server::AppendRapidCommit(Message &aMessage)
{
RapidCommit option;
diff --git a/src/core/net/dhcp6_server.hpp b/src/core/net/dhcp6_server.hpp
index 0890633..e8f36ea 100644
--- a/src/core/net/dhcp6_server.hpp
+++ b/src/core/net/dhcp6_server.hpp
@@ -45,9 +45,14 @@
#include "thread/network_data_leader.hpp"
namespace ot {
-
namespace Dhcp6 {
+#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
+
+#if OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT
+#error "OPENTHREAD_ENABLE_DHCP6_MULTICAST_SOLICIT requires DHCPv6 server on Border Router side to be enabled."
+#endif
+
/**
* @addtogroup core-dhcp6
*
@@ -73,7 +78,7 @@
* This method updates DHCP Agents and DHCP Alocs.
*
*/
- otError UpdateService(void);
+ Error UpdateService(void);
/**
* This method applies the Mesh Local Prefix.
@@ -185,16 +190,16 @@
void AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext);
- otError AppendHeader(Message &aMessage, const TransactionId &aTransactionId);
- otError AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClientId);
- otError AppendServerIdentifier(Message &aMessage);
- otError AppendIaNa(Message &aMessage, IaNa &aIaNa);
- otError AppendStatusCode(Message &aMessage, Status aStatusCode);
- otError AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId);
- otError AppendRapidCommit(Message &aMessage);
- otError AppendVendorSpecificInformation(Message &aMessage);
+ Error AppendHeader(Message &aMessage, const TransactionId &aTransactionId);
+ Error AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClientId);
+ Error AppendServerIdentifier(Message &aMessage);
+ Error AppendIaNa(Message &aMessage, IaNa &aIaNa);
+ Error AppendStatusCode(Message &aMessage, Status aStatusCode);
+ Error AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId);
+ Error AppendRapidCommit(Message &aMessage);
+ Error AppendVendorSpecificInformation(Message &aMessage);
- otError AddIaAddress(Message &aMessage, const Ip6::Address &aPrefix, ClientIdentifier &aClientId);
+ Error AddIaAddress(Message &aMessage, const Ip6::Address &aPrefix, ClientIdentifier &aClientId);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
@@ -202,15 +207,15 @@
void ProcessSolicit(Message &aMessage, const Ip6::Address &aDst, const TransactionId &aTransactionId);
uint16_t FindOption(Message &aMessage, uint16_t aOffset, uint16_t aLength, Code aCode);
- otError ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClientId);
- otError ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa);
- otError ProcessIaAddress(Message &aMessage, uint16_t aOffset);
- otError ProcessElapsedTime(Message &aMessage, uint16_t aOffset);
+ Error ProcessClientIdentifier(Message &aMessage, uint16_t aOffset, ClientIdentifier &aClientId);
+ Error ProcessIaNa(Message &aMessage, uint16_t aOffset, IaNa &aIaNa);
+ Error ProcessIaAddress(Message &aMessage, uint16_t aOffset);
+ Error ProcessElapsedTime(Message &aMessage, uint16_t aOffset);
- otError SendReply(const Ip6::Address & aDst,
- const TransactionId &aTransactionId,
- ClientIdentifier & aClientId,
- IaNa & aIaNa);
+ Error SendReply(const Ip6::Address & aDst,
+ const TransactionId &aTransactionId,
+ ClientIdentifier & aClientId,
+ IaNa & aIaNa);
Ip6::Udp::Socket mSocket;
@@ -219,6 +224,13 @@
uint8_t mPrefixAgentsMask;
};
+/**
+ * @}
+ *
+ */
+
+#endif // OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
+
} // namespace Dhcp6
} // namespace ot
diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp
index c59fc9b..769314e 100644
--- a/src/core/net/dns_client.cpp
+++ b/src/core/net/dns_client.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2017-2021, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,20 +43,411 @@
* This file implements the DNS client.
*/
-using ot::Encoding::BigEndian::HostSwap16;
-
namespace ot {
namespace Dns {
-Client::Client(Instance &aInstance)
- : mSocket(aInstance)
- , mRetransmissionTimer(aInstance, Client::HandleRetransmissionTimer, this)
+//---------------------------------------------------------------------------------------------------------------------
+// Client::QueryConfig
+
+const char Client::QueryConfig::kDefaultServerAddressString[] = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS;
+
+Client::QueryConfig::QueryConfig(InitMode aMode)
{
+ OT_UNUSED_VARIABLE(aMode);
+
+ IgnoreError(GetServerSockAddr().GetAddress().FromString(kDefaultServerAddressString));
+ GetServerSockAddr().SetPort(kDefaultServerPort);
+ SetResponseTimeout(kDefaultResponseTimeout);
+ SetMaxTxAttempts(kDefaultMaxTxAttempts);
+ SetRecursionFlag(kDefaultRecursionDesired ? kFlagRecursionDesired : kFlagNoRecursion);
}
-otError Client::Start(void)
+void Client::QueryConfig::SetFrom(const QueryConfig &aConfig, const QueryConfig &aDefaultConfig)
{
- otError error;
+ // This method sets the config from `aConfig` replacing any
+ // unspecified fields (value zero) with the fields from
+ // `aDefaultConfig`.
+
+ *this = aConfig;
+
+ if (GetServerSockAddr().GetAddress().IsUnspecified())
+ {
+ GetServerSockAddr().GetAddress() = aDefaultConfig.GetServerSockAddr().GetAddress();
+ }
+
+ if (GetServerSockAddr().GetPort() == 0)
+ {
+ GetServerSockAddr().SetPort(aDefaultConfig.GetServerSockAddr().GetPort());
+ }
+
+ if (GetResponseTimeout() == 0)
+ {
+ SetResponseTimeout(aDefaultConfig.GetResponseTimeout());
+ }
+
+ if (GetMaxTxAttempts() == 0)
+ {
+ SetMaxTxAttempts(aDefaultConfig.GetMaxTxAttempts());
+ }
+
+ if (GetRecursionFlag() == kFlagUnspecified)
+ {
+ SetRecursionFlag(aDefaultConfig.GetRecursionFlag());
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// Client::Response
+
+void Client::Response::SelectSection(Section aSection, uint16_t &aOffset, uint16_t &aNumRecord) const
+{
+ switch (aSection)
+ {
+ case kAnswerSection:
+ aOffset = mAnswerOffset;
+ aNumRecord = mAnswerRecordCount;
+ break;
+ case kAdditionalDataSection:
+ default:
+ aOffset = mAdditionalOffset;
+ aNumRecord = mAdditionalRecordCount;
+ break;
+ }
+}
+
+Error Client::Response::GetName(char *aNameBuffer, uint16_t aNameBufferSize) const
+{
+ uint16_t offset = kNameOffsetInQuery;
+
+ return Name::ReadName(*mQuery, offset, aNameBuffer, aNameBufferSize);
+}
+
+Error Client::Response::FindHostAddress(Section aSection,
+ const Name & aHostName,
+ uint16_t aIndex,
+ Ip6::Address &aAddress,
+ uint32_t & aTtl) const
+{
+ Error error;
+ uint16_t offset;
+ uint16_t numRecords;
+ Name name = aHostName;
+ CnameRecord cnameRecord;
+ AaaaRecord aaaaRecord;
+
+ VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
+
+ // If the response includes a CNAME record mapping the query host
+ // name to a canonical name, we then search for AAAA records
+ // matching the canonical name.
+
+ SelectSection(aSection, offset, numRecords);
+ error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aHostName, cnameRecord);
+
+ if (error == kErrorNone)
+ {
+ name.SetFromMessage(*mMessage, offset);
+ SuccessOrExit(error = Name::ParseName(*mMessage, offset));
+ }
+ else
+ {
+ VerifyOrExit(error == kErrorNotFound);
+ }
+
+ SelectSection(aSection, offset, numRecords);
+ SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, aIndex, name, aaaaRecord));
+ aAddress = aaaaRecord.GetAddress();
+ aTtl = aaaaRecord.GetTtl();
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+Error Client::Response::FindServiceInfo(Section aSection, const Name &aName, ServiceInfo &aServiceInfo) const
+{
+ // This method searches for SRV and TXT records in the given
+ // section matching the record name against `aName`, and updates
+ // the `aServiceInfo` accordingly. It also searches for AAAA
+ // record for host name associated with the service (from SRV
+ // record). The search for AAAA record is always performed in
+ // Additional Data section (independent of the value given in
+ // `aSection`).
+
+ Error error;
+ uint16_t offset;
+ uint16_t numRecords;
+ Name hostName;
+ SrvRecord srvRecord;
+ TxtRecord txtRecord;
+
+ VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
+
+ // Search for a matching SRV record
+ SelectSection(aSection, offset, numRecords);
+ SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aName, srvRecord));
+
+ aServiceInfo.mTtl = srvRecord.GetTtl();
+ aServiceInfo.mPort = srvRecord.GetPort();
+ aServiceInfo.mPriority = srvRecord.GetPriority();
+ aServiceInfo.mWeight = srvRecord.GetWeight();
+
+ hostName.SetFromMessage(*mMessage, offset);
+
+ if (aServiceInfo.mHostNameBuffer != nullptr)
+ {
+ SuccessOrExit(error = srvRecord.ReadTargetHostName(*mMessage, offset, aServiceInfo.mHostNameBuffer,
+ aServiceInfo.mHostNameBufferSize));
+ }
+ else
+ {
+ SuccessOrExit(error = Name::ParseName(*mMessage, offset));
+ }
+
+ // Search in additional section for AAAA record for the host name.
+
+ error = FindHostAddress(kAdditionalDataSection, hostName, /* aIndex */ 0,
+ static_cast<Ip6::Address &>(aServiceInfo.mHostAddress), aServiceInfo.mHostAddressTtl);
+
+ if (error == kErrorNotFound)
+ {
+ static_cast<Ip6::Address &>(aServiceInfo.mHostAddress).Clear();
+ aServiceInfo.mHostAddressTtl = 0;
+ }
+ else
+ {
+ SuccessOrExit(error);
+ }
+
+ // A null `mTxtData` indicates that caller does not want to retrieve TXT data.
+ VerifyOrExit(aServiceInfo.mTxtData != nullptr);
+
+ // Search for a matching TXT record. If not found, indicate this by
+ // setting `aServiceInfo.mTxtDataSize` to zero.
+
+ SelectSection(aSection, offset, numRecords);
+ error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, /* aIndex */ 0, aName, txtRecord);
+
+ switch (error)
+ {
+ case kErrorNone:
+ SuccessOrExit(error =
+ txtRecord.ReadTxtData(*mMessage, offset, aServiceInfo.mTxtData, aServiceInfo.mTxtDataSize));
+ aServiceInfo.mTxtDataTtl = txtRecord.GetTtl();
+ break;
+
+ case kErrorNotFound:
+ aServiceInfo.mTxtDataSize = 0;
+ aServiceInfo.mTxtDataTtl = 0;
+ break;
+
+ default:
+ ExitNow();
+ }
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+//---------------------------------------------------------------------------------------------------------------------
+// Client::AddressResponse
+
+Error Client::AddressResponse::GetAddress(uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const
+{
+ return FindHostAddress(kAnswerSection, Name(*mQuery, kNameOffsetInQuery), aIndex, aAddress, aTtl);
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+//---------------------------------------------------------------------------------------------------------------------
+// Client::BrowseResponse
+
+Error Client::BrowseResponse::GetServiceInstance(uint16_t aIndex, char *aLabelBuffer, uint8_t aLabelBufferSize) const
+{
+ Error error;
+ uint16_t offset;
+ uint16_t numRecords;
+ Name serviceName(*mQuery, kNameOffsetInQuery);
+ PtrRecord ptrRecord;
+
+ VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
+
+ SelectSection(kAnswerSection, offset, numRecords);
+ SuccessOrExit(error = ResourceRecord::FindRecord(*mMessage, offset, numRecords, aIndex, serviceName, ptrRecord));
+ error = ptrRecord.ReadPtrName(*mMessage, offset, aLabelBuffer, aLabelBufferSize, nullptr, 0);
+
+exit:
+ return error;
+}
+
+Error Client::BrowseResponse::GetServiceInfo(const char *aInstanceLabel, ServiceInfo &aServiceInfo) const
+{
+ Error error;
+ Name instanceName;
+
+ // Find a matching PTR record for the service instance label.
+ // Then search and read SRV, TXT and AAAA records in Additional Data section
+ // matching the same name to populate `aServiceInfo`.
+
+ SuccessOrExit(error = FindPtrRecord(aInstanceLabel, instanceName));
+ error = FindServiceInfo(kAdditionalDataSection, instanceName, aServiceInfo);
+
+exit:
+ return error;
+}
+
+Error Client::BrowseResponse::GetHostAddress(const char * aHostName,
+ uint16_t aIndex,
+ Ip6::Address &aAddress,
+ uint32_t & aTtl) const
+{
+ return FindHostAddress(kAdditionalDataSection, Name(aHostName), aIndex, aAddress, aTtl);
+}
+
+Error Client::BrowseResponse::FindPtrRecord(const char *aInstanceLabel, Name &aInstanceName) const
+{
+ // This method searches within the Answer Section for a PTR record
+ // matching a given instance label @aInstanceLabel. If found, the
+ // `aName` is updated to return the name in the message.
+
+ Error error;
+ uint16_t offset;
+ Name serviceName(*mQuery, kNameOffsetInQuery);
+ uint16_t numRecords;
+ uint16_t labelOffset;
+ PtrRecord ptrRecord;
+
+ VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
+
+ SelectSection(kAnswerSection, offset, numRecords);
+
+ for (; numRecords > 0; numRecords--)
+ {
+ SuccessOrExit(error = Name::CompareName(*mMessage, offset, serviceName));
+
+ error = ResourceRecord::ReadRecord(*mMessage, offset, ptrRecord);
+
+ if (error == kErrorNotFound)
+ {
+ // `ReadRecord()` updates `offset` to skip over a
+ // non-matching record.
+ continue;
+ }
+
+ SuccessOrExit(error);
+
+ // It is a PTR record. Check the first label to match the
+ // instance label and the rest of the name to match the service
+ // name from `mQuery`.
+
+ labelOffset = offset;
+ error = Name::CompareLabel(*mMessage, labelOffset, aInstanceLabel);
+
+ if (error == kErrorNone)
+ {
+ error = Name::CompareName(*mMessage, labelOffset, serviceName);
+
+ if (error == kErrorNone)
+ {
+ aInstanceName.SetFromMessage(*mMessage, offset);
+ ExitNow();
+ }
+ }
+
+ VerifyOrExit(error == kErrorNotFound);
+
+ // Update offset to skip over the PTR record.
+ offset += static_cast<uint16_t>(ptrRecord.GetSize()) - sizeof(ptrRecord);
+ }
+
+ error = kErrorNotFound;
+
+exit:
+ return error;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// Client::ServiceResponse
+
+Error Client::ServiceResponse::GetServiceName(char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const
+{
+ Error error;
+ uint16_t offset = kNameOffsetInQuery;
+
+ SuccessOrExit(error = Name::ReadLabel(*mQuery, offset, aLabelBuffer, aLabelBufferSize));
+
+ VerifyOrExit(aNameBuffer != nullptr);
+ SuccessOrExit(error = Name::ReadName(*mQuery, offset, aNameBuffer, aNameBufferSize));
+
+exit:
+ return error;
+}
+
+Error Client::ServiceResponse::GetServiceInfo(ServiceInfo &aServiceInfo) const
+{
+ // Search and read SRV, TXT records in Answer Section
+ // matching name from query.
+
+ return FindServiceInfo(kAnswerSection, Name(*mQuery, kNameOffsetInQuery), aServiceInfo);
+}
+
+Error Client::ServiceResponse::GetHostAddress(const char * aHostName,
+ uint16_t aIndex,
+ Ip6::Address &aAddress,
+ uint32_t & aTtl) const
+{
+ return FindHostAddress(kAdditionalDataSection, Name(aHostName), aIndex, aAddress, aTtl);
+}
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+//---------------------------------------------------------------------------------------------------------------------
+// Client
+
+const uint16_t Client::kAddressQueryRecordTypes[] = {ResourceRecord::kTypeAaaa};
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+const uint16_t Client::kBrowseQueryRecordTypes[] = {ResourceRecord::kTypePtr};
+const uint16_t Client::kServiceQueryRecordTypes[] = {ResourceRecord::kTypeSrv, ResourceRecord::kTypeTxt};
+#endif
+
+const uint8_t Client::kQuestionCount[] = {
+ /* (0) kAddressQuery -> */ OT_ARRAY_LENGTH(kAddressQueryRecordTypes), // AAAA records
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ /* (1) kBrowseQuery -> */ OT_ARRAY_LENGTH(kBrowseQueryRecordTypes), // PTR records
+ /* (2) kServiceQuery -> */ OT_ARRAY_LENGTH(kServiceQueryRecordTypes), // SRV and TXT records
+#endif
+};
+
+const uint16_t *Client::kQuestionRecordTypes[] = {
+ /* (0) kAddressQuery -> */ kAddressQueryRecordTypes,
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ /* (1) kBrowseQuery -> */ kBrowseQueryRecordTypes,
+ /* (2) kServiceQuery -> */ kServiceQueryRecordTypes,
+#endif
+};
+
+Client::Client(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mSocket(aInstance)
+ , mTimer(aInstance, Client::HandleTimer)
+ , mDefaultConfig(QueryConfig::kInitFromDefaults)
+{
+ static_assert(kAddressQuery == 0, "kAddressQuery value is not correct");
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ static_assert(kBrowseQuery == 1, "kBrowseQuery value is not correct");
+ static_assert(kServiceQuery == 2, "kServiceQuery value is not correct");
+#endif
+}
+
+Error Client::Start(void)
+{
+ Error error;
SuccessOrExit(error = mSocket.Open(&Client::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Bind());
@@ -65,351 +456,442 @@
return error;
}
-otError Client::Stop(void)
+void Client::Stop(void)
{
- Message * message;
- QueryMetadata queryMetadata;
+ Query *query;
- // Remove all pending queries.
- while ((message = mPendingQueries.GetHead()) != nullptr)
+ while ((query = mQueries.GetHead()) != nullptr)
{
- queryMetadata.ReadFrom(*message);
- FinalizeDnsTransaction(*message, queryMetadata, nullptr, 0, OT_ERROR_ABORT);
+ FinalizeQuery(*query, kErrorAbort);
}
- return mSocket.Close();
+ IgnoreError(mSocket.Close());
}
-otError Client::Query(const QueryInfo &aQuery, ResponseHandler aHandler, void *aContext)
+void Client::SetDefaultConfig(const QueryConfig &aQueryConfig)
{
- otError error;
- QueryMetadata queryMetadata;
- Message * message = nullptr;
- Message * messageCopy = nullptr;
- Header header;
- QuestionAaaa question;
- uint16_t messageId;
+ QueryConfig startingDefault(QueryConfig::kInitFromDefaults);
- VerifyOrExit(aQuery.IsValid(), error = OT_ERROR_INVALID_ARGS);
+ mDefaultConfig.SetFrom(aQueryConfig, startingDefault);
+}
- SuccessOrExit(error = GenerateUniqueRandomId(messageId));
+void Client::ResetDefaultConfig(void)
+{
+ mDefaultConfig = QueryConfig(QueryConfig::kInitFromDefaults);
+}
- header.SetMessageId(messageId);
+Error Client::ResolveAddress(const char * aHostName,
+ AddressCallback aCallback,
+ void * aContext,
+ const QueryConfig *aConfig)
+{
+ QueryInfo info;
+
+ info.Clear();
+ info.mQueryType = kAddressQuery;
+ info.mCallback.mAddressCallback = aCallback;
+
+ return StartQuery(info, aConfig, nullptr, aHostName, aContext);
+}
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+Error Client::Browse(const char *aServiceName, BrowseCallback aCallback, void *aContext, const QueryConfig *aConfig)
+{
+ QueryInfo info;
+
+ info.Clear();
+ info.mQueryType = kBrowseQuery;
+ info.mCallback.mBrowseCallback = aCallback;
+
+ return StartQuery(info, aConfig, nullptr, aServiceName, aContext);
+}
+
+Error Client::ResolveService(const char * aInstanceLabel,
+ const char * aServiceName,
+ ServiceCallback aCallback,
+ void * aContext,
+ const QueryConfig *aConfig)
+{
+ QueryInfo info;
+ Error error;
+
+ VerifyOrExit(aInstanceLabel != nullptr, error = kErrorInvalidArgs);
+
+ info.Clear();
+ info.mQueryType = kServiceQuery;
+ info.mCallback.mServiceCallback = aCallback;
+
+ error = StartQuery(info, aConfig, aInstanceLabel, aServiceName, aContext);
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+Error Client::StartQuery(QueryInfo & aInfo,
+ const QueryConfig *aConfig,
+ const char * aLabel,
+ const char * aName,
+ void * aContext)
+{
+ // This method assumes that `mQueryType` and `mCallback` to be
+ // already set by caller on `aInfo`. The `aLabel` can be `nullptr`
+ // and then `aName` provides the full name, otherwise the name is
+ // appended as `{aLabel}.{aName}`.
+
+ Error error;
+ Query *query;
+
+ VerifyOrExit(mSocket.IsBound(), error = kErrorInvalidState);
+
+ if (aConfig == nullptr)
+ {
+ aInfo.mConfig = mDefaultConfig;
+ }
+ else
+ {
+ // To form the config for this query, replace any unspecified
+ // fields (zero value) in the given `aConfig` with the fields
+ // from `mDefaultConfig`.
+
+ aInfo.mConfig.SetFrom(*aConfig, mDefaultConfig);
+ }
+
+ aInfo.mCallbackContext = aContext;
+
+ SuccessOrExit(error = AllocateQuery(aInfo, aLabel, aName, query));
+ mQueries.Enqueue(*query);
+
+ SendQuery(*query);
+
+exit:
+ return error;
+}
+
+Error Client::AllocateQuery(const QueryInfo &aInfo, const char *aLabel, const char *aName, Query *&aQuery)
+{
+ Error error = kErrorNone;
+
+ aQuery = Get<MessagePool>().New(Message::kTypeOther, /* aReserveHeader */ 0);
+ VerifyOrExit(aQuery != nullptr, error = kErrorNoBufs);
+
+ SuccessOrExit(error = aQuery->Append(aInfo));
+
+ if (aLabel != nullptr)
+ {
+ SuccessOrExit(error = Name::AppendLabel(aLabel, *aQuery));
+ }
+
+ SuccessOrExit(error = Name::AppendName(aName, *aQuery));
+
+exit:
+ FreeAndNullMessageOnError(aQuery, error);
+ return error;
+}
+
+void Client::FreeQuery(Query &aQuery)
+{
+ mQueries.Dequeue(aQuery);
+ aQuery.Free();
+}
+
+void Client::SendQuery(Query &aQuery)
+{
+ QueryInfo info;
+
+ info.ReadFrom(aQuery);
+
+ SendQuery(aQuery, info, /* aUpdateTimer */ true);
+}
+
+void Client::SendQuery(Query &aQuery, QueryInfo &aInfo, bool aUpdateTimer)
+{
+ // This method prepares and sends a query message represented by
+ // `aQuery` and `aInfo`. This method updates `aInfo` (e.g., sets
+ // the new `mRetransmissionTime`) and updates it in `aQuery` as
+ // well. `aUpdateTimer` indicates whether the timer should be
+ // updated when query is sent or not (used in the case where timer
+ // is handled by caller).
+
+ Error error = kErrorNone;
+ Message * message = nullptr;
+ Header header;
+ Ip6::MessageInfo messageInfo;
+
+ aInfo.mTransmissionCount++;
+ aInfo.mRetransmissionTime = TimerMilli::GetNow() + aInfo.mConfig.GetResponseTimeout();
+
+ if (aInfo.mMessageId == 0)
+ {
+ do
+ {
+ SuccessOrExit(error = header.SetRandomMessageId());
+ } while ((header.GetMessageId() == 0) || (FindQueryById(header.GetMessageId()) != nullptr));
+
+ aInfo.mMessageId = header.GetMessageId();
+ }
+ else
+ {
+ header.SetMessageId(aInfo.mMessageId);
+ }
+
header.SetType(Header::kTypeQuery);
header.SetQueryType(Header::kQueryTypeStandard);
- if (!aQuery.IsNoRecursion())
+ if (aInfo.mConfig.GetRecursionFlag() == QueryConfig::kFlagRecursionDesired)
{
header.SetRecursionDesiredFlag();
}
- header.SetQuestionCount(1);
+ header.SetQuestionCount(kQuestionCount[aInfo.mQueryType]);
- VerifyOrExit((message = NewMessage(header)) != nullptr, error = OT_ERROR_NO_BUFS);
+ message = mSocket.NewMessage(0);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
- SuccessOrExit(error = Name::AppendName(aQuery.GetHostname(), *message));
- SuccessOrExit(error = question.AppendTo(*message));
+ SuccessOrExit(error = message->Append(header));
- queryMetadata.mHostname = aQuery.GetHostname();
- queryMetadata.mResponseHandler = aHandler;
- queryMetadata.mResponseContext = aContext;
- queryMetadata.mTransmissionTime = TimerMilli::GetNow() + kResponseTimeout;
- queryMetadata.mSourceAddress = aQuery.GetMessageInfo().GetSockAddr();
- queryMetadata.mDestinationAddress = aQuery.GetMessageInfo().GetPeerAddr();
- queryMetadata.mDestinationPort = aQuery.GetMessageInfo().GetPeerPort();
- queryMetadata.mRetransmissionCount = 0;
+ // Prepare the question section.
- VerifyOrExit((messageCopy = CopyAndEnqueueMessage(*message, queryMetadata)) != nullptr, error = OT_ERROR_NO_BUFS);
- SuccessOrExit(error = SendMessage(*message, aQuery.GetMessageInfo()));
+ for (uint8_t num = 0; num < kQuestionCount[aInfo.mQueryType]; num++)
+ {
+ SuccessOrExit(error = AppendNameFromQuery(aQuery, *message));
+ SuccessOrExit(error = message->Append(Question(kQuestionRecordTypes[aInfo.mQueryType][num])));
+ }
+
+ messageInfo.SetPeerAddr(aInfo.mConfig.GetServerSockAddr().GetAddress());
+ messageInfo.SetPeerPort(aInfo.mConfig.GetServerSockAddr().GetPort());
+
+ SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
exit:
+ FreeMessageOnError(message, error);
- if (error != OT_ERROR_NONE)
+ UpdateQuery(aQuery, aInfo);
+
+ if (aUpdateTimer)
{
- FreeMessage(message);
+ mTimer.FireAtIfEarlier(aInfo.mRetransmissionTime);
+ }
+}
- if (messageCopy)
+Error Client::AppendNameFromQuery(const Query &aQuery, Message &aMessage)
+{
+ Error error = kErrorNone;
+ uint16_t offset;
+ uint16_t length;
+
+ // The name is encoded and included after the `Info` in `aQuery`. We
+ // first calculate the encoded length of the name, then grow the
+ // message, and finally copy the encoded name bytes from `aQuery`
+ // into `aMessage`.
+
+ length = aQuery.GetLength() - kNameOffsetInQuery;
+
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.SetLength(offset + length));
+
+ aQuery.CopyTo(/* aSourceOffset */ kNameOffsetInQuery, /* aDestOffset */ offset, length, aMessage);
+
+exit:
+ return error;
+}
+
+void Client::FinalizeQuery(Query &aQuery, Error aError)
+{
+ Response response;
+ QueryInfo info;
+
+ response.mQuery = &aQuery;
+ info.ReadFrom(aQuery);
+
+ FinalizeQuery(response, info.mQueryType, aError);
+}
+
+void Client::FinalizeQuery(Response &aResponse, QueryType aType, Error aError)
+{
+ Callback callback;
+ void * context;
+
+ GetCallback(*aResponse.mQuery, callback, context);
+
+ switch (aType)
+ {
+ case kAddressQuery:
+ if (callback.mAddressCallback != nullptr)
{
- DequeueMessage(*messageCopy);
+ callback.mAddressCallback(aError, &aResponse, context);
}
- }
+ break;
- return error;
-}
-
-Message *Client::NewMessage(const Header &aHeader)
-{
- Message *message = mSocket.NewMessage(sizeof(aHeader));
-
- VerifyOrExit(message != nullptr);
- IgnoreError(message->Prepend(aHeader));
- message->SetOffset(0);
-
-exit:
- return message;
-}
-
-Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata)
-{
- otError error = OT_ERROR_NONE;
- Message *messageCopy = aMessage.Clone();
-
- VerifyOrExit(messageCopy != nullptr, error = OT_ERROR_NO_BUFS);
-
- SuccessOrExit(error = aQueryMetadata.AppendTo(*messageCopy));
- mPendingQueries.Enqueue(*messageCopy);
-
- mRetransmissionTimer.FireAtIfEarlier(aQueryMetadata.mTransmissionTime);
-
-exit:
- FreeAndNullMessageOnError(messageCopy, error);
- return messageCopy;
-}
-
-void Client::DequeueMessage(Message &aMessage)
-{
- mPendingQueries.Dequeue(aMessage);
-
- if (mPendingQueries.GetHead() == nullptr)
- {
- mRetransmissionTimer.Stop();
- }
-
- aMessage.Free();
-}
-
-otError Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
-{
- return mSocket.SendTo(aMessage, aMessageInfo);
-}
-
-void Client::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
-{
- otError error;
- Message *messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(QueryMetadata));
-
- VerifyOrExit(messageCopy != nullptr, error = OT_ERROR_NO_BUFS);
-
- error = SendMessage(*messageCopy, aMessageInfo);
-
-exit:
-
- if (error != OT_ERROR_NONE)
- {
- FreeMessage(messageCopy);
- otLogWarnIp6("Failed to send DNS request: %s", otThreadErrorToString(error));
- }
-}
-
-otError Client::GenerateUniqueRandomId(uint16_t &aRandomId)
-{
- otError error;
-
- do
- {
- SuccessOrExit(error = Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&aRandomId), sizeof(aRandomId)));
- } while (FindQueryById(aRandomId) != nullptr);
-
-exit:
- return error;
-}
-
-otError Client::CompareQuestions(Message &aMessageResponse, Message &aMessageQuery, uint16_t &aOffset)
-{
- otError error = OT_ERROR_NONE;
- uint8_t bufQuery[kBufSize];
- uint8_t bufResponse[kBufSize];
- uint16_t read = 0;
-
- // Compare question section of the query with the response.
- uint16_t length = aMessageQuery.GetLength() - aMessageQuery.GetOffset() - sizeof(Header) - sizeof(QueryMetadata);
- uint16_t offset = aMessageQuery.GetOffset() + sizeof(Header);
-
- while (length > 0)
- {
- VerifyOrExit((read = aMessageQuery.ReadBytes(offset, bufQuery,
- length < sizeof(bufQuery) ? length : sizeof(bufQuery))) > 0,
- error = OT_ERROR_PARSE);
- SuccessOrExit(error = aMessageResponse.Read(aOffset, bufResponse, read));
-
- VerifyOrExit(memcmp(bufResponse, bufQuery, read) == 0, error = OT_ERROR_NOT_FOUND);
-
- aOffset += read;
- offset += read;
- length -= read;
- }
-
-exit:
- return error;
-}
-
-Message *Client::FindQueryById(uint16_t aMessageId)
-{
- uint16_t messageId;
- Message *message;
-
- for (message = mPendingQueries.GetHead(); message != nullptr; message = message->GetNext())
- {
- // Partially read DNS header to obtain message ID only.
- if (message->Read(message->GetOffset(), messageId) != OT_ERROR_NONE)
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ case kBrowseQuery:
+ if (callback.mBrowseCallback != nullptr)
{
- OT_ASSERT(false);
+ callback.mBrowseCallback(aError, &aResponse, context);
}
+ break;
- if (HostSwap16(messageId) == aMessageId)
+ case kServiceQuery:
+ if (callback.mServiceCallback != nullptr)
+ {
+ callback.mServiceCallback(aError, &aResponse, context);
+ }
+ break;
+#endif
+ }
+
+ FreeQuery(*aResponse.mQuery);
+}
+
+void Client::GetCallback(const Query &aQuery, Callback &aCallback, void *&aContext)
+{
+ QueryInfo info;
+
+ info.ReadFrom(aQuery);
+
+ aCallback = info.mCallback;
+ aContext = info.mCallbackContext;
+}
+
+Client::Query *Client::FindQueryById(uint16_t aMessageId)
+{
+ Query * query;
+ QueryInfo info;
+
+ for (query = mQueries.GetHead(); query != nullptr; query = query->GetNext())
+ {
+ info.ReadFrom(*query);
+
+ if (info.mMessageId == aMessageId)
{
break;
}
}
- return message;
+ return query;
}
-void Client::FinalizeDnsTransaction(Message & aQuery,
- const QueryMetadata &aQueryMetadata,
- const Ip6::Address * aAddress,
- uint32_t aTtl,
- otError aResult)
+void Client::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo)
{
- DequeueMessage(aQuery);
+ OT_UNUSED_VARIABLE(aMsgInfo);
- if (aQueryMetadata.mResponseHandler != nullptr)
+ static_cast<Client *>(aContext)->ProcessResponse(*static_cast<Message *>(aMessage));
+}
+
+void Client::ProcessResponse(const Message &aMessage)
+{
+ Response response;
+ QueryType type;
+ Error responseError;
+
+ response.mMessage = &aMessage;
+
+ SuccessOrExit(ParseResponse(response, type, responseError));
+ FinalizeQuery(response, type, responseError);
+
+exit:
+ return;
+}
+
+Error Client::ParseResponse(Response &aResponse, QueryType &aType, Error &aResponseError)
+{
+ Error error = kErrorNone;
+ const Message &message = *aResponse.mMessage;
+ uint16_t offset = message.GetOffset();
+ Header header;
+ QueryInfo info;
+
+ SuccessOrExit(error = message.Read(offset, header));
+ offset += sizeof(Header);
+
+ VerifyOrExit((header.GetType() == Header::kTypeResponse) && (header.GetQueryType() == Header::kQueryTypeStandard) &&
+ !header.IsTruncationFlagSet(),
+ error = kErrorDrop);
+
+ aResponse.mQuery = FindQueryById(header.GetMessageId());
+ VerifyOrExit(aResponse.mQuery != nullptr, error = kErrorNotFound);
+
+ info.ReadFrom(*aResponse.mQuery);
+ aType = info.mQueryType;
+
+ // Check the Question Section
+
+ VerifyOrExit(header.GetQuestionCount() == kQuestionCount[aType], error = kErrorParse);
+
+ for (uint8_t num = 0; num < kQuestionCount[aType]; num++)
{
- aQueryMetadata.mResponseHandler(aQueryMetadata.mResponseContext, aQueryMetadata.mHostname, aAddress, aTtl,
- aResult);
+ // The name is encoded after `Info` struct in `query`.
+ SuccessOrExit(error = Name::CompareName(message, offset, *aResponse.mQuery, kNameOffsetInQuery));
+ offset += sizeof(Question);
}
-}
-void Client::HandleRetransmissionTimer(Timer &aTimer)
-{
- aTimer.GetOwner<Client>().HandleRetransmissionTimer();
-}
+ // Check the answer, authority and additional record sections
-void Client::HandleRetransmissionTimer(void)
-{
- TimeMilli now = TimerMilli::GetNow();
- TimeMilli nextTime = now.GetDistantFuture();
- QueryMetadata queryMetadata;
- Message * message;
- Message * nextMessage;
- Ip6::MessageInfo messageInfo;
+ aResponse.mAnswerOffset = offset;
+ SuccessOrExit(error = ResourceRecord::ParseRecords(message, offset, header.GetAnswerCount()));
+ SuccessOrExit(error = ResourceRecord::ParseRecords(message, offset, header.GetAuthorityRecordCount()));
+ aResponse.mAdditionalOffset = offset;
+ SuccessOrExit(error = ResourceRecord::ParseRecords(message, offset, header.GetAdditionalRecordCount()));
- for (message = mPendingQueries.GetHead(); message != nullptr; message = nextMessage)
+ aResponse.mAnswerRecordCount = header.GetAnswerCount();
+ aResponse.mAdditionalRecordCount = header.GetAdditionalRecordCount();
+
+ // Check the response code from server
+
+ aResponseError = Header::ResponseCodeToError(header.GetResponseCode());
+
+exit:
+ if (error != kErrorNone)
{
- nextMessage = message->GetNext();
+ otLogInfoDns("Failed to parse response %s", ErrorToString(error));
+ }
- queryMetadata.ReadFrom(*message);
+ return error;
+}
- if (now >= queryMetadata.mTransmissionTime)
+void Client::HandleTimer(Timer &aTimer)
+{
+ aTimer.Get<Client>().HandleTimer();
+}
+
+void Client::HandleTimer(void)
+{
+ TimeMilli now = TimerMilli::GetNow();
+ TimeMilli nextTime = now.GetDistantFuture();
+ Query * nextQuery;
+ QueryInfo info;
+
+ for (Query *query = mQueries.GetHead(); query != nullptr; query = nextQuery)
+ {
+ nextQuery = query->GetNext();
+
+ info.ReadFrom(*query);
+
+ if (now >= info.mRetransmissionTime)
{
- if (queryMetadata.mRetransmissionCount >= kMaxRetransmit)
+ if (info.mTransmissionCount >= info.mConfig.GetMaxTxAttempts())
{
- FinalizeDnsTransaction(*message, queryMetadata, nullptr, 0, OT_ERROR_RESPONSE_TIMEOUT);
-
+ FinalizeQuery(*query, kErrorResponseTimeout);
continue;
}
- // Increment retransmission counter and timer.
- queryMetadata.mRetransmissionCount++;
- queryMetadata.mTransmissionTime = now + kResponseTimeout;
- queryMetadata.UpdateIn(*message);
-
- // Retransmit
- messageInfo.SetPeerAddr(queryMetadata.mDestinationAddress);
- messageInfo.SetPeerPort(queryMetadata.mDestinationPort);
- messageInfo.SetSockAddr(queryMetadata.mSourceAddress);
-
- SendCopy(*message, messageInfo);
+ SendQuery(*query, info, /* aUpdateTimer */ false);
}
- if (nextTime > queryMetadata.mTransmissionTime)
+ if (nextTime > info.mRetransmissionTime)
{
- nextTime = queryMetadata.mTransmissionTime;
+ nextTime = info.mRetransmissionTime;
}
}
if (nextTime < now.GetDistantFuture())
{
- mRetransmissionTimer.FireAt(nextTime);
+ mTimer.FireAt(nextTime);
}
}
-void Client::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
-{
- static_cast<Client *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
- *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
-}
-
-void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
-{
- // RFC1035 7.3. Resolver cannot rely that a response will come from the same address
- // which it sent the corresponding query to.
- OT_UNUSED_VARIABLE(aMessageInfo);
-
- otError error = OT_ERROR_NOT_FOUND;
- Header responseHeader;
- QueryMetadata queryMetadata;
- ResourceRecordAaaa record;
- Message * message = nullptr;
- uint16_t offset;
-
- SuccessOrExit(aMessage.Read(aMessage.GetOffset(), responseHeader));
- VerifyOrExit(responseHeader.GetType() == Header::kTypeResponse && responseHeader.GetQuestionCount() == 1 &&
- !responseHeader.IsTruncationFlagSet());
-
- aMessage.MoveOffset(sizeof(responseHeader));
- offset = aMessage.GetOffset();
-
- VerifyOrExit((message = FindQueryById(responseHeader.GetMessageId())) != nullptr);
- queryMetadata.ReadFrom(*message);
-
- VerifyOrExit(responseHeader.GetResponseCode() == Header::kResponseSuccess, error = OT_ERROR_FAILED);
-
- // Parse and check the question section.
- SuccessOrExit(error = CompareQuestions(aMessage, *message, offset));
-
- // Parse and check the answer section.
- for (uint32_t index = 0; index < responseHeader.GetAnswerCount(); index++)
- {
- uint32_t newOffset;
-
- SuccessOrExit(error = Name::ParseName(aMessage, offset));
-
- SuccessOrExit(error = aMessage.Read(offset, record));
-
- if (record.Matches(ResourceRecord::kTypeAaaa))
- {
- // Return the first found IPv6 address.
- FinalizeDnsTransaction(*message, queryMetadata, &record.GetAddress(), record.GetTtl(), OT_ERROR_NONE);
- ExitNow(error = OT_ERROR_NONE);
- }
-
- newOffset = offset + record.GetSize();
- VerifyOrExit(newOffset <= aMessage.GetLength(), error = OT_ERROR_PARSE);
- offset = static_cast<uint16_t>(newOffset);
- }
-
-exit:
-
- if (message != nullptr && error != OT_ERROR_NONE)
- {
- FinalizeDnsTransaction(*message, queryMetadata, nullptr, 0, error);
- }
-}
-
-void Client::QueryMetadata::ReadFrom(const Message &aMessage)
-{
- uint16_t length = aMessage.GetLength();
-
- OT_ASSERT(length >= sizeof(*this));
- IgnoreError(aMessage.Read(length - sizeof(*this), *this));
-}
-
-void Client::QueryMetadata::UpdateIn(Message &aMessage) const
-{
- aMessage.Write(aMessage.GetLength() - sizeof(*this), *this);
-}
-
} // namespace Dns
} // namespace ot
diff --git a/src/core/net/dns_client.hpp b/src/core/net/dns_client.hpp
index 656f5c4..23eea18 100644
--- a/src/core/net/dns_client.hpp
+++ b/src/core/net/dns_client.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The OpenThread Authors.
+ * Copyright (c) 2017-2021, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,12 +31,13 @@
#include "openthread-core-config.h"
-#include <openthread/dns.h>
+#include <openthread/dns_client.h>
+#include "common/clearable.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
#include "common/timer.hpp"
-#include "net/dns_headers.hpp"
+#include "net/dns_types.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
@@ -45,6 +46,34 @@
* This file includes definitions for the DNS client.
*/
+/**
+ * This struct represents an opaque (and empty) type for a response to an address resolution DNS query.
+ *
+ */
+struct otDnsAddressResponse
+{
+};
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+/**
+ * This struct represents an opaque (and empty) type for a response to browse (service instance enumeration) DNS query.
+ *
+ */
+struct otDnsBrowseResponse
+{
+};
+
+/**
+ * This struct represents an opaque (and empty) type for a response to service inst resolution DNS query.
+ *
+ */
+struct otDnsServiceResponse
+{
+};
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
namespace ot {
namespace Dns {
@@ -52,57 +81,409 @@
* This class implements DNS client.
*
*/
-class Client : private NonCopyable
+class Client : public InstanceLocator, private NonCopyable
{
+ typedef Message Query; // `Message` is used to save `Query` related info.
+
public:
/**
- * This type represents a DNS Query info/parameters.
+ * This type represents a DNS query configuration (e.g., server address, response wait timeout, etc).
*
*/
- class QueryInfo : public otDnsQuery
+ class QueryConfig : public otDnsQueryConfig, public Clearable<QueryConfig>
{
+ friend class Client;
+
public:
/**
- * This method indicates whether the `QueryInfo` object is valid or not.
- *
- * @returns TRUE if the `QueryInfo` is valid, FALSE otherwise.
+ * This enumeration type represents the "Recursion Desired" (RD) flag in a `otDnsQueryConfig`.
*
*/
- bool IsValid(void) const { return (mHostname != nullptr) && (mMessageInfo != nullptr); }
-
- /**
- * This method gets the host name in a DNS query.
- *
- * @return The host name.
- *
- */
- const char *GetHostname(void) const { return mHostname; }
-
- /**
- * This method gets the `MessageInfo` related to DNS Server.
- *
- * @returns The `MessageInfo` of DNS Server.
- *
- */
- const Ip6::MessageInfo &GetMessageInfo(void) const
+ enum RecursionFlag
{
- return *static_cast<const Ip6::MessageInfo *>(mMessageInfo);
+ kFlagUnspecified = OT_DNS_FLAG_UNSPECIFIED, ///< The flag is not specified.
+ kFlagRecursionDesired = OT_DNS_FLAG_RECURSION_DESIRED, ///< Server can resolve the query recursively.
+ kFlagNoRecursion = OT_DNS_FLAG_NO_RECURSION, ///< Server can not resolve the query recursively.
+ };
+
+ /**
+ * This is the default constructor for `QueryConfig` object.
+ *
+ */
+ QueryConfig(void) = default;
+
+ /**
+ * This method gets the server socket address (IPv6 address and port number).
+ *
+ * @returns The server socket address.
+ *
+ */
+ const Ip6::SockAddr &GetServerSockAddr(void) const
+ {
+ return static_cast<const Ip6::SockAddr &>(mServerSockAddr);
}
/**
- * This method indicates whether or not the name server can pursue the query recursively.
+ * This method gets the wait time to receive response from server (in msec).
*
- * @returns TRUE if no recursion is allowed, FALSE otherwise.
+ * @returns The timeout interval in msec.
*
*/
- bool IsNoRecursion(void) const { return mNoRecursion; }
+ uint32_t GetResponseTimeout(void) const { return mResponseTimeout; }
+
+ /**
+ * This method gets the maximum number of query transmit attempts before reporting failure.
+ *
+ * @returns The maximum number of query transmit attempts.
+ *
+ */
+ uint8_t GetMaxTxAttempts(void) const { return mMaxTxAttempts; }
+
+ /**
+ * This method gets the recursion flag indicating whether the server can resolve the query recursively or not.
+ *
+ * @returns The recursion flag.
+ *
+ */
+ RecursionFlag GetRecursionFlag(void) const { return static_cast<RecursionFlag>(mRecursionFlag); }
+
+ private:
+ enum : uint32_t
+ {
+ kDefaultResponseTimeout = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RESPONSE_TIMEOUT, // in msec
+ };
+
+ enum : uint16_t
+ {
+ kDefaultServerPort = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_PORT,
+ };
+
+ enum : uint8_t
+ {
+ kDefaultMaxTxAttempts = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_MAX_TX_ATTEMPTS,
+ };
+
+ enum : bool
+ {
+ kDefaultRecursionDesired = OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_RECURSION_DESIRED_FLAG,
+ };
+
+ enum InitMode : uint8_t
+ {
+ kInitFromDefaults,
+ };
+
+ static const char kDefaultServerAddressString[];
+
+ explicit QueryConfig(InitMode aMode);
+
+ Ip6::SockAddr &GetServerSockAddr(void) { return static_cast<Ip6::SockAddr &>(mServerSockAddr); }
+
+ void SetResponseTimeout(uint32_t aResponseTimeout) { mResponseTimeout = aResponseTimeout; }
+ void SetMaxTxAttempts(uint8_t aMaxTxAttempts) { mMaxTxAttempts = aMaxTxAttempts; }
+ void SetRecursionFlag(RecursionFlag aFlag) { mRecursionFlag = static_cast<otDnsRecursionFlag>(aFlag); }
+
+ void SetFrom(const QueryConfig &aConfig, const QueryConfig &aDefaultConfig);
+ };
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ /**
+ * This structure provides info for a DNS service instance.
+ *
+ */
+ typedef otDnsServiceInfo ServiceInfo;
+#endif
+
+ /**
+ * This class represents a DNS query response.
+ *
+ */
+ class Response : public Clearable<Response>,
+ public otDnsAddressResponse
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ ,
+ public otDnsBrowseResponse,
+ public otDnsServiceResponse
+#endif
+
+ {
+ friend class Client;
+
+ protected:
+ enum Section : uint8_t
+ {
+ kAnswerSection,
+ kAdditionalDataSection,
+ };
+
+ Response(void) { Clear(); }
+
+ Error GetName(char *aNameBuffer, uint16_t aNameBufferSize) const;
+ void SelectSection(Section aSection, uint16_t &aOffset, uint16_t &aNumRecord) const;
+ Error FindHostAddress(Section aSection,
+ const Name & aHostName,
+ uint16_t aIndex,
+ Ip6::Address &aAddress,
+ uint32_t & aTtl) const;
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ Error FindServiceInfo(Section aSection, const Name &aName, ServiceInfo &aServiceInfo) const;
+#endif
+
+ Query * mQuery; // The associated query.
+ const Message *mMessage; // The response message.
+ uint16_t mAnswerOffset; // Answer section offset in `mMessage`.
+ uint16_t mAnswerRecordCount; // Number of records in answer section.
+ uint16_t mAdditionalOffset; // Additional data section offset in `mMessage`.
+ uint16_t mAdditionalRecordCount; // Number of records in additional data section.
};
/**
- * This type represents the function pointer type which is called when a DNS response is received.
+ * This type represents the function pointer callback which is called when a DNS response for an address resolution
+ * query is received.
*
*/
- typedef otDnsResponseHandler ResponseHandler;
+ typedef otDnsAddressCallback AddressCallback;
+
+ /**
+ * This type represents an address resolution query DNS response.
+ *
+ */
+ class AddressResponse : public Response
+ {
+ friend class Client;
+
+ public:
+ /**
+ * This method gets the host name associated with an address resolution DNS response.
+ *
+ * This method MUST only be used from `AddressCallback`.
+ *
+ * @param[out] aNameBuffer A buffer to char array to output the host name.
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The host name was read successfully.
+ * @retval kErrorNoBufs The name does not fit in @p aNameBuffer.
+ *
+ */
+ Error GetHostName(char *aNameBuffer, uint16_t aNameBufferSize) const
+ {
+ return GetName(aNameBuffer, aNameBufferSize);
+ }
+
+ /**
+ * This method gets the IPv6 address associated with an address resolution DNS response.
+ *
+ * This method MUST only be used from `AddressCallback`.
+ *
+ * The response may include multiple IPv6 address records. @p aIndex can be used to iterate through the list of
+ * addresses. Index zero gets the the first address and so on. When we reach end of the list, this method
+ * returns `kErrorNotFound`.
+ *
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A reference to an IPv6 address to output the address.
+ * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address.
+ *
+ * @retval kErrorNone The address was read successfully.
+ * @retval kErrorNotFound No address record at @p aIndex.
+ * @retval kErrorParse Could not parse the records.
+ *
+ */
+ Error GetAddress(uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const;
+ };
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+ /**
+ * This type represents the function pointer callback which is called when a response for a browse (service
+ * instance enumeration) DNS query is received.
+ *
+ */
+ typedef otDnsBrowseCallback BrowseCallback;
+
+ /**
+ * This type represents a browse (service instance enumeration) DNS response.
+ *
+ */
+ class BrowseResponse : public Response
+ {
+ friend class Client;
+
+ public:
+ /**
+ * This method gets the service name associated with a DNS browse response.
+ *
+ * This method MUST only be used from `BrowseCallback`.
+ *
+ * @param[out] aNameBuffer A buffer to char array to output the host name.
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The host name was read successfully.
+ * @retval kErrorNoBufs The name does not fit in @p aNameBuffer.
+ *
+ */
+ Error GetServiceName(char *aNameBuffer, uint16_t aNameBufferSize) const
+ {
+ return GetName(aNameBuffer, aNameBufferSize);
+ }
+
+ /**
+ * This method gets a service instance associated with a DNS browse (service instance enumeration) response.
+ *
+ * This method MUST only be used from `BrowseCallback`.
+ *
+ * A 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, `kErrorNotFound` is returned.
+ *
+ * Note that this method gets the service instance label and not the full service instance name which is of the
+ * form `<Instance>.<Service>.<Domain>`.
+ *
+ * @param[in] aResponse A pointer to a response.
+ * @param[in] aIndex The service instance record index to retrieve.
+ * @param[out] aLabelBuffer A char array to output the service instance label (MUST NOT be NULL).
+ * @param[in] aLabelBufferSize The size of @p aLabelBuffer.
+ *
+ * @retval kErrorNone The service instance was read successfully.
+ * @retval kErrorNoBufs The name does not fit in @p aNameBuffer.
+ * @retval kErrorNotFound No service instance record at @p aIndex.
+ * @retval kErrorParse Could not parse the records.
+ *
+ */
+ Error GetServiceInstance(uint16_t aIndex, char *aLabelBuffer, uint8_t aLabelBufferSize) const;
+
+ /**
+ * This method gets info for a service instance from a DNS browse (service instance enumeration) response.
+ *
+ * This method MUST only be used from `BrowseCallback`.
+ *
+ * A browse DNS response should include the SRV, TXT, and AAAA records for the service instances that are
+ * enumerated (note that it is a SHOULD and not a MUST requirement). This method tries to retrieve this info
+ * for a given service instance.
+ *
+ * - If no matching SRV record is found, `kErrorNotFound` is returned.
+ * - If a matching SRV record is found, @p aServiceInfo is updated returning `kErrorNone`.
+ * - If no matching TXT record is found, `mTxtDataSize` in @p aServiceInfo is set to zero.
+ * - If no matching AAAA record is found, `mHostAddress is set to all zero or unspecified address.
+ * - If there are multiple AAAA records for the host name `mHostAddress` is set to the first one. The other
+ * addresses can be retrieved using `GetHostAddress()` method.
+ *
+ * @param[in] aInstanceLabel The service instance label (MUST NOT be `nullptr`).
+ * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information.
+ *
+ * @retval kErrorNone The service instance info was read. @p aServiceInfo is updated.
+ * @retval kErrorNotFound Could not find a matching SRV record for @p aInstanceLabel.
+ * @retval kErrorNoBufs The host name and/or the TXT data could not fit in given buffers.
+ * @retval kErrorParse Could not parse the records.
+ *
+ */
+ Error GetServiceInfo(const char *aInstanceLabel, ServiceInfo &aServiceInfo) const;
+
+ /**
+ * This method gets the host IPv6 address from a DNS browse (service instance enumeration) response.
+ *
+ * This method MUST only be used from `BrowseCallback`.
+ *
+ * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the
+ * list of addresses. Index zero gets the first address and so on. When we reach end of the list, this method
+ * returns `kErrorNotFound`.
+ *
+ * @param[in] aHostName The host name to get the address (MUST NOT be `nullptr`).
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A reference to an IPv6 address to output the address.
+ * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address.
+ *
+ * @retval kErrorNone The address was read successfully.
+ * @retval kErrorNotFound No address record for @p aHostname at @p aIndex.
+ * @retval kErrorParse Could not parse the records.
+ *
+ */
+ Error GetHostAddress(const char *aHostName, uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const;
+
+ private:
+ Error FindPtrRecord(const char *aInstanceLabel, Name &aInstanceName) const;
+ };
+
+ /**
+ * This type represents the function pointer callback which is called when a response for a service instance
+ * resolution DNS query is received.
+ *
+ */
+ typedef otDnsServiceCallback ServiceCallback;
+
+ /**
+ * This type represents a service instance resolution DNS response.
+ *
+ */
+ class ServiceResponse : public Response
+ {
+ friend class Client;
+
+ public:
+ /**
+ * This method gets the service instance name associated with a DNS service instance resolution response.
+ *
+ * This method MUST only be used from `ServiceCallback`.
+ *
+ * @param[out] aLabelBuffer A buffer to char array to output the service instance label (MUST NOT be NULL).
+ * @param[in] aLabelBufferSize The size of @p aLabelBuffer.
+ * @param[out] aNameBuffer A buffer to char array to output the rest of service name (can be NULL if user
+ * is not interested in getting the name).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The service instance name was read successfully.
+ * @retval kErrorNoBufs Either the label or name does not fit in the given buffers.
+ *
+ */
+ Error GetServiceName(char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const;
+
+ /**
+ * This method gets info for a service instance from a DNS service instance resolution response.
+ *
+ * This method MUST only be used from `ServiceCallback`.
+ *
+ * - If no matching SRV record is found, `kErrorNotFound` is returned.
+ * - If a matching SRV record is found, @p aServiceInfo is updated and `kErrorNone` is returned.
+ * - If no matching TXT record is found, `mTxtDataSize` in @p aServiceInfo is set to zero.
+ * - If no matching AAAA record is found, `mHostAddress is set to all zero or unspecified address.
+ * - If there are multiple AAAA records for the host name, `mHostAddress` is set to the first one. The other
+ * addresses can be retrieved using `GetHostAddress()` method.
+ *
+ * @param[out] aServiceInfo A `ServiceInfo` to output the service instance information
+ *
+ * @retval kErrorNone The service instance info was read. @p aServiceInfo is updated.
+ * @retval kErrorNotFound Could not find a matching SRV record.
+ * @retval kErrorNoBufs The host name and/or TXT data could not fit in the given buffers.
+ * @retval kErrorParse Could not parse the records in the @p aResponse.
+ *
+ */
+ Error GetServiceInfo(ServiceInfo &aServiceInfo) const;
+
+ /**
+ * This method gets the host IPv6 address from a DNS service instance resolution response.
+ *
+ * This method MUST only be used from `ServiceCallback`.
+ *
+ * The response can include zero or more IPv6 address records. @p aIndex can be used to iterate through the
+ * list of addresses. Index zero gets the first address and so on. When we reach end of the list, this method
+ * returns `kErrorNotFound`.
+ *
+ * @param[in] aHostName The host name to get the address (MUST NOT be `nullptr`).
+ * @param[in] aIndex The address record index to retrieve.
+ * @param[out] aAddress A reference to an IPv6 address to output the address.
+ * @param[out] aTtl A reference to a `uint32_t` to output TTL for the address.
+ *
+ * @retval kErrorNone The address was read successfully.
+ * @retval kErrorNotFound No address record for @p aHostname at @p aIndex.
+ * @retval kErrorParse Could not parse the records.
+ *
+ */
+ Error GetHostAddress(const char *aHostName, uint16_t aIndex, Ip6::Address &aAddress, uint32_t &aTtl) const;
+ };
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
/**
* This constructor initializes the object.
@@ -115,93 +496,191 @@
/**
* This method starts the DNS client.
*
- * @retval OT_ERROR_NONE Successfully started the DNS client.
- * @retval OT_ERROR_ALREADY The socket is already open.
+ * @retval kErrorNone Successfully started the DNS client.
+ * @retval kErrorAlready The socket is already open.
*
*/
- otError Start(void);
+ Error Start(void);
/**
* This method stops the DNS client.
*
- * @retval OT_ERROR_NONE Successfully stopped the DNS client.
- *
*/
- otError Stop(void);
+ void Stop(void);
/**
- * This method sends a DNS query.
+ * This method gets the current default query config being used by DNS client.
*
- * @param[in] aQuery A pointer to specify DNS query parameters.
- * @param[in] aHandler A function pointer that shall be called on response reception or time-out.
- * @param[in] aContext A pointer to arbitrary context information.
- *
- * @retval OT_ERROR_NONE Successfully sent DNS query.
- * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
- * @retval OT_ERROR_INVALID_ARGS Invalid arguments supplied.
+ * @returns The current default query config.
*
*/
- otError Query(const QueryInfo &aQuery, ResponseHandler aHandler, void *aContext);
+ const QueryConfig &GetDefaultConfig(void) const { return mDefaultConfig; }
+
+ /**
+ * This method sets the default query config.
+ *
+ * @param[in] aQueryConfig The new default query config.
+ *
+ */
+ void SetDefaultConfig(const QueryConfig &aQueryConfig);
+
+ /**
+ * This method resets the default config to the config used when the OpenThread stack starts.
+ *
+ * When OpenThread stack starts, the default DNS query config is determined from a set of OT config options such as
+ * `OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_IP6_ADDRESS`, `_DEFAULT_SERVER_PORT`, or `_DEFAULT_RESPONSE_TIMEOUT`
+ * etc. (see `config/dns_clinet.h` for all related config options).
+ *
+ */
+ void ResetDefaultConfig(void);
+
+ /**
+ * This method sends an address resolution DNS query for AAAA (IPv6) record for a given host name.
+ *
+ * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as
+ * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero).
+ * The unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aHostName The host name for which to query the address (MUST NOT be `nullptr`).
+ * @param[in] aCallback A callback function pointer to report the result of query.
+ * @param[in] aContext A pointer to arbitrary context information passed to @p aCallback.
+ * @param[in] aConfig The config to use for this query.
+ *
+ * @retval kErrorNone Successfully sent DNS query.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidArgs The host name is not valid format.
+ * @retval kErrorInvalidState Cannot send query since Thread interface is not up.
+ *
+ */
+ Error ResolveAddress(const char * aHostName,
+ AddressCallback aCallback,
+ void * aContext,
+ const QueryConfig *aConfig = nullptr);
+
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+
+ /**
+ * This method sends a browse (service instance enumeration) DNS query for a given service name.
+ *
+ * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as
+ * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero).
+ * The unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aServiceName The service name to query for (MUST NOT be `nullptr`).
+ * @param[in] aCallback The callback to report the response or errors (such as time-out).
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aConfig The config to use for this query.
+ *
+ * @retval kErrorNone Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval kErrorNoBufs Insufficient buffer to prepare and send query.
+ *
+ */
+ Error Browse(const char * aServiceName,
+ BrowseCallback aCallback,
+ void * aContext,
+ const QueryConfig *aConfig = nullptr);
+
+ /**
+ * This method sends a DNS service instance resolution query for a given service instance.
+ *
+ * The @p aConfig can be nullptr. In this case the default config (from `GetDefaultConfig()`) will be used as
+ * the config for this query. In a non-nullptr @p aConfig, some of the fields can be left unspecified (value zero).
+ * The unspecified fields are then replaced by the values from the default config.
+ *
+ * @param[in] aServerSockAddr The server socket address.
+ * @param[in] aInstanceLabel The service instance label.
+ * @param[in] aServiceName The service name (together with @p aInstanceLabel form full instance name).
+ * @param[in] aCallback A function pointer that shall be called on response reception or time-out.
+ * @param[in] aContext A pointer to arbitrary context information.
+ * @param[in] aConfig The config to use for this query.
+ *
+ * @retval kErrorNone Query sent successfully. @p aCallback will be invoked to report the status.
+ * @retval kErrorNoBufs Insufficient buffer to prepare and send query.
+ * @retval kErrorInvalidArgs @p aInstanceLabel is `nullptr`.
+ *
+ */
+ Error ResolveService(const char * aInstanceLabel,
+ const char * aServiceName,
+ otDnsServiceCallback aCallback,
+ void * aContext,
+ const QueryConfig * aConfig = nullptr);
+
+#endif // OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
private:
- /**
- * Retransmission parameters.
- *
- */
- enum
+ enum QueryType : uint8_t
{
- kResponseTimeout = OPENTHREAD_CONFIG_DNS_RESPONSE_TIMEOUT,
- kMaxRetransmit = OPENTHREAD_CONFIG_DNS_MAX_RETRANSMIT,
+ kAddressQuery, // Address resolution.
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ kBrowseQuery, // Browse (service instance enumeration).
+ kServiceQuery, // Service instance resolution.
+#endif
};
- enum
+ union Callback
{
- kBufSize = 16
+ AddressCallback mAddressCallback;
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ BrowseCallback mBrowseCallback;
+ ServiceCallback mServiceCallback;
+#endif
};
- struct QueryMetadata
- {
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
- void UpdateIn(Message &aMessage) const;
+ typedef MessageQueue QueryList; // List of queries.
- const char * mHostname;
- ResponseHandler mResponseHandler;
- void * mResponseContext;
- TimeMilli mTransmissionTime;
- Ip6::Address mSourceAddress;
- Ip6::Address mDestinationAddress;
- uint16_t mDestinationPort;
- uint8_t mRetransmissionCount;
+ struct QueryInfo : public Clearable<QueryInfo> // Query related Info
+ {
+ void ReadFrom(const Query &aQuery) { IgnoreError(aQuery.Read(0, *this)); }
+
+ QueryType mQueryType;
+ uint16_t mMessageId;
+ Callback mCallback;
+ void * mCallbackContext;
+ TimeMilli mRetransmissionTime;
+ QueryConfig mConfig;
+ uint8_t mTransmissionCount;
+ // Followed by the name (service, host, instance) encoded as a `Dns::Name`.
};
- Message *NewMessage(const Header &aHeader);
- Message *CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata);
- void DequeueMessage(Message &aMessage);
- otError SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ enum : uint16_t
+ {
+ kNameOffsetInQuery = sizeof(QueryInfo),
+ };
- otError GenerateUniqueRandomId(uint16_t &aRandomId);
+ Error StartQuery(QueryInfo & aInfo,
+ const QueryConfig *aConfig,
+ const char * aLabel,
+ const char * aName,
+ void * aContext);
+ Error AllocateQuery(const QueryInfo &aInfo, const char *aLabel, const char *aName, Query *&aQuery);
+ void FreeQuery(Query &aQuery);
+ void UpdateQuery(Query &aQuery, const QueryInfo &aInfo) { aQuery.Write(0, aInfo); }
+ void SendQuery(Query &aQuery);
+ void SendQuery(Query &aQuery, QueryInfo &aInfo, bool aUpdateTimer);
+ void FinalizeQuery(Query &aQuery, Error aError);
+ void FinalizeQuery(Response &Response, QueryType aType, Error aError);
+ static void GetCallback(const Query &aQuery, Callback &aCallback, void *&aContext);
+ Error AppendNameFromQuery(const Query &aQuery, Message &aMessage);
+ Query * FindQueryById(uint16_t aMessageId);
+ static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMsgInfo);
+ void ProcessResponse(const Message &aMessage);
+ Error ParseResponse(Response &aResponse, QueryType &aType, Error &aResponseError);
+ static void HandleTimer(Timer &aTimer);
+ void HandleTimer(void);
- otError CompareQuestions(Message &aMessageResponse, Message &aMessageQuery, uint16_t &aOffset);
+ static const uint8_t kQuestionCount[];
+ static const uint16_t *kQuestionRecordTypes[];
- Message *FindQueryById(uint16_t aMessageId);
- void FinalizeDnsTransaction(Message & aQuery,
- const QueryMetadata &aQueryMetadata,
- const Ip6::Address * aAddress,
- uint32_t aTtl,
- otError aResult);
-
- static void HandleRetransmissionTimer(Timer &aTimer);
- void HandleRetransmissionTimer(void);
-
- static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
- void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static const uint16_t kAddressQueryRecordTypes[];
+#if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
+ static const uint16_t kBrowseQueryRecordTypes[];
+ static const uint16_t kServiceQueryRecordTypes[];
+#endif
Ip6::Udp::Socket mSocket;
-
- MessageQueue mPendingQueries;
- TimerMilli mRetransmissionTimer;
+ QueryList mQueries;
+ TimerMilli mTimer;
+ QueryConfig mDefaultConfig;
};
} // namespace Dns
diff --git a/src/core/net/dns_headers.cpp b/src/core/net/dns_headers.cpp
deleted file mode 100644
index 21ff0db..0000000
--- a/src/core/net/dns_headers.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2020, The OpenThread Authors.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * This file implements generating and processing of DNS headers and helper functions/methods.
- */
-
-#include "dns_headers.hpp"
-
-#include "common/code_utils.hpp"
-#include "common/debug.hpp"
-#include "common/string.hpp"
-
-namespace ot {
-namespace Dns {
-
-using ot::Encoding::BigEndian::HostSwap16;
-
-otError Name::AppendLabel(const char *aLabel, Message &aMessage)
-{
- return AppendLabel(aLabel, static_cast<uint8_t>(StringLength(aLabel, kMaxLabelLength + 1)), aMessage);
-}
-
-otError Name::AppendLabel(const char *aLabel, uint8_t aLabelLength, Message &aMessage)
-{
- otError error = OT_ERROR_NONE;
-
- VerifyOrExit((0 < aLabelLength) && (aLabelLength <= kMaxLabelLength), error = OT_ERROR_INVALID_ARGS);
-
- SuccessOrExit(error = aMessage.Append(aLabelLength));
- error = aMessage.AppendBytes(aLabel, aLabelLength);
-
-exit:
- return error;
-}
-
-otError Name::AppendMultipleLabels(const char *aLabels, Message &aMessage)
-{
- otError error = OT_ERROR_NONE;
- uint16_t index = 0;
- uint16_t labelStartIndex = 0;
- char ch;
-
- VerifyOrExit(aLabels != nullptr);
-
- do
- {
- VerifyOrExit(index < kMaxLength, error = OT_ERROR_INVALID_ARGS);
-
- ch = aLabels[index];
-
- if ((ch == kNullChar) || (ch == kLabelSeperatorChar))
- {
- uint8_t labelLength = static_cast<uint8_t>(index - labelStartIndex);
-
- if (labelLength == 0)
- {
- // Empty label (e.g., consecutive dots) is invalid, but we
- // allow for two cases: (1) where `aLabels` ends with a dot
- // (`labelLength` is zero but we are at end of `aLabels` string
- // and `ch` is null char. (2) if `aLabels` is just "." (we
- // see a dot at index 0, and index 1 is null char).
-
- error = ((ch == kNullChar) || ((index == 0) && (aLabels[1] == kNullChar))) ? OT_ERROR_NONE
- : OT_ERROR_INVALID_ARGS;
- ExitNow();
- }
-
- SuccessOrExit(error = AppendLabel(&aLabels[labelStartIndex], labelLength, aMessage));
-
- labelStartIndex = index + 1;
- }
-
- index++;
-
- } while (ch != kNullChar);
-
-exit:
- return error;
-}
-
-otError Name::AppendTerminator(Message &aMessage)
-{
- uint8_t terminator = 0;
-
- return aMessage.Append(terminator);
-}
-
-otError Name::AppendPointerLabel(uint16_t aOffset, Message &aMessage)
-{
- // A pointer label takes the form of a two byte sequence as a
- // `uint16_t` value. The first two bits are ones. This allows a
- // pointer to be distinguished from a text label, since the text
- // label must begin with two zero bits (note that labels are
- // restricted to 63 octets or less). The next 14-bits specify
- // an offset value relative to start of DNS header.
-
- uint16_t value;
-
- OT_ASSERT(aOffset < kPointerLabelTypeUint16);
-
- value = HostSwap16(aOffset | kPointerLabelTypeUint16);
-
- return aMessage.Append(value);
-}
-
-otError Name::AppendName(const char *aName, Message &aMessage)
-{
- otError error;
-
- SuccessOrExit(error = AppendMultipleLabels(aName, aMessage));
- error = AppendTerminator(aMessage);
-
-exit:
- return error;
-}
-
-otError Name::ParseName(const Message &aMessage, uint16_t &aOffset)
-{
- otError error;
- LabelIterator iterator(aMessage, aOffset);
-
- while (true)
- {
- error = iterator.GetNextLabel();
-
- VerifyOrExit((error == OT_ERROR_NONE) || (error == OT_ERROR_NOT_FOUND));
-
- if (iterator.IsEndOffsetSet())
- {
- aOffset = iterator.mNameEndOffset;
- ExitNow(error = OT_ERROR_NONE);
- }
- }
-
-exit:
- return error;
-}
-
-otError Name::ReadLabel(const Message &aMessage,
- uint16_t & aOffset,
- uint16_t aHeaderOffset,
- char * aLabelBuffer,
- uint8_t & aLabelLength)
-{
- otError error;
- LabelIterator iterator(aMessage, aOffset, aHeaderOffset);
-
- SuccessOrExit(error = iterator.GetNextLabel());
- SuccessOrExit(error = iterator.ReadLabel(aLabelBuffer, aLabelLength, /* aAllowDotCharInLabel */ true));
- aOffset = iterator.mNextLabelOffset;
-
-exit:
- return error;
-}
-
-otError Name::ReadName(const Message &aMessage,
- uint16_t & aOffset,
- uint16_t aHeaderOffset,
- char * aNameBuffer,
- uint16_t aNameBufferSize)
-{
- otError error;
- LabelIterator iterator(aMessage, aOffset, aHeaderOffset);
- bool firstLabel = true;
- uint8_t labelLength;
-
- while (true)
- {
- error = iterator.GetNextLabel();
-
- switch (error)
- {
- case OT_ERROR_NONE:
-
- if (!firstLabel)
- {
- *aNameBuffer++ = kLabelSeperatorChar;
- aNameBufferSize--;
-
- // No need to check if we have reached end of the name buffer
- // here since `iterator.ReadLabel()` would verify it.
- }
-
- labelLength = static_cast<uint8_t>(OT_MIN(kMaxLabelLength + 1, aNameBufferSize));
- SuccessOrExit(error = iterator.ReadLabel(aNameBuffer, labelLength, /* aAllowDotCharInLabel */ false));
- aNameBuffer += labelLength;
- aNameBufferSize -= labelLength;
- firstLabel = false;
- break;
-
- case OT_ERROR_NOT_FOUND:
- // We reach the end of name successfully. Always add a terminating dot
- // at the end.
- *aNameBuffer++ = kLabelSeperatorChar;
- aNameBufferSize--;
- VerifyOrExit(aNameBufferSize >= sizeof(uint8_t), error = OT_ERROR_NO_BUFS);
- *aNameBuffer = kNullChar;
- aOffset = iterator.mNameEndOffset;
- error = OT_ERROR_NONE;
-
- // Fall through
-
- default:
- ExitNow();
- }
- }
-
-exit:
- return error;
-}
-
-otError Name::LabelIterator::GetNextLabel(void)
-{
- otError error;
-
- while (true)
- {
- uint8_t labelLength;
- uint8_t labelType;
-
- SuccessOrExit(error = mMessage.Read(mNextLabelOffset, labelLength));
-
- labelType = labelLength & kLabelTypeMask;
-
- if (labelType == kTextLabelType)
- {
- if (labelLength == 0)
- {
- // Zero label length indicates end of a name.
-
- if (!IsEndOffsetSet())
- {
- mNameEndOffset = mNextLabelOffset + sizeof(uint8_t);
- }
-
- ExitNow(error = OT_ERROR_NOT_FOUND);
- }
-
- mLabelStartOffset = mNextLabelOffset + sizeof(uint8_t);
- mLabelLength = labelLength;
- mNextLabelOffset = mLabelStartOffset + labelLength;
- ExitNow();
- }
- else if (labelType == kPointerLabelType)
- {
- // A pointer label takes the form of a two byte sequence as a
- // `uint16_t` value. The first two bits are ones. The next 14 bits
- // specify an offset value from the start of the DNS header.
-
- uint16_t pointerValue;
-
- SuccessOrExit(error = mMessage.Read(mNextLabelOffset, pointerValue));
-
- if (!IsEndOffsetSet())
- {
- mNameEndOffset = mNextLabelOffset + sizeof(uint16_t);
- }
-
- mNextLabelOffset = mHeaderOffset + (HostSwap16(pointerValue) & kPointerLabelOffsetMask);
-
- // Go back through the `while(true)` loop to get the next label.
- }
- else
- {
- ExitNow(error = OT_ERROR_PARSE);
- }
- }
-
-exit:
- return error;
-}
-
-otError Name::LabelIterator::ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength, bool aAllowDotCharInLabel) const
-{
- otError error;
-
- VerifyOrExit(mLabelLength < aLabelLength, error = OT_ERROR_NO_BUFS);
-
- SuccessOrExit(error = mMessage.Read(mLabelStartOffset, aLabelBuffer, mLabelLength));
- aLabelBuffer[mLabelLength] = kNullChar;
- aLabelLength = mLabelLength;
-
- if (!aAllowDotCharInLabel)
- {
- VerifyOrExit(StringFind(aLabelBuffer, kLabelSeperatorChar) == nullptr, error = OT_ERROR_PARSE);
- }
-
-exit:
- return error;
-}
-
-void ResourceRecord::Init(uint16_t aType, uint16_t aClass, uint32_t aTtl)
-{
- SetType(aType);
- SetClass(aClass);
- SetTtl(aTtl);
- SetLength(0);
-}
-
-void ResourceRecordAaaa::Init(void)
-{
- ResourceRecord::Init(kTypeAaaa);
- SetLength(sizeof(mAddress));
- mAddress.Clear();
-}
-
-} // namespace Dns
-} // namespace ot
diff --git a/src/core/net/dns_headers.hpp b/src/core/net/dns_headers.hpp
deleted file mode 100644
index 9d35d1f..0000000
--- a/src/core/net/dns_headers.hpp
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * Copyright (c) 2017, The OpenThread Authors.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * This file includes definitions for generating and processing DNS headers.
- */
-
-#ifndef DNS_HEADER_HPP_
-#define DNS_HEADER_HPP_
-
-#include "openthread-core-config.h"
-
-#include "common/clearable.hpp"
-#include "common/encoding.hpp"
-#include "common/message.hpp"
-#include "net/ip6_address.hpp"
-
-namespace ot {
-
-/**
- * @namespace ot::Dns
- * @brief
- * This namespace includes definitions for DNS.
- *
- */
-namespace Dns {
-
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
-/**
- * @addtogroup core-dns
- *
- * @brief
- * This module includes definitions for DNS.
- *
- * @{
- *
- */
-
-/**
- * This class implements DNS header generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class Header : public Clearable<Header>
-{
-public:
- /**
- * Default constructor for DNS Header.
- *
- */
- Header(void) { Clear(); }
-
- /**
- * This method returns the Message ID.
- *
- * @returns The Message ID value.
- *
- */
- uint16_t GetMessageId(void) const { return HostSwap16(mMessageId); }
-
- /**
- * This method sets the Message ID.
- *
- * @param[in] aMessageId The Message ID value.
- *
- */
- void SetMessageId(uint16_t aMessageId) { mMessageId = HostSwap16(aMessageId); }
-
- /**
- * Defines types of DNS message.
- *
- */
- enum Type
- {
- kTypeQuery = 0,
- kTypeResponse = 1,
- };
-
- /**
- * This method returns the type of the message.
- *
- * @returns The type of the message.
- *
- */
- Type GetType(void) const { return static_cast<Type>((mFlags[0] & kQrFlagMask) >> kQrFlagOffset); }
-
- /**
- * This method sets the type of the message.
- *
- * @param[in] aType The type of the message.
- *
- */
- void SetType(Type aType)
- {
- mFlags[0] &= ~kQrFlagMask;
- mFlags[0] |= static_cast<uint8_t>(aType) << kQrFlagOffset;
- }
-
- /**
- * Defines types of query.
- *
- */
- enum QueryType
- {
- kQueryTypeStandard = 0,
- kQueryTypeInverse = 1,
- kQueryTypeStatus = 2,
- kQueryTypeNotify = 4,
- kQueryTypeUpdate = 5
- };
-
- /**
- * This method returns the type of the query.
- *
- * @returns The type of the query.
- *
- */
- QueryType GetQueryType(void) const { return static_cast<QueryType>((mFlags[0] & kOpCodeMask) >> kOpCodeOffset); }
-
- /**
- * This method sets the type of the query.
- *
- * @param[in] aType The type of the query.
- *
- */
- void SetQueryType(QueryType aType)
- {
- mFlags[0] &= ~kOpCodeMask;
- mFlags[0] |= static_cast<uint8_t>(aType) << kOpCodeOffset;
- }
-
- /**
- * This method specifies in response message if the responding name server is an
- * authority for the domain name in question section.
- *
- * @returns True if Authoritative Answer flag (AA) is set in the header, false otherwise.
- *
- */
- bool IsAuthoritativeAnswerFlagSet(void) const { return (mFlags[0] & kAaFlagMask) == kAaFlagMask; }
-
- /**
- * This method clears the Authoritative Answer flag (AA) in the header.
- *
- */
- void ClearAuthoritativeAnswerFlag(void) { mFlags[0] &= ~kAaFlagMask; }
-
- /**
- * This method sets the Authoritative Answer flag (AA) in the header.
- *
- */
- void SetAuthoritativeAnswerFlag(void) { mFlags[0] |= kAaFlagMask; }
-
- /**
- * This method specifies if message is truncated.
- *
- * @returns True if Truncation flag (TC) is set in the header, false otherwise.
- *
- */
- bool IsTruncationFlagSet(void) const { return (mFlags[0] & kTcFlagMask) == kTcFlagMask; }
-
- /**
- * This method clears the Truncation flag (TC) in the header.
- *
- */
- void ClearTruncationFlag(void) { mFlags[0] &= ~kTcFlagMask; }
-
- /**
- * This method sets the Truncation flag (TC) in the header.
- *
- */
- void SetTruncationFlag(void) { mFlags[0] |= kTcFlagMask; }
-
- /**
- * This method specifies if resolver wants to direct the name server to pursue
- * the query recursively.
- *
- * @returns True if Recursion Desired flag (RD) is set in the header, false otherwise.
- *
- */
- bool IsRecursionDesiredFlagSet(void) const { return (mFlags[0] & kRdFlagMask) == kRdFlagMask; }
-
- /**
- * This method clears the Recursion Desired flag (RD) in the header.
- *
- */
- void ClearRecursionDesiredFlag(void) { mFlags[0] &= ~kRdFlagMask; }
-
- /**
- * This method sets the Recursion Desired flag (RD) in the header.
- *
- */
- void SetRecursionDesiredFlag(void) { mFlags[0] |= kRdFlagMask; }
-
- /**
- * This method denotes whether recursive query support is available in the name server.
- *
- * @returns True if Recursion Available flag (RA) is set in the header, false otherwise.
- */
- bool IsRecursionAvailableFlagSet(void) const { return (mFlags[1] & kRaFlagMask) == kRaFlagMask; }
-
- /**
- * This method clears the Recursion Available flag (RA) in the header.
- *
- */
- void ClearRecursionAvailableFlag(void) { mFlags[1] &= ~kRaFlagMask; }
-
- /**
- * This method sets the Recursion Available flag (RA) in the header.
- *
- */
- void SetRecursionAvailableFlag(void) { mFlags[1] |= kRaFlagMask; }
-
- /**
- * Defines response codes.
- *
- */
- enum Response
- {
- kResponseSuccess = 0,
- kResponseFormatError = 1,
- kResponseServerFailure = 2,
- kResponseNameError = 3,
- kResponseNotImplemented = 4,
- kResponseRefused = 5,
- kResponseNotAuth = 9,
- kResponseNotZone = 10,
- kResponseBadName = 20,
- kResponseBadAlg = 21,
- kResponseBadTruncation = 22,
- };
-
- /**
- * This method returns the response code.
- *
- * @returns The response code from the header.
- *
- */
- Response GetResponseCode(void) const { return static_cast<Response>((mFlags[1] & kRCodeMask) >> kRCodeOffset); }
-
- /**
- * This method sets the response code.
- *
- * @param[in] aResponse The type of the response.
- *
- */
- void SetResponseCode(Response aResponse)
- {
- mFlags[1] &= ~kRCodeMask;
- mFlags[1] |= static_cast<uint8_t>(aResponse) << kRCodeOffset;
- }
-
- /**
- * This method returns the number of entries in question section.
- *
- * @returns The number of entries in question section.
- *
- */
- uint16_t GetQuestionCount(void) const { return HostSwap16(mQdCount); }
-
- /**
- * This method sets the number of entries in question section.
- *
- * @param[in] aCount The number of entries in question section.
- *
- */
- void SetQuestionCount(uint16_t aCount) { mQdCount = HostSwap16(aCount); }
-
- /**
- * This method returns the number of entries in answer section.
- *
- * @returns The number of entries in answer section.
- *
- */
- uint16_t GetAnswerCount(void) const { return HostSwap16(mAnCount); }
-
- /**
- * This method sets the number of entries in answer section.
- *
- * @param[in] aCount The number of entries in answer section.
- *
- */
- void SetAnswerCount(uint16_t aCount) { mAnCount = HostSwap16(aCount); }
-
- /**
- * This method returns the number of entries in authority records section.
- *
- * @returns The number of entries in authority records section.
- *
- */
- uint16_t GetAuthorityRecordsCount(void) const { return HostSwap16(mNsCount); }
-
- /**
- * This method sets the number of entries in authority records section.
- *
- * @param[in] aCount The number of entries in authority records section.
- *
- */
- void SetAuthorityRecordsCount(uint16_t aCount) { mNsCount = HostSwap16(aCount); }
-
- /**
- * This method returns the number of entries in additional records section.
- *
- * @returns The number of entries in additional records section.
- *
- */
- uint16_t GetAdditionalRecordsCount(void) const { return HostSwap16(mArCount); }
-
- /**
- * This method sets the number of entries in additional records section.
- *
- * @param[in] aCount The number of entries in additional records section.
- *
- */
- void SetAdditionalRecordsCount(uint16_t aCount) { mArCount = HostSwap16(aCount); }
-
-private:
- /**
- * Protocol Constants (RFC 1035).
- *
- */
- enum
- {
- kQrFlagOffset = 7, // QR Flag offset.
- kQrFlagMask = 0x01 << kQrFlagOffset, // QR Flag mask.
- kOpCodeOffset = 3, // OpCode field offset.
- kOpCodeMask = 0x0f << kOpCodeOffset, // OpCode field mask.
- kAaFlagOffset = 2, // AA Flag offset.
- kAaFlagMask = 0x01 << kAaFlagOffset, // AA Flag mask.
- kTcFlagOffset = 1, // TC Flag offset.
- kTcFlagMask = 0x01 << kTcFlagOffset, // TC Flag mask.
- kRdFlagOffset = 0, // RD Flag offset.
- kRdFlagMask = 0x01 << kRdFlagOffset, // RD Flag mask.
-
- kRaFlagOffset = 7, // RA Flag offset.
- kRaFlagMask = 0x01 << kRaFlagOffset, // RA Flag mask.
- kRCodeOffset = 0, // RCODE field offset.
- kRCodeMask = 0x0f << kRCodeOffset, // RCODE field mask.
- };
-
- uint16_t mMessageId; // Message identifier for requester to match up replies to outstanding queries.
- uint8_t mFlags[2]; // DNS header flags.
- uint16_t mQdCount; // Number of entries in the question section.
- uint16_t mAnCount; // Number of entries in the answer section.
- uint16_t mNsCount; // Number of entries in the authority records section.
- uint16_t mArCount; // Number of entries in the additional records section.
-
-} OT_TOOL_PACKED_END;
-
-/**
- * This class implement helper methods for encoding/decoding of DNS Names.
- *
- */
-class Name
-{
-public:
- enum : uint8_t
- {
- kMaxLabelLength = 63, ///< Max number of characters in a label.
- kMaxLength = 255, ///< Max number of characters in a name.
- };
-
- /**
- * This static method encodes and appends a single name label to a message.
- *
- * The @p aLabel is assumed to contain a single name label as a C string (null-terminated). Unlike
- * `AppendMultipleLabels()` which parses the label string and treats it as sequence of multiple (dot-separated)
- * labels, this method always appends @p aLabel as a single whole label. This allows the label string to even
- * contain dot '.' character, which, for example, is useful for "Service Instance Names" where <Instance> portion
- * is a user-friendly name and can contain dot characters.
- *
- * @param[in] aLabel The label string to append. MUST NOT be nullptr.
- * @param[in] aMessage The message to append to.
- *
- * @retval OT_ERROR_NONE Successfully encoded and appended the name label to @p aMessage.
- * @retval OT_ERROR_INVALID_ARGS @p aLabel is not valid (e.g., label length is not within valid range).
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- static otError AppendLabel(const char *aLabel, Message &aMessage);
-
- /**
- * This static method encodes and appends a sequence of name labels to a given message.
- *
- * The @p aLabels must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
- * E.g., "_http._tcp", "_http._tcp." (same as previous one), "host-1.test".
- *
- * This method validates that the @p aLabels is a valid name format, i.e., no empty label, and labels are
- * `kMaxLabelLength` (63) characters or less.
- *
- * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels
- * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test".
- *
- * @param[in] aLabels A name label string. Can be nullptr (then treated as "").
- * @param[in] aMessage The message to which to append the encoded name.
- *
- * @retval OT_ERROR_NONE Successfully encoded and appended the name label(s) to @p aMessage.
- * @retval OT_ERROR_INVALID_ARGS Name label @p aLabels is not valid.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- static otError AppendMultipleLabels(const char *aLabels, Message &aMessage);
-
- /**
- * This static method appends a name label terminator to a message.
- *
- * An encoded name is terminated by an empty label (a zero byte).
- *
- * @param[in] aMessage The message to append to.
- *
- * @retval OT_ERROR_NONE Successfully encoded and appended the terminator label to @p aMessage.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- static otError AppendTerminator(Message &aMessage);
-
- /**
- * This static method appends a pointer type name label to a message.
- *
- * Pointer label is used for name compression. It allows an entire name or a list of labels at the end of an
- * encoded name to be replaced with a pointer to a prior occurrence of the same name within the message.
- *
- * @param[in] aOffset The offset from the start of DNS header to use for pointer value.
- * @param[in] aMessage The message to append to.
- *
- * @retval OT_ERROR_NONE Successfully encoded and appended the pointer label to @p aMessage.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- static otError AppendPointerLabel(uint16_t aOffset, Message &aMessage);
-
- /**
- * This static method encodes and appends a full name to a message.
- *
- * The @p aName must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
- * E.g., "example.com", "example.com." (same as previous one), local.", "default.service.arpa", "." or "" (root).
- *
- * This method validates that the @p aName is a valid name format, i.e. no empty labels, and labels are
- * `kMaxLabelLength` (63) characters or less, and the name is `kMaxLength` (255) characters or less.
- *
- * @param[in] aName A name string. Can be nullptr (then treated as "." or root).
- * @param[in] aMessage The message to append to.
- *
- * @retval OT_ERROR_NONE Successfully encoded and appended the name to @p aMessage.
- * @retval OT_ERROR_INVALID_ARGS Name @p aName is not valid.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- static otError AppendName(const char *aName, Message &aMessage);
-
- /**
- * This static method parses and skips over a full name in a message.
- *
- * @param[in] aMessage The message to parse the name from.
- * @param[inout] 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.
- *
- * @retval OT_ERROR_NONE Successfully parsed and skipped over name, @p Offset is updated.
- * @retval OT_ERROR_PARSE Name could not be parsed (invalid format).
- *
- */
- static otError ParseName(const Message &aMessage, uint16_t &aOffset);
-
- /**
- * This static method reads a name label from a message.
- *
- * This method can be used to read labels one by one in a name. After a successful label read, @p aOffset is
- * updated to point to the start of the next label. When we reach the end of the name, OT_ERROR_NOT_FOUND is
- * returned. This method handles compressed names which use pointer labels. So as the labels in a name are read,
- * the @p aOffset may jump back in the message and at the end the @p aOffset does not necessarily point to the end
- * of the original name field.
- *
- * Unlike `ReadName()` which requires and verifies that the read label to contain no dot '.' character, this method
- * allows the read label to include any character.
- *
- * @param[in] aMessage The message to read the label from.
- * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the label to read.
- * On exit, when successfully read, @p aOffset is updated to point to the start of
- * the next label.
- * @param[in] aHeaderOffset The offset in @p aMessage to the start of the DNS header.
- * @param[out] aLabelBuffer A pointer to a char array to output the read label as a null-terminated C string.
- * @param[inout] aLabelLength On input, the maximum number chars in @p aLabelBuffer array.
- * On output, when label is successfully read, @aLabelLength is updated to return
- * the label's length (number of chars in the label string, excluding the null char).
- *
- * @retval OT_ERROR_NONE Successfully read the label and updated @p aLabelBuffer, @p aLabelLength, and
- * @p aOffset.
- * @retval OT_ERROR_NOT_FOUND Reached the end of name and no more label to read.
- * @retval OT_ERROR_PARSE Name could not be parsed (invalid format).
- * @retval OT_ERROR_NO_BUFS Label could not fit in @p aLabelLength chars.
- *
- */
- static otError ReadLabel(const Message &aMessage,
- uint16_t & aOffset,
- uint16_t aHeaderOffset,
- char * aLabelBuffer,
- uint8_t & aLabelLength);
-
- /**
- * This static method reads a full name from a message.
- *
- * On successful read, the read name follows "<label1>.<label2>.<label3>.", i.e., a sequence of labels separated by
- * dot '.' character. The read name will ALWAYS end with a dot.
- *
- * This method verifies that the read labels in message do not contain any dot character, otherwise it returns
- * `OT_ERROR_PARSE`).
- *
- * @param[in] aMessage The message to read the name from.
- * @param[inout] 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[in] aHeaderOffset The offset in @p aMessage to the start of the DNS header.
- * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string.
- * @param[inout] aNameBufferSize The maximum number chars in @p aNameBuffer array.
- *
- * @retval OT_ERROR_NONE Successfully read the name, @p aNameBuffer and @p Offset are updated.
- * @retval OT_ERROR_PARSE Name could not be parsed (invalid format).
- * @retval OT_ERROR_NO_BUFS Name could not fit in @p aNameBufferSize chars.
- *
- */
- static otError ReadName(const Message &aMessage,
- uint16_t & aOffset,
- uint16_t aHeaderOffset,
- char * aNameBuffer,
- uint16_t aNameBufferSize);
-
-private:
- enum : char
- {
- kNullChar = '\0',
- kLabelSeperatorChar = '.',
- };
-
- enum : uint8_t
- {
- // The first 2 bits of the encoded label specifies label type.
- //
- // - Value 00 indicates normal text label (lower 6-bits indicates the label length).
- // - Value 11 indicates pointer label type (lower 14-bits indicates the pointer offset).
- // - Values 01,10 are reserved (RFC 6891 recommends to not use)
-
- kLabelTypeMask = 0xc0, // 0b1100_0000 (first two bits)
- kTextLabelType = 0x00, // Text label type (00)
- kPointerLabelType = 0xc0, // Pointer label type - compressed name (11)
- };
-
- enum : uint16_t
- {
- kPointerLabelTypeUint16 = 0xc000, // Pointer label type as `uint16_t` mask (first 2 bits).
- kPointerLabelOffsetMask = 0x3fff, // Mask to get the offset field in a pointer label (lower 14 bits).
- };
-
- struct LabelIterator
- {
- enum : uint16_t
- {
- kUnsetNameEndOffset = 0, // Special value indicating `mNameEndOffset` is not yet set.
- };
-
- LabelIterator(const Message &aMessage, uint16_t aLabelOffset, uint16_t aHeaderOffset = 0)
- : mMessage(aMessage)
- , mHeaderOffset(aHeaderOffset)
- , mNextLabelOffset(aLabelOffset)
- , mNameEndOffset(kUnsetNameEndOffset)
- {
- }
-
- bool IsEndOffsetSet(void) const { return (mNameEndOffset != kUnsetNameEndOffset); }
- otError GetNextLabel(void);
- otError ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength, bool aAllowDotCharInLabel) const;
-
- const Message &mMessage; // Message to read labels from.
- const uint16_t mHeaderOffset; // Offset in `mMessage` to the start of DNS header.
- uint16_t mLabelStartOffset; // Offset in `mMessage` to the first char of current label text.
- uint8_t mLabelLength; // Length of current label (number of chars).
- uint16_t mNextLabelOffset; // Offset in `mMessage` to the start of the next label.
- uint16_t mNameEndOffset; // Offset in `mMessage` to the byte after the end of domain name field.
- };
-
- Name(void) = default;
-
- static otError AppendLabel(const char *aLabel, uint8_t aLabelLength, Message &aMessage);
-};
-
-/**
- * This class implements Resource Record body format (RR).
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ResourceRecord
-{
-public:
- /**
- * Resource Record Types.
- *
- */
- enum : uint16_t
- {
- kTypeA = 1, ///< Address record (IPv4).
- kTypePtr = 12, ///< PTR record.
- kTypeTxt = 16, ///< TXT record.
- kTypeSrv = 33, ///< SRV locator record.
- kTypeAaaa = 28, ///< IPv6 address record.
- kTypeKey = 25, ///< Key record.
- kTypeOpt = 41, ///< Option record.
- };
-
- /**
- * Resource Record Class Codes.
- *
- */
- enum : uint16_t
- {
- kClassInternet = 1, ///< Class code Internet (IN).
- };
-
- /**
- * This method initializes the resource record.
- *
- * @param[in] aType The type of the resource record.
- * @param[in] aClass The class of the resource record (default is `kClassInternet`).
- * @param[in] aTtl The time to live field of the resource record (default is zero).
- *
- */
- void Init(uint16_t aType, uint16_t aClass = kClassInternet, uint32_t aTtl = 0);
-
- /**
- * This method indicates whether the resources records matches a given type and class code.
- *
- * @param[in] aType The resource record type to compare with.
- * @param[in] aClass The resource record class code to compare with (default is `kClassInternet`).
- *
- * @returns TRUE if the resources records matches @p aType and @p aClass, FALSE otherwise.
- *
- */
- bool Matches(uint16_t aType, uint16_t aClass = kClassInternet)
- {
- return (mType == HostSwap16(aType)) && (mClass == HostSwap16(aClass));
- }
-
- /**
- * This method returns the type of the resource record.
- *
- * @returns The type of the resource record.
- *
- */
- uint16_t GetType(void) const { return HostSwap16(mType); }
-
- /**
- * This method sets the type of the resource record.
- *
- * @param[in] aType The type of the resource record.
- *
- */
- void SetType(uint16_t aType) { mType = HostSwap16(aType); }
-
- /**
- * This method returns the class of the resource record.
- *
- * @returns The class of the resource record.
- */
- uint16_t GetClass(void) const { return HostSwap16(mClass); }
-
- /**
- * This method sets the class of the resource record.
- *
- * @param[in] aClass The class of the resource record.
- *
- */
- void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
-
- /**
- * This method returns the time to live field of the resource record.
- *
- * @returns The time to live field of the resource record.
- *
- */
- uint32_t GetTtl(void) const { return HostSwap32(mTtl); }
-
- /**
- * This method sets the time to live field of the resource record.
- *
- * @param[in] aTtl The time to live field of the resource record.
- *
- */
- void SetTtl(uint32_t aTtl) { mTtl = HostSwap32(aTtl); }
-
- /**
- * This method returns the length of the resource record.
- *
- * @returns The length of the resource record.
- */
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
-
- /**
- * This method sets the length of the resource record.
- *
- * @param[in] aLength The length of the resource record.
- *
- */
- void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
-
- /**
- * This method returns the size of (number of bytes) in resource record and its data RDATA section (excluding the
- * name field).
- *
- * @returns Size (number of bytes) of resource record and its data section (excluding the name field)
- *
- */
- uint32_t GetSize(void) const { return sizeof(ResourceRecord) + GetLength(); }
-
-private:
- uint16_t mType; // The type of the data in RDATA section.
- uint16_t mClass; // The class of the data in RDATA section.
- uint32_t mTtl; // Specifies the maximum time that the resource record may be cached.
- uint16_t mLength; // The length of RDATA section in bytes.
-
-} OT_TOOL_PACKED_END;
-
-/**
- * This class implements Resource Record body format of AAAA type.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class ResourceRecordAaaa : public ResourceRecord
-{
-public:
- /**
- * This method initializes the AAAA Resource Record.
- *
- */
- void Init(void);
-
- /**
- * This method sets the IPv6 address of the resource record.
- *
- * @param[in] aAddress The IPv6 address of the resource record.
- *
- */
- void SetAddress(Ip6::Address &aAddress) { mAddress = aAddress; }
-
- /**
- * This method returns the reference to IPv6 address of the resource record.
- *
- * @returns The reference to IPv6 address of the resource record.
- *
- */
- Ip6::Address &GetAddress(void) { return mAddress; }
-
-private:
- Ip6::Address mAddress; // IPv6 Address of AAAA Resource Record.
-} OT_TOOL_PACKED_END;
-
-/**
- * This class implements Question format.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class Question
-{
-public:
- /**
- * Constructor for Question.
- *
- */
- Question(uint16_t aType, uint16_t aClass)
- {
- SetType(aType);
- SetClass(aClass);
- }
-
- /**
- * This method returns the type of the question.
- *
- * @returns The type of the question.
- *
- */
- uint16_t GetType(void) const { return HostSwap16(mType); }
-
- /**
- * This method sets the type of the question.
- *
- * @param[in] aType The type of the question.
- *
- */
- void SetType(uint16_t aType) { mType = HostSwap16(aType); }
-
- /**
- * This method returns the class of the question.
- *
- * @returns The class of the question.
- *
- */
- uint16_t GetClass(void) const { return HostSwap16(mClass); }
-
- /**
- * This method sets the class of the question.
- *
- * @param[in] aClass The class of the question.
- *
- */
- void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
-
-private:
- uint16_t mType; // The type of the data in question section.
- uint16_t mClass; // The class of the data in question section.
-
-} OT_TOOL_PACKED_END;
-
-/**
- * This class implements Question format of AAAA type.
- *
- */
-class QuestionAaaa : public Question
-{
-public:
- /**
- * Default constructor for AAAA Question.
- *
- */
- QuestionAaaa(void)
- : Question(kType, kClass)
- {
- }
-
- /**
- * This method appends request data to the message.
- *
- * @param[in] aMessage A reference to the message.
- *
- * @retval OT_ERROR_NONE Successfully appended the bytes.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
- *
- */
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
-
-private:
- enum
- {
- kType = 0x1C, // AAAA Resource Record type.
- kClass = 0x01, // The value of the Internet class.
- };
-};
-
-/**
- * @}
- *
- */
-
-} // namespace Dns
-} // namespace ot
-
-#endif // DNS_HEADER_HPP_
diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp
new file mode 100644
index 0000000..631051b
--- /dev/null
+++ b/src/core/net/dns_types.cpp
@@ -0,0 +1,1042 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements generating and processing of DNS headers and helper functions/methods.
+ */
+
+#include "dns_types.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/logging.hpp"
+#include "common/random.hpp"
+#include "common/string.hpp"
+
+namespace ot {
+namespace Dns {
+
+using ot::Encoding::BigEndian::HostSwap16;
+
+Error Header::SetRandomMessageId(void)
+{
+ return Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&mMessageId), sizeof(mMessageId));
+}
+
+Error Header::ResponseCodeToError(Response aResponse)
+{
+ Error error = kErrorFailed;
+
+ switch (aResponse)
+ {
+ case kResponseSuccess:
+ error = kErrorNone;
+ break;
+
+ case kResponseFormatError: // Server unable to interpret request due to format error.
+ case kResponseBadName: // Bad name.
+ case kResponseBadTruncation: // Bad truncation.
+ case kResponseNotZone: // A name is not in the zone.
+ error = kErrorParse;
+ break;
+
+ case kResponseServerFailure: // Server encountered an internal failure.
+ error = kErrorFailed;
+ break;
+
+ case kResponseNameError: // Name that ought to exist, does not exists.
+ case kResponseRecordNotExists: // Some RRset that ought to exist, does not exist.
+ error = kErrorNotFound;
+ break;
+
+ case kResponseNotImplemented: // Server does not support the query type (OpCode).
+ error = kErrorNotImplemented;
+ break;
+
+ case kResponseBadAlg: // Bad algorithm.
+ error = kErrorNotCapable;
+ break;
+
+ case kResponseNameExists: // Some name that ought not to exist, does exist.
+ case kResponseRecordExists: // Some RRset that ought not to exist, does exist.
+ error = kErrorDuplicated;
+ break;
+
+ case kResponseRefused: // Server refused to perform operation for policy or security reasons.
+ case kResponseNotAuth: // Service is not authoritative for zone.
+ error = kErrorSecurity;
+ break;
+
+ default:
+ break;
+ }
+
+ return error;
+}
+
+Error Name::AppendLabel(const char *aLabel, Message &aMessage)
+{
+ return AppendLabel(aLabel, static_cast<uint8_t>(StringLength(aLabel, kMaxLabelSize)), aMessage);
+}
+
+Error Name::AppendLabel(const char *aLabel, uint8_t aLength, Message &aMessage)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit((0 < aLength) && (aLength <= kMaxLabelLength), error = kErrorInvalidArgs);
+
+ SuccessOrExit(error = aMessage.Append(aLength));
+ error = aMessage.AppendBytes(aLabel, aLength);
+
+exit:
+ return error;
+}
+
+Error Name::AppendMultipleLabels(const char *aLabels, Message &aMessage)
+{
+ return AppendMultipleLabels(aLabels, kMaxNameLength, aMessage);
+}
+
+Error Name::AppendMultipleLabels(const char *aLabels, uint8_t aLength, Message &aMessage)
+{
+ Error error = kErrorNone;
+ uint16_t index = 0;
+ uint16_t labelStartIndex = 0;
+ char ch;
+
+ VerifyOrExit(aLabels != nullptr);
+
+ do
+ {
+ ch = index < aLength ? aLabels[index] : static_cast<char>(kNullChar);
+
+ if ((ch == kNullChar) || (ch == kLabelSeperatorChar))
+ {
+ uint8_t labelLength = static_cast<uint8_t>(index - labelStartIndex);
+
+ if (labelLength == 0)
+ {
+ // Empty label (e.g., consecutive dots) is invalid, but we
+ // allow for two cases: (1) where `aLabels` ends with a dot
+ // (`labelLength` is zero but we are at end of `aLabels` string
+ // and `ch` is null char. (2) if `aLabels` is just "." (we
+ // see a dot at index 0, and index 1 is null char).
+
+ error =
+ ((ch == kNullChar) || ((index == 0) && (aLabels[1] == kNullChar))) ? kErrorNone : kErrorInvalidArgs;
+ ExitNow();
+ }
+
+ VerifyOrExit(index + 1 < kMaxEncodedLength, error = kErrorInvalidArgs);
+ SuccessOrExit(error = AppendLabel(&aLabels[labelStartIndex], labelLength, aMessage));
+
+ labelStartIndex = index + 1;
+ }
+
+ index++;
+
+ } while (ch != kNullChar);
+
+exit:
+ return error;
+}
+
+Error Name::AppendTerminator(Message &aMessage)
+{
+ uint8_t terminator = 0;
+
+ return aMessage.Append(terminator);
+}
+
+Error Name::AppendPointerLabel(uint16_t aOffset, Message &aMessage)
+{
+ // A pointer label takes the form of a two byte sequence as a
+ // `uint16_t` value. The first two bits are ones. This allows a
+ // pointer to be distinguished from a text label, since the text
+ // label must begin with two zero bits (note that labels are
+ // restricted to 63 octets or less). The next 14-bits specify
+ // an offset value relative to start of DNS header.
+
+ uint16_t value;
+
+ OT_ASSERT(aOffset < kPointerLabelTypeUint16);
+
+ value = HostSwap16(aOffset | kPointerLabelTypeUint16);
+
+ return aMessage.Append(value);
+}
+
+Error Name::AppendName(const char *aName, Message &aMessage)
+{
+ Error error;
+
+ SuccessOrExit(error = AppendMultipleLabels(aName, aMessage));
+ error = AppendTerminator(aMessage);
+
+exit:
+ return error;
+}
+
+Error Name::ParseName(const Message &aMessage, uint16_t &aOffset)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+
+ while (true)
+ {
+ error = iterator.GetNextLabel();
+
+ switch (error)
+ {
+ case kErrorNone:
+ break;
+
+ case kErrorNotFound:
+ // We reached the end of name successfully.
+ aOffset = iterator.mNameEndOffset;
+ error = kErrorNone;
+
+ OT_FALL_THROUGH;
+
+ default:
+ ExitNow();
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Name::ReadLabel(const Message &aMessage, uint16_t &aOffset, char *aLabelBuffer, uint8_t &aLabelLength)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+
+ SuccessOrExit(error = iterator.GetNextLabel());
+ SuccessOrExit(error = iterator.ReadLabel(aLabelBuffer, aLabelLength, /* aAllowDotCharInLabel */ true));
+ aOffset = iterator.mNextLabelOffset;
+
+exit:
+ return error;
+}
+
+Error Name::ReadName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+ bool firstLabel = true;
+ uint8_t labelLength;
+
+ while (true)
+ {
+ error = iterator.GetNextLabel();
+
+ switch (error)
+ {
+ case kErrorNone:
+
+ if (!firstLabel)
+ {
+ *aNameBuffer++ = kLabelSeperatorChar;
+ aNameBufferSize--;
+
+ // No need to check if we have reached end of the name buffer
+ // here since `iterator.ReadLabel()` would verify it.
+ }
+
+ labelLength = static_cast<uint8_t>(OT_MIN(static_cast<uint8_t>(kMaxLabelSize), aNameBufferSize));
+ SuccessOrExit(error = iterator.ReadLabel(aNameBuffer, labelLength, /* aAllowDotCharInLabel */ false));
+ aNameBuffer += labelLength;
+ aNameBufferSize -= labelLength;
+ firstLabel = false;
+ break;
+
+ case kErrorNotFound:
+ // We reach the end of name successfully. Always add a terminating dot
+ // at the end.
+ *aNameBuffer++ = kLabelSeperatorChar;
+ aNameBufferSize--;
+ VerifyOrExit(aNameBufferSize >= sizeof(uint8_t), error = kErrorNoBufs);
+ *aNameBuffer = kNullChar;
+ aOffset = iterator.mNameEndOffset;
+ error = kErrorNone;
+
+ OT_FALL_THROUGH;
+
+ default:
+ ExitNow();
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Name::CompareLabel(const Message &aMessage, uint16_t &aOffset, const char *aLabel)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+
+ SuccessOrExit(error = iterator.GetNextLabel());
+ VerifyOrExit(iterator.CompareLabel(aLabel, /* aIsSingleLabel */ true), error = kErrorNotFound);
+ aOffset = iterator.mNextLabelOffset;
+
+exit:
+ return error;
+}
+
+Error Name::CompareName(const Message &aMessage, uint16_t &aOffset, const char *aName)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+ bool matches = true;
+
+ if (*aName == kLabelSeperatorChar)
+ {
+ aName++;
+ VerifyOrExit(*aName == kNullChar, error = kErrorInvalidArgs);
+ }
+
+ while (true)
+ {
+ error = iterator.GetNextLabel();
+
+ switch (error)
+ {
+ case kErrorNone:
+ if (matches && !iterator.CompareLabel(aName, /* aIsSingleLabel */ false))
+ {
+ matches = false;
+ }
+
+ break;
+
+ case kErrorNotFound:
+ // We reached the end of the name in `aMessage`. We check if
+ // all the previous labels matched so far, and we are also
+ // at the end of `aName` string (see null char), then we
+ // return `kErrorNone` indicating a successful comparison
+ // (full match). Otherwise we return `kErrorNotFound` to
+ // indicate failed comparison.
+
+ if (matches && (*aName == kNullChar))
+ {
+ error = kErrorNone;
+ }
+
+ aOffset = iterator.mNameEndOffset;
+
+ OT_FALL_THROUGH;
+
+ default:
+ ExitNow();
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Name::CompareName(const Message &aMessage, uint16_t &aOffset, const Message &aMessage2, uint16_t aOffset2)
+{
+ Error error;
+ LabelIterator iterator(aMessage, aOffset);
+ LabelIterator iterator2(aMessage2, aOffset2);
+ bool matches = true;
+
+ while (true)
+ {
+ error = iterator.GetNextLabel();
+
+ switch (error)
+ {
+ case kErrorNone:
+ // If all the previous labels matched so far, then verify
+ // that we can get the next label on `iterator2` and that it
+ // matches the label from `iterator`.
+ if (matches && (iterator2.GetNextLabel() != kErrorNone || !iterator.CompareLabel(iterator2)))
+ {
+ matches = false;
+ }
+
+ break;
+
+ case kErrorNotFound:
+ // We reached the end of the name in `aMessage`. We check
+ // that `iterator2` is also at its end, and if all previous
+ // labels matched we return `kErrorNone`.
+
+ if (matches && (iterator2.GetNextLabel() == kErrorNotFound))
+ {
+ error = kErrorNone;
+ }
+
+ aOffset = iterator.mNameEndOffset;
+
+ OT_FALL_THROUGH;
+
+ default:
+ ExitNow();
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Name::CompareName(const Message &aMessage, uint16_t &aOffset, const Name &aName)
+{
+ return aName.IsFromCString()
+ ? CompareName(aMessage, aOffset, aName.mString)
+ : (aName.IsFromMessage() ? CompareName(aMessage, aOffset, *aName.mMessage, aName.mOffset)
+ : ParseName(aMessage, aOffset));
+}
+
+Error Name::LabelIterator::GetNextLabel(void)
+{
+ Error error;
+
+ while (true)
+ {
+ uint8_t labelLength;
+ uint8_t labelType;
+
+ SuccessOrExit(error = mMessage.Read(mNextLabelOffset, labelLength));
+
+ labelType = labelLength & kLabelTypeMask;
+
+ if (labelType == kTextLabelType)
+ {
+ if (labelLength == 0)
+ {
+ // Zero label length indicates end of a name.
+
+ if (!IsEndOffsetSet())
+ {
+ mNameEndOffset = mNextLabelOffset + sizeof(uint8_t);
+ }
+
+ ExitNow(error = kErrorNotFound);
+ }
+
+ mLabelStartOffset = mNextLabelOffset + sizeof(uint8_t);
+ mLabelLength = labelLength;
+ mNextLabelOffset = mLabelStartOffset + labelLength;
+ ExitNow();
+ }
+ else if (labelType == kPointerLabelType)
+ {
+ // A pointer label takes the form of a two byte sequence as a
+ // `uint16_t` value. The first two bits are ones. The next 14 bits
+ // specify an offset value from the start of the DNS header.
+
+ uint16_t pointerValue;
+
+ SuccessOrExit(error = mMessage.Read(mNextLabelOffset, pointerValue));
+
+ if (!IsEndOffsetSet())
+ {
+ mNameEndOffset = mNextLabelOffset + sizeof(uint16_t);
+ }
+
+ // `mMessage.GetOffset()` must point to the start of the
+ // DNS header.
+ mNextLabelOffset = mMessage.GetOffset() + (HostSwap16(pointerValue) & kPointerLabelOffsetMask);
+
+ // Go back through the `while(true)` loop to get the next label.
+ }
+ else
+ {
+ ExitNow(error = kErrorParse);
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Name::LabelIterator::ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength, bool aAllowDotCharInLabel) const
+{
+ Error error;
+
+ VerifyOrExit(mLabelLength < aLabelLength, error = kErrorNoBufs);
+
+ SuccessOrExit(error = mMessage.Read(mLabelStartOffset, aLabelBuffer, mLabelLength));
+ aLabelBuffer[mLabelLength] = kNullChar;
+ aLabelLength = mLabelLength;
+
+ if (!aAllowDotCharInLabel)
+ {
+ VerifyOrExit(StringFind(aLabelBuffer, kLabelSeperatorChar) == nullptr, error = kErrorParse);
+ }
+
+exit:
+ return error;
+}
+
+bool Name::LabelIterator::CompareLabel(const char *&aName, bool aIsSingleLabel) const
+{
+ // This method compares the current label in the iterator with the
+ // `aName` string. `aIsSingleLabel` indicates whether `aName` is a
+ // single label, or a sequence of labels separated by dot '.' char.
+ // If the label matches `aName`, then `aName` pointer is moved
+ // forward to the start of the next label (skipping over the `.`
+ // char). This method returns `true` when the labels match, `false`
+ // otherwise.
+
+ bool matches = false;
+
+ VerifyOrExit(StringLength(aName, mLabelLength) == mLabelLength);
+ matches = mMessage.CompareBytes(mLabelStartOffset, aName, mLabelLength);
+
+ VerifyOrExit(matches);
+
+ aName += mLabelLength;
+
+ // If `aName` is a single label, we should be also at the end of the
+ // `aName` string. Otherwise, we should see either null or dot '.'
+ // character (in case `aName` contains multiple labels).
+
+ matches = (*aName == kNullChar);
+
+ if (!aIsSingleLabel && (*aName == kLabelSeperatorChar))
+ {
+ matches = true;
+ aName++;
+ }
+
+exit:
+ return matches;
+}
+
+bool Name::LabelIterator::CompareLabel(const LabelIterator &aOtherIterator) const
+{
+ // This method compares the current label in the iterator with the
+ // label from another iterator.
+
+ return (mLabelLength == aOtherIterator.mLabelLength) &&
+ mMessage.CompareBytes(mLabelStartOffset, aOtherIterator.mMessage, aOtherIterator.mLabelStartOffset,
+ mLabelLength);
+}
+
+bool Name::IsSubDomainOf(const char *aName, const char *aDomain)
+{
+ bool match = false;
+ uint16_t nameLength = StringLength(aName, kMaxNameLength);
+ uint16_t domainLength = StringLength(aDomain, kMaxNameLength);
+
+ if (nameLength > 0 && aName[nameLength - 1] == kLabelSeperatorChar)
+ {
+ --nameLength;
+ }
+
+ if (domainLength > 0 && aDomain[domainLength - 1] == kLabelSeperatorChar)
+ {
+ --domainLength;
+ }
+
+ VerifyOrExit(nameLength >= domainLength);
+ aName += nameLength - domainLength;
+
+ if (nameLength > domainLength)
+ {
+ VerifyOrExit(aName[-1] == kLabelSeperatorChar);
+ }
+ VerifyOrExit(memcmp(aName, aDomain, domainLength) == 0);
+
+ match = true;
+
+exit:
+ return match;
+}
+
+Error ResourceRecord::ParseRecords(const Message &aMessage, uint16_t &aOffset, uint16_t aNumRecords)
+{
+ Error error = kErrorNone;
+
+ while (aNumRecords > 0)
+ {
+ ResourceRecord record;
+
+ SuccessOrExit(error = Name::ParseName(aMessage, aOffset));
+ SuccessOrExit(error = record.ReadFrom(aMessage, aOffset));
+ aOffset += static_cast<uint16_t>(record.GetSize());
+ aNumRecords--;
+ }
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::FindRecord(const Message &aMessage, uint16_t &aOffset, uint16_t &aNumRecords, const Name &aName)
+{
+ Error error;
+
+ while (aNumRecords > 0)
+ {
+ bool matches = true;
+ ResourceRecord record;
+
+ error = Name::CompareName(aMessage, aOffset, aName);
+
+ switch (error)
+ {
+ case kErrorNone:
+ break;
+ case kErrorNotFound:
+ matches = false;
+ break;
+ default:
+ ExitNow();
+ }
+
+ SuccessOrExit(error = record.ReadFrom(aMessage, aOffset));
+ aNumRecords--;
+ VerifyOrExit(!matches);
+ aOffset += static_cast<uint16_t>(record.GetSize());
+ }
+
+ error = kErrorNotFound;
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::FindRecord(const Message & aMessage,
+ uint16_t & aOffset,
+ uint16_t aNumRecords,
+ uint16_t aIndex,
+ const Name & aName,
+ uint16_t aType,
+ ResourceRecord &aRecord,
+ uint16_t aMinRecordSize)
+{
+ // This static method searches in `aMessage` starting from `aOffset`
+ // up to maximum of `aNumRecords`, for the `(aIndex+1)`th
+ // occurrence of a resource record of type `aType` with record name
+ // matching `aName`. It also verifies that the record size is larger
+ // than `aMinRecordSize`. If found, `aMinRecordSize` bytes from the
+ // record are read and copied into `aRecord`. In this case `aOffset`
+ // is updated to point to the last record byte read from the message
+ // (so that the caller can read any remaining fields in the record
+ // data).
+
+ Error error;
+ uint16_t offset = aOffset;
+ uint16_t recordOffset;
+
+ while (aNumRecords > 0)
+ {
+ SuccessOrExit(error = FindRecord(aMessage, offset, aNumRecords, aName));
+
+ // Save the offset to start of `ResourceRecord` fields.
+ recordOffset = offset;
+
+ error = ReadRecord(aMessage, offset, aType, aRecord, aMinRecordSize);
+
+ if (error == kErrorNotFound)
+ {
+ // `ReadRecord()` already updates the `offset` to skip
+ // over a non-matching record.
+ continue;
+ }
+
+ SuccessOrExit(error);
+
+ if (aIndex == 0)
+ {
+ aOffset = offset;
+ ExitNow();
+ }
+
+ aIndex--;
+
+ // Skip over the record.
+ offset = static_cast<uint16_t>(recordOffset + aRecord.GetSize());
+ }
+
+ error = kErrorNotFound;
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::ReadRecord(const Message & aMessage,
+ uint16_t & aOffset,
+ uint16_t aType,
+ ResourceRecord &aRecord,
+ uint16_t aMinRecordSize)
+{
+ // This static method tries to read a matching resource record of a
+ // given type and a minimum record size from a message. The `aType`
+ // value of `kTypeAny` matches any type. If the record in the
+ // message does not match, it skips over the record. Please see
+ // `ReadRecord<RecordType>()` for more details.
+
+ Error error;
+ ResourceRecord record;
+
+ SuccessOrExit(error = record.ReadFrom(aMessage, aOffset));
+
+ if (((aType == kTypeAny) || (record.GetType() == aType)) && (record.GetSize() >= aMinRecordSize))
+ {
+ IgnoreError(aMessage.Read(aOffset, &aRecord, aMinRecordSize));
+ aOffset += aMinRecordSize;
+ }
+ else
+ {
+ // Skip over the entire record.
+ aOffset += static_cast<uint16_t>(record.GetSize());
+ error = kErrorNotFound;
+ }
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::ReadName(const Message &aMessage,
+ uint16_t & aOffset,
+ uint16_t aStartOffset,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize,
+ bool aSkipRecord) const
+{
+ // This protected method parses and reads a name field in a record
+ // from a message. It is intended only for sub-classes of
+ // `ResourceRecord`.
+ //
+ // On input `aOffset` gives the offset in `aMessage` to the start of
+ // name field. `aStartOffset` gives the offset to the start of the
+ // `ResourceRecord`. `aSkipRecord` indicates whether to skip over
+ // the entire resource record or just the read name. On exit, when
+ // successfully read, `aOffset` is updated to either point after the
+ // end of record or after the the name field.
+ //
+ // When read successfully, this method returns `kErrorNone`. On a
+ // parse error (invalid format) returns `kErrorParse`. If the
+ // name does not fit in the given name buffer it returns
+ // `kErrorNoBufs`
+
+ Error error = kErrorNone;
+
+ SuccessOrExit(error = Name::ReadName(aMessage, aOffset, aNameBuffer, aNameBufferSize));
+ VerifyOrExit(aOffset <= aStartOffset + GetSize(), error = kErrorParse);
+
+ VerifyOrExit(aSkipRecord);
+ aOffset = aStartOffset;
+ error = SkipRecord(aMessage, aOffset);
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::SkipRecord(const Message &aMessage, uint16_t &aOffset) const
+{
+ // This protected method parses and skips over a resource record
+ // in a message.
+ //
+ // On input `aOffset` gives the offset in `aMessage` to the start of
+ // the `ResourceRecord`. On exit, when successfully parsed, `aOffset`
+ // is updated to point to byte after the entire record.
+
+ Error error;
+
+ SuccessOrExit(error = CheckRecord(aMessage, aOffset));
+ aOffset += static_cast<uint16_t>(GetSize());
+
+exit:
+ return error;
+}
+
+Error ResourceRecord::CheckRecord(const Message &aMessage, uint16_t aOffset) const
+{
+ // This method checks that the entire record (including record data)
+ // is present in `aMessage` at `aOffset` (pointing to the start of
+ // the `ResourceRecord` in `aMessage`).
+
+ return (aOffset + GetSize() <= aMessage.GetLength()) ? kErrorNone : kErrorParse;
+}
+
+Error ResourceRecord::ReadFrom(const Message &aMessage, uint16_t aOffset)
+{
+ // This method reads the `ResourceRecord` from `aMessage` at
+ // `aOffset`. It verifies that the entire record (including record
+ // data) is present in the message.
+
+ Error error;
+
+ SuccessOrExit(error = aMessage.Read(aOffset, *this));
+ error = CheckRecord(aMessage, aOffset);
+
+exit:
+ return error;
+}
+
+void TxtEntry::Iterator::Init(const uint8_t *aTxtData, uint16_t aTxtDataLength)
+{
+ SetTxtData(aTxtData);
+ SetTxtDataLength(aTxtDataLength);
+ SetTxtDataPosition(0);
+}
+
+Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry)
+{
+ Error error = kErrorNone;
+ uint8_t length;
+ uint8_t index;
+ const char *cur;
+ char * keyBuffer = GetKeyBuffer();
+
+ static_assert(sizeof(mChar) == TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length");
+
+ VerifyOrExit(GetTxtData() != nullptr, error = kErrorParse);
+
+ aEntry.mKey = keyBuffer;
+
+ while ((cur = GetTxtData() + GetTxtDataPosition()) < GetTxtDataEnd())
+ {
+ length = static_cast<uint8_t>(*cur);
+
+ cur++;
+ VerifyOrExit(cur + length <= GetTxtDataEnd(), error = kErrorParse);
+ IncreaseTxtDataPosition(sizeof(uint8_t) + length);
+
+ // Silently skip over an empty string or if the string starts with
+ // a `=` character (i.e., missing key) - RFC 6763 - section 6.4.
+
+ if ((length == 0) || (cur[0] == kKeyValueSeparator))
+ {
+ continue;
+ }
+
+ for (index = 0; index < length; index++)
+ {
+ if (cur[index] == kKeyValueSeparator)
+ {
+ keyBuffer[index++] = kNullChar; // Increment index to skip over `=`.
+ aEntry.mValue = reinterpret_cast<const uint8_t *>(&cur[index]);
+ aEntry.mValueLength = length - index;
+ ExitNow();
+ }
+
+ if (index >= kMaxKeyLength)
+ {
+ // The key is larger than recommended max key length.
+ // In this case, we return the full encoded string in
+ // `mValue` and `mValueLength` and set `mKey` to
+ // `nullptr`.
+
+ aEntry.mKey = nullptr;
+ aEntry.mValue = reinterpret_cast<const uint8_t *>(cur);
+ aEntry.mValueLength = length;
+ ExitNow();
+ }
+
+ keyBuffer[index] = cur[index];
+ }
+
+ // If we reach the end of the string without finding `=` then
+ // it is a boolean key attribute (encoded as "key").
+
+ keyBuffer[index] = kNullChar;
+ aEntry.mValue = nullptr;
+ aEntry.mValueLength = 0;
+ ExitNow();
+ }
+
+ error = kErrorNotFound;
+
+exit:
+ return error;
+}
+
+Error TxtEntry::AppendTo(Message &aMessage) const
+{
+ Error error = kErrorNone;
+ uint16_t keyLength;
+
+ if (mKey == nullptr)
+ {
+ VerifyOrExit((mValue != nullptr) && (mValueLength != 0));
+ error = aMessage.AppendBytes(mValue, mValueLength);
+ ExitNow();
+ }
+
+ keyLength = StringLength(mKey, static_cast<uint16_t>(kMaxKeyValueEncodedSize) + 1);
+
+ VerifyOrExit(kMinKeyLength <= keyLength, error = kErrorInvalidArgs);
+
+ if (mValue == nullptr)
+ {
+ // Treat as a boolean attribute and encoded as "key" (with no `=`).
+ SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength)));
+ error = aMessage.AppendBytes(mKey, keyLength);
+ ExitNow();
+ }
+
+ // Treat as key/value and encode as "key=value", value may be empty.
+
+ VerifyOrExit(mValueLength + keyLength + sizeof(char) <= kMaxKeyValueEncodedSize, error = kErrorInvalidArgs);
+
+ SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength + mValueLength + sizeof(char))));
+ SuccessOrExit(error = aMessage.AppendBytes(mKey, keyLength));
+ SuccessOrExit(error = aMessage.Append<char>(kKeyValueSeparator));
+ error = aMessage.AppendBytes(mValue, mValueLength);
+
+exit:
+ return error;
+}
+
+Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage)
+{
+ Error error = kErrorNone;
+ uint16_t startOffset = aMessage.GetLength();
+
+ for (uint8_t index = 0; index < aNumEntries; index++)
+ {
+ SuccessOrExit(error = aEntries[index].AppendTo(aMessage));
+ }
+
+ if (aMessage.GetLength() == startOffset)
+ {
+ error = aMessage.Append<uint8_t>(0);
+ }
+
+exit:
+ return error;
+}
+
+bool AaaaRecord::IsValid(void) const
+{
+ return GetType() == Dns::ResourceRecord::kTypeAaaa && GetSize() == sizeof(*this);
+}
+
+bool KeyRecord::IsValid(void) const
+{
+ return GetType() == Dns::ResourceRecord::kTypeKey;
+}
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+void Ecdsa256KeyRecord::Init(void)
+{
+ KeyRecord::Init();
+ SetAlgorithm(kAlgorithmEcdsaP256Sha256);
+}
+
+bool Ecdsa256KeyRecord::IsValid(void) const
+{
+ return KeyRecord::IsValid() && GetLength() == sizeof(*this) - sizeof(ResourceRecord) &&
+ GetAlgorithm() == kAlgorithmEcdsaP256Sha256;
+}
+#endif
+
+bool SigRecord::IsValid(void) const
+{
+ return GetType() == Dns::ResourceRecord::kTypeSig && GetLength() >= sizeof(*this) - sizeof(ResourceRecord);
+}
+
+bool LeaseOption::IsValid(void) const
+{
+ return GetLeaseInterval() <= GetKeyLeaseInterval();
+}
+
+Error PtrRecord::ReadPtrName(const Message &aMessage,
+ uint16_t & aOffset,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const
+{
+ Error error = kErrorNone;
+ uint16_t startOffset = aOffset - sizeof(PtrRecord); // start of `PtrRecord`.
+
+ // Verify that the name is within the record data length.
+ SuccessOrExit(error = Name::ParseName(aMessage, aOffset));
+ VerifyOrExit(aOffset <= startOffset + GetSize(), error = kErrorParse);
+
+ aOffset = startOffset + sizeof(PtrRecord);
+ SuccessOrExit(error = Name::ReadLabel(aMessage, aOffset, aLabelBuffer, aLabelBufferSize));
+
+ if (aNameBuffer != nullptr)
+ {
+ SuccessOrExit(error = Name::ReadName(aMessage, aOffset, aNameBuffer, aNameBufferSize));
+ }
+
+ aOffset = startOffset;
+ error = SkipRecord(aMessage, aOffset);
+
+exit:
+ return error;
+}
+
+Error TxtRecord::ReadTxtData(const Message &aMessage,
+ uint16_t & aOffset,
+ uint8_t * aTxtBuffer,
+ uint16_t & aTxtBufferSize) const
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(GetLength() <= aTxtBufferSize, error = kErrorNoBufs);
+ SuccessOrExit(error = aMessage.Read(aOffset, aTxtBuffer, GetLength()));
+ VerifyOrExit(VerifyTxtData(aTxtBuffer, GetLength()), error = kErrorParse);
+ aTxtBufferSize = GetLength();
+ aOffset += GetLength();
+
+exit:
+ return error;
+}
+
+bool TxtRecord::VerifyTxtData(const uint8_t *aTxtData, uint16_t aTxtLength)
+{
+ bool valid = false;
+ uint8_t curEntryLength = 0;
+
+ // Per RFC 1035, TXT-DATA MUST have one or more <character-string>s.
+ VerifyOrExit(aTxtLength > 0);
+
+ for (uint16_t i = 0; i < aTxtLength; ++i)
+ {
+ if (curEntryLength == 0)
+ {
+ curEntryLength = aTxtData[i];
+ }
+ else
+ {
+ --curEntryLength;
+ }
+ }
+
+ valid = (curEntryLength == 0);
+
+exit:
+ return valid;
+}
+
+} // namespace Dns
+} // namespace ot
diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp
new file mode 100644
index 0000000..b9d40cb
--- /dev/null
+++ b/src/core/net/dns_types.hpp
@@ -0,0 +1,2608 @@
+/*
+ * Copyright (c) 2017, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for generating and processing DNS headers.
+ */
+
+#ifndef DNS_HEADER_HPP_
+#define DNS_HEADER_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/dns.h>
+#include <openthread/dns_client.h>
+
+#include "common/clearable.hpp"
+#include "common/encoding.hpp"
+#include "common/equatable.hpp"
+#include "common/message.hpp"
+#include "crypto/ecdsa.hpp"
+#include "net/ip6_address.hpp"
+
+namespace ot {
+
+/**
+ * @namespace ot::Dns
+ * @brief
+ * This namespace includes definitions for DNS.
+ *
+ */
+namespace Dns {
+
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+/**
+ * @addtogroup core-dns
+ *
+ * @brief
+ * This module includes definitions for DNS.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This class implements DNS header generation and parsing.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Header : public Clearable<Header>
+{
+public:
+ /**
+ * Default constructor for DNS Header.
+ *
+ */
+ Header(void) { Clear(); }
+
+ /**
+ * This method returns the Message ID.
+ *
+ * @returns The Message ID value.
+ *
+ */
+ uint16_t GetMessageId(void) const { return HostSwap16(mMessageId); }
+
+ /**
+ * This method sets the Message ID.
+ *
+ * @param[in] aMessageId The Message ID value.
+ *
+ */
+ void SetMessageId(uint16_t aMessageId) { mMessageId = HostSwap16(aMessageId); }
+
+ /**
+ * This method sets the Message ID to a crypto-secure randomly generated number.
+ *
+ * @retval kErrorNone Successfully generated random Message ID.
+ * @retval kErrorFailed Could not generate random Message ID.
+ *
+ */
+ Error SetRandomMessageId(void);
+
+ /**
+ * Defines types of DNS message.
+ *
+ */
+ enum Type
+ {
+ kTypeQuery = 0,
+ kTypeResponse = 1,
+ };
+
+ /**
+ * This method returns the type of the message.
+ *
+ * @returns The type of the message.
+ *
+ */
+ Type GetType(void) const { return static_cast<Type>((mFlags[0] & kQrFlagMask) >> kQrFlagOffset); }
+
+ /**
+ * This method sets the type of the message.
+ *
+ * @param[in] aType The type of the message.
+ *
+ */
+ void SetType(Type aType)
+ {
+ mFlags[0] &= ~kQrFlagMask;
+ mFlags[0] |= static_cast<uint8_t>(aType) << kQrFlagOffset;
+ }
+
+ /**
+ * Defines types of query.
+ *
+ */
+ enum QueryType
+ {
+ kQueryTypeStandard = 0,
+ kQueryTypeInverse = 1,
+ kQueryTypeStatus = 2,
+ kQueryTypeNotify = 4,
+ kQueryTypeUpdate = 5
+ };
+
+ /**
+ * This method returns the type of the query.
+ *
+ * @returns The type of the query.
+ *
+ */
+ QueryType GetQueryType(void) const { return static_cast<QueryType>((mFlags[0] & kOpCodeMask) >> kOpCodeOffset); }
+
+ /**
+ * This method sets the type of the query.
+ *
+ * @param[in] aType The type of the query.
+ *
+ */
+ void SetQueryType(QueryType aType)
+ {
+ mFlags[0] &= ~kOpCodeMask;
+ mFlags[0] |= static_cast<uint8_t>(aType) << kOpCodeOffset;
+ }
+
+ /**
+ * This method specifies in response message if the responding name server is an
+ * authority for the domain name in question section.
+ *
+ * @returns True if Authoritative Answer flag (AA) is set in the header, false otherwise.
+ *
+ */
+ bool IsAuthoritativeAnswerFlagSet(void) const { return (mFlags[0] & kAaFlagMask) == kAaFlagMask; }
+
+ /**
+ * This method clears the Authoritative Answer flag (AA) in the header.
+ *
+ */
+ void ClearAuthoritativeAnswerFlag(void) { mFlags[0] &= ~kAaFlagMask; }
+
+ /**
+ * This method sets the Authoritative Answer flag (AA) in the header.
+ *
+ */
+ void SetAuthoritativeAnswerFlag(void) { mFlags[0] |= kAaFlagMask; }
+
+ /**
+ * This method specifies if message is truncated.
+ *
+ * @returns True if Truncation flag (TC) is set in the header, false otherwise.
+ *
+ */
+ bool IsTruncationFlagSet(void) const { return (mFlags[0] & kTcFlagMask) == kTcFlagMask; }
+
+ /**
+ * This method clears the Truncation flag (TC) in the header.
+ *
+ */
+ void ClearTruncationFlag(void) { mFlags[0] &= ~kTcFlagMask; }
+
+ /**
+ * This method sets the Truncation flag (TC) in the header.
+ *
+ */
+ void SetTruncationFlag(void) { mFlags[0] |= kTcFlagMask; }
+
+ /**
+ * This method specifies if resolver wants to direct the name server to pursue
+ * the query recursively.
+ *
+ * @returns True if Recursion Desired flag (RD) is set in the header, false otherwise.
+ *
+ */
+ bool IsRecursionDesiredFlagSet(void) const { return (mFlags[0] & kRdFlagMask) == kRdFlagMask; }
+
+ /**
+ * This method clears the Recursion Desired flag (RD) in the header.
+ *
+ */
+ void ClearRecursionDesiredFlag(void) { mFlags[0] &= ~kRdFlagMask; }
+
+ /**
+ * This method sets the Recursion Desired flag (RD) in the header.
+ *
+ */
+ void SetRecursionDesiredFlag(void) { mFlags[0] |= kRdFlagMask; }
+
+ /**
+ * This method denotes whether recursive query support is available in the name server.
+ *
+ * @returns True if Recursion Available flag (RA) is set in the header, false otherwise.
+ *
+ */
+ bool IsRecursionAvailableFlagSet(void) const { return (mFlags[1] & kRaFlagMask) == kRaFlagMask; }
+
+ /**
+ * This method clears the Recursion Available flag (RA) in the header.
+ *
+ */
+ void ClearRecursionAvailableFlag(void) { mFlags[1] &= ~kRaFlagMask; }
+
+ /**
+ * This method sets the Recursion Available flag (RA) in the header.
+ *
+ */
+ void SetRecursionAvailableFlag(void) { mFlags[1] |= kRaFlagMask; }
+
+ /**
+ * Defines response codes.
+ *
+ */
+ enum Response
+ {
+ kResponseSuccess = 0, ///< Success (no error condition).
+ kResponseFormatError = 1, ///< Server unable to interpret request due to format error.
+ kResponseServerFailure = 2, ///< Server encountered an internal failure.
+ kResponseNameError = 3, ///< Name that ought to exist, does not exists.
+ kResponseNotImplemented = 4, ///< Server does not support the query type (OpCode).
+ kResponseRefused = 5, ///< Server refused to perform operation for policy or security reasons.
+ kResponseNameExists = 6, ///< Some name that ought not to exist, does exist.
+ kResponseRecordExists = 7, ///< Some RRset that ought not to exist, does exist.
+ kResponseRecordNotExists = 8, ///< Some RRset that ought to exist, does not exist.
+ kResponseNotAuth = 9, ///< Service is not authoritative for zone.
+ kResponseNotZone = 10, ///< A name is not in the zone.
+ kResponseBadName = 20, ///< Bad name.
+ kResponseBadAlg = 21, ///< Bad algorithm.
+ kResponseBadTruncation = 22, ///< Bad truncation.
+ };
+
+ /**
+ * This method returns the response code.
+ *
+ * @returns The response code from the header.
+ *
+ */
+ Response GetResponseCode(void) const { return static_cast<Response>((mFlags[1] & kRCodeMask) >> kRCodeOffset); }
+
+ /**
+ * This method sets the response code.
+ *
+ * @param[in] aResponse The type of the response.
+ *
+ */
+ void SetResponseCode(Response aResponse)
+ {
+ mFlags[1] &= ~kRCodeMask;
+ mFlags[1] |= static_cast<uint8_t>(aResponse) << kRCodeOffset;
+ }
+
+ /**
+ * This method converts a Response Code into a related `Error`.
+ *
+ * - kResponseSuccess (0) : Success (no error condition) -> kErrorNone
+ * - kResponseFormatError (1) : Server unable to interpret due to format error -> kErrorParse
+ * - kResponseServerFailure (2) : Server encountered an internal failure -> kErrorFailed
+ * - kResponseNameError (3) : Name that ought to exist, does not exists -> kErrorNotFound
+ * - kResponseNotImplemented (4) : Server does not support the query type (OpCode) -> kErrorNotImplemented
+ * - kResponseRefused (5) : Server refused for policy/security reasons -> kErrorSecurity
+ * - kResponseNameExists (6) : Some name that ought not to exist, does exist -> kErrorDuplicated
+ * - kResponseRecordExists (7) : Some RRset that ought not to exist, does exist -> kErrorDuplicated
+ * - kResponseRecordNotExists (8) : Some RRset that ought to exist, does not exist -> kErrorNotFound
+ * - kResponseNotAuth (9) : Service is not authoritative for zone -> kErrorSecurity
+ * - kResponseNotZone (10) : A name is not in the zone -> kErrorParse
+ * - kResponseBadName (20) : Bad name -> kErrorParse
+ * - kResponseBadAlg (21) : Bad algorithm -> kErrorSecurity
+ * - kResponseBadTruncation (22) : Bad truncation -> kErrorParse
+ * - Other error -> kErrorFailed
+ *
+ * @param[in] aResponse The response code to convert.
+ *
+ */
+ static Error ResponseCodeToError(Response aResponse);
+
+ /**
+ * This method returns the number of entries in question section.
+ *
+ * @returns The number of entries in question section.
+ *
+ */
+ uint16_t GetQuestionCount(void) const { return HostSwap16(mQdCount); }
+
+ /**
+ * This method sets the number of entries in question section.
+ *
+ * @param[in] aCount The number of entries in question section.
+ *
+ */
+ void SetQuestionCount(uint16_t aCount) { mQdCount = HostSwap16(aCount); }
+
+ /**
+ * This method returns the number of entries in answer section.
+ *
+ * @returns The number of entries in answer section.
+ *
+ */
+ uint16_t GetAnswerCount(void) const { return HostSwap16(mAnCount); }
+
+ /**
+ * This method sets the number of entries in answer section.
+ *
+ * @param[in] aCount The number of entries in answer section.
+ *
+ */
+ void SetAnswerCount(uint16_t aCount) { mAnCount = HostSwap16(aCount); }
+
+ /**
+ * This method returns the number of entries in authority records section.
+ *
+ * @returns The number of entries in authority records section.
+ *
+ */
+ uint16_t GetAuthorityRecordCount(void) const { return HostSwap16(mNsCount); }
+
+ /**
+ * This method sets the number of entries in authority records section.
+ *
+ * @param[in] aCount The number of entries in authority records section.
+ *
+ */
+ void SetAuthorityRecordCount(uint16_t aCount) { mNsCount = HostSwap16(aCount); }
+
+ /**
+ * This method returns the number of entries in additional records section.
+ *
+ * @returns The number of entries in additional records section.
+ *
+ */
+ uint16_t GetAdditionalRecordCount(void) const { return HostSwap16(mArCount); }
+
+ /**
+ * This method sets the number of entries in additional records section.
+ *
+ * @param[in] aCount The number of entries in additional records section.
+ *
+ */
+ void SetAdditionalRecordCount(uint16_t aCount) { mArCount = HostSwap16(aCount); }
+
+private:
+ /**
+ * Protocol Constants (RFC 1035).
+ *
+ */
+ enum
+ {
+ kQrFlagOffset = 7, // QR Flag offset.
+ kQrFlagMask = 0x01 << kQrFlagOffset, // QR Flag mask.
+ kOpCodeOffset = 3, // OpCode field offset.
+ kOpCodeMask = 0x0f << kOpCodeOffset, // OpCode field mask.
+ kAaFlagOffset = 2, // AA Flag offset.
+ kAaFlagMask = 0x01 << kAaFlagOffset, // AA Flag mask.
+ kTcFlagOffset = 1, // TC Flag offset.
+ kTcFlagMask = 0x01 << kTcFlagOffset, // TC Flag mask.
+ kRdFlagOffset = 0, // RD Flag offset.
+ kRdFlagMask = 0x01 << kRdFlagOffset, // RD Flag mask.
+ kRaFlagOffset = 7, // RA Flag offset.
+ kRaFlagMask = 0x01 << kRaFlagOffset, // RA Flag mask.
+ kRCodeOffset = 0, // RCODE field offset.
+ kRCodeMask = 0x0f << kRCodeOffset, // RCODE field mask.
+ };
+
+ uint16_t mMessageId; // Message identifier for requester to match up replies to outstanding queries.
+ uint8_t mFlags[2]; // DNS header flags.
+ uint16_t mQdCount; // Number of entries in the question section.
+ uint16_t mAnCount; // Number of entries in the answer section.
+ uint16_t mNsCount; // Number of entries in the authority records section.
+ uint16_t mArCount; // Number of entries in the additional records section.
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements DNS Update message header generation and parsing.
+ *
+ * The DNS header specifies record counts for its four sections: Question, Answer, Authority, and Additional. A DNS
+ * Update header uses the same fields, and the same section formats, but the naming and use of these sections differs:
+ * DNS Update header uses Zone, Prerequisite, Update, Additional Data sections.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class UpdateHeader : public Header
+{
+public:
+ /**
+ * Default constructor for DNS Update message header.
+ *
+ */
+ UpdateHeader(void) { SetQueryType(kQueryTypeUpdate); }
+
+ /**
+ * This method returns the number of records in Zone section.
+ *
+ * @returns The number of records in Zone section.
+ *
+ */
+ uint16_t GetZoneRecordCount(void) const { return GetQuestionCount(); }
+
+ /**
+ * This method sets the number of records in Zone section.
+ *
+ * @param[in] aCount The number of records in Zone section.
+ *
+ */
+ void SetZoneRecordCount(uint16_t aCount) { SetQuestionCount(aCount); }
+
+ /**
+ * This method returns the number of records in Prerequisite section.
+ *
+ * @returns The number of records in Prerequisite section.
+ *
+ */
+ uint16_t GetPrerequisiteRecordCount(void) const { return GetAnswerCount(); }
+
+ /**
+ * This method sets the number of records in Prerequisite section.
+ *
+ * @param[in] aCount The number of records in Prerequisite section.
+ *
+ */
+ void SetPrerequisiteRecordCount(uint16_t aCount) { SetAnswerCount(aCount); }
+
+ /**
+ * This method returns the number of records in Update section.
+ *
+ * @returns The number of records in Update section.
+ *
+ */
+ uint16_t GetUpdateRecordCount(void) const { return GetAuthorityRecordCount(); }
+
+ /**
+ * This method sets the number of records in Update section.
+ *
+ * @param[in] aCount The number of records in Update section.
+ *
+ */
+ void SetUpdateRecordCount(uint16_t aCount) { SetAuthorityRecordCount(aCount); }
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class represents a DNS name and implements helper methods for encoding/decoding of DNS Names.
+ *
+ */
+class Name : public Clearable<Name>
+{
+public:
+ enum : uint8_t
+ {
+ /**
+ * Max size (number of chars) in a name string array (includes null char at the end of string).
+ *
+ */
+ kMaxNameSize = OT_DNS_MAX_NAME_SIZE,
+
+ /**
+ * Maximum length in a name string (does not include null char at the end of string).
+ *
+ */
+ kMaxNameLength = kMaxNameSize - 1,
+
+ /**
+ * Max size (number of chars) in a label string array (includes null char at the end of the string).
+ *
+ */
+ kMaxLabelSize = OT_DNS_MAX_LABEL_SIZE,
+
+ /**
+ * Maximum length in a label string (does not include null char at the end of string).
+ *
+ */
+ kMaxLabelLength = kMaxLabelSize - 1,
+ };
+
+ enum : char
+ {
+ kLabelSeperatorChar = '.',
+ };
+
+ /**
+ * This enumeration represents the name type.
+ *
+ */
+ enum Type : uint8_t
+ {
+ kTypeEmpty, ///< The name is empty (not specified).
+ kTypeCString, ///< The name is given as a C string (dot '.' separated sequence of labels).
+ kTypeMessage, ///< The name is specified from a message at a given offset (encoded in the message).
+ };
+
+ /**
+ * This constructor initializes the `Name` object as empty (not specified).
+ *
+ */
+ Name(void)
+ : Name(nullptr, nullptr, 0)
+ {
+ }
+
+ /**
+ * This constructor initializes the `Name` object with a given string.
+ *
+ * @param[in] aString A C string specifying the name (dot '.' separated sequence of labels').
+ *
+ */
+ explicit Name(const char *aString)
+ : Name(aString, nullptr, 0)
+ {
+ }
+
+ /**
+ * This constructor initializes the `Name` object from a message at a given offset.
+ *
+ * @param[in] aMessage The message containing the encoded name. `aMessage.GetOffset()` MUST point to the start of
+ * the DNS header in the message (used to parse compressed name).
+ * @param[in] aOffset The offset in @p aMessage pointing to the start of the name.
+ *
+ */
+ Name(const Message &aMessage, uint16_t aOffset)
+ : Name(nullptr, &aMessage, aOffset)
+ {
+ }
+
+ /**
+ * This method indicates whether the name is empty (not specified).
+ *
+ * @returns TRUE if the name is empty, FALSE otherwise.
+ *
+ */
+ bool IsEmpty(void) const { return (mString == nullptr) && (mMessage == nullptr); }
+
+ /**
+ * This method indicates whether the name is specified from a C string.
+ *
+ * @returns TRUE if the name is specified from a string, FALSE otherwise.
+ *
+ */
+ bool IsFromCString(void) const { return mString != nullptr; }
+
+ /**
+ * This method indicates whether the name is specified from a message.
+ *
+ * @returns TRUE if the name is specified from a message, FALSE otherwise.
+ *
+ */
+ bool IsFromMessage(void) const { return mMessage != nullptr; }
+
+ /**
+ * This method gets the type of `Name` object indicating whether it is empty, specified by a C string or from a
+ * message
+ *
+ * @returns The name type.
+ *
+ */
+ Type GetFromType(void) const
+ {
+ return IsFromCString() ? kTypeCString : (IsFromMessage() ? kTypeMessage : kTypeEmpty);
+ }
+
+ /**
+ * This method sets the name from a given C string.
+ *
+ * @param[in] aString A C string specifying the name (dot '.' separated sequence of labels).
+ *
+ */
+ void Set(const char *aString)
+ {
+ mString = aString;
+ mMessage = nullptr;
+ }
+
+ /**
+ * This method sets the name from a message at a given offset.
+ *
+ * @param[in] aMessage The message containing the encoded name. `aMessage.GetOffset()` MUST point to the start of
+ * the DNS header in the message (used to parse compressed name).
+ * @param[in] aOffset The offset in @p aMessage pointing to the start of the name.
+ *
+ */
+ void SetFromMessage(const Message &aMessage, uint16_t aOffset)
+ {
+ mString = nullptr;
+ mMessage = &aMessage;
+ mOffset = aOffset;
+ }
+
+ /**
+ * This method gets the name as a C string.
+ *
+ * This method MUST be used only when the type is `kTypeString`. Otherwise its behavior is undefined.
+ *
+ * @returns A pointer to the C string.
+ *
+ */
+ const char *GetAsCString(void) const { return mString; }
+
+ /**
+ * This method gets the name message and offset.
+ *
+ * This method MUST be used only when the type is `kTypeMessage`. Otherwise its behavior is undefined.
+ *
+ * @param[out] aOffset A reference to a variable to output the offset of the start of the name in the message.
+ *
+ * @returns A reference to the message containing the name.
+ *
+ */
+ const Message &GetAsMessage(uint16_t &aOffset) const
+ {
+ aOffset = mOffset;
+ return *mMessage;
+ }
+
+ /**
+ * This static method encodes and appends a single name label to a message.
+ *
+ * The @p aLabel is assumed to contain a single name label as a C string (null-terminated). Unlike
+ * `AppendMultipleLabels()` which parses the label string and treats it as sequence of multiple (dot-separated)
+ * labels, this method always appends @p aLabel as a single whole label. This allows the label string to even
+ * contain dot '.' character, which, for example, is useful for "Service Instance Names" where <Instance> portion
+ * is a user-friendly name and can contain dot characters.
+ *
+ * @param[in] aLabel The label string to append. MUST NOT be nullptr.
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Successfully encoded and appended the name label to @p aMessage.
+ * @retval kErrorInvalidArgs @p aLabel is not valid (e.g., label length is not within valid range).
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendLabel(const char *aLabel, Message &aMessage);
+
+ /**
+ * This static method encodes and appends a single name label of specified length to a message.
+ *
+ * The @p aLabel is assumed to contain a single name label of given @p aLength. @p aLabel must not contain
+ * '\0' characters within the length @p aLength. Unlike `AppendMultipleLabels()` which parses the label string
+ * and treats it as sequence of multiple (dot-separated) labels, this method always appends @p aLabel as a single
+ * whole label. This allows the label string to even contain dot '.' character, which, for example, is useful for
+ * "Service Instance Names" where <Instance> portion is a user-friendly name and can contain dot characters.
+ *
+ * @param[in] aLabel The label string to append. MUST NOT be nullptr.
+ * @param[in] aLength The length of the label to append.
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Successfully encoded and appended the name label to @p aMessage.
+ * @retval kErrorInvalidArgs @p aLabel is not valid (e.g., label length is not within valid range).
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendLabel(const char *aLabel, uint8_t aLength, Message &aMessage);
+
+ /**
+ * This static method encodes and appends a sequence of name labels to a given message.
+ *
+ * The @p aLabels must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
+ * E.g., "_http._tcp", "_http._tcp." (same as previous one), "host-1.test".
+ *
+ * This method validates that the @p aLabels is a valid name format, i.e., no empty label, and labels are
+ * `kMaxLabelLength` (63) characters or less.
+ *
+ * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels
+ * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test".
+ *
+ * @param[in] aLabels A name label string. Can be nullptr (then treated as "").
+ * @param[in] aMessage The message to which to append the encoded name.
+ *
+ * @retval kErrorNone Successfully encoded and appended the name label(s) to @p aMessage.
+ * @retval kErrorInvalidArgs Name label @p aLabels is not valid.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendMultipleLabels(const char *aLabels, Message &aMessage);
+
+ /**
+ * This static method encodes and appends a sequence of name labels within the specified length to a given message.
+ * This method stops appending labels if @p aLength characters are read or '\0' is found before @p aLength
+ * characters.
+ *
+ * This method is useful for appending a number of labels of the name instead of appending all labels.
+ *
+ * The @p aLabels must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
+ * E.g., "_http._tcp", "_http._tcp." (same as previous one), "host-1.test".
+ *
+ * This method validates that the @p aLabels is a valid name format, i.e., no empty label, and labels are
+ * `kMaxLabelLength` (63) characters or less.
+ *
+ * @note This method NEVER adds a label terminator (empty label) to the message, even in the case where @p aLabels
+ * ends with a dot character, e.g., "host-1.test." is treated same as "host-1.test".
+ *
+ * @param[in] aLabels A name label string. Can be nullptr (then treated as "").
+ * @param[in] aLength The max length of the name labels to encode.
+ * @param[in] aMessage The message to which to append the encoded name.
+ *
+ * @retval kErrorNone Successfully encoded and appended the name label(s) to @p aMessage.
+ * @retval kErrorInvalidArgs Name label @p aLabels is not valid.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendMultipleLabels(const char *aLabels, uint8_t aLength, Message &aMessage);
+
+ /**
+ * This static method appends a name label terminator to a message.
+ *
+ * An encoded name is terminated by an empty label (a zero byte).
+ *
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Successfully encoded and appended the terminator label to @p aMessage.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendTerminator(Message &aMessage);
+
+ /**
+ * This static method appends a pointer type name label to a message.
+ *
+ * Pointer label is used for name compression. It allows an entire name or a list of labels at the end of an
+ * encoded name to be replaced with a pointer to a prior occurrence of the same name within the message.
+ *
+ * @param[in] aOffset The offset from the start of DNS header to use for pointer value.
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Successfully encoded and appended the pointer label to @p aMessage.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendPointerLabel(uint16_t aOffset, Message &aMessage);
+
+ /**
+ * This static method encodes and appends a full name to a message.
+ *
+ * The @p aName must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
+ * E.g., "example.com", "example.com." (same as previous one), "local.", "default.service.arpa", "." or "" (root).
+ *
+ * This method validates that the @p aName is a valid name format, i.e. no empty labels, and labels are
+ * `kMaxLabelLength` (63) characters or less, and the name is `kMaxLength` (255) characters or less.
+ *
+ * @param[in] aName A name string. Can be nullptr (then treated as "." or root).
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Successfully encoded and appended the name to @p aMessage.
+ * @retval kErrorInvalidArgs Name @p aName is not valid.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendName(const char *aName, Message &aMessage);
+
+ /**
+ * This static method parses and skips over a full name in a message.
+ *
+ * @param[in] aMessage The message to parse the name from. `aMessage.GetOffset()` MUST point to
+ * the start of DNS header (this is used to handle compressed names).
+ * @param[inout] 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.
+ *
+ * @retval kErrorNone Successfully parsed and skipped over name, @p Offset is updated.
+ * @retval kErrorParse Name could not be parsed (invalid format).
+ *
+ */
+ static Error ParseName(const Message &aMessage, uint16_t &aOffset);
+
+ /**
+ * This static method reads a name label from a message.
+ *
+ * This method can be used to read labels one by one in a name. After a successful label read, @p aOffset is
+ * updated to point to the start of the next label. When we reach the end of the name, kErrorNotFound is
+ * returned. This method handles compressed names which use pointer labels. So as the labels in a name are read,
+ * the @p aOffset may jump back in the message and at the end the @p aOffset does not necessarily point to the end
+ * of the original name field.
+ *
+ * Unlike `ReadName()` which requires and verifies that the read label to contain no dot '.' character, this method
+ * allows the read label to include any character.
+ *
+ * @param[in] aMessage The message to read the label from. `aMessage.GetOffset()` MUST point to
+ * the start of DNS header (this is used to handle compressed names).
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the label to read.
+ * On exit, when successfully read, @p aOffset is updated to point to the start of
+ * the next label.
+ * @param[out] aLabelBuffer A pointer to a char array to output the read label as a null-terminated C string.
+ * @param[inout] aLabelLength On input, the maximum number chars in @p aLabelBuffer array.
+ * On output, when label is successfully read, @p aLabelLength is updated to return
+ * the label's length (number of chars in the label string, excluding the null char).
+ *
+ * @retval kErrorNone Successfully read the label and updated @p aLabelBuffer, @p aLabelLength, and @p aOffset.
+ * @retval kErrorNotFound Reached the end of name and no more label to read.
+ * @retval kErrorParse Name could not be parsed (invalid format).
+ * @retval kErrorNoBufs Label could not fit in @p aLabelLength chars.
+ *
+ */
+ static Error ReadLabel(const Message &aMessage, uint16_t &aOffset, char *aLabelBuffer, uint8_t &aLabelLength);
+
+ /**
+ * This static method reads a full name from a message.
+ *
+ * On successful read, the read name follows "<label1>.<label2>.<label3>.", i.e., a sequence of labels separated by
+ * dot '.' character. The read name will ALWAYS end with a dot.
+ *
+ * This method verifies that the read labels in message do not contain any dot character, otherwise it returns
+ * `kErrorParse`).
+ *
+ * @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[inout] 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 A pointer to a char array to output the read name as a null-terminated C string.
+ * @param[inout] aNameBufferSize The maximum number of chars in @p aNameBuffer array.
+ *
+ * @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 aNameBufferSize chars.
+ *
+ */
+ static Error ReadName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize);
+
+ /**
+ * This static method compares a single name label from a message with a given label string.
+ *
+ * This method can be used to compare labels one by one. It checks whether the label read from @p aMessage matches
+ * @p aLabel string.
+ *
+ * Unlike `CompareName()` which requires the labels in the the name string to contain no dot '.' character, this
+ * method allows @p aLabel to include any character.
+ *
+ * @param[in] aMessage The message to read the label from to compare. `aMessage.GetOffset()` MUST point
+ * to the start of DNS header (this is used to handle compressed names).
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the label to read.
+ * On exit and only when label is successfully read and does match @p aLabel,
+ * @p aOffset is updated to point to the start of the next label.
+ * @param[in] aLabel A pointer to a null terminated string containing the label to compare with.
+
+ * @retval kErrorNone The label from @p aMessage matches @p aLabel. @p aOffset is updated.
+ * @retval kErrorNotFound The label 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 CompareLabel(const Message &aMessage, uint16_t &aOffset, const char *aLabel);
+
+ /**
+ * This static method parses and compares a full name from a message with a given name.
+ *
+ * This method checks whether the encoded name in a message matches a given name string. It checks the name in
+ * the message in place and handles compressed names. If the name read from the message does not match @p aName, it
+ * returns `kErrorNotFound`. `kErrorNone` indicates that the name matches @p aName.
+ *
+ * The @p aName must follow "<label1>.<label2>.<label3>", i.e., a sequence of labels separated by dot '.' char.
+ * E.g., "example.com", "example.com." (same as previous one), "local.", "default.service.arpa", "." or "" (root).
+ *
+ * @param[in] aMessage The message to read the name from and compare with @p aName.
+ * `aMessage.GetOffset()` MUST point to the start of DNS header (this is used to
+ * handle compressed names).
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the name field.
+ * On exit (when parsed successfully independent of whether the read name matches
+ * @p aName or not), @p aOffset is updated to point to the byte after the end of
+ * the name field.
+ * @param[in] aName A pointer to a null terminated string containing the name to compare with.
+ *
+ * @retval kErrorNone The name from @p aMessage matches @p aName. @p aOffset is updated.
+ * @retval kErrorNotFound The name from @p aMessage does not match @p aName. @p aOffset is updated.
+ * @retval kErrorParse Name could not be parsed (invalid format).
+ * @retval kErrorInvalidArgs The @p aName is not a valid name (e.g. back to back "." chars)
+ *
+ */
+ static Error CompareName(const Message &aMessage, uint16_t &aOffset, const char *aName);
+
+ /**
+ * This static method parses and compares a full name from a message with a name from another message.
+ *
+ * This method checks whether the encoded name in @p aMessage matches the name from @p aMessage2. It compares the
+ * names in both messages in place and handles compressed names. Note that this method works correctly even when
+ * the same message instance is used for both @p aMessage and @p aMessage2 (e.g., at different offsets).
+ *
+ * Only the name in @p aMessage is fully parsed and checked for parse errors. This method assumes that the name in
+ * @p aMessage2 was previously parsed and validated before calling this method (if there is a parse error in
+ * @p aMessage2, it is treated as a name mismatch with @p aMessage).
+ *
+ * If the name in @p aMessage can be parsed fully (independent of whether the name matches or not with the name
+ * from @p aMessage2), the @p aOffset is updated (note that @p aOffset2 for @p aMessage2 is not changed).
+ *
+ * @param[in] aMessage The message to read the name from and compare. `aMessage.GetOffset()` MUST point
+ * to the start of DNS header (this is used to handle compressed names).
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the name field.
+ * On exit (when parsed successfully independent of whether the read name matches
+ * or not), @p aOffset is updated to point to the byte after the end of the name
+ * field.
+ * @param[in] aMessage2 The second message to read the name from and compare with name from @p aMessage.
+ * `aMessage2.GetOffset()` MUST point to the start of DNS header.
+ * @param[in] aOffset2 The offset in @p aMessage2 pointing to the start of the name field.
+ *
+ * @retval kErrorNone The name from @p aMessage matches the name from @p aMessage2. @p aOffset is updated.
+ * @retval kErrorNotFound The name from @p aMessage does not match the name from @p aMessage2. @p aOffset is
+ * updated.
+ * @retval kErrorParse Name in @p aMessage could not be parsed (invalid format).
+ *
+ */
+ static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Message &aMessage2, uint16_t aOffset2);
+
+ /**
+ * This static method parses and compares a full name from a message with a given name.
+ *
+ * If @p aName is empty (not specified), then any name in @p aMessage is considered a match to it.
+ *
+ * @param[in] aMessage The message to read the name from and compare. `aMessage.GetOffset()` MUST point
+ * to the start of DNS header (this is used to handle compressed names).
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the name field.
+ * On exit (when parsed successfully independent of whether the read name matches
+ * or not), @p aOffset is updated to point to the byte after the end of the name
+ * field.
+ * @param[in] aName A reference to a name to compare with.
+ *
+ * @retval kErrorNone The name from @p aMessage matches @p aName. @p aOffset is updated.
+ * @retval kErrorNotFound The name from @p aMessage does not match @p aName. @p aOffset is updated.
+ * @retval kErrorParse Name in @p aMessage could not be parsed (invalid format).
+ *
+ */
+ static Error CompareName(const Message &aMessage, uint16_t &aOffset, const Name &aName);
+
+ /**
+ * This static method tests if a DNS name is a sub-domain of a given domain.
+ *
+ * Both @p aName and @p aDomain can end without dot ('.').
+ *
+ * @param[in] aName The dot-separated name.
+ * @param[in] aDomain The dot-separated domain.
+ *
+ * @returns TRUE if the name is a sub-domain of @p aDomain, FALSE if is not.
+ *
+ */
+ static bool IsSubDomainOf(const char *aName, const char *aDomain);
+
+private:
+ enum : char
+ {
+ kNullChar = '\0',
+ };
+
+ enum : uint8_t
+ {
+ // The first 2 bits of the encoded label specifies label type.
+ //
+ // - Value 00 indicates normal text label (lower 6-bits indicates the label length).
+ // - Value 11 indicates pointer label type (lower 14-bits indicates the pointer offset).
+ // - Values 01,10 are reserved (RFC 6891 recommends to not use)
+
+ kLabelTypeMask = 0xc0, // 0b1100_0000 (first two bits)
+ kTextLabelType = 0x00, // Text label type (00)
+ kPointerLabelType = 0xc0, // Pointer label type - compressed name (11)
+
+ kMaxEncodedLength = 255, ///< Max length of an encoded name.
+ };
+
+ enum : uint16_t
+ {
+ kPointerLabelTypeUint16 = 0xc000, // Pointer label type as `uint16_t` mask (first 2 bits).
+ kPointerLabelOffsetMask = 0x3fff, // Mask to get the offset field in a pointer label (lower 14 bits).
+ };
+
+ struct LabelIterator
+ {
+ enum : uint16_t
+ {
+ kUnsetNameEndOffset = 0, // Special value indicating `mNameEndOffset` is not yet set.
+ };
+
+ LabelIterator(const Message &aMessage, uint16_t aLabelOffset)
+ : mMessage(aMessage)
+ , mNextLabelOffset(aLabelOffset)
+ , mNameEndOffset(kUnsetNameEndOffset)
+ {
+ }
+
+ bool IsEndOffsetSet(void) const { return (mNameEndOffset != kUnsetNameEndOffset); }
+ Error GetNextLabel(void);
+ Error ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength, bool aAllowDotCharInLabel) const;
+ bool CompareLabel(const char *&aName, bool aIsSingleLabel) const;
+ bool CompareLabel(const LabelIterator &aOtherIterator) const;
+
+ const Message &mMessage; // Message to read labels from.
+ uint16_t mLabelStartOffset; // Offset in `mMessage` to the first char of current label text.
+ uint8_t mLabelLength; // Length of current label (number of chars).
+ uint16_t mNextLabelOffset; // Offset in `mMessage` to the start of the next label.
+ uint16_t mNameEndOffset; // Offset in `mMessage` to the byte after the end of domain name field.
+ };
+
+ Name(const char *aString, const Message *aMessage, uint16_t aOffset)
+ : mString(aString)
+ , mMessage(aMessage)
+ , mOffset(aOffset)
+ {
+ }
+
+ const char * mString; // String containing the name or `nullptr` if name is not from string.
+ const Message *mMessage; // Message containing the encoded name, or `nullptr` if `Name` is not from message.
+ uint16_t mOffset; // Offset in `mMessage` to the start of name (used when name is from `mMessage`).
+};
+
+/**
+ * This type represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3).
+ *
+ */
+class TxtEntry : public otDnsTxtEntry
+{
+ friend class TxtRecord;
+
+public:
+ enum : uint8_t
+ {
+ kMinKeyLength = OT_DNS_TXT_KEY_MIN_LENGTH, ///< Minimum length of key string (RFC 6763 - section 6.4).
+ kMaxKeyLength = OT_DNS_TXT_KEY_MAX_LENGTH, ///< Recommended max length of key string (RFC 6763 - section 6.4).
+ };
+
+ /**
+ * This class represents an iterator for TXT record entires (key/value pairs).
+ *
+ */
+ class Iterator : public otDnsTxtEntryIterator
+ {
+ friend class TxtEntry;
+
+ public:
+ /**
+ * This method initializes a TXT record iterator.
+ *
+ * The buffer pointer @p aTxtData and its content MUST persist and remain unchanged while the iterator object
+ * is being used.
+ *
+ * @param[in] aTxtData A pointer to buffer containing the encoded TXT data.
+ * @param[in] aTxtDataLength The length (number of bytes) of @p aTxtData.
+ *
+ */
+ void Init(const uint8_t *aTxtData, uint16_t aTxtDataLength);
+
+ /**
+ * This method parses the TXT data from the `Iterator` and gets the next TXT record entry (key/value pair).
+ *
+ * The `Iterator` instance MUST be initialized using `Init()` before calling this method and the TXT data
+ * buffer used to initialize the iterator MUST persist and remain unchanged.
+ *
+ * If the parsed key string length is smaller than or equal to `kMaxKeyLength` (recommended max key length)
+ * the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and
+ * the entire encoded TXT entry is returned in `mValue` and `mValueLength`.
+ *
+ * @param[out] aEntry A reference to a `TxtEntry` to output the parsed/read entry.
+ *
+ * @retval kErrorNone The next entry was parsed successfully. @p aEntry is updated.
+ * @retval kErrorNotFound No more entries in TXT data.
+ * @retval kErrorParse The TXT data from `Iterator` is not well-formed.
+ *
+ */
+ Error GetNextEntry(TxtEntry &aEntry);
+
+ private:
+ enum : uint8_t
+ {
+ kIndexTxtLength = 0,
+ kIndexTxtPosition = 1,
+ };
+
+ const char *GetTxtData(void) const { return reinterpret_cast<const char *>(mPtr); }
+ void SetTxtData(const uint8_t *aTxtData) { mPtr = aTxtData; }
+ uint16_t GetTxtDataLength(void) const { return mData[kIndexTxtLength]; }
+ void SetTxtDataLength(uint16_t aLength) { mData[kIndexTxtLength] = aLength; }
+ uint16_t GetTxtDataPosition(void) const { return mData[kIndexTxtPosition]; }
+ void SetTxtDataPosition(uint16_t aValue) { mData[kIndexTxtPosition] = aValue; }
+ void IncreaseTxtDataPosition(uint16_t aIncrement) { mData[kIndexTxtPosition] += aIncrement; }
+ char * GetKeyBuffer(void) { return mChar; }
+ const char *GetTxtDataEnd(void) const { return GetTxtData() + GetTxtDataLength(); }
+ };
+
+ /**
+ * This is the default constructor for a `TxtEntry` object.
+ *
+ */
+ TxtEntry(void) = default;
+
+ /**
+ * This constructor initializes a `TxtEntry` object.
+ *
+ * @param[in] aKey A pointer to the key string.
+ * @param[in] aValue A pointer to a buffer containing the value.
+ * @param[in] aValueLength Number of bytes in @p aValue buffer.
+ *
+ */
+ TxtEntry(const char *aKey, const uint8_t *aValue, uint8_t aValueLength)
+ {
+ mKey = aKey;
+ mValue = aValue;
+ mValueLength = aValueLength;
+ }
+
+ /**
+ * This method encodes and appends the `TxtEntry` to a message.
+ *
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Entry was appended successfully to @p aMessage.
+ * @retval kErrorInvalidArgs The `TxTEntry` info is not valid.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ Error AppendTo(Message &aMessage) const;
+
+ /**
+ * This static method appends an array of `TxtEntry` items to a message.
+ *
+ * @param[in] aEntries A pointer to array of `TxtEntry` items.
+ * @param[in] aNumEntries The number of entries in @p aEntries array.
+ * @param[in] aMessage The message to append to.
+ *
+ * @retval kErrorNone Entries appended successfully to @p aMessage.
+ * @retval kErrorInvalidArgs The `TxTEntry` info is not valid.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
+ *
+ */
+ static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage);
+
+private:
+ enum : uint8_t
+ {
+ kMaxKeyValueEncodedSize = 255,
+ };
+
+ enum : char
+ {
+ kKeyValueSeparator = '=',
+ kNullChar = '\0',
+ };
+};
+
+/**
+ * This class implements Resource Record (RR) body format.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class ResourceRecord
+{
+ friend class OptRecord;
+
+public:
+ /**
+ * Resource Record Types.
+ *
+ */
+ enum : uint16_t
+ {
+ kTypeZero = 0, ///< Zero is used as a special indicator for the SIG RR (SIG(0) from RFC 2931).
+ kTypeA = 1, ///< Address record (IPv4).
+ kTypeSoa = 6, ///< Start of (zone of) authority.
+ kTypeCname = 5, ///< CNAME record.
+ kTypePtr = 12, ///< PTR record.
+ kTypeTxt = 16, ///< TXT record.
+ kTypeSig = 24, ///< SIG record.
+ kTypeKey = 25, ///< KEY record.
+ kTypeAaaa = 28, ///< IPv6 address record.
+ kTypeSrv = 33, ///< SRV locator record.
+ kTypeOpt = 41, ///< Option record.
+ kTypeAny = 255, ///< ANY record.
+ };
+
+ /**
+ * Resource Record Class Codes.
+ *
+ */
+ enum : uint16_t
+ {
+ kClassInternet = 1, ///< Class code Internet (IN).
+ kClassNone = 254, ///< Class code None (NONE) - RFC 2136.
+ kClassAny = 255, ///< Class code Any (ANY).
+ };
+
+ /**
+ * This method initializes the resource record by setting its type and class.
+ *
+ * This method only sets the type and class fields. Other fields (TTL and length) remain unchanged/uninitialized.
+ *
+ * @param[in] aType The type of the resource record.
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aType, uint16_t aClass = kClassInternet)
+ {
+ SetType(aType);
+ SetClass(aClass);
+ }
+
+ /**
+ * This method indicates whether the resources records matches a given type and class code.
+ *
+ * @param[in] aType The resource record type to compare with.
+ * @param[in] aClass The resource record class code to compare with (default is `kClassInternet`).
+ *
+ * @returns TRUE if the resources records matches @p aType and @p aClass, FALSE otherwise.
+ *
+ */
+ bool Matches(uint16_t aType, uint16_t aClass = kClassInternet)
+ {
+ return (mType == HostSwap16(aType)) && (mClass == HostSwap16(aClass));
+ }
+
+ /**
+ * This method returns the type of the resource record.
+ *
+ * @returns The type of the resource record.
+ *
+ */
+ uint16_t GetType(void) const { return HostSwap16(mType); }
+
+ /**
+ * This method sets the type of the resource record.
+ *
+ * @param[in] aType The type of the resource record.
+ *
+ */
+ void SetType(uint16_t aType) { mType = HostSwap16(aType); }
+
+ /**
+ * This method returns the class of the resource record.
+ *
+ * @returns The class of the resource record.
+ *
+ */
+ uint16_t GetClass(void) const { return HostSwap16(mClass); }
+
+ /**
+ * This method sets the class of the resource record.
+ *
+ * @param[in] aClass The class of the resource record.
+ *
+ */
+ void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
+
+ /**
+ * This method returns the time to live field of the resource record.
+ *
+ * @returns The time to live field of the resource record.
+ *
+ */
+ uint32_t GetTtl(void) const { return HostSwap32(mTtl); }
+
+ /**
+ * This method sets the time to live field of the resource record.
+ *
+ * @param[in] aTtl The time to live field of the resource record.
+ *
+ */
+ void SetTtl(uint32_t aTtl) { mTtl = HostSwap32(aTtl); }
+
+ /**
+ * This method returns the length of the resource record data.
+ *
+ * @returns The length of the resource record data.
+ *
+ */
+ uint16_t GetLength(void) const { return HostSwap16(mLength); }
+
+ /**
+ * This method sets the length of the resource record data.
+ *
+ * @param[in] aLength The length of the resource record data.
+ *
+ */
+ void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
+
+ /**
+ * This method returns the size of (number of bytes) in resource record and its data RDATA section (excluding the
+ * name field).
+ *
+ * @returns Size (number of bytes) of resource record and its data section (excluding the name field)
+ *
+ */
+ uint32_t GetSize(void) const { return sizeof(ResourceRecord) + GetLength(); }
+
+ /**
+ * This static method parses and skips over a given number of resource records in a message from a given offset.
+ *
+ * @param[in] aMessage The message from which to parse/read the resource records. `aMessage.GetOffset()`
+ * MUST point to the start of DNS header.
+ * @param[inout] aOffset On input the offset in @p aMessage pointing to the start of the first record.
+ * On exit (when parsed successfully), @p aOffset is updated to point to the byte after
+ * the last parsed record.
+ * @param[in] aNumRecords Number of resource records to parse.
+ *
+ * @retval kErrorNone Parsed records successfully. @p aOffset is updated.
+ * @retval kErrorParse Could not parse the records from @p aMessage (e.g., ran out of bytes in @p aMessage).
+ *
+ */
+ static Error ParseRecords(const Message &aMessage, uint16_t &aOffset, uint16_t aNumRecords);
+
+ /**
+ * This static method searches in a given message to find the first resource record matching a given record name.
+ *
+ * @param[in] aMessage The message in which to search for a matching resource record.
+ * `aMessage.GetOffset()` MUST point to the start of DNS header.
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the first record.
+ * On exit, if a matching record is found, @p aOffset is updated to point to the byte
+ * after the record name.
+ * If a matching record could not be found, @p aOffset is updated to point to the byte
+ * after the last record that was checked.
+ * @param[inout] aNumRecords On input, the maximum number of records to check (starting from @p aOffset).
+ * On exit and if a matching record is found, @p aNumRecords is updated to give the
+ * number of remaining records after @p aOffset (excluding the matching record).
+ * @param[in] aName The record name to match against.
+ *
+ * @retval kErrorNone A matching record was found. @p aOffset, @p aNumRecords are updated.
+ * @retval kErrorNotFound A matching record could not be found. @p aOffset and @p aNumRecords are updated.
+ * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage).
+ *
+ */
+ static Error FindRecord(const Message &aMessage, uint16_t &aOffset, uint16_t &aNumRecords, const Name &aName);
+
+ /**
+ * This template static method searches in a message to find the i-th occurrence of resource records of specific
+ * type with a given record name and if found, reads the record from the message.
+ *
+ * This method searches in @p aMessage starting from @p aOffset up to maximum of @p aNumRecords, for the
+ * `(aIndex+1)`th occurrence of a resource record of `RecordType` with record name @p aName.
+ *
+ * On success (i.e., when a matching record is found and read from the message), @p aOffset is updated to point
+ * to after the last byte read from the message and copied into @p aRecord. This allows the caller to read any
+ * remaining fields in the record data.
+ *
+ * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`).
+ *
+ * @param[in] aMessage The message to search within for matching resource records.
+ * `aMessage.GetOffset()` MUST point to the start of DNS header.
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the start of the first record.
+ * On exit and only if a matching record is found, @p aOffset is updated to point to
+ * the last read byte in the record (allowing caller to read any remaining fields in
+ * the record data from the message).
+ * @param[in] aNumRecords The maximum number of records to check (starting from @p aOffset).
+ * @param[in] aIndex The matching record index to find. @p aIndex value of zero returns the first
+ * matching record.
+ * @param[in] aName The record name to match against.
+ * @param[in] aRecord A reference to a record object to read a matching record into.
+ * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are
+ * read and copied into @p aRecord.
+ *
+ * @retval kErrorNone A matching record was found. @p aOffset is updated.
+ * @retval kErrorNotFound A matching record could not be found.
+ * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage).
+ *
+ */
+ template <class RecordType>
+ static Error FindRecord(const Message &aMessage,
+ uint16_t & aOffset,
+ uint16_t aNumRecords,
+ uint16_t aIndex,
+ const Name & aName,
+ RecordType & aRecord)
+ {
+ return FindRecord(aMessage, aOffset, aNumRecords, aIndex, aName, RecordType::kType, aRecord,
+ sizeof(RecordType));
+ }
+
+ /**
+ * This template static method tries to read a resource record of a given type from a message. If the record type
+ * does not matches the type, it skips over the record.
+ *
+ * This method requires the record name to be already parsed/read from the message. On input, @p aOffset should
+ * point to the start of the `ResourceRecord` fields (type, class, TTL, data length) in @p aMessage.
+ *
+ * This method verifies that the record is well-formed in the message. It then reads the record type and compares
+ * it with `RecordType::kType` and ensures that the record size is at least `sizeof(RecordType)`. If it all matches,
+ * the record is read into @p aRecord.
+ *
+ * On success (i.e., when a matching record is read from the message), the @p aOffset is updated to point to after
+ * the last byte read from the message and copied into @p aRecord and not necessarily the end of the record.
+ * Depending on the `RecordType` format, there may still be more data bytes left in the record to be read. For
+ * example, when reading a SRV record using `SrvRecord` type, @p aOffset would point to after the last field in
+ * `SrvRecord` which is the start of "target host domain name" field.
+ *
+ * @tparam RecordType The resource record type (i.e., a sub-class of `ResourceRecord`).
+ *
+ * @param[in] aMessage The message from which to read the record.
+ * @param[inout] aOffset On input, the offset in @p aMessage pointing to the byte after the record name.
+ * On exit, if a matching record is read, @p aOffset is updated to point to the last
+ * read byte in the record.
+ * If a matching record could not be read, @p aOffset is updated to point to the byte
+ * after the entire record (skipping over the record).
+ * @param[out] aRecord A reference to a record to read a matching record into.
+ * If a matching record is found, `sizeof(RecordType)` bytes from @p aMessage are
+ * read and copied into @p aRecord.
+ *
+ * @retval kErrorNone A matching record was read successfully. @p aOffset, and @p aRecord are updated.
+ * @retval kErrorNotFound A matching record could not be found. @p aOffset is updated.
+ * @retval kErrorParse Could not parse records from @p aMessage (e.g., ran out of bytes in @p aMessage).
+ *
+ */
+ template <class RecordType> static Error ReadRecord(const Message &aMessage, uint16_t &aOffset, RecordType &aRecord)
+ {
+ return ReadRecord(aMessage, aOffset, RecordType::kType, aRecord, sizeof(RecordType));
+ }
+
+protected:
+ Error ReadName(const Message &aMessage,
+ uint16_t & aOffset,
+ uint16_t aStartOffset,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize,
+ bool aSkipRecord) const;
+ Error SkipRecord(const Message &aMessage, uint16_t &aOffset) const;
+
+private:
+ enum : uint8_t
+ {
+ kType = kTypeAny, // This is intended for used by `ReadRecord()` only.
+ };
+
+ static Error FindRecord(const Message & aMessage,
+ uint16_t & aOffset,
+ uint16_t aNumRecords,
+ uint16_t aIndex,
+ const Name & aName,
+ uint16_t aType,
+ ResourceRecord &aRecord,
+ uint16_t aMinRecordSize);
+
+ static Error ReadRecord(const Message & aMessage,
+ uint16_t & aOffset,
+ uint16_t aType,
+ ResourceRecord &aRecord,
+ uint16_t aMinRecordSize);
+
+ Error CheckRecord(const Message &aMessage, uint16_t aOffset) const;
+ Error ReadFrom(const Message &aMessage, uint16_t aOffset);
+
+ uint16_t mType; // The type of the data in RDATA section.
+ uint16_t mClass; // The class of the data in RDATA section.
+ uint32_t mTtl; // Specifies the maximum time that the resource record may be cached.
+ uint16_t mLength; // The length of RDATA section in bytes.
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of CNAME type.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class CnameRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeCname, ///< The CNAME record type.
+ };
+
+ /**
+ * This method initializes the CNAME Resource Record by setting its type and class.
+ *
+ * Other record fields (TTL, length) remain unchanged/uninitialized.
+ *
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeCname, aClass); }
+
+ /**
+ * This method parses and reads the CNAME alias name from a message.
+ *
+ * This method also verifies that the CNAME record is well-formed (e.g., the record data length `GetLength()`
+ * matches the CNAME encoded name).
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[inout] aOffset On input, the offset in @p aMessage to start of CNAME 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] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string
+ * (MUST NOT be nullptr).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The CNAME name was read successfully. @p aOffset and @p aNameBuffer are updated.
+ * @retval kErrorParse The CNAME record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars.
+ *
+ */
+ Error ReadCanonicalName(const Message &aMessage,
+ uint16_t & aOffset,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const
+ {
+ return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(CnameRecord),
+ aNameBuffer, aNameBufferSize, /* aSkipRecord */ true);
+ }
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of PTR type.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class PtrRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypePtr, ///< The PTR record type.
+ };
+
+ /**
+ * This method initializes the PTR Resource Record by setting its type and class.
+ *
+ * Other record fields (TTL, length) remain unchanged/uninitialized.
+ *
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypePtr, aClass); }
+
+ /**
+ * This method parses and reads the PTR name from a message.
+ *
+ * This method also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches
+ * the PTR encoded name).
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[inout] aOffset On input, the offset in @p aMessage to 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] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string
+ * (MUST NOT be nullptr).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The PTR name was read successfully. @p aOffset and @p aNameBuffer are updated.
+ * @retval kErrorParse The PTR record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars.
+ *
+ */
+ Error ReadPtrName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const
+ {
+ return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(PtrRecord), aNameBuffer,
+ aNameBufferSize,
+ /* aSkipRecord */ true);
+ }
+
+ /**
+ * This method parses and reads the PTR name from a message.
+ *
+ * This method also verifies that the PTR record is well-formed (e.g., the record data length `GetLength()` matches
+ * the PTR encoded name).
+ *
+ * Unlike the previous method which reads the entire PTR name into a single char buffer, this method reads the
+ * first label separately and into a different buffer @p aLabelBuffer and the rest of the name into @p aNameBuffer.
+ * The @p aNameBuffer can be set to `nullptr` if the caller is only interested in the first label. This method is
+ * intended for "Service Instance Name" where first label (`<Instance>` portion) can be a user-friendly string and
+ * can contain dot character.
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[inout] 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 pointer to a char array to output the first label as a null-terminated C
+ * string (MUST NOT be nullptr).
+ * @param[in] aLabelBufferSize The size of @p aLabelBuffer.
+ * @param[out] aNameBuffer A pointer to a char array to output the rest of name (after first label). Can
+ * be `nullptr` if caller is only interested in the first label.
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @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 char buffers.
+ *
+ */
+ Error ReadPtrName(const Message &aMessage,
+ uint16_t & aOffset,
+ char * aLabelBuffer,
+ uint8_t aLabelBufferSize,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const;
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of TXT type.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class TxtRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeTxt, ///< The TXT record type.
+ };
+
+ /**
+ * This method initializes the TXT Resource Record by setting its type and class.
+ *
+ * Other record fields (TTL, length) remain unchanged/uninitialized.
+ *
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeTxt, aClass); }
+
+ /**
+ * This method parses and reads the TXT record data from a message.
+ *
+ * This method also checks if the TXT data is well-formed by calling `VerifyTxtData()`.
+ *
+ * @param[in] aMessage The message to read from.
+ * @param[inout] aOffset On input, the offset in @p aMessage to start of TXT record data.
+ * On exit when successfully read, @p aOffset is updated to point to the byte
+ * after the entire TXT record (skipping over the record).
+ * @param[out] aTxtBuffer A pointer to a byte array to output the read TXT data.
+ * @param[inout] aTxtBufferSize On input, the size of @p aTxtBuffer (max bytes that can be read).
+ * On exit, @p aTxtBufferSize gives number of bytes written to @p aTxtBuffer.
+ *
+ * @retval kErrorNone The TXT data was read successfully. @p aOffset, @p aTxtBuffer and @p aTxtBufferSize
+ * are updated.
+ * @retval kErrorParse The TXT record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs TXT data could not fit in @p aTxtBufferSize bytes.
+ *
+ */
+ Error ReadTxtData(const Message &aMessage, uint16_t &aOffset, uint8_t *aTxtBuffer, uint16_t &aTxtBufferSize) const;
+
+ /**
+ * This static method tests if a buffer contains valid encoded TXT data.
+ *
+ * @param[in] aTxtData The TXT data buffer.
+ * @param[in] aTxtLength The length of the TXT data buffer.
+ *
+ * @returns TRUE if @p aTxtData contains valid encoded TXT data, FALSE if not.
+ *
+ */
+ static bool VerifyTxtData(const uint8_t *aTxtData, uint16_t aTxtLength);
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of AAAA type.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class AaaaRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeAaaa, ///< The AAAA record type.
+ };
+
+ /**
+ * This method initializes the AAAA Resource Record by setting its type, class, and length.
+ *
+ * Other record fields (TTL, address) remain unchanged/uninitialized.
+ *
+ */
+ void Init(void)
+ {
+ ResourceRecord::Init(kTypeAaaa);
+ SetLength(sizeof(Ip6::Address));
+ }
+
+ /**
+ * This method tells whether this is a valid AAAA record.
+ *
+ * @returns A boolean indicates whether this is a valid AAAA record.
+ *
+ */
+ bool IsValid(void) const;
+
+ /**
+ * This method sets the IPv6 address of the resource record.
+ *
+ * @param[in] aAddress The IPv6 address of the resource record.
+ *
+ */
+ void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
+
+ /**
+ * This method returns the reference to IPv6 address of the resource record.
+ *
+ * @returns The reference to IPv6 address of the resource record.
+ *
+ */
+ const Ip6::Address &GetAddress(void) const { return mAddress; }
+
+private:
+ Ip6::Address mAddress; // IPv6 Address of AAAA Resource Record.
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of SRV type (RFC 2782).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class SrvRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeSrv, ///< The SRV record type.
+ };
+
+ /**
+ * This method initializes the SRV Resource Record by settings its type and class.
+ *
+ * Other record fields (TTL, length, propriety, weight, port, ...) remain unchanged/uninitialized.
+ *
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeSrv, aClass); }
+
+ /**
+ * This method returns the SRV record's priority value.
+ *
+ * @returns The priority value.
+ *
+ */
+ uint16_t GetPriority(void) const { return HostSwap16(mPriority); }
+
+ /**
+ * This method sets the SRV record's priority value.
+ *
+ * @param[in] aPriority The priority value.
+ *
+ */
+ void SetPriority(uint16_t aPriority) { mPriority = HostSwap16(aPriority); }
+
+ /**
+ * This method returns the SRV record's weight value.
+ *
+ * @returns The weight value.
+ *
+ */
+ uint16_t GetWeight(void) const { return HostSwap16(mWeight); }
+
+ /**
+ * This method sets the SRV record's weight value.
+ *
+ * @param[in] aWeight The weight value.
+ *
+ */
+ void SetWeight(uint16_t aWeight) { mWeight = HostSwap16(aWeight); }
+
+ /**
+ * This method returns the SRV record's port number on the target host for this service.
+ *
+ * @returns The port number.
+ *
+ */
+ uint16_t GetPort(void) const { return HostSwap16(mPort); }
+
+ /**
+ * This method sets the SRV record's port number on the target host for this service.
+ *
+ * @param[in] aPort The port number.
+ *
+ */
+ void SetPort(uint16_t aPort) { mPort = HostSwap16(aPort); }
+
+ /**
+ * This method parses and reads the SRV target host name from a message.
+ *
+ * This method also verifies that the SRV record is well-formed (e.g., the record data length `GetLength()` matches
+ * the SRV encoded name).
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of
+ * DNS header.
+ * @param[inout] 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 pointer to a char array to output the read name as a null-terminated C string
+ * (MUST NOT be nullptr).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @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 aNameBufferSize chars.
+ *
+ */
+ Error ReadTargetHostName(const Message &aMessage,
+ uint16_t & aOffset,
+ char * aNameBuffer,
+ uint16_t aNameBufferSize) const
+ {
+ return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SrvRecord), aNameBuffer,
+ aNameBufferSize,
+ /* aSkipRecord */ true);
+ }
+
+private:
+ uint16_t mPriority;
+ uint16_t mWeight;
+ uint16_t mPort;
+ // Followed by the target host domain name.
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Resource Record body format of KEY type (RFC 2535).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class KeyRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeKey, ///< The KEY record type.
+ };
+
+ /**
+ * This enumeration defines protocol field values (RFC 2535 - section 3.1.3).
+ *
+ */
+ enum : uint8_t
+ {
+ kProtocolTls = 1, ///< TLS protocol code.
+ kProtocolDnsSec = 3, ///< DNS security protocol code.
+ };
+
+ /**
+ * This enumeration defines algorithm field values (RFC 8624 - section 3.1).
+ *
+ */
+ enum : uint8_t
+ {
+ kAlgorithmEcdsaP256Sha256 = 13, ///< ECDSA-P256-SHA256 algorithm.
+ kAlgorithmEcdsaP384Sha384 = 14, ///< ECDSA-P384-SHA384 algorithm.
+ kAlgorithmEd25519 = 15, ///< ED25519 algorithm.
+ kAlgorithmEd448 = 16, ///< ED448 algorithm.
+ };
+
+ /**
+ * This enumeration type represents the use (or key type) flags (RFC 2535 - section 3.1.2).
+ *
+ */
+ enum UseFlags : uint8_t
+ {
+ kAuthConfidPermitted = 0x00, ///< Use of the key for authentication and/or confidentiality is permitted.
+ kAuthPermitted = 0x40, ///< Use of the key is only permitted for authentication.
+ kConfidPermitted = 0x80, ///< Use of the key is only permitted for confidentiality.
+ kNoKey = 0xc0, ///< No key value (e.g., can indicate zone is not secure).
+ };
+
+ /**
+ * This enumeration type represents key owner (or name type) flags (RFC 2535 - section 3.1.2).
+ *
+ */
+ enum OwnerFlags : uint8_t
+ {
+ kOwnerUser = 0x00, ///< Key is associated with a "user" or "account" at end entity.
+ kOwnerZone = 0x01, ///< Key is a zone key (used for data origin authentication).
+ kOwnerNonZone = 0x02, ///< Key is associated with a non-zone "entity".
+ kOwnerReserved = 0x03, ///< Reserved for future use.
+ };
+
+ /**
+ * This enumeration defines flag bits for the "signatory" flags (RFC 2137).
+ *
+ * The flags defined are for non-zone (`kOwnerNoneZone`) keys (RFC 2137 - section 3.1.3).
+ *
+ */
+ enum : uint8_t
+ {
+ kSignatoryFlagZone = 1 << 3, ///< Key is authorized to attach, detach, and move zones.
+ kSignatoryFlagStrong = 1 << 2, ///< Key is authorized to add and delete RRs even if RRs auth with other key.
+ kSignatoryFlagUnique = 1 << 1, ///< Key is authorized to add and update RRs for only a single owner name.
+ kSignatoryFlagGeneral = 1 << 0, ///< If the other flags are zero, this is used to indicate it is an update key.
+ };
+
+ /**
+ * This method initializes the KEY Resource Record by setting its type and class.
+ *
+ * Other record fields (TTL, length, flags, protocol, algorithm) remain unchanged/uninitialized.
+ *
+ * @param[in] aClass The class of the resource record (default is `kClassInternet`).
+ *
+ */
+ void Init(uint16_t aClass = kClassInternet) { ResourceRecord::Init(kTypeKey, aClass); }
+
+ /**
+ * This method tells whether the KEY record is valid.
+ *
+ * @returns TRUE if this is a valid KEY record, FALSE if an invalid KEY record.
+ *
+ */
+ bool IsValid(void) const;
+
+ /**
+ * This method gets the key use (or key type) flags.
+ *
+ * @returns The key use flags.
+ *
+ */
+ UseFlags GetUseFlags(void) const { return static_cast<UseFlags>(mFlags[0] & kUseFlagsMask); }
+
+ /**
+ * This method gets the owner (or name type) flags.
+ *
+ * @returns The key owner flags.
+ *
+ */
+ OwnerFlags GetOwnerFlags(void) const { return static_cast<OwnerFlags>(mFlags[0] & kOwnerFlagsMask); }
+
+ /**
+ * This method gets the signatory flags.
+ *
+ * @returns The signatory flags.
+ *
+ */
+ uint8_t GetSignatoryFlags(void) const { return (mFlags[1] & kSignatoryFlagsMask); }
+
+ /**
+ * This method sets the flags field.
+ *
+ * @param[in] aUseFlags The `UseFlags` value.
+ * @param[in] aOwnerFlags The `OwnerFlags` value.
+ * @param[in] aSignatoryFlags The signatory flags.
+ *
+ */
+ void SetFlags(UseFlags aUseFlags, OwnerFlags aOwnerFlags, uint8_t aSignatoryFlags)
+ {
+ mFlags[0] = (static_cast<uint8_t>(aUseFlags) | static_cast<uint8_t>(aOwnerFlags));
+ mFlags[1] = (aSignatoryFlags & kSignatoryFlagsMask);
+ }
+
+ /**
+ * This method returns the KEY record's protocol value.
+ *
+ * @returns The protocol value.
+ *
+ */
+ uint8_t GetProtocol(void) const { return mProtocol; }
+
+ /**
+ * This method sets the KEY record's protocol value.
+ *
+ * @param[in] aProtocol The protocol value.
+ *
+ */
+ void SetProtocol(uint8_t aProtocol) { mProtocol = aProtocol; }
+
+ /**
+ * This method returns the KEY record's algorithm value.
+ *
+ * @returns The algorithm value.
+ *
+ */
+ uint8_t GetAlgorithm(void) const { return mAlgorithm; }
+
+ /**
+ * This method sets the KEY record's algorithm value.
+ *
+ * @param[in] aAlgorithm The algorithm value.
+ *
+ */
+ void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; }
+
+private:
+ enum : uint8_t
+ {
+ kUseFlagsMask = 0xc0, // top two bits in the first flag byte.
+ kOwnerFlagsMask = 0x03, // lowest two bits in the first flag byte.
+ kSignatoryFlagsMask = 0x0f, // lower 4 bits in the second flag byte.
+ };
+
+ // Flags format:
+ //
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ // | Use | Z | XT| Z | Z | Owner | Z | Z | Z | Z | SIG |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ // \ / \ /
+ // ---------- mFlags[0] --------- -------- mFlags[1] ----------
+
+ uint8_t mFlags[2];
+ uint8_t mProtocol;
+ uint8_t mAlgorithm;
+ // Followed by the public key
+
+} OT_TOOL_PACKED_END;
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+OT_TOOL_PACKED_BEGIN
+class Ecdsa256KeyRecord : public KeyRecord, public Clearable<Ecdsa256KeyRecord>, public Equatable<Ecdsa256KeyRecord>
+{
+public:
+ /**
+ * This method initializes the KEY Resource Record to ECDSA with curve P-256.
+ *
+ * Other record fields (TTL, length, flags, protocol) remain unchanged/uninitialized.
+ *
+ */
+ void Init(void);
+
+ /**
+ * This method tells whether this is a valid ECDSA DNSKEY with curve P-256.
+ *
+ * @returns A boolean that indicates whether this is a valid ECDSA DNSKEY RR with curve P-256.
+ *
+ */
+ bool IsValid(void) const;
+
+ /**
+ * This method returns the ECDSA P-256 public kek.
+ *
+ * @returns A reference to the public key.
+ *
+ */
+ const Crypto::Ecdsa::P256::PublicKey &GetKey(void) const { return mKey; }
+
+private:
+ Crypto::Ecdsa::P256::PublicKey mKey;
+} OT_TOOL_PACKED_END;
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+/**
+ * This class implements Resource Record body format of SIG type (RFC 2535 - section-4.1).
+ *
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class SigRecord : public ResourceRecord, public Clearable<SigRecord>
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeSig, ///< The SIG record type.
+ };
+
+ /**
+ * This method initializes the SIG Resource Record by setting its type and class.
+ *
+ * Other record fields (TTL, length, ...) remain unchanged/uninitialized.
+ *
+ * SIG(0) requires SIG RR to set class field as ANY or `kClassAny` (RFC 2931 - section 3).
+ *
+ * @param[in] aClass The class of the resource record.
+ *
+ */
+ void Init(uint16_t aClass) { ResourceRecord::Init(kTypeSig, aClass); }
+
+ /**
+ * This method tells whether the SIG record is valid.
+ *
+ * @returns TRUE if this is a valid SIG record, FALSE if not a valid SIG record.
+ *
+ */
+ bool IsValid(void) const;
+
+ /**
+ * This method returns the SIG record's type-covered value.
+ *
+ * @returns The type-covered value.
+ *
+ */
+ uint16_t GetTypeCovered(void) const { return HostSwap16(mTypeCovered); }
+
+ /**
+ * This method sets the SIG record's type-covered value.
+ *
+ * @param[in] aTypeCovered The type-covered value.
+ *
+ */
+ void SetTypeCovered(uint8_t aTypeCovered) { mTypeCovered = HostSwap16(aTypeCovered); }
+
+ /**
+ * This method returns the SIG record's algorithm value.
+ *
+ * @returns The algorithm value.
+ *
+ */
+ uint8_t GetAlgorithm(void) const { return mAlgorithm; }
+
+ /**
+ * This method sets the SIG record's algorithm value.
+ *
+ * @param[in] aAlgorithm The algorithm value.
+ *
+ */
+ void SetAlgorithm(uint8_t aAlgorithm) { mAlgorithm = aAlgorithm; }
+
+ /**
+ * This method returns the SIG record's labels-count (number of labels, not counting null label, in the original
+ * name of the owner).
+ *
+ * @returns The labels-count value.
+ *
+ */
+ uint8_t GetLabels(void) const { return mLabels; }
+
+ /**
+ * This method sets the SIG record's labels-count (number of labels, not counting null label, in the original
+ * name of the owner).
+ *
+ * @param[in] aLabels The labels-count value.
+ *
+ */
+ void SetLabels(uint8_t aLabels) { mLabels = aLabels; }
+
+ /**
+ * This method returns the SIG record's original TTL value.
+ *
+ * @returns The original TTL value.
+ *
+ */
+ uint32_t GetOriginalTtl(void) const { return HostSwap32(mOriginalTtl); }
+
+ /**
+ * This method sets the SIG record's original TTL value.
+ *
+ * @param[in] aOriginalTtl The original TTL value.
+ *
+ */
+ void SetOriginalTtl(uint32_t aOriginalTtl) { mOriginalTtl = HostSwap32(aOriginalTtl); }
+
+ /**
+ * This method returns the SIG record's expiration time value.
+ *
+ * @returns The expiration time value (seconds since Jan 1, 1970).
+ *
+ */
+ uint32_t GetExpiration(void) const { return HostSwap32(mExpiration); }
+
+ /**
+ * This method sets the SIG record's expiration time value.
+ *
+ * @param[in] aExpiration The expiration time value (seconds since Jan 1, 1970).
+ *
+ */
+ void SetExpiration(uint32_t aExpiration) { mExpiration = HostSwap32(aExpiration); }
+
+ /**
+ * This method returns the SIG record's inception time value.
+ *
+ * @returns The inception time value (seconds since Jan 1, 1970).
+ *
+ */
+ uint32_t GetInception(void) const { return HostSwap32(mInception); }
+
+ /**
+ * This method sets the SIG record's inception time value.
+ *
+ * @param[in] aInception The inception time value (seconds since Jan 1, 1970).
+ *
+ */
+ void SetInception(uint32_t aInception) { mInception = HostSwap32(aInception); }
+
+ /**
+ * This method returns the SIG record's key tag value.
+ *
+ * @returns The key tag value.
+ *
+ */
+ uint16_t GetKeyTag(void) const { return HostSwap16(mKeyTag); }
+
+ /**
+ * This method sets the SIG record's key tag value.
+ *
+ * @param[in] aKeyTag The key tag value.
+ *
+ */
+ void SetKeyTag(uint16_t aKeyTag) { mKeyTag = HostSwap16(aKeyTag); }
+
+ /**
+ * This method returns a pointer to the start of the record data fields.
+ *
+ * @returns A pointer to the start of the record data fields.
+ *
+ */
+ const uint8_t *GetRecordData(void) const { return reinterpret_cast<const uint8_t *>(&mTypeCovered); }
+
+ /**
+ * This method parses and reads the SIG signer name from a message.
+ *
+ * @param[in] aMessage The message to read from. `aMessage.GetOffset()` MUST point to the start of DNS
+ * header.
+ * @param[inout] aOffset On input, the offset in @p aMessage to start of signer name field.
+ * On exit when successfully read, @p aOffset is updated to point to the byte
+ * after the name field (i.e., start of signature field).
+ * @param[out] aNameBuffer A pointer to a char array to output the read name as a null-terminated C string
+ * (MUST NOT be nullptr).
+ * @param[in] aNameBufferSize The size of @p aNameBuffer.
+ *
+ * @retval kErrorNone The name was read successfully. @p aOffset and @p aNameBuffer are updated.
+ * @retval kErrorParse The SIG record in @p aMessage could not be parsed (invalid format).
+ * @retval kErrorNoBufs Name could not fit in @p aNameBufferSize chars.
+ *
+ */
+ Error ReadSignerName(const Message &aMessage, uint16_t &aOffset, char *aNameBuffer, uint16_t aNameBufferSize) const
+ {
+ return ResourceRecord::ReadName(aMessage, aOffset, /* aStartOffset */ aOffset - sizeof(SigRecord), aNameBuffer,
+ aNameBufferSize,
+ /* aSkipRecord */ false);
+ }
+
+private:
+ uint16_t mTypeCovered; // type of the other RRs covered by this SIG. set to zero for SIG(0).
+ uint8_t mAlgorithm; // Algorithm number (see `KeyRecord` enumeration).
+ uint8_t mLabels; // Number of labels (not counting null label) in the original name of the owner of RR.
+ uint32_t mOriginalTtl; // Original time-to-live (should set to zero for SIG(0)).
+ uint32_t mExpiration; // Signature expiration time (seconds since Jan 1, 1970).
+ uint32_t mInception; // Signature inception time (seconds since Jan 1, 1970).
+ uint16_t mKeyTag; // Key tag.
+ // Followed by signer name fields and signature fields
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements DNS OPT Pseudo Resource Record header for EDNS(0) (RFC 6891 - Section 6.1).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class OptRecord : public ResourceRecord
+{
+public:
+ enum : uint16_t
+ {
+ kType = kTypeOpt, ///< The OPT record type.
+ };
+
+ /**
+ * This method initializes the OPT Resource Record by setting its type and clearing extended Response Code, version
+ * and all flags.
+ *
+ * Other record fields (UDP payload size, length) remain unchanged/uninitialized.
+ *
+ */
+ void Init(void)
+ {
+ SetType(kTypeOpt);
+ SetTtl(0);
+ }
+
+ /**
+ * This method gets the requester's UDP payload size (the number of bytes of the largest UDP payload that can be
+ * delivered in the requester's network).
+ *
+ * The field is encoded in the CLASS field.
+ *
+ * @returns The UDP payload size.
+ *
+ */
+ uint16_t GetUdpPayloadSize(void) const { return GetClass(); }
+
+ /**
+ * This method gets the requester's UDP payload size (the number of bytes of the largest UDP payload that can be
+ * delivered in the requester's network).
+ *
+ * @param[in] aPayloadSize The UDP payload size.
+ *
+ */
+ void SetUdpPayloadSize(uint16_t aPayloadSize) { SetClass(aPayloadSize); }
+
+ /**
+ * This method gets the upper 8-bit of the extended 12-bit Response Code.
+ *
+ * Value of 0 indicates that an unextended Response code is in use.
+ *
+ * @return The upper 8-bit of the extended 12-bit Response Code.
+ *
+ */
+ uint8_t GetExtendedResponseCode(void) const { return GetTtlByteAt(kExtRCodeByteIndex); }
+
+ /**
+ * This method sets the upper 8-bit of the extended 12-bit Response Code.
+ *
+ * Value of 0 indicates that an unextended Response code is in use.
+ *
+ * @param[in] aExtendedResponse The upper 8-bit of the extended 12-bit Response Code.
+ *
+ */
+ void SetExtnededResponseCode(uint8_t aExtendedResponse) { GetTtlByteAt(kExtRCodeByteIndex) = aExtendedResponse; }
+
+ /**
+ * This method gets the Version field.
+ *
+ * @returns The version.
+ *
+ */
+ uint8_t GetVersion(void) const { return GetTtlByteAt(kVersionByteIndex); }
+
+ /**
+ * This method set the Version field.
+ *
+ * @param[in] aVersion The version.
+ *
+ */
+ void SetVersion(uint8_t aVersion) { GetTtlByteAt(kVersionByteIndex) = aVersion; }
+
+ /**
+ * This method indicates whether the DNSSEC OK flag is set or not.
+ *
+ * @returns True if DNSSEC OK flag is set in the header, false otherwise.
+ *
+ */
+ bool IsDnsSecurityFlagSet(void) const { return (GetTtlByteAt(kFlagByteIndex) & kDnsSecFlag) != 0; }
+
+ /**
+ * This method clears the DNSSEC OK bit flag.
+ *
+ */
+ void ClearDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) &= ~kDnsSecFlag; }
+
+ /**
+ * This method sets the DNSSEC OK bit flag.
+ *
+ */
+ void SetDnsSecurityFlag(void) { GetTtlByteAt(kFlagByteIndex) |= kDnsSecFlag; }
+
+private:
+ // The OPT RR re-purposes the existing CLASS and TTL fields in the
+ // RR. The CLASS field (`uint16_t`) is used for requester UDP
+ // payload size. The TTL field is used for extended Response Code,
+ // version and flags as follows:
+ //
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ // | EXTENDED-RCODE | VERSION |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ // | DO| Z | Z |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ //
+ // The variable data part of OPT RR can contain zero of more `Option`.
+
+ enum : uint8_t
+ {
+ kExtRCodeByteIndex = 0, // Byte index of Extended RCODE within the TTL field.
+ kVersionByteIndex = 1, // Byte index of Version within the TTL field.
+ kFlagByteIndex = 2, // Byte index of flag byte within the TTL field.
+ kDnsSecFlag = 1 << 7, // DNSSec OK bit flag.
+ };
+
+ uint8_t GetTtlByteAt(uint8_t aIndex) const { return reinterpret_cast<const uint8_t *>(&mTtl)[aIndex]; }
+ uint8_t &GetTtlByteAt(uint8_t aIndex) { return reinterpret_cast<uint8_t *>(&mTtl)[aIndex]; }
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements the body of an Option in OPT Pseudo Resource Record (RFC 6981 - Section 6.1).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Option
+{
+public:
+ /**
+ * This enumeration defines option code values.
+ *
+ */
+ enum : uint16_t
+ {
+ kUpdateLease = 2, ///< Update lease option code.
+ };
+
+ /**
+ * This method returns the option code value.
+ *
+ * @returns The option code value.
+ *
+ */
+ uint16_t GetOptionCode(void) const { return HostSwap16(mOptionCode); }
+
+ /**
+ * This method sets the option code value.
+ *
+ * @param[in] aOptionCode The option code value.
+ *
+ */
+ void SetOptionCode(uint16_t aOptionCode) { mOptionCode = HostSwap16(aOptionCode); }
+
+ /**
+ * This method returns the option length value.
+ *
+ * @returns The option length (size of option data in bytes).
+ *
+ */
+ uint16_t GetOptionLength(void) const { return HostSwap16(mOptionLength); }
+
+ /**
+ * This method sets the option length value.
+ *
+ * @param[in] aOptionLength The option length (size of option data in bytes).
+ *
+ */
+ void SetOptionLength(uint16_t aOptionLength) { mOptionLength = HostSwap16(aOptionLength); }
+
+ /**
+ * This method returns the size of (number of bytes) in the Option and its data.
+ *
+ * @returns Size (number of bytes) of the Option its data section.
+ *
+ */
+ uint32_t GetSize(void) const { return sizeof(Option) + GetOptionLength(); }
+
+private:
+ uint16_t mOptionCode;
+ uint16_t mOptionLength;
+ // Followed by Option data (varies per option code).
+
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements an Update Lease Option body.
+ *
+ * This implementation is intended for use in Dynamic DNS Update Lease Requests and Responses as specified in
+ * https://tools.ietf.org/html/draft-sekar-dns-ul-02.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class LeaseOption : public Option
+{
+public:
+ enum : uint16_t
+ {
+ kOptionLength = sizeof(uint32_t) + sizeof(uint32_t), ///< Option length (lease and key lease values)
+ };
+
+ /**
+ * This method initialize the Update Lease Option by setting the Option Code and Option Length.
+ *
+ * The lease and key lease intervals remain unchanged/uninitialized.
+ *
+ */
+ void Init(void)
+ {
+ SetOptionCode(kUpdateLease);
+ SetOptionLength(kOptionLength);
+ }
+
+ /**
+ * This method tells whether this is a valid Lease Option.
+ *
+ * @returns TRUE if this is a valid Lease Option, FALSE if not a valid Lease Option.
+ *
+ */
+ bool IsValid(void) const;
+
+ /**
+ * This method returns the Update Lease OPT record's lease interval value.
+ *
+ * @returns The lease interval value (in seconds).
+ *
+ */
+ uint32_t GetLeaseInterval(void) const { return HostSwap32(mLeaseInterval); }
+
+ /**
+ * This method sets the Update Lease OPT record's lease interval value.
+ *
+ * @param[in] aLeaseInterval The lease interval value.
+ *
+ */
+ void SetLeaseInterval(uint32_t aLeaseInterval) { mLeaseInterval = HostSwap32(aLeaseInterval); }
+
+ /**
+ * This method returns the Update Lease OPT record's key lease interval value.
+ *
+ * @returns The key lease interval value (in seconds).
+ *
+ */
+ uint32_t GetKeyLeaseInterval(void) const { return HostSwap32(mKeyLeaseInterval); }
+
+ /**
+ * This method sets the Update Lease OPT record's key lease interval value.
+ *
+ * @param[in] aKeyLeaseInterval The key lease interval value (in seconds).
+ *
+ */
+ void SetKeyLeaseInterval(uint32_t aKeyLeaseInterval) { mKeyLeaseInterval = HostSwap32(aKeyLeaseInterval); }
+
+private:
+ uint32_t mLeaseInterval;
+ uint32_t mKeyLeaseInterval;
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Question format.
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Question
+{
+public:
+ /**
+ * Default constructor for Question
+ *
+ */
+ Question(void) = default;
+
+ /**
+ * Constructor for Question.
+ *
+ */
+ explicit Question(uint16_t aType, uint16_t aClass = ResourceRecord::kClassInternet)
+ {
+ SetType(aType);
+ SetClass(aClass);
+ }
+
+ /**
+ * This method returns the type of the question.
+ *
+ * @returns The type of the question.
+ *
+ */
+ uint16_t GetType(void) const { return HostSwap16(mType); }
+
+ /**
+ * This method sets the type of the question.
+ *
+ * @param[in] aType The type of the question.
+ *
+ */
+ void SetType(uint16_t aType) { mType = HostSwap16(aType); }
+
+ /**
+ * This method returns the class of the question.
+ *
+ * @returns The class of the question.
+ *
+ */
+ uint16_t GetClass(void) const { return HostSwap16(mClass); }
+
+ /**
+ * This method sets the class of the question.
+ *
+ * @param[in] aClass The class of the question.
+ *
+ */
+ void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
+
+private:
+ uint16_t mType; // The type of the data in question section.
+ uint16_t mClass; // The class of the data in question section.
+} OT_TOOL_PACKED_END;
+
+/**
+ * This class implements Zone section body for DNS Update (RFC 2136 - section 2.3).
+ *
+ */
+OT_TOOL_PACKED_BEGIN
+class Zone : public Question
+{
+public:
+ /**
+ * Constructor for Zone.
+ *
+ * @param[in] aClass The class of the zone (default is `kClassInternet`).
+ *
+ */
+ explicit Zone(uint16_t aClass = ResourceRecord::kClassInternet)
+ : Question(ResourceRecord::kTypeSoa, aClass)
+ {
+ }
+} OT_TOOL_PACKED_END;
+
+/**
+ * @}
+ *
+ */
+
+} // namespace Dns
+} // namespace ot
+
+#endif // DNS_HEADER_HPP_
diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp
new file mode 100644
index 0000000..15aa100
--- /dev/null
+++ b/src/core/net/dnssd_server.cpp
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2021, 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 DNS-SD server.
+ */
+
+#include "dnssd_server.hpp"
+
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
+#include "net/srp_server.hpp"
+#include "net/udp6.hpp"
+
+using ot::Encoding::BigEndian::HostSwap16;
+
+namespace ot {
+namespace Dns {
+namespace ServiceDiscovery {
+
+const char Server::kDnssdProtocolUdp[4] = {'_', 'u', 'd', 'p'};
+const char Server::kDnssdProtocolTcp[4] = {'_', 't', 'c', 'p'};
+const char Server::kDefaultDomainName[] = "default.service.arpa.";
+
+Server::Server(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mSocket(aInstance)
+{
+}
+
+Error Server::Start(void)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(!IsRunning());
+
+ SuccessOrExit(error = mSocket.Open(&Server::HandleUdpReceive, this));
+ SuccessOrExit(error = mSocket.Bind(kPort, OT_NETIF_UNSPECIFIED));
+
+exit:
+ otLogInfoDns("[server] started: %s", ErrorToString(error));
+ return error;
+}
+
+void Server::Stop(void)
+{
+ IgnoreError(mSocket.Close());
+ otLogInfoDns("[server] stopped");
+}
+
+void Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+{
+ static_cast<Server *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
+ *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
+}
+
+void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+{
+ Error error = kErrorNone;
+ Header requestHeader;
+ Message *responseMessage = nullptr;
+
+ SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), requestHeader));
+ VerifyOrExit(requestHeader.GetType() == Header::kTypeQuery, error = kErrorDrop);
+
+ responseMessage = mSocket.NewMessage(0);
+ VerifyOrExit(responseMessage != nullptr, error = kErrorNoBufs);
+
+ // Allocate space for DNS header
+ SuccessOrExit(error = responseMessage->SetLength(sizeof(Header)));
+
+ // ProcessQuery is assumed to always prepare the response DNS message and header properly even in the case of system
+ // failures (e.g. no more buffers).
+ ProcessQuery(aMessage, *responseMessage, requestHeader);
+
+ error = mSocket.SendTo(*responseMessage, aMessageInfo);
+
+exit:
+ FreeMessageOnError(responseMessage, error);
+}
+
+void Server::ProcessQuery(Message &aMessage, Message &aResponse, const Header &aRequestHeader)
+{
+ Header responseHeader;
+ uint16_t readOffset;
+ Question question;
+ char name[Dns::Name::kMaxNameSize];
+ NameCompressInfo compressInfo(kDefaultDomainName);
+ Header::Response response = Header::Response::kResponseSuccess;
+ Error error = kErrorNone;
+ uint8_t resolveAdditional = kResolveAdditionalAll;
+
+ // Setup initial DNS response header
+ responseHeader.Clear();
+ responseHeader.SetType(Header::kTypeResponse);
+ responseHeader.SetMessageId(aRequestHeader.GetMessageId());
+
+ // Validate the query
+ VerifyOrExit(aRequestHeader.GetQueryType() == Header::kQueryTypeStandard,
+ response = Header::kResponseNotImplemented);
+ VerifyOrExit(!aRequestHeader.IsTruncationFlagSet(), response = Header::kResponseFormatError);
+ VerifyOrExit(aRequestHeader.GetQuestionCount() > 0, response = Header::kResponseFormatError);
+
+ readOffset = sizeof(Header);
+
+ // Check and append the questions
+ for (uint16_t i = 0; i < aRequestHeader.GetQuestionCount(); i++)
+ {
+ NameComponentsOffsetInfo nameComponentsOffsetInfo;
+
+ VerifyOrExit(kErrorNone == Dns::Name::ReadName(aMessage, readOffset, name, sizeof(name)),
+ response = Header::kResponseFormatError);
+ VerifyOrExit(kErrorNone == aMessage.Read(readOffset, question), response = Header::kResponseFormatError);
+ readOffset += sizeof(question);
+
+ uint16_t qtype = question.GetType();
+
+ VerifyOrExit(qtype == ResourceRecord::kTypePtr || qtype == ResourceRecord::kTypeSrv ||
+ qtype == ResourceRecord::kTypeTxt || qtype == ResourceRecord::kTypeAaaa,
+ response = Header::kResponseNotImplemented);
+
+ VerifyOrExit(kErrorNone == FindNameComponents(name, compressInfo.GetDomainName(), nameComponentsOffsetInfo),
+ response = Header::kResponseNameError);
+
+ switch (question.GetType())
+ {
+ case ResourceRecord::kTypePtr:
+ VerifyOrExit(nameComponentsOffsetInfo.IsServiceName(), response = Header::kResponseNameError);
+ break;
+ case ResourceRecord::kTypeSrv:
+ VerifyOrExit(nameComponentsOffsetInfo.IsServiceInstanceName(), response = Header::kResponseNameError);
+ resolveAdditional &= ~kResolveAdditionalSrv;
+ break;
+ case ResourceRecord::kTypeTxt:
+ VerifyOrExit(nameComponentsOffsetInfo.IsServiceInstanceName(), response = Header::kResponseNameError);
+ resolveAdditional &= ~kResolveAdditionalTxt;
+ break;
+ case ResourceRecord::kTypeAaaa:
+ VerifyOrExit(nameComponentsOffsetInfo.IsHostName(), response = Header::kResponseNameError);
+ resolveAdditional &= ~kResolveAdditionalAaaa;
+ break;
+ default:
+ ExitNow(response = Header::kResponseNotImplemented);
+ }
+
+ SuccessOrExit(error = AppendQuestion(name, question, aResponse, compressInfo));
+ }
+
+ responseHeader.SetQuestionCount(aRequestHeader.GetQuestionCount());
+
+ // Answer the questions
+ readOffset = sizeof(Header);
+ for (uint16_t i = 0; i < aRequestHeader.GetQuestionCount(); i++)
+ {
+ uint8_t resolveKind = kResolveAnswer;
+
+ IgnoreError(Dns::Name::ReadName(aMessage, readOffset, name, sizeof(name)));
+ IgnoreError(aMessage.Read(readOffset, question));
+ readOffset += sizeof(question);
+
+ response = ResolveQuestion(name, question, responseHeader, aResponse, resolveKind, compressInfo);
+
+ otLogInfoDns("[server] ANSWER: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d",
+ aRequestHeader.GetMessageId(), name, question.GetClass(), question.GetType(), response);
+ }
+
+ // Answer the questions with additional RRs if required
+ VerifyOrExit(resolveAdditional != kResolveNone);
+
+ readOffset = sizeof(Header);
+ for (uint16_t i = 0; i < aRequestHeader.GetQuestionCount(); i++)
+ {
+ IgnoreError(Dns::Name::ReadName(aMessage, readOffset, name, sizeof(name)));
+ IgnoreError(aMessage.Read(readOffset, question));
+ readOffset += sizeof(question);
+
+ VerifyOrExit(Header::kResponseServerFailure !=
+ ResolveQuestion(name, question, responseHeader, aResponse, resolveAdditional, compressInfo),
+ response = Header::kResponseServerFailure);
+
+ otLogInfoDns("[server] ADDITIONAL: TRANSACTION=0x%04x, QUESTION=[%s %d %d], RCODE=%d",
+ aRequestHeader.GetMessageId(), name, question.GetClass(), question.GetType(), response);
+ }
+
+exit:
+ response = (error == kErrorNone) ? response : Header::Response::kResponseServerFailure;
+
+ if (response == Header::Response::kResponseServerFailure)
+ {
+ otLogWarnDns("[server] failed to handle DNS query due to server failure");
+ responseHeader.SetQuestionCount(0);
+ responseHeader.SetAnswerCount(0);
+ responseHeader.SetAdditionalRecordCount(0);
+ IgnoreError(aResponse.SetLength(sizeof(Header)));
+ }
+
+ responseHeader.SetResponseCode(response);
+ aResponse.Write(0, responseHeader);
+}
+
+Header::Response Server::ResolveQuestion(const char * aName,
+ const Question & aQuestion,
+ Header & aResponseHeader,
+ Message & aResponseMessage,
+ uint8_t aResolveKind,
+ NameCompressInfo &aCompressInfo)
+{
+ OT_UNUSED_VARIABLE(aName);
+ OT_UNUSED_VARIABLE(aQuestion);
+ OT_UNUSED_VARIABLE(aResponseHeader);
+ OT_UNUSED_VARIABLE(aResponseMessage);
+ OT_UNUSED_VARIABLE(aCompressInfo);
+
+ Header::Response response = Header::kResponseNameError;
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ response = ResolveQuestionBySrp(aName, aQuestion, aResponseHeader, aResponseMessage, aResolveKind, aCompressInfo);
+#endif
+
+ return response;
+}
+
+Error Server::AppendQuestion(const char * aName,
+ const Question & aQuestion,
+ Message & aMessage,
+ NameCompressInfo &aCompressInfo)
+{
+ Error error = kErrorNone;
+
+ switch (aQuestion.GetType())
+ {
+ case ResourceRecord::kTypePtr:
+ SuccessOrExit(error = AppendServiceName(aMessage, aName, aCompressInfo));
+ break;
+ case ResourceRecord::kTypeSrv:
+ case ResourceRecord::kTypeTxt:
+ SuccessOrExit(error = AppendInstanceName(aMessage, aName, aCompressInfo));
+ break;
+ case ResourceRecord::kTypeAaaa:
+ SuccessOrExit(error = AppendHostName(aMessage, aName, aCompressInfo));
+ break;
+ default:
+ OT_ASSERT(false);
+ }
+
+ error = aMessage.Append(aQuestion);
+
+exit:
+ return error;
+}
+
+Error Server::AppendPtrRecord(Message & aMessage,
+ const char * aServiceName,
+ const char * aInstanceName,
+ uint32_t aTtl,
+ NameCompressInfo &aCompressInfo)
+{
+ Error error;
+ PtrRecord ptrRecord;
+ uint16_t recordOffset;
+
+ ptrRecord.Init();
+ ptrRecord.SetTtl(aTtl);
+
+ SuccessOrExit(error = AppendServiceName(aMessage, aServiceName, aCompressInfo));
+
+ recordOffset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.SetLength(recordOffset + sizeof(ptrRecord)));
+
+ SuccessOrExit(error = AppendInstanceName(aMessage, aInstanceName, aCompressInfo));
+
+ ptrRecord.SetLength(aMessage.GetLength() - (recordOffset + sizeof(ResourceRecord)));
+ aMessage.Write(recordOffset, ptrRecord);
+
+exit:
+ return error;
+}
+
+Error Server::AppendSrvRecord(Message & aMessage,
+ const char * aInstanceName,
+ const char * aHostName,
+ uint32_t aTtl,
+ uint16_t aPriority,
+ uint16_t aWeight,
+ uint16_t aPort,
+ NameCompressInfo &aCompressInfo)
+{
+ SrvRecord srvRecord;
+ Error error = kErrorNone;
+ uint16_t recordOffset;
+
+ srvRecord.Init();
+ srvRecord.SetTtl(aTtl);
+ srvRecord.SetPriority(aPriority);
+ srvRecord.SetWeight(aWeight);
+ srvRecord.SetPort(aPort);
+
+ SuccessOrExit(error = AppendInstanceName(aMessage, aInstanceName, aCompressInfo));
+
+ recordOffset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.SetLength(recordOffset + sizeof(srvRecord)));
+
+ SuccessOrExit(error = AppendHostName(aMessage, aHostName, aCompressInfo));
+
+ srvRecord.SetLength(aMessage.GetLength() - (recordOffset + sizeof(ResourceRecord)));
+ aMessage.Write(recordOffset, srvRecord);
+
+exit:
+ return error;
+}
+
+Error Server::AppendAaaaRecord(Message & aMessage,
+ const char * aHostName,
+ const Ip6::Address &aAddress,
+ uint32_t aTtl,
+ NameCompressInfo & aCompressInfo)
+{
+ AaaaRecord aaaaRecord;
+ Error error;
+
+ aaaaRecord.Init();
+ aaaaRecord.SetTtl(aTtl);
+ aaaaRecord.SetAddress(aAddress);
+
+ SuccessOrExit(error = AppendHostName(aMessage, aHostName, aCompressInfo));
+ error = aMessage.Append(aaaaRecord);
+
+exit:
+ return error;
+}
+
+Error Server::AppendServiceName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo)
+{
+ Error error;
+ uint16_t serviceCompressOffset = aCompressInfo.GetServiceNameOffset(aName);
+
+ if (serviceCompressOffset != NameCompressInfo::kUnknownOffset)
+ {
+ error = Dns::Name::AppendPointerLabel(serviceCompressOffset, aMessage);
+ }
+ else
+ {
+ uint8_t domainStart = static_cast<uint8_t>(StringLength(aName, Name::kMaxNameSize - 1) -
+ StringLength(aCompressInfo.GetDomainName(), Name::kMaxNameSize - 1));
+ uint16_t domainCompressOffset = aCompressInfo.GetDomainNameOffset();
+
+ serviceCompressOffset = aMessage.GetLength();
+ aCompressInfo.SetServiceNameOffset(serviceCompressOffset, aName);
+
+ if (domainCompressOffset == NameCompressInfo::kUnknownOffset)
+ {
+ aCompressInfo.SetDomainNameOffset(serviceCompressOffset + domainStart);
+ error = Dns::Name::AppendName(aName, aMessage);
+ }
+ else
+ {
+ SuccessOrExit(error = Dns::Name::AppendMultipleLabels(aName, domainStart, aMessage));
+ error = Dns::Name::AppendPointerLabel(domainCompressOffset, aMessage);
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Server::AppendInstanceName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo)
+{
+ Error error;
+
+ uint16_t instanceCompressOffset = aCompressInfo.GetInstanceNameOffset(aName);
+
+ if (instanceCompressOffset != NameCompressInfo::kUnknownOffset)
+ {
+ error = Dns::Name::AppendPointerLabel(instanceCompressOffset, aMessage);
+ }
+ else
+ {
+ NameComponentsOffsetInfo nameComponentsInfo;
+
+ IgnoreError(FindNameComponents(aName, aCompressInfo.GetDomainName(), nameComponentsInfo));
+ OT_ASSERT(nameComponentsInfo.IsServiceInstanceName());
+
+ aCompressInfo.SetInstanceNameOffset(aMessage.GetLength(), aName);
+
+ // Append the instance name as one label
+ SuccessOrExit(error = Dns::Name::AppendLabel(aName, nameComponentsInfo.mServiceOffset - 1, aMessage));
+
+ {
+ const char *serviceName = aName + nameComponentsInfo.mServiceOffset;
+ uint16_t serviceCompressOffset = aCompressInfo.GetServiceNameOffset(serviceName);
+
+ if (serviceCompressOffset != NameCompressInfo::kUnknownOffset)
+ {
+ error = Dns::Name::AppendPointerLabel(serviceCompressOffset, aMessage);
+ }
+ else
+ {
+ aCompressInfo.SetServiceNameOffset(aMessage.GetLength(), serviceName);
+ error = Dns::Name::AppendName(serviceName, aMessage);
+ }
+ }
+ }
+
+exit:
+ return error;
+}
+
+Error Server::AppendHostName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo)
+{
+ Error error;
+ uint16_t hostCompressOffset = aCompressInfo.GetHostNameOffset(aName);
+
+ if (hostCompressOffset != NameCompressInfo::kUnknownOffset)
+ {
+ error = Dns::Name::AppendPointerLabel(hostCompressOffset, aMessage);
+ }
+ else
+ {
+ uint8_t domainStart = static_cast<uint8_t>(StringLength(aName, Name::kMaxNameLength) -
+ StringLength(aCompressInfo.GetDomainName(), Name::kMaxNameSize - 1));
+ uint16_t domainCompressOffset = aCompressInfo.GetDomainNameOffset();
+
+ hostCompressOffset = aMessage.GetLength();
+ aCompressInfo.SetHostNameOffset(hostCompressOffset, aName);
+
+ if (domainCompressOffset == NameCompressInfo::kUnknownOffset)
+ {
+ aCompressInfo.SetDomainNameOffset(hostCompressOffset + domainStart);
+ error = Dns::Name::AppendName(aName, aMessage);
+ }
+ else
+ {
+ SuccessOrExit(error = Dns::Name::AppendMultipleLabels(aName, domainStart, aMessage));
+ error = Dns::Name::AppendPointerLabel(domainCompressOffset, aMessage);
+ }
+ }
+
+exit:
+ return error;
+}
+
+void Server::IncResourceRecordCount(Header &aHeader, bool aAdditional)
+{
+ if (aAdditional)
+ {
+ aHeader.SetAdditionalRecordCount(aHeader.GetAdditionalRecordCount() + 1);
+ }
+ else
+ {
+ aHeader.SetAnswerCount(aHeader.GetAnswerCount() + 1);
+ }
+}
+
+Error Server::FindNameComponents(const char *aName, const char *aDomain, NameComponentsOffsetInfo &aInfo)
+{
+ uint8_t nameLen = static_cast<uint8_t>(StringLength(aName, Name::kMaxNameLength));
+ uint8_t domainLen = static_cast<uint8_t>(StringLength(aDomain, Name::kMaxNameLength));
+ Error error = kErrorNone;
+ uint8_t labelBegin, labelEnd;
+
+ VerifyOrExit(Dns::Name::IsSubDomainOf(aName, aDomain), error = kErrorInvalidArgs);
+
+ labelBegin = nameLen - domainLen;
+ aInfo.mDomainOffset = labelBegin;
+
+ while (true)
+ {
+ error = FindPreviousLabel(aName, labelBegin, labelEnd);
+
+ VerifyOrExit(error == kErrorNone, error = (error == kErrorNotFound ? kErrorNone : error));
+
+ if (labelEnd == labelBegin + kProtocolLabelLength &&
+ (memcmp(&aName[labelBegin], kDnssdProtocolUdp, kProtocolLabelLength) == 0 ||
+ memcmp(&aName[labelBegin], kDnssdProtocolTcp, kProtocolLabelLength) == 0))
+ {
+ // <Protocol> label found
+ aInfo.mProtocolOffset = labelBegin;
+ break;
+ }
+ }
+
+ // Get service label <Service>
+ error = FindPreviousLabel(aName, labelBegin, labelEnd);
+ VerifyOrExit(error == kErrorNone, error = (error == kErrorNotFound ? kErrorNone : error));
+
+ aInfo.mServiceOffset = labelBegin;
+
+ // Treat everything before <Service> as <Instance> label
+ error = FindPreviousLabel(aName, labelBegin, labelEnd);
+ VerifyOrExit(error == kErrorNone, error = (error == kErrorNotFound ? kErrorNone : error));
+
+ aInfo.mInstanceOffset = 0;
+
+exit:
+ return error;
+}
+
+Error Server::FindPreviousLabel(const char *aName, uint8_t &aStart, uint8_t &aStop)
+{
+ // This method finds the previous label before the current label (whose start index is @p aStart), and updates @p
+ // aStart to the start index of the label and @p aStop to the index of the dot just after the label.
+ // @note The input value of @p aStop does not matter because it is only used to output.
+
+ Error error = kErrorNone;
+ uint8_t start = aStart;
+ uint8_t end;
+
+ VerifyOrExit(start > 0, error = kErrorNotFound);
+ VerifyOrExit(aName[--start] == Name::kLabelSeperatorChar, error = kErrorInvalidArgs);
+
+ end = start;
+ while (start > 0 && aName[start - 1] != Name::kLabelSeperatorChar)
+ {
+ start--;
+ }
+
+ VerifyOrExit(start < end, error = kErrorInvalidArgs);
+
+ aStart = start;
+ aStop = end;
+
+exit:
+ return error;
+}
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+Header::Response Server::ResolveQuestionBySrp(const char * aName,
+ const Question & aQuestion,
+ Header & aResponseHeader,
+ Message & aResponseMessage,
+ uint8_t aResolveKind,
+ NameCompressInfo &aCompressInfo)
+{
+ Error error = kErrorNone;
+ const Srp::Server::Host *host = nullptr;
+ TimeMilli now = TimerMilli::GetNow();
+ uint16_t qtype = aQuestion.GetType();
+ Header::Response response = Header::kResponseNameError;
+
+ while ((host = GetNextSrpHost(host)) != nullptr)
+ {
+ bool needAdditionalAaaaRecord = false;
+ const char *hostName = host->GetFullName();
+
+ // Handle PTR/SRV/TXT query
+ if (qtype == ResourceRecord::kTypePtr || qtype == ResourceRecord::kTypeSrv || qtype == ResourceRecord::kTypeTxt)
+ {
+ const Srp::Server::Service *service = nullptr;
+
+ while ((service = GetNextSrpService(*host, service)) != nullptr)
+ {
+ uint32_t instanceTtl = TimeMilli::MsecToSec(service->GetExpireTime() - TimerMilli::GetNow());
+ const char *instanceName = service->GetFullName();
+ bool serviceNameMatched = service->MatchesServiceName(aName);
+ bool instanceNameMatched = service->Matches(aName);
+ bool ptrQueryMatched = qtype == ResourceRecord::kTypePtr && serviceNameMatched;
+ bool srvQueryMatched = qtype == ResourceRecord::kTypeSrv && instanceNameMatched;
+ bool txtQueryMatched = qtype == ResourceRecord::kTypeTxt && instanceNameMatched;
+
+ if (ptrQueryMatched || srvQueryMatched)
+ {
+ needAdditionalAaaaRecord = true;
+ }
+
+ if (aResolveKind == kResolveAnswer && ptrQueryMatched)
+ {
+ SuccessOrExit(
+ error = AppendPtrRecord(aResponseMessage, aName, instanceName, instanceTtl, aCompressInfo));
+ IncResourceRecordCount(aResponseHeader, aResolveKind != kResolveAnswer);
+ response = Header::Response::kResponseSuccess;
+ }
+
+ if ((aResolveKind == kResolveAnswer && srvQueryMatched) ||
+ ((aResolveKind & kResolveAdditionalSrv) && ptrQueryMatched))
+ {
+ SuccessOrExit(error = AppendSrvRecord(aResponseMessage, instanceName, hostName, instanceTtl,
+ service->GetPriority(), service->GetWeight(),
+ service->GetPort(), aCompressInfo));
+ IncResourceRecordCount(aResponseHeader, aResolveKind != kResolveAnswer);
+ response = Header::Response::kResponseSuccess;
+ }
+
+ if ((aResolveKind == kResolveAnswer && txtQueryMatched) ||
+ ((aResolveKind & kResolveAdditionalTxt) && ptrQueryMatched))
+ {
+ SuccessOrExit(
+ error = AppendTxtRecord(aResponseMessage, instanceName, *service, instanceTtl, aCompressInfo));
+ IncResourceRecordCount(aResponseHeader, aResolveKind != kResolveAnswer);
+ response = Header::Response::kResponseSuccess;
+ }
+ }
+ }
+
+ // Handle AAAA query
+ if ((aResolveKind == kResolveAnswer && qtype == ResourceRecord::kTypeAaaa && host->Matches(aName)) ||
+ ((aResolveKind & kResolveAdditionalAaaa) && needAdditionalAaaaRecord))
+ {
+ uint8_t addrNum;
+ const Ip6::Address *addrs = host->GetAddresses(addrNum);
+ uint32_t hostTtl = TimeMilli::MsecToSec(host->GetExpireTime() - now);
+
+ for (uint8_t i = 0; i < addrNum; i++)
+ {
+ SuccessOrExit(error = AppendAaaaRecord(aResponseMessage, hostName, addrs[i], hostTtl, aCompressInfo));
+ IncResourceRecordCount(aResponseHeader, aResolveKind != kResolveAnswer);
+ }
+
+ response = Header::Response::kResponseSuccess;
+ }
+ }
+
+exit:
+ return error == kErrorNone ? response : Header::Response::kResponseServerFailure;
+}
+
+const Srp::Server::Host *Server::GetNextSrpHost(const Srp::Server::Host *aHost)
+{
+ const Srp::Server::Host *host = Get<Srp::Server>().GetNextHost(aHost);
+
+ while (host != nullptr && host->IsDeleted())
+ {
+ host = Get<Srp::Server>().GetNextHost(host);
+ }
+
+ return host;
+}
+
+const Srp::Server::Service *Server::GetNextSrpService(const Srp::Server::Host & aHost,
+ const Srp::Server::Service *aService)
+{
+ const Srp::Server::Service *service = aHost.GetNextService(aService);
+
+ while (service != nullptr && service->IsDeleted())
+ {
+ service = aHost.GetNextService(service);
+ }
+
+ return service;
+}
+
+Error Server::AppendTxtRecord(Message & aMessage,
+ const char * aInstanceName,
+ const Srp::Server::Service &aService,
+ uint32_t aTtl,
+ NameCompressInfo & aCompressInfo)
+{
+ Error error;
+ uint16_t recordOffset;
+ TxtRecord txtRecord;
+
+ SuccessOrExit(error = AppendInstanceName(aMessage, aInstanceName, aCompressInfo));
+
+ recordOffset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.SetLength(recordOffset + sizeof(txtRecord)));
+
+ SuccessOrExit(error = aMessage.AppendBytes(aService.GetTxtData(), aService.GetTxtDataLength()));
+
+ txtRecord.Init();
+ txtRecord.SetTtl(aTtl);
+ txtRecord.SetLength(aMessage.GetLength() - (recordOffset + sizeof(ResourceRecord)));
+
+ aMessage.Write(recordOffset, txtRecord);
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+} // namespace ServiceDiscovery
+} // namespace Dns
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_DNS_SERVER_ENABLE
diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp
new file mode 100644
index 0000000..af04ba2
--- /dev/null
+++ b/src/core/net/dnssd_server.hpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2021, 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 DNS_SERVER_HPP_
+#define DNS_SERVER_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+
+#include <openthread/dns.h>
+
+#include "common/message.hpp"
+#include "common/non_copyable.hpp"
+#include "common/timer.hpp"
+#include "net/dns_types.hpp"
+#include "net/ip6.hpp"
+#include "net/netif.hpp"
+#include "net/srp_server.hpp"
+
+/**
+ * @file
+ * This file includes definitions for the DNS-SD server.
+ */
+
+namespace ot {
+namespace Dns {
+namespace ServiceDiscovery {
+
+/**
+ * This class implements DNS-SD server.
+ *
+ */
+class Server : public InstanceLocator, private NonCopyable
+{
+public:
+ /**
+ * This constructor initializes the object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ */
+ explicit Server(Instance &aInstance);
+
+ /**
+ * This method starts the DNS-SD server.
+ *
+ * @retval kErrorNone Successfully started the DNS-SD server.
+ * @retval kErrorFailed If failed to open or bind the UDP socket.
+ *
+ */
+ Error Start(void);
+
+ /**
+ * This method stops the DNS-SD server.
+ *
+ */
+ void Stop(void);
+
+private:
+ enum
+ {
+ kPort = OPENTHREAD_CONFIG_DNSSD_SERVER_PORT,
+ kProtocolLabelLength = 4,
+ };
+
+ enum : uint8_t
+ {
+ kResolveNone = 0,
+ kResolveAnswer = 1u << 0,
+ kResolveAdditionalSrv = 1u << 1,
+ kResolveAdditionalTxt = 1u << 2,
+ kResolveAdditionalAaaa = 1u << 3,
+ kResolveAdditionalAll = kResolveAdditionalSrv | kResolveAdditionalTxt | kResolveAdditionalAaaa,
+ };
+
+ class NameCompressInfo : public Clearable<NameCompressInfo>
+ {
+ public:
+ enum : uint16_t
+ {
+ kUnknownOffset = 0, // Unknown offset value (used when offset is not yet set).
+ };
+
+ explicit NameCompressInfo(const char *aDomainName)
+ : mDomainName(aDomainName)
+ , mServiceName(nullptr)
+ , mInstanceName(nullptr)
+ , mHostName(nullptr)
+ , mDomainNameOffset(kUnknownOffset)
+ , mServiceNameOffset(kUnknownOffset)
+ , mInstanceNameOffset(kUnknownOffset)
+ , mHostNameOffset(kUnknownOffset)
+ {
+ }
+
+ uint16_t GetDomainNameOffset(void) const { return mDomainNameOffset; }
+
+ void SetDomainNameOffset(uint16_t aOffset) { mDomainNameOffset = aOffset; }
+
+ const char *GetDomainName(void) const { return mDomainName; }
+
+ uint16_t GetServiceNameOffset(const char *aServiceName) const
+ {
+ uint16_t offset = mServiceNameOffset;
+
+ if (offset != kUnknownOffset && strcmp(aServiceName, mServiceName) != 0)
+ {
+ offset = kUnknownOffset;
+ }
+
+ return offset;
+ };
+
+ void SetServiceNameOffset(uint16_t aOffset, const char *aName)
+ {
+ if (mServiceName == nullptr)
+ {
+ mServiceName = aName;
+ mServiceNameOffset = aOffset;
+ }
+ }
+
+ const char *GetServiceName() const { return mServiceName; }
+
+ uint16_t GetInstanceNameOffset(const char *aName) const
+ {
+ uint16_t offset = mInstanceNameOffset;
+
+ if (offset != kUnknownOffset && strcmp(aName, mInstanceName) != 0)
+ {
+ offset = kUnknownOffset;
+ }
+
+ return offset;
+ }
+
+ void SetInstanceNameOffset(uint16_t aOffset, const char *aName)
+ {
+ if (mInstanceName == nullptr)
+ {
+ mInstanceName = aName;
+ mInstanceNameOffset = aOffset;
+ }
+ }
+
+ uint16_t GetHostNameOffset(const char *aName) const
+ {
+ uint16_t offset = mHostNameOffset;
+
+ if (offset != kUnknownOffset && strcmp(aName, mHostName) != 0)
+ {
+ offset = kUnknownOffset;
+ }
+
+ return offset;
+ }
+
+ void SetHostNameOffset(uint16_t aOffset, const char *aName)
+ {
+ if (mHostName == nullptr)
+ {
+ mHostName = aName;
+ mHostNameOffset = aOffset;
+ }
+ }
+
+ private:
+ const char *const mDomainName; // The serialized domain name.
+ const char * mServiceName; // The serialized service name (only support one service name).
+ const char * mInstanceName; // The serialized instance name or nullptr (only support one instance name).
+ const char * mHostName; // The serialized host name or nullptr (only support one host name).
+ uint16_t mDomainNameOffset; // Offset of domain name serialization into the response message.
+ uint16_t mServiceNameOffset; // Offset of service name serialization into the response message.
+ uint16_t mInstanceNameOffset; // Offset of instance name serialization into the response message.
+ uint16_t mHostNameOffset; // Offset of host name serialization into the response message.
+ };
+
+ // This structure represents the splitting information of a full name.
+ struct NameComponentsOffsetInfo
+ {
+ enum : uint8_t
+ {
+ kNotPresent = 0xff, // Indicates the component is not present.
+ };
+
+ explicit NameComponentsOffsetInfo(void)
+ : mDomainOffset(kNotPresent)
+ , mProtocolOffset(kNotPresent)
+ , mServiceOffset(kNotPresent)
+ , mInstanceOffset(kNotPresent)
+ {
+ }
+
+ bool IsServiceInstanceName(void) const { return mInstanceOffset != kNotPresent; }
+
+ bool IsServiceName(void) const { return mServiceOffset != kNotPresent && mInstanceOffset == kNotPresent; }
+
+ bool IsHostName(void) const { return mProtocolOffset == kNotPresent && mDomainOffset != 0; }
+
+ uint8_t mDomainOffset; // The offset to the beginning of <Domain>.
+ uint8_t mProtocolOffset; // The offset to the beginning of <Protocol> (i.e. _tcp or _udp) or `kNotPresent` if
+ // the name is not a service or instance.
+ uint8_t mServiceOffset; // The offset to the beginning of <Service> or `kNotPresent` if the name is not a
+ // service or instance.
+ uint8_t mInstanceOffset; // The offset to the beginning of <Instance> or `kNotPresent` if the name is not a
+ // instance.
+ };
+
+ bool IsRunning(void) const { return mSocket.IsBound(); }
+ static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+ void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ void ProcessQuery(Message &aMessage, Message &aResponse, const Header &aRequestHeader);
+ Header::Response ResolveQuestion(const char * aName,
+ const Question & aQuestion,
+ Header & aResponseHeader,
+ Message & aResponseMessage,
+ uint8_t aResolveKind,
+ NameCompressInfo &aCompressInfo);
+ static Error AppendQuestion(const char * aName,
+ const Question & aQuestion,
+ Message & aMessage,
+ NameCompressInfo &aCompressInfo);
+ static Error AppendPtrRecord(Message & aMessage,
+ const char * aServiceName,
+ const char * aInstanceName,
+ uint32_t aTtl,
+ NameCompressInfo &aCompressInfo);
+ static Error AppendSrvRecord(Message & aMessage,
+ const char * aInstanceName,
+ const char * aHostName,
+ uint32_t aTtl,
+ uint16_t aPriority,
+ uint16_t aWeight,
+ uint16_t aPort,
+ NameCompressInfo &aCompressInfo);
+ static Error AppendAaaaRecord(Message & aMessage,
+ const char * aHostName,
+ const Ip6::Address &aAddress,
+ uint32_t aTtl,
+ NameCompressInfo & aCompressInfo);
+ static Error AppendServiceName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo);
+ static Error AppendInstanceName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo);
+ static Error AppendHostName(Message &aMessage, const char *aName, NameCompressInfo &aCompressInfo);
+ static void IncResourceRecordCount(Header &aHeader, bool aAdditional);
+ static Error FindNameComponents(const char *aName, const char *aDomain, NameComponentsOffsetInfo &aInfo);
+ static Error FindPreviousLabel(const char *aName, uint8_t &aStart, uint8_t &aStop);
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ Header::Response ResolveQuestionBySrp(const char * aName,
+ const Question & aQuestion,
+ Header & aResponseHeader,
+ Message & aResponseMessage,
+ uint8_t aResolveKind,
+ NameCompressInfo &aCompressInfo);
+ const Srp::Server::Host * GetNextSrpHost(const Srp::Server::Host *aHost);
+ static const Srp::Server::Service *GetNextSrpService(const Srp::Server::Host & aHost,
+ const Srp::Server::Service *aService);
+ static Error AppendTxtRecord(Message & aMessage,
+ const char * aInstanceName,
+ const Srp::Server::Service &aService,
+ uint32_t aTtl,
+ NameCompressInfo & aCompressInfo);
+#endif
+
+ static const char kDnssdProtocolUdp[4];
+ static const char kDnssdProtocolTcp[4];
+ static const char kDefaultDomainName[];
+
+ Ip6::Udp::Socket mSocket;
+};
+
+} // namespace ServiceDiscovery
+} // namespace Dns
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+
+#endif // DNS_SERVER_HPP_
diff --git a/src/core/net/icmp6.cpp b/src/core/net/icmp6.cpp
index 51a30a8..0fd4bce 100644
--- a/src/core/net/icmp6.cpp
+++ b/src/core/net/icmp6.cpp
@@ -57,14 +57,14 @@
return Get<Ip6>().NewMessage(sizeof(Header) + aReserved);
}
-otError Icmp::RegisterHandler(Handler &aHandler)
+Error Icmp::RegisterHandler(Handler &aHandler)
{
return mHandlers.Add(aHandler);
}
-otError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier)
+Error Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MessageInfo messageInfoLocal;
Header icmpHeader;
@@ -85,12 +85,9 @@
return error;
}
-otError Icmp::SendError(Header::Type aType,
- Header::Code aCode,
- const MessageInfo &aMessageInfo,
- const Message & aMessage)
+Error Icmp::SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MessageInfo messageInfoLocal;
Message * message = nullptr;
Header icmp6Header;
@@ -107,7 +104,7 @@
messageInfoLocal = aMessageInfo;
- VerifyOrExit((message = Get<Ip6>().NewMessage(0, settings)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Ip6>().NewMessage(0, settings)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + sizeof(ip6Header)));
message->Write(sizeof(icmp6Header), ip6Header);
@@ -126,10 +123,10 @@
return error;
}
-otError Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
+Error Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
- Header icmp6Header;
+ Error error = kErrorNone;
+ Header icmp6Header;
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), icmp6Header));
@@ -174,9 +171,9 @@
return rval;
}
-otError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo)
+Error Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header icmp6Header;
Message * replyMessage = nullptr;
MessageInfo replyMessageInfo;
diff --git a/src/core/net/icmp6.hpp b/src/core/net/icmp6.hpp
index 592d4f0..88eda46 100644
--- a/src/core/net/icmp6.hpp
+++ b/src/core/net/icmp6.hpp
@@ -87,6 +87,8 @@
kTypeParameterProblem = OT_ICMP6_TYPE_PARAMETER_PROBLEM, ///< Parameter Problem
kTypeEchoRequest = OT_ICMP6_TYPE_ECHO_REQUEST, ///< Echo Request
kTypeEchoReply = OT_ICMP6_TYPE_ECHO_REPLY, ///< Echo Reply
+ kTypeRouterSolicit = OT_ICMP6_TYPE_ROUTER_SOLICIT, ///< Router Solicitation
+ kTypeRouterAdvert = OT_ICMP6_TYPE_ROUTER_ADVERT, ///< Router Advertisement
};
/**
@@ -195,7 +197,6 @@
*
*/
void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
-
} OT_TOOL_PACKED_END;
/**
@@ -251,11 +252,11 @@
*
* @param[in] aHandler A reference to the ICMPv6 handler.
*
- * @retval OT_ERROR_NONE Successfully registered the ICMPv6 handler.
- * @retval OT_ERROR_ALREADY The ICMPv6 handler is already registered.
+ * @retval kErrorNone Successfully registered the ICMPv6 handler.
+ * @retval kErrorAlready The ICMPv6 handler is already registered.
*
*/
- otError RegisterHandler(Handler &aHandler);
+ Error RegisterHandler(Handler &aHandler);
/**
* This method sends an ICMPv6 Echo Request message.
@@ -265,11 +266,11 @@
* @param[in] aIdentifier An identifier to aid in matching Echo Replies to this Echo Request.
* May be zero.
*
- * @retval OT_ERROR_NONE Successfully enqueued the ICMPv6 Echo Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to generate an ICMPv6 Echo Request message.
+ * @retval kErrorNone Successfully enqueued the ICMPv6 Echo Request message.
+ * @retval kErrorNoBufs Insufficient buffers available to generate an ICMPv6 Echo Request message.
*
*/
- otError SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
+ Error SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier);
/**
* This method sends an ICMPv6 error message.
@@ -279,11 +280,11 @@
* @param[in] aMessageInfo A reference to the message info.
* @param[in] aMessage The error-causing IPv6 message.
*
- * @retval OT_ERROR_NONE Successfully enqueued the ICMPv6 error message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available.
+ * @retval kErrorNone Successfully enqueued the ICMPv6 error message.
+ * @retval kErrorNoBufs Insufficient buffers available.
*
*/
- otError SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage);
+ Error SendError(Header::Type aType, Header::Code aCode, const MessageInfo &aMessageInfo, const Message &aMessage);
/**
* This method handles an ICMPv6 message.
@@ -291,12 +292,12 @@
* @param[in] aMessage A reference to the ICMPv6 message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
- * @retval OT_ERROR_NONE Successfully processed the ICMPv6 message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to generate the reply.
- * @retval OT_ERROR_DROP The ICMPv6 message was invalid and dropped.
+ * @retval kErrorNone Successfully processed the ICMPv6 message.
+ * @retval kErrorNoBufs Insufficient buffers available to generate the reply.
+ * @retval kErrorDrop The ICMPv6 message was invalid and dropped.
*
*/
- otError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
+ Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
/**
* This method indicates whether or not ICMPv6 Echo processing is enabled.
@@ -325,7 +326,7 @@
bool ShouldHandleEchoRequest(const MessageInfo &aMessageInfo);
private:
- otError HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
+ Error HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
LinkedList<Handler> mHandlers;
diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp
index 0624318..d2f237f 100644
--- a/src/core/net/ip6.cpp
+++ b/src/core/net/ip6.cpp
@@ -51,6 +51,13 @@
#include "net/udp6.hpp"
#include "thread/mle.hpp"
+using IcmpType = ot::Ip6::Icmp::Header::Type;
+
+static const IcmpType sForwardICMPTypes[] = {
+ IcmpType::kTypeDstUnreach, IcmpType::kTypePacketToBig, IcmpType::kTypeTimeExceeded,
+ IcmpType::kTypeParameterProblem, IcmpType::kTypeEchoRequest, IcmpType::kTypeEchoReply,
+};
+
namespace ot {
namespace Ip6 {
@@ -60,7 +67,7 @@
, mIsReceiveIp6FilterEnabled(false)
, mReceiveIp6DatagramCallback(nullptr)
, mReceiveIp6DatagramCallbackContext(nullptr)
- , mSendQueueTask(aInstance, Ip6::HandleSendQueue, this)
+ , mSendQueueTask(aInstance, Ip6::HandleSendQueue)
, mIcmp(aInstance)
, mUdp(aInstance)
, mMpl(aInstance)
@@ -79,7 +86,7 @@
VerifyOrExit(message != nullptr);
- if (message->AppendBytes(aData, aDataLength) != OT_ERROR_NONE)
+ if (message->AppendBytes(aData, aDataLength) != kErrorNone)
{
message->Free();
message = nullptr;
@@ -156,16 +163,16 @@
return dscp;
}
-otError Ip6::GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority)
+Error Ip6::GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const Header *header;
- VerifyOrExit((aData != nullptr) && (aDataLen >= sizeof(Header)), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((aData != nullptr) && (aDataLen >= sizeof(Header)), error = kErrorInvalidArgs);
header = reinterpret_cast<const Header *>(aData);
- VerifyOrExit(header->IsValid(), error = OT_ERROR_PARSE);
- VerifyOrExit(sizeof(Header) + header->GetPayloadLength() == aDataLen, error = OT_ERROR_PARSE);
+ VerifyOrExit(header->IsValid(), error = kErrorParse);
+ VerifyOrExit(sizeof(Header) + header->GetPayloadLength() == aDataLen, error = kErrorParse);
aPriority = DscpToPriority(header->GetDscp());
@@ -179,9 +186,9 @@
mReceiveIp6DatagramCallbackContext = aCallbackContext;
}
-otError Ip6::AddMplOption(Message &aMessage, Header &aHeader)
+Error Ip6::AddMplOption(Message &aMessage, Header &aHeader)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
HopByHopHeader hbhHeader;
OptionMpl mplOption;
OptionPadN padOption;
@@ -206,9 +213,9 @@
return error;
}
-otError Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
+Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header tunnelHeader;
const NetifUnicastAddress *source;
MessageInfo messageInfo(aMessageInfo);
@@ -222,7 +229,7 @@
tunnelHeader.SetDestination(messageInfo.GetPeerAddr());
tunnelHeader.SetNextHeader(kProtoIp6);
- VerifyOrExit((source = SelectSourceAddress(messageInfo)) != nullptr, error = OT_ERROR_INVALID_SOURCE_ADDRESS);
+ VerifyOrExit((source = SelectSourceAddress(messageInfo)) != nullptr, error = kErrorInvalidSourceAddress);
tunnelHeader.SetSource(source->GetAddress());
@@ -233,9 +240,9 @@
return error;
}
-otError Ip6::InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
+Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(aHeader.GetDestination().IsMulticast() &&
aHeader.GetDestination().GetScope() >= Address::kRealmLocalScope);
@@ -254,7 +261,7 @@
IgnoreError(aMessage.Read(0, hbh));
hbhLength = (hbh.GetLength() + 1) * 8;
- VerifyOrExit(hbhLength <= aHeader.GetPayloadLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(hbhLength <= aHeader.GetPayloadLength(), error = kErrorParse);
// increase existing hop-by-hop option header length by 8 bytes
hbh.SetLength(hbh.GetLength() + 1);
@@ -313,9 +320,9 @@
return error;
}
-otError Ip6::RemoveMplOption(Message &aMessage)
+Error Ip6::RemoveMplOption(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header ip6Header;
HopByHopHeader hbh;
uint16_t offset;
@@ -331,7 +338,7 @@
IgnoreError(aMessage.Read(offset, hbh));
endOffset = offset + (hbh.GetLength() + 1) * 8;
- VerifyOrExit(aMessage.GetLength() >= endOffset, error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessage.GetLength() >= endOffset, error = kErrorParse);
offset += sizeof(hbh);
@@ -345,12 +352,12 @@
{
case OptionMpl::kType:
// if multiple MPL options exist, discard packet
- VerifyOrExit(mplOffset == 0, error = OT_ERROR_PARSE);
+ VerifyOrExit(mplOffset == 0, error = kErrorParse);
mplOffset = offset;
mplLength = option.GetLength();
- VerifyOrExit(mplLength <= sizeof(OptionMpl) - sizeof(OptionHeader), error = OT_ERROR_PARSE);
+ VerifyOrExit(mplLength <= sizeof(OptionMpl) - sizeof(OptionHeader), error = kErrorParse);
if (mplOffset == sizeof(ip6Header) + sizeof(hbh) && hbh.GetLength() == 0)
{
@@ -383,7 +390,7 @@
}
// verify that IPv6 Options header is properly formed
- VerifyOrExit(offset == endOffset, error = OT_ERROR_PARSE);
+ VerifyOrExit(offset == endOffset, error = kErrorParse);
if (remove)
{
@@ -435,9 +442,9 @@
mSendQueueTask.Post();
}
-otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
+Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
uint16_t payloadLength = aMessage.GetLength();
@@ -455,12 +462,11 @@
header.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
}
- if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast() ||
- Get<Mle::Mle>().IsAnycastLocator(aMessageInfo.GetSockAddr()))
+ if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
{
const NetifUnicastAddress *source = SelectSourceAddress(aMessageInfo);
- VerifyOrExit(source != nullptr, error = OT_ERROR_INVALID_SOURCE_ADDRESS);
+ VerifyOrExit(source != nullptr, error = kErrorInvalidSourceAddress);
header.SetSource(source->GetAddress());
}
else
@@ -519,7 +525,7 @@
void Ip6::HandleSendQueue(Tasklet &aTasklet)
{
- aTasklet.GetOwner<Ip6>().HandleSendQueue();
+ aTasklet.Get<Ip6>().HandleSendQueue();
}
void Ip6::HandleSendQueue(void)
@@ -533,9 +539,9 @@
}
}
-otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive)
+Error Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
HopByHopHeader hbhHeader;
OptionHeader optionHeader;
uint16_t endOffset;
@@ -543,7 +549,7 @@
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), hbhHeader));
endOffset = aMessage.GetOffset() + (hbhHeader.GetLength() + 1) * 8;
- VerifyOrExit(endOffset <= aMessage.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(endOffset <= aMessage.GetLength(), error = kErrorParse);
aMessage.MoveOffset(sizeof(optionHeader));
@@ -558,7 +564,7 @@
}
VerifyOrExit(aMessage.GetOffset() + sizeof(optionHeader) + optionHeader.GetLength() <= endOffset,
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
switch (optionHeader.GetType())
{
@@ -573,15 +579,15 @@
break;
case OptionHeader::kActionDiscard:
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
case OptionHeader::kActionForceIcmp:
// TODO: send icmp error
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
case OptionHeader::kActionIcmp:
// TODO: send icmp error
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
break;
@@ -595,9 +601,9 @@
}
#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
-otError Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
+Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
FragmentHeader fragmentHeader;
Message * fragment = nullptr;
@@ -637,7 +643,7 @@
offset = fragmentCnt * FragmentHeader::BytesToFragmentOffset(maxPayloadFragment);
fragmentHeader.SetOffset(offset);
- VerifyOrExit((fragment = NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((fragment = NewMessage(0)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = fragment->SetLength(aMessage.GetOffset() + sizeof(fragmentHeader) + payloadFragment));
header.SetPayloadLength(payloadFragment + sizeof(fragmentHeader));
@@ -649,7 +655,7 @@
VerifyOrExit(aMessage.CopyTo(aMessage.GetOffset() + FragmentHeader::FragmentOffsetToBytes(offset),
aMessage.GetOffset() + sizeof(fragmentHeader), payloadFragment,
*fragment) == static_cast<int>(payloadFragment),
- error = OT_ERROR_NO_BUFS);
+ error = kErrorNoBufs);
EnqueueDatagram(*fragment);
@@ -663,7 +669,7 @@
exit:
- if (error == OT_ERROR_NO_BUFS)
+ if (error == kErrorNoBufs)
{
otLogWarnIp6("No buffer for Ip6 fragmentation");
}
@@ -672,9 +678,9 @@
return error;
}
-otError Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header, headerBuffer;
FragmentHeader fragmentHeader;
Message * message = nullptr;
@@ -715,12 +721,14 @@
if (offset + payloadFragment + aMessage.GetOffset() > kMaxAssembledDatagramLength)
{
otLogWarnIp6("Packet too large for fragment buffer");
- ExitNow(error = OT_ERROR_NO_BUFS);
+ ExitNow(error = kErrorNoBufs);
}
if (message == nullptr)
{
- VerifyOrExit((message = NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ otLogDebgIp6("start reassembly");
+ VerifyOrExit((message = NewMessage(0)) != nullptr, error = kErrorNoBufs);
+ mReassemblyList.Enqueue(*message);
SuccessOrExit(error = message->SetLength(aMessage.GetOffset()));
message->SetTimeout(kIp6ReassemblyTimeout);
@@ -732,10 +740,6 @@
OT_ASSERT(assertValue == aMessage.GetOffset());
Get<TimeTicker>().RegisterReceiver(TimeTicker::kIp6FragmentReassembler);
-
- mReassemblyList.Enqueue(*message);
-
- otLogDebgIp6("start reassembly.");
}
// increase message buffer if necessary
@@ -769,20 +773,20 @@
}
exit:
- if (error != OT_ERROR_DROP && error != OT_ERROR_NONE && isFragmented)
+ if (error != kErrorDrop && error != kErrorNone && isFragmented)
{
if (message != nullptr)
{
mReassemblyList.Dequeue(*message);
message->Free();
}
- otLogWarnIp6("Reassembly failed: %s", otThreadErrorToString(error));
+ otLogWarnIp6("Reassembly failed: %s", ErrorToString(error));
}
if (isFragmented)
{
// drop all fragments, the payload is stored in the fragment buffer
- error = OT_ERROR_DROP;
+ error = kErrorDrop;
}
return error;
@@ -834,7 +838,7 @@
void Ip6::SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
MessageInfo messageInfo;
@@ -849,34 +853,34 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnIp6("Failed to send ICMP error: %s", otThreadErrorToString(error));
+ otLogWarnIp6("Failed to send ICMP error: %s", ErrorToString(error));
}
}
#else
-otError Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
+Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
{
OT_UNUSED_VARIABLE(aIpProto);
EnqueueDatagram(aMessage);
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-otError Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost)
{
OT_UNUSED_VARIABLE(aNetif);
OT_UNUSED_VARIABLE(aMessageInfo);
OT_UNUSED_VARIABLE(aFromNcpHost);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
FragmentHeader fragmentHeader;
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), fragmentHeader));
- VerifyOrExit(fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet(), error = OT_ERROR_DROP);
+ VerifyOrExit(fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet(), error = kErrorDrop);
aMessage.MoveOffset(sizeof(fragmentHeader));
@@ -885,16 +889,16 @@
}
#endif // OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
-otError Ip6::HandleExtensionHeaders(Message & aMessage,
- Netif * aNetif,
- MessageInfo &aMessageInfo,
- Header & aHeader,
- uint8_t & aNextHeader,
- bool aIsOutbound,
- bool aFromNcpHost,
- bool & aReceive)
+Error Ip6::HandleExtensionHeaders(Message & aMessage,
+ Netif * aNetif,
+ MessageInfo &aMessageInfo,
+ Header & aHeader,
+ uint8_t & aNextHeader,
+ bool aIsOutbound,
+ bool aFromNcpHost,
+ bool & aReceive)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ExtensionHeader extHeader;
while (aReceive || aNextHeader == kProtoHopOpts)
@@ -923,7 +927,7 @@
case kProtoRouting:
case kProtoNone:
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
default:
ExitNow();
@@ -936,12 +940,12 @@
return error;
}
-otError Ip6::HandlePayload(Message & aMessage,
- MessageInfo & aMessageInfo,
- uint8_t aIpProto,
- Message::Ownership aMessageOwnership)
+Error Ip6::HandlePayload(Message & aMessage,
+ MessageInfo & aMessageInfo,
+ uint8_t aIpProto,
+ Message::Ownership aMessageOwnership)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = nullptr;
VerifyOrExit(aIpProto == kProtoUdp || aIpProto == kProtoIcmp6);
@@ -953,7 +957,7 @@
break;
case Message::kCopyToUse:
- VerifyOrExit((message = aMessage.Clone()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = aMessage.Clone()) != nullptr, error = kErrorNoBufs);
break;
}
@@ -961,7 +965,7 @@
{
case kProtoUdp:
error = mUdp.HandleMessage(*message, aMessageInfo);
- if (error == OT_ERROR_DROP)
+ if (error == kErrorDrop)
{
otLogNoteIp6("Error UDP Checksum");
}
@@ -976,9 +980,9 @@
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogNoteIp6("Failed to handle payload: %s", otThreadErrorToString(error));
+ otLogNoteIp6("Failed to handle payload: %s", ErrorToString(error));
}
FreeMessage(message);
@@ -986,29 +990,31 @@
return error;
}
-otError Ip6::ProcessReceiveCallback(Message & aMessage,
- const MessageInfo &aMessageInfo,
- uint8_t aIpProto,
- bool aFromNcpHost,
- Message::Ownership aMessageOwnership)
+Error Ip6::ProcessReceiveCallback(Message & aMessage,
+ const MessageInfo &aMessageInfo,
+ uint8_t aIpProto,
+ bool aFromNcpHost,
+ Message::Ownership aMessageOwnership)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = &aMessage;
- VerifyOrExit(!aFromNcpHost, error = OT_ERROR_NO_ROUTE);
- VerifyOrExit(mReceiveIp6DatagramCallback != nullptr, error = OT_ERROR_NO_ROUTE);
+ VerifyOrExit(!aFromNcpHost, error = kErrorNoRoute);
+ VerifyOrExit(mReceiveIp6DatagramCallback != nullptr, error = kErrorNoRoute);
// Do not forward reassembled IPv6 packets.
- VerifyOrExit(aMessage.GetLength() <= kMinimalMtu, error = OT_ERROR_DROP);
+ VerifyOrExit(aMessage.GetLength() <= kMinimalMtu, error = kErrorDrop);
if (mIsReceiveIp6FilterEnabled)
{
+#if !OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
// do not pass messages sent to an RLOC/ALOC, except Service Locator
bool isLocator = Get<Mle::Mle>().IsMeshLocalAddress(aMessageInfo.GetSockAddr()) &&
aMessageInfo.GetSockAddr().GetIid().IsLocator();
VerifyOrExit(!isLocator || aMessageInfo.GetSockAddr().GetIid().IsAnycastServiceLocator(),
- error = OT_ERROR_NO_ROUTE);
+ error = kErrorNoRoute);
+#endif
switch (aIpProto)
{
@@ -1019,7 +1025,7 @@
IgnoreError(aMessage.Read(aMessage.GetOffset(), icmp));
// do not pass ICMP Echo Request messages
- VerifyOrExit(icmp.GetType() != Icmp::Header::kTypeEchoRequest, error = OT_ERROR_DROP);
+ VerifyOrExit(icmp.GetType() != Icmp::Header::kTypeEchoRequest, error = kErrorDrop);
}
break;
@@ -1027,30 +1033,10 @@
case kProtoUdp:
{
Udp::Header udp;
- uint16_t destPort;
IgnoreError(aMessage.Read(aMessage.GetOffset(), udp));
+ VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(udp.GetDestinationPort()), error = kErrorNoRoute);
- destPort = udp.GetDestinationPort();
-
- if ((destPort == Mle::kUdpPort) &&
- (aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast()))
- {
- // do not pass MLE messages
- ExitNow(error = OT_ERROR_NO_ROUTE);
- }
- else if ((destPort == Tmf::kUdpPort) && Get<Tmf::TmfAgent>().IsTmfMessage(aMessageInfo))
- {
- // do not pass TMF messages
- ExitNow(error = OT_ERROR_NO_ROUTE);
- }
-
-#if OPENTHREAD_FTD
- if (destPort == Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort())
- {
- ExitNow(error = OT_ERROR_NO_ROUTE);
- }
-#endif
break;
}
@@ -1070,7 +1056,7 @@
if (message == nullptr)
{
otLogWarnIp6("No buff to clone msg (len: %d) to pass to host", aMessage.GetLength());
- ExitNow(error = OT_ERROR_NO_BUFS);
+ ExitNow(error = kErrorNoBufs);
}
break;
@@ -1081,7 +1067,7 @@
exit:
- if ((error != OT_ERROR_NONE) && (aMessageOwnership == Message::kTakeCustody))
+ if ((error != kErrorNone) && (aMessageOwnership == Message::kTakeCustody))
{
aMessage.Free();
}
@@ -1089,15 +1075,15 @@
return error;
}
-otError Ip6::SendRaw(Message &aMessage)
+Error Ip6::SendRaw(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
MessageInfo messageInfo;
bool freed = false;
SuccessOrExit(error = header.Init(aMessage));
- VerifyOrExit(!header.GetSource().IsMulticast(), error = OT_ERROR_INVALID_SOURCE_ADDRESS);
+ VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress);
messageInfo.SetPeerAddr(header.GetSource());
messageInfo.SetSockAddr(header.GetDestination());
@@ -1121,9 +1107,9 @@
return error;
}
-otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost)
+Error Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost)
{
- otError error;
+ Error error;
MessageInfo messageInfo;
Header header;
bool receive;
@@ -1241,7 +1227,7 @@
error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost, Message::kCopyToUse);
- if ((error == OT_ERROR_NONE || error == OT_ERROR_NO_ROUTE) && forwardHost)
+ if ((error == kErrorNone || error == kErrorNoRoute) && forwardHost)
{
forwardHost = false;
}
@@ -1273,27 +1259,52 @@
header.SetHopLimit(header.GetHopLimit() - 1);
}
- VerifyOrExit(header.GetHopLimit() > 0, error = OT_ERROR_DROP);
+ VerifyOrExit(header.GetHopLimit() > 0, error = kErrorDrop);
hopLimit = header.GetHopLimit();
aMessage.Write(Header::kHopLimitFieldOffset, hopLimit);
-#if OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
- // check whether source port is an unsecure port
+ if (aFromNcpHost && nextHeader == kProtoIcmp6)
+ {
+ uint8_t icmpType;
+ bool isAllowedType = false;
+
+ SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), icmpType));
+ for (IcmpType type : sForwardICMPTypes)
+ {
+ if (icmpType == type)
+ {
+ isAllowedType = true;
+ break;
+ }
+ }
+ VerifyOrExit(isAllowedType, error = kErrorDrop);
+ }
if (aFromNcpHost && (nextHeader == kProtoTcp || nextHeader == kProtoUdp))
{
- uint16_t sourcePort;
+ uint16_t sourcePort, destPort;
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), sourcePort));
+ SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + sizeof(sourcePort), destPort));
sourcePort = HostSwap16(sourcePort);
+ destPort = HostSwap16(destPort);
+ if (nextHeader == kProtoUdp)
+ {
+ VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(destPort), error = kErrorDrop);
+ }
+
+#if OPENTHREAD_CONFIG_UNSECURE_TRAFFIC_MANAGED_BY_STACK_ENABLE
+ // check whether source port is an unsecure port
if (Get<Filter>().IsUnsecurePort(sourcePort))
{
aMessage.SetLinkSecurityEnabled(false);
otLogInfoIp6("Disabled link security for packet to %s", header.GetDestination().ToString().AsCString());
}
- }
+#else
+ OT_UNUSED_VARIABLE(sourcePort);
#endif
+ }
// `SendMessage()` takes custody of message in the success case
SuccessOrExit(error = Get<ThreadNetif>().SendMessage(aMessage));
@@ -1337,7 +1348,7 @@
#endif
}
else if (Get<ThreadNetif>().RouteLookup(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), nullptr) ==
- OT_ERROR_NONE)
+ kErrorNone)
{
// route
ExitNow(rval = true);
diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp
index 6ca1101..d6138c6 100644
--- a/src/core/net/ip6.hpp
+++ b/src/core/net/ip6.hpp
@@ -185,28 +185,28 @@
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aIpProto The Internet Protocol value.
*
- * @retval OT_ERROR_NONE Successfully enqueued the message into an output interface.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the IPv6 headers.
+ * @retval kErrorNone Successfully enqueued the message into an output interface.
+ * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers.
*
*/
- otError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
+ Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
/**
* This method sends a raw IPv6 datagram with a fully formed IPv6 header.
*
* The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
- * processing is complete, including when a value other than `OT_ERROR_NONE` is returned.
+ * processing is complete, including when a value other than `kErrorNone` is returned.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully processed the message.
- * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing rules.
- * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram.
- * @retval OT_ERROR_NO_ROUTE No route to host.
- * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message.
+ * @retval kErrorNone Successfully processed the message.
+ * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules.
+ * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram.
+ * @retval kErrorNoRoute No route to host.
+ * @retval kErrorParse Encountered a malformed header when processing the message.
*
*/
- otError SendRaw(Message &aMessage);
+ Error SendRaw(Message &aMessage);
/**
* This method processes a received IPv6 datagram.
@@ -216,14 +216,14 @@
* @param[in] aLinkMessageInfo A pointer to link-specific message information.
* @param[in] aFromNcpHost TRUE if the message was submitted by the NCP host, FALSE otherwise.
*
- * @retval OT_ERROR_NONE Successfully processed the message.
- * @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing rules.
- * @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram.
- * @retval OT_ERROR_NO_ROUTE No route to host.
- * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message.
+ * @retval kErrorNone Successfully processed the message.
+ * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules.
+ * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram.
+ * @retval kErrorNoRoute No route to host.
+ * @retval kErrorParse Encountered a malformed header when processing the message.
*
*/
- otError HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost);
+ Error HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkMessageInfo, bool aFromNcpHost);
/**
* This method registers a callback to provide received raw IPv6 datagrams.
@@ -328,41 +328,41 @@
void HandleSendQueue(void);
static uint8_t PriorityToDscp(Message::Priority aPriority);
- static otError GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority);
+ static Error GetDatagramPriority(const uint8_t *aData, uint16_t aDataLen, Message::Priority &aPriority);
- void EnqueueDatagram(Message &aMessage);
- otError ProcessReceiveCallback(Message & aMessage,
- const MessageInfo &aMessageInfo,
- uint8_t aIpProto,
- bool aFromNcpHost,
- Message::Ownership aMessageOwnership);
- otError HandleExtensionHeaders(Message & aMessage,
- Netif * aNetif,
- MessageInfo &aMessageInfo,
- Header & aHeader,
- uint8_t & aNextHeader,
- bool aIsOutbound,
- bool aFromNcpHost,
- bool & aReceive);
- otError FragmentDatagram(Message &aMessage, uint8_t aIpProto);
- otError HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost);
+ void EnqueueDatagram(Message &aMessage);
+ Error ProcessReceiveCallback(Message & aMessage,
+ const MessageInfo &aMessageInfo,
+ uint8_t aIpProto,
+ bool aFromNcpHost,
+ Message::Ownership aMessageOwnership);
+ Error HandleExtensionHeaders(Message & aMessage,
+ Netif * aNetif,
+ MessageInfo &aMessageInfo,
+ Header & aHeader,
+ uint8_t & aNextHeader,
+ bool aIsOutbound,
+ bool aFromNcpHost,
+ bool & aReceive);
+ Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
+ Error HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost);
#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
void CleanupFragmentationBuffer(void);
void HandleTimeTick(void);
void UpdateReassemblyList(void);
void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
#endif
- otError AddMplOption(Message &aMessage, Header &aHeader);
- otError AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
- otError InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
- otError RemoveMplOption(Message &aMessage);
- otError HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
- otError HandlePayload(Message & aMessage,
- MessageInfo & aMessageInfo,
- uint8_t aIpProto,
- Message::Ownership aMessageOwnership);
- bool ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const;
- bool IsOnLink(const Address &aAddress) const;
+ Error AddMplOption(Message &aMessage, Header &aHeader);
+ Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
+ Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
+ Error RemoveMplOption(Message &aMessage);
+ Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
+ Error HandlePayload(Message & aMessage,
+ MessageInfo & aMessageInfo,
+ uint8_t aIpProto,
+ Message::Ownership aMessageOwnership);
+ bool ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const;
+ bool IsOnLink(const Address &aAddress) const;
bool mForwardingEnabled;
bool mIsReceiveIp6FilterEnabled;
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index f5ed71d..808d531 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -49,7 +49,7 @@
//---------------------------------------------------------------------------------------------------------------------
// NetworkPrefix methods
-otError NetworkPrefix::GenerateRandomUla(void)
+Error NetworkPrefix::GenerateRandomUla(void)
{
m8[0] = 0xfd;
@@ -70,6 +70,23 @@
return (mLength == aPrefixLength) && (MatchLength(GetBytes(), aPrefixBytes, GetBytesSize()) >= mLength);
}
+bool Prefix::operator<(const Prefix &aOther) const
+{
+ bool isSmaller;
+ uint8_t matchedLength;
+
+ VerifyOrExit(GetLength() == aOther.GetLength(), isSmaller = GetLength() < aOther.GetLength());
+
+ matchedLength = MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize());
+
+ VerifyOrExit(matchedLength < GetLength(), isSmaller = false);
+
+ isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT];
+
+exit:
+ return isSmaller;
+}
+
uint8_t Prefix::MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize)
{
uint8_t matchedLength = 0;
@@ -152,13 +169,13 @@
void InterfaceIdentifier::GenerateRandom(void)
{
- otError error;
+ Error error;
OT_UNUSED_VARIABLE(error);
error = Random::Crypto::FillBuffer(mFields.m8, kSize);
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
}
void InterfaceIdentifier::SetBytes(const uint8_t *aBuffer)
@@ -434,9 +451,9 @@
return matches;
}
-otError Address::FromString(const char *aBuf)
+Error Address::FromString(const char *aBuf)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t * dst = reinterpret_cast<uint8_t *>(mFields.m8);
uint8_t * endp = reinterpret_cast<uint8_t *>(mFields.m8 + 15);
uint8_t * colonp = nullptr;
@@ -465,7 +482,7 @@
{
if (count)
{
- VerifyOrExit(dst + 2 <= endp, error = OT_ERROR_PARSE);
+ VerifyOrExit(dst + 2 <= endp, error = kErrorParse);
*(dst + 1) = static_cast<uint8_t>(val >> 8);
*(dst + 2) = static_cast<uint8_t>(val);
dst += 2;
@@ -474,7 +491,7 @@
}
else if (ch == ':')
{
- VerifyOrExit(colonp == nullptr || first, error = OT_ERROR_PARSE);
+ VerifyOrExit(colonp == nullptr || first, error = kErrorParse);
colonp = dst;
}
@@ -494,21 +511,21 @@
// Do not count bytes of the embedded IPv4 address.
endp -= kIp4AddressSize;
- VerifyOrExit(dst <= endp, error = OT_ERROR_PARSE);
+ VerifyOrExit(dst <= endp, error = kErrorParse);
break;
}
else
{
- VerifyOrExit('0' <= ch && ch <= '9', error = OT_ERROR_PARSE);
+ VerifyOrExit('0' <= ch && ch <= '9', error = kErrorParse);
}
first = false;
val = static_cast<uint16_t>((val << 4) | d);
- VerifyOrExit(++count <= 4, error = OT_ERROR_PARSE);
+ VerifyOrExit(++count <= 4, error = kErrorParse);
}
- VerifyOrExit(colonp || dst == endp, error = OT_ERROR_PARSE);
+ VerifyOrExit(colonp || dst == endp, error = kErrorParse);
while (colonp && dst > colonp)
{
@@ -534,7 +551,7 @@
if (ch == '.' || ch == '\0' || ch == ' ')
{
- VerifyOrExit(dst <= endp, error = OT_ERROR_PARSE);
+ VerifyOrExit(dst <= endp, error = kErrorParse);
*dst++ = static_cast<uint8_t>(val);
val = 0;
@@ -542,18 +559,18 @@
if (ch == '\0' || ch == ' ')
{
// Check if embedded IPv4 address had exactly four parts.
- VerifyOrExit(dst == endp + 1, error = OT_ERROR_PARSE);
+ VerifyOrExit(dst == endp + 1, error = kErrorParse);
break;
}
}
else
{
- VerifyOrExit('0' <= ch && ch <= '9', error = OT_ERROR_PARSE);
+ VerifyOrExit('0' <= ch && ch <= '9', error = kErrorParse);
val = (10 * val) + (ch & 0xf);
// Single part of IPv4 address has to fit in one byte.
- VerifyOrExit(val <= 0xff, error = OT_ERROR_PARSE);
+ VerifyOrExit(val <= 0xff, error = kErrorParse);
}
}
}
diff --git a/src/core/net/ip6_address.hpp b/src/core/net/ip6_address.hpp
index 00c82a0..d7aa689 100644
--- a/src/core/net/ip6_address.hpp
+++ b/src/core/net/ip6_address.hpp
@@ -74,11 +74,11 @@
* This method generates and sets the Network Prefix to a crypto-secure random Unique Local Address (ULA) based
* on the pattern `fdxx:xxxx:xxxx:` (RFC 4193).
*
- * @retval OT_ERROR_NONE Successfully generated a random ULA Network Prefix
- * @retval OT_ERROR_FAILED Failed to generate random ULA Network Prefix.
+ * @retval kErrorNone Successfully generated a random ULA Network Prefix
+ * @retval kErrorFailed Failed to generate random ULA Network Prefix.
*
*/
- otError GenerateRandomUla(void);
+ Error GenerateRandomUla(void);
} OT_TOOL_PACKED_END;
@@ -87,7 +87,7 @@
*
*/
OT_TOOL_PACKED_BEGIN
-class Prefix : public otIp6Prefix
+class Prefix : public otIp6Prefix, public Clearable<Prefix>, public Unequatable<Prefix>
{
public:
enum : uint8_t
@@ -223,15 +223,18 @@
}
/**
- * This method overloads operator `==` to evaluate whether or not two prefixes are unequal.
+ * This method overloads operator `<` to compare two prefixes.
*
- * @param[in] aOther The other prefix to compare with.
+ * A prefix with shorter length is considered smaller than the one with longer length. If the prefix lengths are
+ * equal, then the prefix bytes are compared directly.
*
- * @retval TRUE If the two prefixes are unequal.
- * @retval FALSE If the two prefixes are not unequal.
+ * @param[in] aOther The other prefix to compare against.
+ *
+ * @retval TRUE If the prefix is smaller than @p aOther.
+ * @retval FALSE If the prefix is not smaller than @p aOther.
*
*/
- bool operator!=(const Prefix &aOther) const { return !(*this == aOther); }
+ bool operator<(const Prefix &aOther) const;
/**
* This static method converts a prefix length (in bits) to size (number of bytes).
@@ -880,11 +883,11 @@
*
* @param[in] aBuf A pointer to the null-terminated string.
*
- * @retval OT_ERROR_NONE Successfully parsed the IPv6 address string.
- * @retval OT_ERROR_INVALID_ARGS Failed to parse the IPv6 address string.
+ * @retval kErrorNone Successfully parsed the IPv6 address string.
+ * @retval kErrorInvalidArgs Failed to parse the IPv6 address string.
*
*/
- otError FromString(const char *aBuf);
+ Error FromString(const char *aBuf);
/**
* This method converts an IPv6 address object to a string
diff --git a/src/core/net/ip6_filter.cpp b/src/core/net/ip6_filter.cpp
index 4c25174..56603e3 100644
--- a/src/core/net/ip6_filter.cpp
+++ b/src/core/net/ip6_filter.cpp
@@ -120,11 +120,11 @@
return rval;
}
-otError Filter::AddUnsecurePort(uint16_t aPort)
+Error Filter::AddUnsecurePort(uint16_t aPort)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aPort != 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aPort != 0, error = kErrorInvalidArgs);
for (uint16_t unsecurePort : mUnsecurePorts)
{
@@ -144,17 +144,17 @@
}
}
- ExitNow(error = OT_ERROR_NO_BUFS);
+ ExitNow(error = kErrorNoBufs);
exit:
return error;
}
-otError Filter::RemoveUnsecurePort(uint16_t aPort)
+Error Filter::RemoveUnsecurePort(uint16_t aPort)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aPort != 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aPort != 0, error = kErrorInvalidArgs);
for (int i = 0; i < kMaxUnsecurePorts; i++)
{
@@ -174,7 +174,7 @@
}
}
- ExitNow(error = OT_ERROR_NOT_FOUND);
+ ExitNow(error = kErrorNotFound);
exit:
return error;
diff --git a/src/core/net/ip6_filter.hpp b/src/core/net/ip6_filter.hpp
index 5fc6374..8549809 100644
--- a/src/core/net/ip6_filter.hpp
+++ b/src/core/net/ip6_filter.hpp
@@ -81,24 +81,24 @@
*
* @param[in] aPort The port value.
*
- * @retval OT_ERROR_NONE The port was successfully added to the allowed unsecure port list.
- * @retval OT_ERROR_INVALID_ARGS The port is invalid (value 0 is reserved for internal use).
- * @retval OT_ERROR_NO_BUFS The unsecure port list is full.
+ * @retval kErrorNone The port was successfully added to the allowed unsecure port list.
+ * @retval kErrorInvalidArgs The port is invalid (value 0 is reserved for internal use).
+ * @retval kErrorNoBufs The unsecure port list is full.
*
*/
- otError AddUnsecurePort(uint16_t aPort);
+ Error AddUnsecurePort(uint16_t aPort);
/**
* This method removes a port from the allowed unsecure port list.
*
* @param[in] aPort The port value.
*
- * @retval OT_ERROR_NONE The port was successfully removed from the allowed unsecure port list.
- * @retval OT_ERROR_INVALID_ARGS The port is invalid (value 0 is reserved for internal use).
- * @retval OT_ERROR_NOT_FOUND The port was not found in the unsecure port list.
+ * @retval kErrorNone The port was successfully removed from the allowed unsecure port list.
+ * @retval kErrorInvalidArgs The port is invalid (value 0 is reserved for internal use).
+ * @retval kErrorNotFound The port was not found in the unsecure port list.
*
*/
- otError RemoveUnsecurePort(uint16_t aPort);
+ Error RemoveUnsecurePort(uint16_t aPort);
/**
* This method checks whether a port is in the unsecure port list.
diff --git a/src/core/net/ip6_headers.cpp b/src/core/net/ip6_headers.cpp
index 78ad218..f545d2c 100644
--- a/src/core/net/ip6_headers.cpp
+++ b/src/core/net/ip6_headers.cpp
@@ -38,14 +38,14 @@
namespace ot {
namespace Ip6 {
-otError Header::Init(const Message &aMessage)
+Error Header::Init(const Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SuccessOrExit(error = aMessage.Read(0, *this));
- VerifyOrExit(IsValid(), error = OT_ERROR_PARSE);
- VerifyOrExit((sizeof(*this) + GetPayloadLength()) == aMessage.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(IsValid(), error = kErrorParse);
+ VerifyOrExit((sizeof(*this) + GetPayloadLength()) == aMessage.GetLength(), error = kErrorParse);
exit:
return error;
diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp
index 88d6012..422de7c 100644
--- a/src/core/net/ip6_headers.hpp
+++ b/src/core/net/ip6_headers.hpp
@@ -151,11 +151,11 @@
*
* @param[in] aMessage The IPv6 datagram.
*
- * @retval OT_ERROR_NONE Successfully read the IPv6 header.
- * @retval OT_ERROR_PARSE Malformed IPv6 header.
+ * @retval kErrorNone Successfully read the IPv6 header.
+ * @retval kErrorParse Malformed IPv6 header.
*
*/
- otError Init(const Message &aMessage);
+ Error Init(const Message &aMessage);
/**
* This method indicates whether or not the header appears to be well-formed.
diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp
index d59af2c..b4b3bbd 100644
--- a/src/core/net/ip6_mpl.cpp
+++ b/src/core/net/ip6_mpl.cpp
@@ -46,11 +46,11 @@
Mpl::Mpl(Instance &aInstance)
: InstanceLocator(aInstance)
, mMatchingAddress(nullptr)
- , mSeedSetTimer(aInstance, Mpl::HandleSeedSetTimer, this)
+ , mSeedSetTimer(aInstance, Mpl::HandleSeedSetTimer)
, mSeedId(0)
, mSequence(0)
#if OPENTHREAD_FTD
- , mRetransmissionTimer(aInstance, Mpl::HandleRetransmissionTimer, this)
+ , mRetransmissionTimer(aInstance, Mpl::HandleRetransmissionTimer)
, mTimerExpirations(0)
#endif
{
@@ -77,15 +77,15 @@
}
}
-otError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive)
+Error Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive)
{
- otError error;
+ Error error;
OptionMpl option;
VerifyOrExit(aMessage.ReadBytes(aMessage.GetOffset(), &option, sizeof(option)) >= OptionMpl::kMinLength &&
(option.GetSeedIdLength() == OptionMpl::kSeedIdLength0 ||
option.GetSeedIdLength() == OptionMpl::kSeedIdLength2),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
if (option.GetSeedIdLength() == OptionMpl::kSeedIdLength0)
{
@@ -96,7 +96,7 @@
// Check if the MPL Data Message is new.
error = UpdateSeedSet(option.GetSeedId(), option.GetSequence());
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
#if OPENTHREAD_FTD
AddBufferedMessage(aMessage, option.GetSeedId(), option.GetSequence(), aIsOutbound);
@@ -107,7 +107,7 @@
aReceive = false;
// In case MPL Data Message is generated locally, ignore potential error of the MPL Seed Set
// to allow subsequent retransmissions with the same sequence number.
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
exit:
@@ -135,9 +135,9 @@
* - Require group size to have >=2 entries.
* - If inserting into existing group, require Sequence to be larger than oldest stored Sequence in group.
*/
-otError Mpl::UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence)
+Error Mpl::UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
SeedEntry *insert = nullptr;
SeedEntry *group = mSeedSet;
SeedEntry *evict = mSeedSet;
@@ -192,7 +192,7 @@
if (diff == 0)
{
// already received, drop message
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
else if (insert == nullptr && diff < 0)
{
@@ -223,7 +223,7 @@
}
// require evict group size to have >= 2 entries
- VerifyOrExit(maxCount > 1, error = OT_ERROR_DROP);
+ VerifyOrExit(maxCount > 1, error = kErrorDrop);
if (insert == nullptr)
{
@@ -233,7 +233,7 @@
else
{
// require Sequence to be larger than oldest stored Sequence in group
- VerifyOrExit(insert > mSeedSet && aSeedId == (insert - 1)->mSeedId, error = OT_ERROR_DROP);
+ VerifyOrExit(insert > mSeedSet && aSeedId == (insert - 1)->mSeedId, error = kErrorDrop);
}
}
@@ -264,7 +264,7 @@
void Mpl::HandleSeedSetTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mpl>().HandleSeedSetTimer();
+ aTimer.Get<Mpl>().HandleSeedSetTimer();
}
void Mpl::HandleSeedSetTimer(void)
@@ -298,7 +298,7 @@
void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *messageCopy = nullptr;
Metadata metadata;
uint8_t hopLimit = 0;
@@ -311,12 +311,12 @@
#endif
VerifyOrExit(GetTimerExpirations() > 0);
- VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = kErrorNoBufs);
if (!aIsOutbound)
{
IgnoreError(aMessage.Read(Header::kHopLimitFieldOffset, hopLimit));
- VerifyOrExit(hopLimit-- > 1, error = OT_ERROR_DROP);
+ VerifyOrExit(hopLimit-- > 1, error = kErrorDrop);
messageCopy->Write(Header::kHopLimitFieldOffset, hopLimit);
}
@@ -337,7 +337,7 @@
void Mpl::HandleRetransmissionTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mpl>().HandleRetransmissionTimer();
+ aTimer.Get<Mpl>().HandleRetransmissionTimer();
}
void Mpl::HandleRetransmissionTimer(void)
@@ -427,9 +427,9 @@
void Mpl::Metadata::RemoveFrom(Message &aMessage) const
{
- otError error = aMessage.SetLength(aMessage.GetLength() - sizeof(*this));
+ Error error = aMessage.SetLength(aMessage.GetLength() - sizeof(*this));
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
}
diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp
index 9549b72..1caab6e 100644
--- a/src/core/net/ip6_mpl.hpp
+++ b/src/core/net/ip6_mpl.hpp
@@ -219,11 +219,11 @@
* @param[out] aReceive Set to FALSE if the MPL message is a duplicate and must not
* go through the receiving process again, untouched otherwise.
*
- * @retval OT_ERROR_NONE Successfully processed the MPL option.
- * @retval OT_ERROR_DROP The MPL message is a duplicate and should be dropped.
+ * @retval kErrorNone Successfully processed the MPL option.
+ * @retval kErrorDrop The MPL message is a duplicate and should be dropped.
*
*/
- otError ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive);
+ Error ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive);
/**
* This method returns the MPL Seed Id value.
@@ -296,7 +296,7 @@
static void HandleSeedSetTimer(Timer &aTimer);
void HandleSeedSetTimer(void);
- otError UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence);
+ Error UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence);
SeedEntry mSeedSet[kNumSeedEntries];
const Address *mMatchingAddress;
@@ -307,11 +307,11 @@
#if OPENTHREAD_FTD
struct Metadata
{
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
- void RemoveFrom(Message &aMessage) const;
- void UpdateIn(Message &aMessage) const;
- void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval);
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ void ReadFrom(const Message &aMessage);
+ void RemoveFrom(Message &aMessage) const;
+ void UpdateIn(Message &aMessage) const;
+ void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval);
TimeMilli mTransmissionTime;
uint16_t mSeedId;
diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp
index e733fa0..4dc6b66 100644
--- a/src/core/net/netif.cpp
+++ b/src/core/net/netif.cpp
@@ -208,7 +208,7 @@
void Netif::SubscribeAllRoutersMulticast(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetifMulticastAddress *prev = nullptr;
NetifMulticastAddress &linkLocalAllRoutersAddress = static_cast<NetifMulticastAddress &>(
const_cast<otNetifMulticastAddress &>(kLinkLocalAllRoutersMulticastAddress));
@@ -222,7 +222,7 @@
// This method MUST be called after `SubscribeAllNodesMulticast()`
// Ensure that the `LinkLocalAll` was found on the list.
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
// The tail of multicast address linked list contains the
@@ -355,15 +355,15 @@
return;
}
-otError Netif::SubscribeExternalMulticast(const Address &aAddress)
+Error Netif::SubscribeExternalMulticast(const Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetifMulticastAddress &linkLocalAllRoutersAddress = static_cast<NetifMulticastAddress &>(
const_cast<otNetifMulticastAddress &>(kLinkLocalAllRoutersMulticastAddress));
ExternalNetifMulticastAddress *entry;
- VerifyOrExit(aAddress.IsMulticast(), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(!IsMulticastSubscribed(aAddress), error = OT_ERROR_ALREADY);
+ VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
+ VerifyOrExit(!IsMulticastSubscribed(aAddress), error = kErrorAlready);
// Check that the address is not one of the fixed addresses:
// LinkLocalAllRouters -> RealmLocalAllRouters -> LinkLocalAllNodes
@@ -371,11 +371,11 @@
for (const NetifMulticastAddress *cur = &linkLocalAllRoutersAddress; cur; cur = cur->GetNext())
{
- VerifyOrExit(cur->GetAddress() != aAddress, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(cur->GetAddress() != aAddress, error = kErrorInvalidArgs);
}
entry = mExtMulticastAddressPool.Allocate();
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
entry->mAddress = aAddress;
#if OPENTHREAD_CONFIG_MLR_ENABLE
@@ -388,16 +388,16 @@
return error;
}
-otError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
+Error Netif::UnsubscribeExternalMulticast(const Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetifMulticastAddress *entry;
NetifMulticastAddress *prev;
entry = mMulticastAddresses.FindMatching(aAddress, prev);
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(entry != nullptr, error = kErrorNotFound);
- VerifyOrExit(IsMulticastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsMulticastAddressExternal(*entry), error = kErrorInvalidArgs);
mMulticastAddresses.PopAfter(prev);
@@ -466,18 +466,18 @@
return;
}
-otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
+Error Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetifUnicastAddress *entry;
- VerifyOrExit(!aAddress.GetAddress().IsMulticast(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aAddress.GetAddress().IsMulticast(), error = kErrorInvalidArgs);
entry = mUnicastAddresses.FindMatching(aAddress.GetAddress());
if (entry != nullptr)
{
- VerifyOrExit(IsUnicastAddressExternal(*entry), error = OT_ERROR_ALREADY);
+ VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorAlready);
entry->mPrefixLength = aAddress.mPrefixLength;
entry->mAddressOrigin = aAddress.mAddressOrigin;
@@ -486,10 +486,10 @@
ExitNow();
}
- VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = kErrorInvalidArgs);
entry = mExtUnicastAddressPool.Allocate();
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
*entry = aAddress;
mUnicastAddresses.Push(*entry);
@@ -499,16 +499,16 @@
return error;
}
-otError Netif::RemoveExternalUnicastAddress(const Address &aAddress)
+Error Netif::RemoveExternalUnicastAddress(const Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetifUnicastAddress *entry;
NetifUnicastAddress *prev;
entry = mUnicastAddresses.FindMatching(aAddress, prev);
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(entry != nullptr, error = kErrorNotFound);
- VerifyOrExit(IsUnicastAddressExternal(*entry), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorInvalidArgs);
mUnicastAddresses.PopAfter(prev);
mExtUnicastAddressPool.Free(*entry);
diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp
index ad2ef31..ca0448f 100644
--- a/src/core/net/netif.hpp
+++ b/src/core/net/netif.hpp
@@ -38,6 +38,7 @@
#include "common/clearable.hpp"
#include "common/code_utils.hpp"
+#include "common/iterator_utils.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
@@ -273,7 +274,9 @@
*
*/
class ExternalMulticastAddressIterator
+ : public ItemPtrIterator<ExternalNetifMulticastAddress, ExternalMulticastAddressIterator>
{
+ friend class ItemPtrIterator<ExternalNetifMulticastAddress, ExternalMulticastAddressIterator>;
friend class ExternalMulticastAddressIteratorBuilder;
public:
@@ -286,88 +289,13 @@
*
*/
explicit ExternalMulticastAddressIterator(const Netif &aNetif, Address::TypeFilter aFilter = Address::kTypeAny)
- : mNetif(aNetif)
+ : ItemPtrIterator(nullptr)
+ , mNetif(aNetif)
, mFilter(aFilter)
{
AdvanceFrom(mNetif.GetMulticastAddresses());
}
- /**
- * This method indicates whether the iterator has reached end of the list.
- *
- * @retval TRUE There are no more entries in the list (reached end of the list).
- * @retval FALSE The current address entry is valid.
- *
- */
- bool IsDone(void) const { return mCurrent != nullptr; }
-
- /**
- * This method overloads `++` operator (pre-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next entry. If there are no more entries matching the iterator becomes
- * empty.
- *
- */
- void operator++(void) { AdvanceFrom(mCurrent->GetNext()); }
-
- /**
- * This method overloads `++` operator (post-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next entry. If there are no more entries matching the iterator becomes
- * empty.
- *
- */
- void operator++(int) { AdvanceFrom(mCurrent->GetNext()); }
-
- /**
- * This method overloads the `*` dereference operator and gets a reference to `ExternalNetifMulticastAddress`
- * entry to which the iterator is currently pointing.
- *
- * This method MUST be used when the iterator is not empty.
- *
- * @returns A reference to the `ExternalNetifMulticastAddress` entry currently pointed by the iterator.
- *
- */
- ExternalNetifMulticastAddress &operator*(void) { return *mCurrent; }
-
- /**
- * This method overloads the `->` dereference operator and gets a pointer to `ExternalNetifMulticastAddress`
- * entry to which the iterator is current pointing.
- *
- * @returns A pointer to the `ExternalNetifMulticastAddress` entry associated with the iterator, or `nullptr` if
- * iterator is empty.
- *
- */
- ExternalNetifMulticastAddress *operator->(void) { return mCurrent; }
-
- /**
- * This method overloads operator `==` to evaluate whether or not two `ExternalMulticastAddressIterator`
- * instances point to the same `ExternalNetifMulticastAddress` entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `ExternalMulticastAddressIterator` objects point to the same
- * `ExternalNetifMulticastAddress` entry or both are done.
- * @retval FALSE If the two `ExternalMulticastAddressIterator` objects do not point to the same
- * `ExternalNetifMulticastAddress` entry.
- *
- */
- bool operator==(const ExternalMulticastAddressIterator &aOther) { return mCurrent == aOther.mCurrent; }
-
- /**
- * This method overloads operator `!=` to evaluate whether or not two `ExternalMulticastAddressIterator`
- * instances point to the same `ExternalNetifMulticastAddress` entry.
- *
- * @param[in] aOther The other `ExternalMulticastAddressIterator` to compare with.
- *
- * @retval TRUE If the two `ExternalMulticastAddressIterator` objects do not point to the same
- * `ExternalNetifMulticastAddress` entry.
- * @retval FALSE If the two `ExternalMulticastAddressIterator` objects point to the same
- * `ExternalNetifMulticastAddress` entry or both are done.
- *
- */
- bool operator!=(const ExternalMulticastAddressIterator &aOther) { return mCurrent != aOther.mCurrent; }
-
private:
enum IteratorType
{
@@ -376,7 +304,6 @@
ExternalMulticastAddressIterator(const Netif &aNetif, IteratorType)
: mNetif(aNetif)
- , mCurrent(nullptr)
{
}
@@ -388,13 +315,14 @@
aAddr = aAddr->GetNext();
}
- mCurrent =
+ mItem =
const_cast<ExternalNetifMulticastAddress *>(static_cast<const ExternalNetifMulticastAddress *>(aAddr));
}
- const Netif & mNetif;
- ExternalNetifMulticastAddress *mCurrent;
- Address::TypeFilter mFilter;
+ void Advance(void) { AdvanceFrom(mItem->GetNext()); }
+
+ const Netif & mNetif;
+ Address::TypeFilter mFilter;
};
/**
@@ -486,24 +414,24 @@
*
* @param[in] aAddress A reference to the unicast address.
*
- * @retval OT_ERROR_NONE Successfully added (or updated) the unicast address.
- * @retval OT_ERROR_INVALID_ARGS The address indicated by @p aAddress is an internal address.
- * @retval OT_ERROR_NO_BUFS The maximum number of allowed external addresses are already added.
+ * @retval kErrorNone Successfully added (or updated) the unicast address.
+ * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address.
+ * @retval kErrorNoBufs The maximum number of allowed external addresses are already added.
*
*/
- otError AddExternalUnicastAddress(const NetifUnicastAddress &aAddress);
+ Error AddExternalUnicastAddress(const NetifUnicastAddress &aAddress);
/**
* This method removes a external (to OpenThread) unicast address from the network interface.
*
* @param[in] aAddress A reference to the unicast address.
*
- * @retval OT_ERROR_NONE Successfully removed the unicast address.
- * @retval OT_ERROR_INVALID_ARGS The address indicated by @p aAddress is an internal address.
- * @retval OT_ERROR_NOT_FOUND The unicast address was not found.
+ * @retval kErrorNone Successfully removed the unicast address.
+ * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address.
+ * @retval kErrorNotFound The unicast address was not found.
*
*/
- otError RemoveExternalUnicastAddress(const Address &aAddress);
+ Error RemoveExternalUnicastAddress(const Address &aAddress);
/**
* This method removes all the previously added external (to OpenThread) unicast addresses from the
@@ -587,25 +515,25 @@
*
* @param[in] aAddress A reference to the multicast address.
*
- * @retval OT_ERROR_NONE Successfully subscribed to @p aAddress.
- * @retval OT_ERROR_ALREADY The multicast address is already subscribed.
- * @retval OT_ERROR_INVALID_ARGS The address indicated by @p aAddress is an internal multicast address.
- * @retval OT_ERROR_NO_BUFS The maximum number of allowed external multicast addresses are already added.
+ * @retval kErrorNone Successfully subscribed to @p aAddress.
+ * @retval kErrorAlready The multicast address is already subscribed.
+ * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal multicast address.
+ * @retval kErrorNoBufs The maximum number of allowed external multicast addresses are already added.
*
*/
- otError SubscribeExternalMulticast(const Address &aAddress);
+ Error SubscribeExternalMulticast(const Address &aAddress);
/**
* This method unsubscribes the network interface to the external (to OpenThread) multicast address.
*
* @param[in] aAddress A reference to the multicast address.
*
- * @retval OT_ERROR_NONE Successfully unsubscribed to the unicast address.
- * @retval OT_ERROR_INVALID_ARGS The address indicated by @p aAddress is an internal address.
- * @retval OT_ERROR_NOT_FOUND The multicast address was not found.
+ * @retval kErrorNone Successfully unsubscribed to the unicast address.
+ * @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address.
+ * @retval kErrorNotFound The multicast address was not found.
*
*/
- otError UnsubscribeExternalMulticast(const Address &aAddress);
+ Error UnsubscribeExternalMulticast(const Address &aAddress);
/**
* This method unsubscribes the network interface from all previously added external (to OpenThread) multicast
diff --git a/src/core/net/sntp_client.cpp b/src/core/net/sntp_client.cpp
index 40ce98d..c2be9ee 100644
--- a/src/core/net/sntp_client.cpp
+++ b/src/core/net/sntp_client.cpp
@@ -92,14 +92,14 @@
Client::Client(Instance &aInstance)
: mSocket(aInstance)
- , mRetransmissionTimer(aInstance, Client::HandleRetransmissionTimer, this)
+ , mRetransmissionTimer(aInstance, Client::HandleRetransmissionTimer)
, mUnixEra(0)
{
}
-otError Client::Start(void)
+Error Client::Start(void)
{
- otError error;
+ Error error;
SuccessOrExit(error = mSocket.Open(&Client::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Bind());
@@ -108,7 +108,7 @@
return error;
}
-otError Client::Stop(void)
+Error Client::Stop(void)
{
Message * message = mPendingQueries.GetHead();
Message * messageToRemove;
@@ -121,27 +121,27 @@
message = message->GetNext();
queryMetadata.ReadFrom(*messageToRemove);
- FinalizeSntpTransaction(*messageToRemove, queryMetadata, 0, OT_ERROR_ABORT);
+ FinalizeSntpTransaction(*messageToRemove, queryMetadata, 0, kErrorAbort);
}
return mSocket.Close();
}
-otError Client::Query(const otSntpQuery *aQuery, otSntpResponseHandler aHandler, void *aContext)
+Error Client::Query(const otSntpQuery *aQuery, otSntpResponseHandler aHandler, void *aContext)
{
- otError error;
+ Error error;
QueryMetadata queryMetadata(aHandler, aContext);
Message * message = nullptr;
Message * messageCopy = nullptr;
Header header;
const Ip6::MessageInfo *messageInfo;
- VerifyOrExit(aQuery->mMessageInfo != nullptr, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aQuery->mMessageInfo != nullptr, error = kErrorInvalidArgs);
// Originate timestamp is used only as a unique token.
header.SetTransmitTimestampSeconds(TimerMilli::GetNow().GetValue() / 1000 + kTimeAt1970);
- VerifyOrExit((message = NewMessage(header)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMessage(header)) != nullptr, error = kErrorNoBufs);
messageInfo = static_cast<const Ip6::MessageInfo *>(aQuery->mMessageInfo);
@@ -152,12 +152,12 @@
queryMetadata.mDestinationAddress = messageInfo->GetPeerAddr();
queryMetadata.mRetransmissionCount = 0;
- VerifyOrExit((messageCopy = CopyAndEnqueueMessage(*message, queryMetadata)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((messageCopy = CopyAndEnqueueMessage(*message, queryMetadata)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = SendMessage(*message, *messageInfo));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
if (message)
{
@@ -187,11 +187,11 @@
Message *Client::CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *messageCopy = nullptr;
// Create a message copy for further retransmissions.
- VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = kErrorNoBufs);
// Append the copy with retransmission data and add it to the queue.
SuccessOrExit(error = aQueryMetadata.AppendTo(*messageCopy));
@@ -218,28 +218,28 @@
aMessage.Free();
}
-otError Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return mSocket.SendTo(aMessage, aMessageInfo);
}
void Client::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error;
+ Error error;
Message *messageCopy = nullptr;
// Create a message copy for lower layers.
VerifyOrExit((messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(QueryMetadata))) != nullptr,
- error = OT_ERROR_NO_BUFS);
+ error = kErrorNoBufs);
// Send the copy.
SuccessOrExit(error = SendMessage(*messageCopy, aMessageInfo));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeMessage(messageCopy);
- otLogWarnIp6("Failed to send SNTP request: %s", otThreadErrorToString(error));
+ otLogWarnIp6("Failed to send SNTP request: %s", ErrorToString(error));
}
}
@@ -268,7 +268,7 @@
void Client::FinalizeSntpTransaction(Message & aQuery,
const QueryMetadata &aQueryMetadata,
uint64_t aTime,
- otError aResult)
+ Error aResult)
{
DequeueMessage(aQuery);
@@ -280,7 +280,7 @@
void Client::HandleRetransmissionTimer(Timer &aTimer)
{
- aTimer.GetOwner<Client>().HandleRetransmissionTimer();
+ aTimer.Get<Client>().HandleRetransmissionTimer();
}
void Client::HandleRetransmissionTimer(void)
@@ -303,7 +303,7 @@
if (queryMetadata.mRetransmissionCount >= kMaxRetransmit)
{
// No expected response.
- FinalizeSntpTransaction(*message, queryMetadata, 0, OT_ERROR_RESPONSE_TIMEOUT);
+ FinalizeSntpTransaction(*message, queryMetadata, 0, kErrorResponseTimeout);
continue;
}
@@ -342,7 +342,7 @@
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header responseHeader;
QueryMetadata queryMetadata;
Message * message = nullptr;
@@ -353,7 +353,7 @@
VerifyOrExit((message = FindRelatedQuery(responseHeader, queryMetadata)) != nullptr);
// Check if response came from the server.
- VerifyOrExit(responseHeader.GetMode() == Header::kModeServer, error = OT_ERROR_FAILED);
+ VerifyOrExit(responseHeader.GetMode() == Header::kModeServer, error = kErrorFailed);
// Check the Kiss-o'-death packet.
if (!responseHeader.GetStratum())
@@ -364,13 +364,13 @@
kissCode[Header::kKissCodeLength] = 0;
otLogInfoIp6("SNTP response contains the Kiss-o'-death packet with %s code", kissCode);
- ExitNow(error = OT_ERROR_BUSY);
+ ExitNow(error = kErrorBusy);
}
// Check if timestamp has been set.
VerifyOrExit(responseHeader.GetTransmitTimestampSeconds() != 0 &&
responseHeader.GetTransmitTimestampFraction() != 0,
- error = OT_ERROR_FAILED);
+ error = kErrorFailed);
// The NTP time starts at 1900 while the unix epoch starts at 1970.
// Due to NTP protocol limitation, this module stops working correctly after around year 2106, if
@@ -388,11 +388,11 @@
}
// Return the time since 1970.
- FinalizeSntpTransaction(*message, queryMetadata, unixTime, OT_ERROR_NONE);
+ FinalizeSntpTransaction(*message, queryMetadata, unixTime, kErrorNone);
exit:
- if (message != nullptr && error != OT_ERROR_NONE)
+ if (message != nullptr && error != kErrorNone)
{
FinalizeSntpTransaction(*message, queryMetadata, 0, error);
}
diff --git a/src/core/net/sntp_client.hpp b/src/core/net/sntp_client.hpp
index a5b55b5..ed1eb59 100644
--- a/src/core/net/sntp_client.hpp
+++ b/src/core/net/sntp_client.hpp
@@ -441,11 +441,11 @@
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the bytes.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
+ * @retval kErrorNone Successfully appended the bytes.
+ * @retval kErrorNoBufs Insufficient available buffers to grow the message.
*
*/
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
/**
* This method reads request data from the message.
@@ -455,9 +455,9 @@
*/
void ReadFrom(const Message &aMessage)
{
- otError error = aMessage.Read(aMessage.GetLength() - sizeof(*this), *this);
+ Error error = aMessage.Read(aMessage.GetLength() - sizeof(*this), *this);
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
}
@@ -498,18 +498,18 @@
/**
* This method starts the SNTP client.
*
- * @retval OT_ERROR_NONE Successfully started the SNTP client.
- * @retval OT_ERROR_ALREADY The socket is already open.
+ * @retval kErrorNone Successfully started the SNTP client.
+ * @retval kErrorAlready The socket is already open.
*/
- otError Start(void);
+ Error Start(void);
/**
* This method stops the SNTP client.
*
- * @retval OT_ERROR_NONE Successfully stopped the SNTP client.
+ * @retval kErrorNone Successfully stopped the SNTP client.
*
*/
- otError Stop(void);
+ Error Stop(void);
/**
* This method returns the unix era number.
@@ -534,12 +534,12 @@
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully sent SNTP query.
- * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data.
- * @retval OT_ERROR_INVALID_ARGS Invalid arguments supplied.
+ * @retval kErrorNone Successfully sent SNTP query.
+ * @retval kErrorNoBufs Failed to allocate retransmission data.
+ * @retval kErrorInvalidArgs Invalid arguments supplied.
*
*/
- otError Query(const otSntpQuery *aQuery, otSntpResponseHandler aHandler, void *aContext);
+ Error Query(const otSntpQuery *aQuery, otSntpResponseHandler aHandler, void *aContext);
private:
/**
@@ -568,11 +568,11 @@
Message *NewMessage(const Header &aHeader);
Message *CopyAndEnqueueMessage(const Message &aMessage, const QueryMetadata &aQueryMetadata);
void DequeueMessage(Message &aMessage);
- otError SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Message *FindRelatedQuery(const Header &aResponseHeader, QueryMetadata &aQueryMetadata);
- void FinalizeSntpTransaction(Message &aQuery, const QueryMetadata &aQueryMetadata, uint64_t aTime, otError aResult);
+ void FinalizeSntpTransaction(Message &aQuery, const QueryMetadata &aQueryMetadata, uint64_t aTime, Error aResult);
static void HandleRetransmissionTimer(Timer &aTimer);
void HandleRetransmissionTimer(void);
diff --git a/src/core/net/socket.cpp b/src/core/net/socket.cpp
new file mode 100644
index 0000000..5e44143
--- /dev/null
+++ b/src/core/net/socket.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, 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 IPv6 sockets related functionality.
+ */
+
+#include "socket.hpp"
+
+namespace ot {
+namespace Ip6 {
+
+SockAddr::InfoString SockAddr::ToString(void) const
+{
+ return InfoString("[%s]:%u", GetAddress().ToString().AsCString(), GetPort());
+}
+
+} // namespace Ip6
+} // namespace ot
diff --git a/src/core/net/socket.hpp b/src/core/net/socket.hpp
index 9c9a2ef..0b59ded 100644
--- a/src/core/net/socket.hpp
+++ b/src/core/net/socket.hpp
@@ -37,6 +37,7 @@
#include "openthread-core-config.h"
#include "common/clearable.hpp"
+#include "common/equatable.hpp"
#include "net/ip6_address.hpp"
namespace ot {
@@ -233,9 +234,20 @@
* This class implements a socket address.
*
*/
-class SockAddr : public otSockAddr, public Clearable<SockAddr>
+class SockAddr : public otSockAddr, public Clearable<SockAddr>, public Unequatable<SockAddr>
{
public:
+ enum : uint16_t
+ {
+ kInfoStringSize = 50, ///< Max chars for the info string (`ToString()`).
+ };
+
+ /**
+ * This type defines the fixed-length `String` object returned from `ToString()`.
+ *
+ */
+ typedef String<kInfoStringSize> InfoString;
+
/**
* This constructor initializes the socket address (all fields are set to zero).
*
@@ -282,6 +294,47 @@
*
*/
const Address &GetAddress(void) const { return *static_cast<const Address *>(&mAddress); }
+
+ /**
+ * This method returns the socket address port number.
+ *
+ * @returns The port number
+ *
+ */
+ uint16_t GetPort(void) const { return mPort; }
+
+ /**
+ * This method sets the socket address port number.
+ *
+ * @param[in] aPort The port number.
+ *
+ */
+ void SetPort(uint16_t aPort) { mPort = aPort; }
+
+ /**
+ * This method overloads operator `==` to evaluate whether or not two `SockAddr` instances are equal (same address
+ * and port number).
+ *
+ * @param[in] aOther The other `SockAddr` instance to compare with.
+ *
+ * @retval TRUE If the two `SockAddr` instances are equal.
+ * @retval FALSE If the two `SockAddr` instances not equal.
+ *
+ */
+ bool operator==(const SockAddr &aOther) const
+ {
+ return (GetPort() == aOther.GetPort()) && (GetAddress() == aOther.GetAddress());
+ }
+
+ /**
+ * This method converts the socket address to a string.
+ *
+ * The string is formatted as "[<ipv6 address>]:<port number>".
+ *
+ * @returns An `InfoString` containing the string representation of the `SockAddr`
+ *
+ */
+ InfoString ToString(void) const;
};
/**
diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp
new file mode 100644
index 0000000..a32da3e
--- /dev/null
+++ b/src/core/net/srp_client.cpp
@@ -0,0 +1,1588 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "srp_client.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
+#include "common/random.hpp"
+#include "common/settings.hpp"
+#include "common/string.hpp"
+#include "thread/network_data_service.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+/**
+ * @file
+ * This file implements the SRP client.
+ */
+
+namespace ot {
+namespace Srp {
+
+//---------------------------------------------------------------------
+// Client::HostInfo
+
+void Client::HostInfo::Init(void)
+{
+ Clearable<HostInfo>::Clear();
+
+ // State is directly set on `mState` instead of using `SetState()`
+ // to avoid logging.
+ mState = OT_SRP_CLIENT_ITEM_STATE_REMOVED;
+}
+
+void Client::HostInfo::Clear(void)
+{
+ Clearable<HostInfo>::Clear();
+ SetState(kRemoved);
+}
+
+void Client::HostInfo::SetState(ItemState aState)
+{
+ if (aState != GetState())
+ {
+ otLogInfoSrp("[client] HostInfo %s -> %s", ItemStateToString(GetState()), ItemStateToString(aState));
+ mState = static_cast<otSrpClientItemState>(aState);
+ }
+}
+
+void Client::HostInfo::SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
+{
+ mAddresses = aAddresses;
+ mNumAddresses = aNumAddresses;
+
+ otLogInfoSrp("[client] HostInfo set %d addrs", GetNumAddresses());
+
+ for (uint8_t index = 0; index < GetNumAddresses(); index++)
+ {
+ otLogInfoSrp("[client] %s", GetAddress(index).ToString().AsCString());
+ }
+}
+
+//---------------------------------------------------------------------
+// Client::Service
+
+Error Client::Service::Init(void)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit((GetName() != nullptr) && (GetInstanceName() != nullptr), error = kErrorInvalidArgs);
+ VerifyOrExit((GetTxtEntries() != nullptr) || (GetNumTxtEntries() == 0), error = kErrorInvalidArgs);
+
+ // State is directly set on `mState` instead of using `SetState()`
+ // to avoid logging.
+ mState = OT_SRP_CLIENT_ITEM_STATE_REMOVED;
+
+exit:
+ return error;
+}
+
+void Client::Service::SetState(ItemState aState)
+{
+ VerifyOrExit(GetState() != aState);
+
+ otLogInfoSrp("[client] Service %s -> %s, \"%s\" \"%s\"", ItemStateToString(GetState()), ItemStateToString(aState),
+ GetInstanceName(), GetName());
+
+ if (aState == kToAdd)
+ {
+ // Log more details only when entering `kToAdd` state.
+
+ otLogInfoSrp("[client] port:%d weight:%d prio:%d txts:%d", GetPort(), GetWeight(), GetPriority(),
+ GetNumTxtEntries());
+ }
+
+ mState = static_cast<otSrpClientItemState>(aState);
+
+exit:
+ return;
+}
+
+//---------------------------------------------------------------------
+// Client
+
+const char Client::kDefaultDomainName[] = "default.service.arpa";
+
+Client::Client(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mState(kStateStopped)
+ , mTxFailureRetryCount(0)
+ , mShouldRemoveKeyLease(false)
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ , mAutoStartModeEnabled(kAutoStartDefaultMode)
+ , mAutoStartDidSelectServer(false)
+#endif
+ , mUpdateMessageId(0)
+ , mRetryWaitInterval(kMinRetryWaitInterval)
+ , mAcceptedLeaseInterval(0)
+ , mLeaseInterval(kDefaultLease)
+ , mKeyLeaseInterval(kDefaultKeyLease)
+ , mSocket(aInstance)
+ , mCallback(nullptr)
+ , mCallbackContext(nullptr)
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ , mAutoStartCallback(nullptr)
+ , mAutoStartContext(nullptr)
+#endif
+ , mDomainName(kDefaultDomainName)
+ , mTimer(aInstance, Client::HandleTimer)
+{
+ mHostInfo.Init();
+
+ // The `Client` implementation uses different constant array of
+ // `ItemState` to define transitions between states in `Pause()`,
+ // `Stop()`, `SendUpdate`, and `ProcessResponse()`, or to convert
+ // an `ItemState` to string. Here, we assert that the enumeration
+ // values are correct.
+
+ static_assert(kToAdd == 0, "kToAdd value is not correct");
+ static_assert(kAdding == 1, "kAdding value is not correct");
+ static_assert(kToRefresh == 2, "kToRefresh value is not correct");
+ static_assert(kRefreshing == 3, "kRefreshing value is not correct");
+ static_assert(kToRemove == 4, "kToRemove value is not correct");
+ static_assert(kRemoving == 5, "kRemoving value is not correct");
+ static_assert(kRegistered == 6, "kRegistered value is not correct");
+ static_assert(kRemoved == 7, "kRemoved value is not correct");
+}
+
+Error Client::Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester)
+{
+ Error error;
+
+ VerifyOrExit(GetState() == kStateStopped,
+ error = (aServerSockAddr == GetServerAddress()) ? kErrorNone : kErrorBusy);
+
+ SuccessOrExit(error = mSocket.Open(Client::HandleUdpReceive, this));
+ SuccessOrExit(error = mSocket.Connect(aServerSockAddr));
+
+ otLogInfoSrp("[client] %starting, server %s", (aRequester == kRequesterUser) ? "S" : "Auto-s",
+ aServerSockAddr.ToString().AsCString());
+
+ Resume();
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ mAutoStartDidSelectServer = (aRequester == kRequesterAuto);
+
+ VerifyOrExit((aRequester == kRequesterAuto) && (mAutoStartCallback != nullptr));
+ mAutoStartCallback(&aServerSockAddr, mAutoStartContext);
+#endif
+
+exit:
+ return error;
+}
+
+void Client::Stop(Requester aRequester)
+{
+ // Change the state of host info and services so that they are
+ // added/removed again once the client is started back. In the
+ // case of `kAdding`, we intentionally move to `kToRefresh`
+ // instead of `kToAdd` since the server may receive our add
+ // request and the item may be registered on the server. This
+ // ensures that if we are later asked to remove the item, we do
+ // notify server.
+
+ static const ItemState kNewStateOnStop[]{
+ /* (0) kToAdd -> */ kToAdd,
+ /* (1) kAdding -> */ kToRefresh,
+ /* (2) kToRefresh -> */ kToRefresh,
+ /* (3) kRefreshing -> */ kToRefresh,
+ /* (4) kToRemove -> */ kToRemove,
+ /* (5) kRemoving -> */ kToRemove,
+ /* (6) kRegistered -> */ kToRefresh,
+ /* (7) kRemoved -> */ kRemoved,
+ };
+
+ VerifyOrExit(GetState() != kStateStopped);
+
+ // State changes:
+ // kAdding -> kToRefresh
+ // kRefreshing -> kToRefresh
+ // kRemoving -> kToRemove
+ // kRegistered -> kToRefresh
+
+ ChangeHostAndServiceStates(kNewStateOnStop);
+
+ IgnoreError(mSocket.Close());
+ mShouldRemoveKeyLease = false;
+ mTxFailureRetryCount = 0;
+ ResetRetryWaitInterval();
+ SetState(kStateStopped);
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ VerifyOrExit((aRequester == kRequesterAuto) && (mAutoStartCallback != nullptr));
+ mAutoStartCallback(nullptr, mAutoStartContext);
+#endif
+
+exit:
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ if (aRequester == kRequesterUser)
+ {
+ DisableAutoStartMode();
+ }
+#endif
+}
+
+void Client::SetCallback(Callback aCallback, void *aContext)
+{
+ mCallback = aCallback;
+ mCallbackContext = aContext;
+}
+
+void Client::Resume(void)
+{
+ SetState(kStateUpdated);
+ UpdateState();
+}
+
+void Client::Pause(void)
+{
+ // Change the state of host info and services that are are being
+ // added or removed so that they are added/removed again once the
+ // client is resumed or started back.
+
+ static const ItemState kNewStateOnPause[]{
+ /* (0) kToAdd -> */ kToAdd,
+ /* (1) kAdding -> */ kToRefresh,
+ /* (2) kToRefresh -> */ kToRefresh,
+ /* (3) kRefreshing -> */ kToRefresh,
+ /* (4) kToRemove -> */ kToRemove,
+ /* (5) kRemoving -> */ kToRemove,
+ /* (6) kRegistered -> */ kRegistered,
+ /* (7) kRemoved -> */ kRemoved,
+ };
+
+ // State changes:
+ // kAdding -> kToRefresh
+ // kRefreshing -> kToRefresh
+ // kRemoving -> kToRemove
+
+ ChangeHostAndServiceStates(kNewStateOnPause);
+
+ SetState(kStatePaused);
+}
+
+void Client::HandleNotifierEvents(Events aEvents)
+{
+ if (aEvents.Contains(kEventThreadRoleChanged))
+ {
+ HandleRoleChanged();
+ }
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ if (aEvents.Contains(kEventThreadNetdataChanged))
+ {
+ ProcessAutoStart();
+ }
+#endif
+}
+
+void Client::HandleRoleChanged(void)
+{
+ if (Get<Mle::Mle>().IsAttached())
+ {
+ VerifyOrExit(GetState() == kStatePaused);
+ Resume();
+ }
+ else
+ {
+ VerifyOrExit(GetState() != kStateStopped);
+ Pause();
+ }
+
+exit:
+ return;
+}
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+Error Client::SetDomainName(const char *aName)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);
+
+ mDomainName = (aName != nullptr) ? aName : kDefaultDomainName;
+ otLogInfoSrp("[client] Domain name \"%s\"", mDomainName);
+
+exit:
+ return error;
+}
+#endif
+
+Error Client::SetHostName(const char *aName)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(aName != nullptr, error = kErrorInvalidArgs);
+
+ VerifyOrExit((mHostInfo.GetState() == kToAdd) || (mHostInfo.GetState() == kRemoved), error = kErrorInvalidState);
+
+ otLogInfoSrp("[client] Host name \"%s\"", aName);
+ mHostInfo.SetName(aName);
+ mHostInfo.SetState(kToAdd);
+ UpdateState();
+
+exit:
+ return error;
+}
+
+Error Client::SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit((aAddresses != nullptr) && (aNumAddresses > 0), error = kErrorInvalidArgs);
+
+ VerifyOrExit((mHostInfo.GetState() != kToRemove) && (mHostInfo.GetState() != kRemoving),
+ error = kErrorInvalidState);
+
+ if (mHostInfo.GetState() == kRemoved)
+ {
+ mHostInfo.SetState(kToAdd);
+ }
+ else if (mHostInfo.GetState() != kToAdd)
+ {
+ mHostInfo.SetState(kToRefresh);
+ }
+
+ mHostInfo.SetAddresses(aAddresses, aNumAddresses);
+ UpdateState();
+
+exit:
+ return error;
+}
+
+Error Client::AddService(Service &aService)
+{
+ Error error;
+
+ VerifyOrExit(!mServices.Contains(aService), error = kErrorAlready);
+
+ SuccessOrExit(error = aService.Init());
+ mServices.Push(aService);
+
+ aService.SetState(kToAdd);
+ UpdateState();
+
+exit:
+ return error;
+}
+
+Error Client::RemoveService(Service &aService)
+{
+ Error error = kErrorNone;
+ LinkedList<Service> removedServices;
+
+ VerifyOrExit(mServices.Contains(aService), error = kErrorNotFound);
+
+ UpdateServiceStateToRemove(aService);
+
+ // Check if the service was removed immediately, if so
+ // invoke the callback to report the removed service.
+ GetRemovedServices(removedServices);
+
+ if (!removedServices.IsEmpty())
+ {
+ InvokeCallback(kErrorNone, mHostInfo, removedServices.GetHead());
+ }
+
+ UpdateState();
+
+exit:
+ return error;
+}
+
+void Client::UpdateServiceStateToRemove(Service &aService)
+{
+ if (aService.GetState() == kToAdd)
+ {
+ // If the service has not been added yet, we can remove it immediately.
+ aService.SetState(kRemoved);
+ }
+ else if (aService.GetState() != kRemoving)
+ {
+ aService.SetState(kToRemove);
+ }
+}
+
+Error Client::RemoveHostAndServices(bool aShouldRemoveKeyLease)
+{
+ Error error = kErrorNone;
+
+ otLogInfoSrp("[client] Remove host & services");
+
+ VerifyOrExit(mHostInfo.GetState() != kRemoved, error = kErrorAlready);
+
+ if ((mHostInfo.GetState() == kToRemove) || (mHostInfo.GetState() == kRemoving))
+ {
+ // Host info remove is already ongoing, if "key lease" remove mode is
+ // the same, there is no need to send a new update message.
+ VerifyOrExit(mShouldRemoveKeyLease != aShouldRemoveKeyLease);
+ }
+
+ mShouldRemoveKeyLease = aShouldRemoveKeyLease;
+
+ for (Service *service = mServices.GetHead(); service != nullptr; service = service->GetNext())
+ {
+ UpdateServiceStateToRemove(*service);
+ }
+
+ if (mHostInfo.GetState() == kToAdd)
+ {
+ // Host info is not added yet (not yet registered with
+ // server), so we can remove it and all services immediately.
+ mHostInfo.SetState(kRemoved);
+ HandleUpdateDone();
+ ExitNow();
+ }
+
+ mHostInfo.SetState(kToRemove);
+ UpdateState();
+
+exit:
+ return error;
+}
+
+void Client::ClearHostAndServices(void)
+{
+ otLogInfoSrp("[client] Clear host & services");
+
+ switch (GetState())
+ {
+ case kStateStopped:
+ case kStatePaused:
+ break;
+
+ case kStateToUpdate:
+ case kStateUpdating:
+ case kStateUpdated:
+ case kStateToRetry:
+ SetState(kStateUpdated);
+ break;
+ }
+
+ mTxFailureRetryCount = 0;
+ ResetRetryWaitInterval();
+
+ mServices.Clear();
+ mHostInfo.Clear();
+}
+
+void Client::SetState(State aState)
+{
+ VerifyOrExit(aState != mState);
+
+ otLogInfoSrp("[client] State %s -> %s", StateToString(mState), StateToString(aState));
+ mState = aState;
+
+ switch (mState)
+ {
+ case kStateStopped:
+ case kStatePaused:
+ case kStateUpdated:
+ mTimer.Stop();
+ break;
+
+ case kStateToUpdate:
+ mTimer.Start(kUpdateTxDelay);
+ break;
+
+ case kStateUpdating:
+ mTimer.Start(GetRetryWaitInterval());
+ break;
+
+ case kStateToRetry:
+ break;
+ }
+exit:
+ return;
+}
+
+void Client::ChangeHostAndServiceStates(const ItemState *aNewStates)
+{
+ mHostInfo.SetState(aNewStates[mHostInfo.GetState()]);
+
+ for (Service *service = mServices.GetHead(); service != nullptr; service = service->GetNext())
+ {
+ service->SetState(aNewStates[service->GetState()]);
+ }
+}
+
+void Client::InvokeCallback(Error aError) const
+{
+ InvokeCallback(aError, mHostInfo, nullptr);
+}
+
+void Client::InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const
+{
+ VerifyOrExit(GetState() != kStateStopped);
+ VerifyOrExit(mCallback != nullptr);
+ mCallback(aError, &aHostInfo, mServices.GetHead(), aRemovedServices, mCallbackContext);
+
+exit:
+ return;
+}
+
+void Client::SendUpdate(void)
+{
+ static const ItemState kNewStateOnMessageTx[]{
+ /* (0) kToAdd -> */ kAdding,
+ /* (1) kAdding -> */ kAdding,
+ /* (2) kToRefresh -> */ kRefreshing,
+ /* (3) kRefreshing -> */ kRefreshing,
+ /* (4) kToRemove -> */ kRemoving,
+ /* (5) kRemoving -> */ kRemoving,
+ /* (6) kRegistered -> */ kRegistered,
+ /* (7) kRemoved -> */ kRemoved,
+ };
+
+ Error error = kErrorNone;
+ Message *message = mSocket.NewMessage(0);
+
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = PrepareUpdateMessage(*message));
+ SuccessOrExit(error = mSocket.SendTo(*message, Ip6::MessageInfo()));
+
+ otLogInfoSrp("[client] Send update");
+
+ // State changes:
+ // kToAdd -> kAdding
+ // kToRefresh -> kRefreshing
+ // kToRemove -> kRemoving
+
+ ChangeHostAndServiceStates(kNewStateOnMessageTx);
+
+ // Remember the update message tx time to use later to determine the
+ // lease renew time.
+ mLeaseRenewTime = TimerMilli::GetNow();
+ mTxFailureRetryCount = 0;
+
+ SetState(kStateUpdating);
+
+ if (!Get<Mle::Mle>().IsRxOnWhenIdle())
+ {
+ // If device is sleepy send fast polls while waiting for
+ // the response from server.
+ Get<DataPollSender>().SendFastPolls(kFastPollsAfterUpdateTx);
+ }
+
+exit:
+ if (error != kErrorNone)
+ {
+ // If there is an error in preparation or transmission of the
+ // update message (e.g., no buffer to allocate message), up to
+ // `kMaxTxFailureRetries` times, we wait for a short interval
+ // `kTxFailureRetryInterval` and try again. After this, we
+ // continue to retry using the `mRetryWaitInterval` (which keeps
+ // growing on each failure).
+
+ otLogInfoSrp("[client] Failed to send update: %s", ErrorToString(error));
+
+ FreeMessage(message);
+
+ SetState(kStateToRetry);
+
+ if (mTxFailureRetryCount < kMaxTxFailureRetries)
+ {
+ uint32_t interval;
+
+ mTxFailureRetryCount++;
+ interval = Random::NonCrypto::AddJitter(kTxFailureRetryInterval, kTxFailureRetryJitter);
+ mTimer.Start(interval);
+
+ otLogInfoSrp("[client] Quick retry %d in %u msec", mTxFailureRetryCount, interval);
+
+ // Do not report message preparation errors to user
+ // until `kMaxTxFailureRetries` are exhausted.
+ }
+ else
+ {
+ LogRetryWaitInterval();
+ mTimer.Start(Random::NonCrypto::AddJitter(GetRetryWaitInterval(), kRetryIntervalJitter));
+ GrowRetryWaitInterval();
+ InvokeCallback(error);
+ }
+ }
+}
+
+Error Client::PrepareUpdateMessage(Message &aMessage)
+{
+ enum : uint16_t
+ {
+ kHeaderOffset = 0,
+ };
+
+ Error error = kErrorNone;
+ Dns::UpdateHeader header;
+ Info info;
+
+ info.Clear();
+
+ SuccessOrExit(error = ReadOrGenerateKey(info.mKeyPair));
+
+ // Generate random Message ID and ensure it is different from last one
+ do
+ {
+ SuccessOrExit(error = header.SetRandomMessageId());
+ } while (header.GetMessageId() == mUpdateMessageId);
+
+ mUpdateMessageId = header.GetMessageId();
+
+ // SRP Update (DNS Update) message must have exactly one record in
+ // Zone section, no records in Prerequisite Section, can have
+ // multiple records in Update Section (tracked as they are added),
+ // and two records in Additional Data Section (OPT and SIG records).
+ // The SIG record itself should not be included in calculation of
+ // SIG(0) signature, so the addition record count is set to one
+ // here. After signature calculation and appending of SIG record,
+ // the additional record count is updated to two and the header is
+ // rewritten in the message.
+
+ header.SetZoneRecordCount(1);
+ header.SetAdditionalRecordCount(1);
+ SuccessOrExit(error = aMessage.Append(header));
+
+ // Prepare Zone section
+
+ info.mDomainNameOffset = aMessage.GetLength();
+ SuccessOrExit(error = Dns::Name::AppendName(mDomainName, aMessage));
+ SuccessOrExit(error = aMessage.Append(Dns::Zone()));
+
+ // Prepare Update section
+
+ if (mHostInfo.GetState() != kToRemove)
+ {
+ for (Service *service = mServices.GetHead(); service != nullptr; service = service->GetNext())
+ {
+ SuccessOrExit(error = AppendServiceInstructions(*service, aMessage, info));
+ }
+ }
+
+ SuccessOrExit(error = AppendHostDescriptionInstruction(aMessage, info));
+
+ header.SetUpdateRecordCount(info.mRecordCount);
+ aMessage.Write(kHeaderOffset, header);
+
+ // Prepare Additional Data section
+
+ SuccessOrExit(error = AppendUpdateLeaseOptRecord(aMessage));
+ SuccessOrExit(error = AppendSignature(aMessage, info));
+
+ header.SetAdditionalRecordCount(2); // Lease OPT and SIG RRs
+ aMessage.Write(kHeaderOffset, header);
+
+exit:
+ return error;
+}
+
+Error Client::ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair)
+{
+ Error error;
+
+ error = Get<Settings>().ReadSrpKey(aKeyPair);
+
+ if (error == kErrorNone)
+ {
+ Crypto::Ecdsa::P256::PublicKey publicKey;
+
+ if (aKeyPair.GetPublicKey(publicKey) == kErrorNone)
+ {
+ ExitNow();
+ }
+ }
+
+ SuccessOrExit(error = aKeyPair.Generate());
+ IgnoreError(Get<Settings>().SaveSrpKey(aKeyPair));
+
+exit:
+ return error;
+}
+
+Error Client::AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo)
+{
+ Error error = kErrorNone;
+ Dns::ResourceRecord rr;
+ Dns::SrvRecord srv;
+ bool removing;
+ uint16_t serviceNameOffset;
+ uint16_t instanceNameOffset;
+ uint16_t offset;
+
+ if (aService.GetState() == kRegistered)
+ {
+ // If the lease needs to be renewed or if we are close to the
+ // renewal time of a registered service, we refresh the service
+ // early and include it in this update. This helps put more
+ // services on the same lease refresh schedule.
+
+ VerifyOrExit(ShouldRenewEarly(aService));
+ aService.SetState(kToRefresh);
+ }
+
+ removing = ((aService.GetState() == kToRemove) || (aService.GetState() == kRemoving));
+
+ //----------------------------------
+ // Service Discovery Instruction
+
+ // PTR record
+
+ // "service name labels" + (pointer to) domain name.
+ serviceNameOffset = aMessage.GetLength();
+ SuccessOrExit(error = Dns::Name::AppendMultipleLabels(aService.GetName(), aMessage));
+ SuccessOrExit(error = Dns::Name::AppendPointerLabel(aInfo.mDomainNameOffset, aMessage));
+
+ // On remove, we use "Delete an RR from an RRSet" where class is set
+ // to NONE and TTL to zero (RFC 2136 - section 2.5.4).
+
+ rr.Init(Dns::ResourceRecord::kTypePtr, removing ? Dns::PtrRecord::kClassNone : Dns::PtrRecord::kClassInternet);
+ rr.SetTtl(removing ? 0 : mLeaseInterval);
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.Append(rr));
+
+ // "Instance name" + (pointer to) service name.
+ instanceNameOffset = aMessage.GetLength();
+ SuccessOrExit(error = Dns::Name::AppendLabel(aService.GetInstanceName(), aMessage));
+ SuccessOrExit(error = Dns::Name::AppendPointerLabel(serviceNameOffset, aMessage));
+
+ UpdateRecordLengthInMessage(rr, offset, aMessage);
+ aInfo.mRecordCount++;
+
+ //----------------------------------
+ // Service Description Instruction
+
+ // "Delete all RRsets from a name" for Instance Name.
+
+ SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
+ SuccessOrExit(error = AppendDeleteAllRrsets(aMessage));
+ aInfo.mRecordCount++;
+
+ VerifyOrExit(!removing);
+
+ // SRV RR
+
+ SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
+ srv.Init();
+ srv.SetTtl(mLeaseInterval);
+ srv.SetPriority(aService.GetPriority());
+ srv.SetWeight(aService.GetWeight());
+ srv.SetPort(aService.GetPort());
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.Append(srv));
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+ UpdateRecordLengthInMessage(srv, offset, aMessage);
+ aInfo.mRecordCount++;
+
+ // TXT RR
+
+ SuccessOrExit(error = Dns::Name::AppendPointerLabel(instanceNameOffset, aMessage));
+ rr.Init(Dns::ResourceRecord::kTypeTxt);
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.Append(rr));
+ SuccessOrExit(error =
+ Dns::TxtEntry::AppendEntries(aService.GetTxtEntries(), aService.GetNumTxtEntries(), aMessage));
+ UpdateRecordLengthInMessage(rr, offset, aMessage);
+ aInfo.mRecordCount++;
+
+exit:
+ return error;
+}
+
+Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const
+{
+ Error error = kErrorNone;
+ Dns::ResourceRecord rr;
+ Dns::KeyRecord key;
+ Crypto::Ecdsa::P256::PublicKey publicKey;
+
+ //----------------------------------
+ // Host Description Instruction
+
+ // "Delete all RRsets from a name" for Host Name.
+
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+ SuccessOrExit(error = AppendDeleteAllRrsets(aMessage));
+ aInfo.mRecordCount++;
+
+ // AAAA RRs
+
+ rr.Init(Dns::ResourceRecord::kTypeAaaa);
+ rr.SetTtl(mLeaseInterval);
+ rr.SetLength(sizeof(Ip6::Address));
+
+ for (uint8_t index = 0; index < mHostInfo.GetNumAddresses(); index++)
+ {
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+ SuccessOrExit(error = aMessage.Append(rr));
+ SuccessOrExit(error = aMessage.Append(mHostInfo.GetAddress(index)));
+ aInfo.mRecordCount++;
+ }
+
+ // KEY RR
+
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+ key.Init();
+ key.SetTtl(mLeaseInterval);
+ key.SetFlags(Dns::KeyRecord::kAuthConfidPermitted, Dns::KeyRecord::kOwnerNonZone,
+ Dns::KeyRecord::kSignatoryFlagGeneral);
+ key.SetProtocol(Dns::KeyRecord::kProtocolDnsSec);
+ key.SetAlgorithm(Dns::KeyRecord::kAlgorithmEcdsaP256Sha256);
+ key.SetLength(sizeof(Dns::KeyRecord) - sizeof(Dns::ResourceRecord) + sizeof(Crypto::Ecdsa::P256::PublicKey));
+ SuccessOrExit(error = aMessage.Append(key));
+ SuccessOrExit(error = aInfo.mKeyPair.GetPublicKey(publicKey));
+ SuccessOrExit(error = aMessage.Append(publicKey));
+ aInfo.mRecordCount++;
+
+exit:
+ return error;
+}
+
+Error Client::AppendDeleteAllRrsets(Message &aMessage) const
+{
+ // "Delete all RRsets from a name" (RFC 2136 - 2.5.3)
+ // Name should be already appended in the message.
+
+ Dns::ResourceRecord rr;
+
+ rr.Init(Dns::ResourceRecord::kTypeAny, Dns::ResourceRecord::kClassAny);
+ rr.SetTtl(0);
+ rr.SetLength(0);
+
+ return aMessage.Append(rr);
+}
+
+Error Client::AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress) const
+{
+ Error error;
+
+ if (aDoNotCompress)
+ {
+ // Uncompressed (canonical form) of host name is used for SIG(0)
+ // calculation.
+ SuccessOrExit(error = Dns::Name::AppendMultipleLabels(mHostInfo.GetName(), aMessage));
+ error = Dns::Name::AppendName(mDomainName, aMessage);
+ ExitNow();
+ }
+
+ // If host name was previously added in the message, add it
+ // compressed as pointer to the previous one. Otherwise,
+ // append it and remember the offset.
+
+ if (aInfo.mHostNameOffset != Info::kUnknownOffset)
+ {
+ ExitNow(error = Dns::Name::AppendPointerLabel(aInfo.mHostNameOffset, aMessage));
+ }
+
+ aInfo.mHostNameOffset = aMessage.GetLength();
+ SuccessOrExit(error = Dns::Name::AppendMultipleLabels(mHostInfo.GetName(), aMessage));
+ error = Dns::Name::AppendPointerLabel(aInfo.mDomainNameOffset, aMessage);
+
+exit:
+ return error;
+}
+
+Error Client::AppendUpdateLeaseOptRecord(Message &aMessage) const
+{
+ Error error;
+ Dns::OptRecord optRecord;
+ Dns::LeaseOption leaseOption;
+
+ // Append empty (root domain) as OPT RR name.
+ SuccessOrExit(error = Dns::Name::AppendTerminator(aMessage));
+
+ // `Init()` sets the type and clears (set to zero) the extended
+ // Response Code, version and all flags.
+ optRecord.Init();
+ optRecord.SetUdpPayloadSize(kUdpPayloadSize);
+ optRecord.SetDnsSecurityFlag();
+ optRecord.SetLength(sizeof(Dns::LeaseOption));
+
+ SuccessOrExit(error = aMessage.Append(optRecord));
+
+ leaseOption.Init();
+
+ if (mHostInfo.GetState() == kToRemove)
+ {
+ leaseOption.SetLeaseInterval(0);
+ leaseOption.SetKeyLeaseInterval(mShouldRemoveKeyLease ? 0 : mKeyLeaseInterval);
+ }
+ else
+ {
+ leaseOption.SetLeaseInterval(mLeaseInterval);
+ leaseOption.SetKeyLeaseInterval(mKeyLeaseInterval);
+ }
+
+ error = aMessage.Append(leaseOption);
+
+exit:
+ return error;
+}
+
+Error Client::AppendSignature(Message &aMessage, Info &aInfo)
+{
+ Error error;
+ Dns::SigRecord sig;
+ Crypto::Sha256 sha256;
+ Crypto::Sha256::Hash hash;
+ Crypto::Ecdsa::P256::Signature signature;
+ uint16_t offset;
+ uint16_t len;
+
+ // Prepare SIG RR: TTL, type covered, labels count should be set
+ // to zero. Since we have no clock, inception and expiration time
+ // are also set to zero. The RDATA length will be set later (not
+ // yet known due to variably (and possible compression) of signer's
+ // name.
+
+ sig.Clear();
+ sig.Init(Dns::ResourceRecord::kClassAny);
+ sig.SetAlgorithm(Dns::KeyRecord::kAlgorithmEcdsaP256Sha256);
+
+ // Append the SIG RR with full uncompressed form of the host name
+ // as the signer's name. This is used for SIG(0) calculation only.
+ // It will be overwritten with host name compressed.
+
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.Append(sig));
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo, /* aDoNotCompress */ true));
+
+ // Calculate signature (RFC 2931): Calculated over "data" which is
+ // concatenation of (1) the SIG RR RDATA wire format (including
+ // the canonical form of the signer's name), entirely omitting the
+ // signature subfield, (2) DNS query message, including DNS header
+ // but not UDP/IP header before the header RR counts have been
+ // adjusted for the inclusion of SIG(0).
+
+ sha256.Start();
+
+ // (1) SIG RR RDATA wire format
+ len = aMessage.GetLength() - offset - sizeof(Dns::ResourceRecord);
+ sha256.Update(aMessage, offset + sizeof(Dns::ResourceRecord), len);
+
+ // (2) Message from DNS header before SIG
+ sha256.Update(aMessage, 0, offset);
+
+ sha256.Finish(hash);
+ SuccessOrExit(error = aInfo.mKeyPair.Sign(hash, signature));
+
+ // Move back in message and append SIG RR now with compressed host
+ // name (as signer's name) along with the calculated signature.
+
+ IgnoreError(aMessage.SetLength(offset));
+
+ // SIG(0) uses owner name of root (single zero byte).
+ SuccessOrExit(error = Dns::Name::AppendTerminator(aMessage));
+
+ offset = aMessage.GetLength();
+ SuccessOrExit(error = aMessage.Append(sig));
+ SuccessOrExit(error = AppendHostName(aMessage, aInfo));
+ SuccessOrExit(error = aMessage.Append(signature));
+ UpdateRecordLengthInMessage(sig, offset, aMessage);
+
+exit:
+ return error;
+}
+
+void Client::UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const
+{
+ // This method is used to calculate an RR DATA length and update
+ // (rewrite) it in a message. This should be called immediately
+ // after all the fields in the record are written in the message.
+ // `aOffset` gives the offset in the message to the start of the
+ // record.
+
+ aRecord.SetLength(aMessage.GetLength() - aOffset - sizeof(Dns::ResourceRecord));
+ aMessage.Write(aOffset, aRecord);
+}
+
+void Client::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+{
+ OT_UNUSED_VARIABLE(aMessageInfo);
+
+ static_cast<Client *>(aContext)->ProcessResponse(*static_cast<Message *>(aMessage));
+}
+
+void Client::ProcessResponse(Message &aMessage)
+{
+ static const ItemState kNewStateOnUpdateDone[]{
+ /* (0) kToAdd -> */ kToAdd,
+ /* (1) kAdding -> */ kRegistered,
+ /* (2) kToRefresh -> */ kToRefresh,
+ /* (3) kRefreshing -> */ kRegistered,
+ /* (4) kToRemove -> */ kToRemove,
+ /* (5) kRemoving -> */ kRemoved,
+ /* (6) kRegistered -> */ kRegistered,
+ /* (7) kRemoved -> */ kRemoved,
+ };
+
+ Error error = kErrorNone;
+ Dns::UpdateHeader header;
+ uint16_t offset = aMessage.GetOffset();
+ uint16_t recordCount;
+ LinkedList<Service> removedServices;
+
+ VerifyOrExit(GetState() == kStateUpdating);
+
+ SuccessOrExit(error = aMessage.Read(offset, header));
+
+ VerifyOrExit(header.GetType() == Dns::Header::kTypeResponse, error = kErrorParse);
+ VerifyOrExit(header.GetQueryType() == Dns::Header::kQueryTypeUpdate, error = kErrorParse);
+ VerifyOrExit(header.GetMessageId() == mUpdateMessageId, error = kErrorDrop);
+
+ if (!Get<Mle::Mle>().IsRxOnWhenIdle())
+ {
+ Get<DataPollSender>().StopFastPolls();
+ }
+
+ // Response is for the earlier request message.
+
+ otLogInfoSrp("[client] Received response");
+
+ error = Dns::Header::ResponseCodeToError(header.GetResponseCode());
+
+ if (error != kErrorNone)
+ {
+ otLogInfoSrp("[client] Server rejected %s code:%d", ErrorToString(error), header.GetResponseCode());
+
+ if (mHostInfo.GetState() == kAdding)
+ {
+ // Since server rejected the update message, we go back to
+ // `kToAdd` state to allow user to give a new name using
+ // `SetHostName()`.
+ mHostInfo.SetState(kToAdd);
+ }
+
+ // Wait for the timer to expire to retry. Note that timer is
+ // already scheduled for the current wait interval when state
+ // was changed to `kStateUpdating`.
+
+ LogRetryWaitInterval();
+ GrowRetryWaitInterval();
+ SetState(kStateToRetry);
+ InvokeCallback(error);
+ ExitNow(error = kErrorNone);
+ }
+
+ offset += sizeof(header);
+
+ // Skip over all sections till Additional Data section
+ // SPEC ENHANCEMENT: Sever can echo the request back or not
+ // include any of RRs. Would be good to explicitly require SRP server
+ // to not echo back RRs.
+
+ if (header.GetZoneRecordCount() != 0)
+ {
+ VerifyOrExit(header.GetZoneRecordCount() == 1, error = kErrorParse);
+ SuccessOrExit(error = Dns::Name::ParseName(aMessage, offset));
+ VerifyOrExit(offset + sizeof(Dns::Zone) <= aMessage.GetLength(), error = kErrorParse);
+ offset += sizeof(Dns::Zone);
+ }
+
+ // Check for Update Lease OPT RR. This determines the lease
+ // interval accepted by server. If not present, then use the
+ // transmitted lease interval from the update request message.
+
+ mAcceptedLeaseInterval = mLeaseInterval;
+ recordCount =
+ header.GetPrerequisiteRecordCount() + header.GetUpdateRecordCount() + header.GetAdditionalRecordCount();
+
+ while (recordCount > 0)
+ {
+ uint16_t startOffset = offset;
+ Dns::ResourceRecord rr;
+
+ SuccessOrExit(error = ReadResourceRecord(aMessage, offset, rr));
+ recordCount--;
+
+ if (rr.GetType() == Dns::ResourceRecord::kTypeOpt)
+ {
+ SuccessOrExit(error = ProcessOptRecord(aMessage, startOffset, static_cast<Dns::OptRecord &>(rr)));
+ }
+ }
+
+ // Calculate the lease renew time based on update message tx time
+ // and the lease time. `kLeaseRenewGuardInterval` is used to
+ // ensure that we renew the lease before server expires it. In the
+ // unlikely (but maybe useful for testing) case where the accepted
+ // lease interval is too short (shorter than the guard time) we
+ // just use half of the accepted lease interval.
+
+ if (mAcceptedLeaseInterval > kLeaseRenewGuardInterval)
+ {
+ mLeaseRenewTime += Time::SecToMsec(mAcceptedLeaseInterval - kLeaseRenewGuardInterval);
+ }
+ else
+ {
+ mLeaseRenewTime += Time::SecToMsec(mAcceptedLeaseInterval) / 2;
+ }
+
+ for (Service *service = mServices.GetHead(); service != nullptr; service = service->GetNext())
+ {
+ if ((service->GetState() == kAdding) || (service->GetState() == kRefreshing))
+ {
+ service->SetLeaseRenewTime(mLeaseRenewTime);
+ }
+ }
+
+ // State changes:
+ // kAdding -> kRegistered
+ // kRefreshing -> kRegistered
+ // kRemoving -> kRemoved
+
+ ChangeHostAndServiceStates(kNewStateOnUpdateDone);
+
+ HandleUpdateDone();
+ UpdateState();
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogInfoSrp("[clinet] Failed to process response %s", ErrorToString(error));
+ }
+}
+
+void Client::HandleUpdateDone(void)
+{
+ HostInfo hostInfoCopy = mHostInfo;
+ LinkedList<Service> removedServices;
+
+ if (mHostInfo.GetState() == kRemoved)
+ {
+ mHostInfo.Clear();
+ }
+
+ ResetRetryWaitInterval();
+ SetState(kStateUpdated);
+
+ GetRemovedServices(removedServices);
+ InvokeCallback(kErrorNone, hostInfoCopy, removedServices.GetHead());
+}
+
+void Client::GetRemovedServices(LinkedList<Service> &aRemovedServices)
+{
+ Service *service;
+ Service *prev;
+ Service *next;
+
+ for (prev = nullptr, service = mServices.GetHead(); service != nullptr; service = next)
+ {
+ next = service->GetNext();
+
+ if (service->GetState() == kRemoved)
+ {
+ mServices.PopAfter(prev);
+ aRemovedServices.Push(*service);
+
+ // When the service is removed from the list
+ // we keep the `prev` pointer same as before.
+ }
+ else
+ {
+ prev = service;
+ }
+ }
+}
+
+Error Client::ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord)
+{
+ // Reads and skips over a Resource Record (RR) from message at
+ // given offset. On success, `aOffset` is updated to point to end
+ // of RR.
+
+ Error error;
+
+ SuccessOrExit(error = Dns::Name::ParseName(aMessage, aOffset));
+ SuccessOrExit(error = aMessage.Read(aOffset, aRecord));
+ VerifyOrExit(aOffset + aRecord.GetSize() <= aMessage.GetLength(), error = kErrorParse);
+ aOffset += static_cast<uint16_t>(aRecord.GetSize());
+
+exit:
+ return error;
+}
+
+Error Client::ProcessOptRecord(const Message &aMessage, uint16_t aOffset, const Dns::OptRecord &aOptRecord)
+{
+ // Read and process all options (in an OPT RR) from a message.
+ // The `aOffset` points to beginning of record in `aMessage`.
+
+ Error error = kErrorNone;
+ uint16_t len;
+
+ IgnoreError(Dns::Name::ParseName(aMessage, aOffset));
+ aOffset += sizeof(Dns::OptRecord);
+
+ len = aOptRecord.GetLength();
+
+ while (len > 0)
+ {
+ Dns::LeaseOption leaseOption;
+ Dns::Option & option = leaseOption;
+ uint16_t size;
+
+ SuccessOrExit(error = aMessage.Read(aOffset, option));
+
+ VerifyOrExit(aOffset + option.GetSize() <= aMessage.GetLength(), error = kErrorParse);
+
+ if ((option.GetOptionCode() == Dns::Option::kUpdateLease) &&
+ (option.GetOptionLength() >= Dns::LeaseOption::kOptionLength))
+ {
+ SuccessOrExit(error = aMessage.Read(aOffset, leaseOption));
+
+ mAcceptedLeaseInterval = leaseOption.GetLeaseInterval();
+
+ if (mAcceptedLeaseInterval > kMaxLease)
+ {
+ mAcceptedLeaseInterval = kMaxLease;
+ }
+ }
+
+ size = static_cast<uint16_t>(option.GetSize());
+ aOffset += size;
+ len -= size;
+ }
+
+exit:
+ return error;
+}
+
+void Client::UpdateState(void)
+{
+ TimeMilli now = TimerMilli::GetNow();
+ TimeMilli earliestRenewTime = now.GetDistantFuture();
+ bool shouldUpdate = false;
+
+ VerifyOrExit((GetState() != kStateStopped) && (GetState() != kStatePaused));
+ VerifyOrExit((mHostInfo.GetName() != nullptr) && (mHostInfo.GetNumAddresses() > 0));
+
+ // Go through the host info and all the services to check if there
+ // are any new changes (i.e., anything new to add or remove). This
+ // is used to determine whether to send an SRP update message or
+ // not. Also keep track of the earliest renew time among the
+ // previously registered services. This is used to schedule the
+ // timer for next refresh.
+
+ switch (mHostInfo.GetState())
+ {
+ case kAdding:
+ case kRefreshing:
+ case kRemoving:
+ break;
+
+ case kRegistered:
+ if (now < mLeaseRenewTime)
+ {
+ break;
+ }
+
+ mHostInfo.SetState(kToRefresh);
+
+ // Fall through
+
+ case kToAdd:
+ case kToRefresh:
+ // Make sure we have at least one service otherwise no need to
+ // send SRP update message with host info only. The exception
+ // is when removing host info where we allow for empty
+ // service list.
+ VerifyOrExit(!mServices.IsEmpty());
+
+ // Fall through
+
+ case kToRemove:
+ shouldUpdate = true;
+ break;
+
+ case kRemoved:
+ ExitNow();
+ }
+
+ // If host info is being removed, we skip over checking service list
+ // for new adds (or removes). This handles the situation where while
+ // remove is ongoing and before we get a response from the server,
+ // user adds a new service to be registered. We wait for remove to
+ // finish (receive response from server) before starting with a new
+ // service adds.
+
+ if (mHostInfo.GetState() != kRemoving)
+ {
+ for (Service *service = mServices.GetHead(); service != nullptr; service = service->GetNext())
+ {
+ switch (service->GetState())
+ {
+ case kToAdd:
+ case kToRefresh:
+ case kToRemove:
+ shouldUpdate = true;
+ break;
+
+ case kRegistered:
+ if (service->GetLeaseRenewTime() <= now)
+ {
+ service->SetState(kToRefresh);
+ shouldUpdate = true;
+ }
+ else if (service->GetLeaseRenewTime() < earliestRenewTime)
+ {
+ earliestRenewTime = service->GetLeaseRenewTime();
+ }
+
+ break;
+
+ case kAdding:
+ case kRefreshing:
+ case kRemoving:
+ case kRemoved:
+ break;
+ }
+ }
+ }
+
+ if (shouldUpdate)
+ {
+ SetState(kStateToUpdate);
+ ExitNow();
+ }
+
+ if ((GetState() == kStateUpdated) && (earliestRenewTime != now.GetDistantFuture()))
+ {
+ mTimer.FireAt(earliestRenewTime);
+ }
+
+exit:
+ return;
+}
+
+void Client::GrowRetryWaitInterval(void)
+{
+ mRetryWaitInterval =
+ mRetryWaitInterval / kRetryIntervalGrowthFactorDenominator * kRetryIntervalGrowthFactorNumerator;
+
+ if (mRetryWaitInterval > kMaxRetryWaitInterval)
+ {
+ mRetryWaitInterval = kMaxRetryWaitInterval;
+ }
+}
+
+uint32_t Client::GetBoundedLeaseInterval(uint32_t aInterval, uint32_t aDefaultInterval) const
+{
+ uint32_t boundedInterval = aDefaultInterval;
+
+ if (aInterval != 0)
+ {
+ boundedInterval = OT_MIN(aInterval, static_cast<uint32_t>(kMaxLease));
+ }
+
+ return boundedInterval;
+}
+
+bool Client::ShouldRenewEarly(const Service &aService) const
+{
+ // Check if we reached the service renew time or close to it. The
+ // "early renew interval" is used to allow early refresh. It is
+ // calculated as a factor of the `mAcceptedLeaseInterval`. The
+ // "early lease renew factor" is given as a fraction (numerator and
+ // denominator). If the denominator is set to zero (i.e., factor is
+ // set to infinity), then service is always included in all SRP
+ // update messages.
+
+ bool shouldRenew;
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR != 0
+ uint32_t earlyRenewInterval =
+ Time::SecToMsec(mAcceptedLeaseInterval) / kEarlyLeaseRenewFactorDenominator * kEarlyLeaseRenewFactorNumerator;
+
+ shouldRenew = (aService.GetLeaseRenewTime() <= TimerMilli::GetNow() + earlyRenewInterval);
+#else
+ OT_UNUSED_VARIABLE(aService);
+ shouldRenew = true;
+#endif
+
+ return shouldRenew;
+}
+
+void Client::HandleTimer(Timer &aTimer)
+{
+ aTimer.Get<Client>().HandleTimer();
+}
+
+void Client::HandleTimer(void)
+{
+ switch (GetState())
+ {
+ case kStateStopped:
+ case kStatePaused:
+ break;
+
+ case kStateToUpdate:
+ case kStateToRetry:
+ SendUpdate();
+ break;
+
+ case kStateUpdating:
+ LogRetryWaitInterval();
+ otLogInfoSrp("[client] Timed out, no response");
+ GrowRetryWaitInterval();
+ SetState(kStateToUpdate);
+ InvokeCallback(kErrorResponseTimeout);
+ break;
+
+ case kStateUpdated:
+ UpdateState();
+ break;
+ }
+}
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+void Client::EnableAutoStartMode(AutoStartCallback aCallback, void *aContext)
+{
+ mAutoStartCallback = aCallback;
+ mAutoStartContext = aContext;
+
+ VerifyOrExit(!mAutoStartModeEnabled);
+ mAutoStartModeEnabled = true;
+ ProcessAutoStart();
+
+exit:
+ return;
+}
+
+void Client::ProcessAutoStart(void)
+{
+ uint16_t numServers = 0;
+ NetworkData::Service::SrpServer::Info selectedServer;
+ NetworkData::Service::SrpServer::Info server;
+ NetworkData::Service::Manager::Iterator iterator;
+
+ VerifyOrExit(mAutoStartModeEnabled);
+
+ // If the client is not running we check if there is any SRP sever
+ // info in Network Data and select one randomly and then start the
+ // client. If the client is already running with a server that was
+ // selected by the auto-start feature, we verify that the selected
+ // server is still present in the Network Data.
+
+ VerifyOrExit(!IsRunning() || mAutoStartDidSelectServer);
+
+ while (Get<NetworkData::Service::Manager>().GetNextSrpServerInfo(iterator, server) == kErrorNone)
+ {
+ numServers++;
+
+ // Choose a server randomly (with uniform distribution) from
+ // the list of servers. As we iterate through server entries,
+ // with probability `1/numServers`, we choose to switch the
+ // current selected server with the new entry. This approach
+ // results in a uniform/same probability of selection among
+ // all server entries.
+
+ if ((numServers == 1) || (Random::NonCrypto::GetUint16InRange(0, numServers) == 0))
+ {
+ selectedServer = server;
+ }
+
+ if (IsRunning() && mAutoStartDidSelectServer && (GetServerAddress() == server.mSockAddr))
+ {
+ ExitNow();
+ }
+ }
+
+ if (IsRunning())
+ {
+ otLogInfoSrp("[client] Server %s is no longer present in net data", GetServerAddress().ToString().AsCString());
+ Stop(kRequesterAuto);
+ }
+
+ VerifyOrExit(numServers > 0);
+ IgnoreError(Start(selectedServer.mSockAddr, kRequesterAuto));
+
+exit:
+ return;
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+const char *Client::ItemStateToString(ItemState aState)
+{
+ static const char *const kItemStateStrings[] = {
+ "ToAdd", // kToAdd (0)
+ "Adding", // kAdding (1)
+ "ToRefresh", // kToRefresh (2)
+ "Refreshing", // kRefreshing (3)
+ "ToRemove", // kToRemove (4)
+ "Removing", // kRemoving (5)
+ "Registered", // kRegistered (6)
+ "Removed", // kRemoved (7)
+ };
+
+ return kItemStateStrings[aState];
+}
+
+#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+
+const char *Client::StateToString(State aState)
+{
+ static const char *const kStateStrings[] = {
+ "Stopped", // kStateStopped (0)
+ "Paused", // kStatePaused (1)
+ "ToUpdate", // kStateToUpdate (2)
+ "Updating", // kStateUpdating (3)
+ "Updated", // kStateUpdated (4)
+ "ToRetry", // kStateToRetry (5)
+ };
+
+ static_assert(kStateStopped == 0, "kStateStopped value is not correct");
+ static_assert(kStatePaused == 1, "kStatePaused value is not correct");
+ static_assert(kStateToUpdate == 2, "kStateToUpdate value is not correct");
+ static_assert(kStateUpdating == 3, "kStateUpdating value is not correct");
+ static_assert(kStateUpdated == 4, "kStateUpdated value is not correct");
+ static_assert(kStateToRetry == 5, "kStateToRetry value is not correct");
+
+ return kStateStrings[aState];
+}
+
+void Client::LogRetryWaitInterval(void) const
+{
+ enum : uint16_t
+ {
+ kLogInMsecLimit = 5000, // Max interval (in msec) to log the value in msec unit
+ kMsecInSec = 1000,
+ };
+
+ uint32_t interval = GetRetryWaitInterval();
+
+ otLogInfoSrp("[client] Retry interval %u %s", (interval < kLogInMsecLimit) ? interval : Time::MsecToSec(interval),
+ (interval < kLogInMsecLimit) ? "ms" : "sec");
+}
+
+#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+
+} // namespace Srp
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
diff --git a/src/core/net/srp_client.hpp b/src/core/net/srp_client.hpp
new file mode 100644
index 0000000..939558a
--- /dev/null
+++ b/src/core/net/srp_client.hpp
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRP_CLIENT_HPP_
+#define SRP_CLIENT_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/srp_client.h>
+
+#include "common/clearable.hpp"
+#include "common/linked_list.hpp"
+#include "common/locator.hpp"
+#include "common/message.hpp"
+#include "common/non_copyable.hpp"
+#include "common/notifier.hpp"
+#include "common/timer.hpp"
+#include "crypto/ecdsa.hpp"
+#include "net/dns_types.hpp"
+#include "net/ip6.hpp"
+#include "net/udp6.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+/**
+ * @file
+ * This file includes definitions for the SRP (Service Registration Protocol) client.
+ */
+
+namespace ot {
+namespace Srp {
+
+#if !OPENTHREAD_CONFIG_ECDSA_ENABLE
+#error "SRP Client feature requires ECDSA support (OPENTHREAD_CONFIG_ECDSA_ENABLE)."
+#endif
+
+/**
+ * This class implements SRP client.
+ *
+ */
+class Client : public InstanceLocator, private NonCopyable
+{
+ friend class ot::Notifier;
+
+public:
+ /**
+ * This enumeration types represents an SRP client item (service or host info) state.
+ *
+ */
+ enum ItemState : uint8_t
+ {
+ kToAdd = OT_SRP_CLIENT_ITEM_STATE_TO_ADD, ///< Item to be added/registered.
+ kAdding = OT_SRP_CLIENT_ITEM_STATE_ADDING, ///< Item is being added/registered.
+ kToRefresh = OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH, ///< Item to be refreshed (renew lease).
+ kRefreshing = OT_SRP_CLIENT_ITEM_STATE_REFRESHING, ///< Item is being refreshed.
+ kToRemove = OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE, ///< Item to be removed.
+ kRemoving = OT_SRP_CLIENT_ITEM_STATE_REMOVING, ///< Item is being removed.
+ kRegistered = OT_SRP_CLIENT_ITEM_STATE_REGISTERED, ///< Item is registered with server.
+ kRemoved = OT_SRP_CLIENT_ITEM_STATE_REMOVED, ///< Item is removed.
+ };
+
+ /**
+ * This function pointer type defines the callback used by SRP client to notify user of a changes/events/errors.
+ *
+ * Please see `otSrpClientCallback` for more details.
+ *
+ */
+ typedef otSrpClientCallback Callback;
+
+ /**
+ * This type represents an SRP client host info.
+ *
+ */
+ class HostInfo : public otSrpClientHostInfo, public Clearable<HostInfo>
+ {
+ friend class Client;
+
+ public:
+ /**
+ * This method initializes the `HostInfo` object.
+ *
+ */
+ void Init(void);
+
+ /**
+ * This method clears the `HostInfo` object.
+ *
+ */
+ void Clear(void);
+
+ /**
+ * This method gets the host name (label) string.
+ *
+ * @returns The host name (label) string, or nullptr if not yet set.
+ *
+ */
+ const char *GetName(void) const { return mName; }
+
+ /**
+ * This method gets the number of host IPv6 addresses.
+ *
+ * @returns The number of host IPv6 addresses.
+ *
+ */
+ uint8_t GetNumAddresses(void) const { return mNumAddresses; }
+
+ /**
+ * This method gets the host IPv6 address at a given index.
+ *
+ * @param[in] aIndex The index to get (MUST be smaller than `GetNumAddresses()`).
+ *
+ * @returns The host IPv6 address at index @p aIndex.
+ *
+ */
+ const Ip6::Address &GetAddress(uint8_t aIndex) const
+ {
+ return static_cast<const Ip6::Address &>(mAddresses[aIndex]);
+ }
+
+ /**
+ * This method gets the state of `HostInfo`.
+ *
+ * @returns The `HostInfo` state.
+ *
+ */
+ ItemState GetState(void) const { return static_cast<ItemState>(mState); }
+
+ private:
+ void SetName(const char *aName) { mName = aName; }
+ void SetState(ItemState aState);
+ void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
+ };
+
+ /**
+ * This type represents an SRP client service.
+ *
+ */
+ class Service : public otSrpClientService, public LinkedListEntry<Service>
+ {
+ friend class Client;
+
+ public:
+ /**
+ * This method initializes and validates the `Service` object and its fields.
+ *
+ * @retval kErrorNone Successfully initialized and validated the `Service` object.
+ * @retval kErrorInvalidArgs The info in `Service` object is not valid (e.g. null name or bad `TxtEntry`).
+ *
+ */
+ Error Init(void);
+
+ /**
+ * This method gets the service name labels string.
+ *
+ * @returns The service name label string (e.g., "_chip._udp", not the full domain name).
+ *
+ */
+ const char *GetName(void) const { return mName; }
+
+ /**
+ * This method gets the service instance name label (not the full name).
+ *
+ * @returns The service instance name label string.
+ *
+ */
+ const char *GetInstanceName(void) const { return mInstanceName; }
+
+ /**
+ * This method gets the service port number.
+ *
+ * @returns The service port number.
+ *
+ */
+ uint16_t GetPort(void) const { return mPort; }
+
+ /**
+ * This method gets the service priority.
+ *
+ * @returns The service priority.
+ *
+ */
+ uint16_t GetPriority(void) const { return mPriority; }
+
+ /**
+ * This method gets the service weight.
+ *
+ * @returns The service weight.
+ *
+ */
+ uint16_t GetWeight(void) const { return mWeight; }
+
+ /**
+ * This method gets the array of service TXT entries.
+ *
+ * @returns A pointer to an array of service TXT entries.
+ *
+ */
+ const Dns::TxtEntry *GetTxtEntries(void) const { return static_cast<const Dns::TxtEntry *>(mTxtEntries); }
+
+ /**
+ * This method gets the number of entries in the service TXT entry array.
+ *
+ * @returns The number of entries in the service TXT entry array.
+ *
+ */
+ uint8_t GetNumTxtEntries(void) const { return mNumTxtEntries; }
+
+ /**
+ * This method get the state of service.
+ *
+ * @returns The service state.
+ *
+ */
+ ItemState GetState(void) const { return static_cast<ItemState>(mState); }
+
+ private:
+ void SetState(ItemState aState);
+ TimeMilli GetLeaseRenewTime(void) const { return TimeMilli(mData); }
+ void SetLeaseRenewTime(TimeMilli aTime) { mData = aTime.GetValue(); }
+ };
+
+ /**
+ * This constructor initializes the SRP `Client` object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ */
+ explicit Client(Instance &aInstance);
+
+ /**
+ * This method starts the SRP client operation.
+ *
+ * SRP client will prepare and send "SRP Update" message to the SRP server once all the following conditions are
+ * met:
+ *
+ * - The SRP client is started - `Start()` is called
+ * - Host name is set - `SetHostName()` is called.
+ * - At least one host IPv6 address is set - `SetHostAddresses()` is called.
+ * - At least one service is added - `AddService()` is called.
+ *
+ * It does not matter in which order these methods are called. When all conditions are met, the SRP client will
+ * wait for a short delay before preparing an "SRP Update" message and sending it to server. This delay allows for
+ * user to add multiple services and/or IPv6 addresses before the first SRP Update message is sent (ensuring a
+ * single SRP Update is sent containing all the info).
+ *
+ * @param[in] aServerSockAddr The socket address (IPv6 address and port number) of the SRP server.
+ *
+ * @retval kErrorNone SRP client operation started successfully or it is already running with same server
+ * socket address and callback.
+ * @retval kErrorBusy SRP client is busy running with a different socket address.
+ * @retval kErrorFailed Failed to open/connect the client's UDP socket.
+ *
+ */
+ Error Start(const Ip6::SockAddr &aServerSockAddr) { return Start(aServerSockAddr, kRequesterUser); }
+
+ /**
+ * This method stops the SRP client operation.
+ *
+ * This method stops any further interactions with the SRP server. Note that it does not remove or clear host info
+ * and/or list of services. It marks all services to be added/removed again once the client is started again.
+ *
+ * If `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` (auto-start feature) is enabled, a call to this method
+ * also disables the auto-start mode.
+ *
+ */
+ void Stop(void) { Stop(kRequesterUser); }
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ /**
+ * This function pointer type defines the callback used by SRP client to notify user when it is auto-started or
+ * stopped.
+ *
+ */
+ typedef otSrpClientAutoStartCallback AutoStartCallback;
+
+ /**
+ * This method enables the auto-start mode.
+ *
+ * Config option `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE` specifies the default auto-start mode
+ * (whether it is enabled or disabled at the start of OT stack).
+ *
+ * When auto-start is enabled, the SRP client will monitor the Thread Network Data for SRP Server Service entries
+ * and automatically start and stop the client when an SRP server is detected.
+ *
+ * If multiple SRP servers are found, a random one will be selected. If the selected SRP server is no longer
+ * detected (not longer present in the Thread Network Data), the SRP client will be stopped and then it may switch
+ * to another SRP server (if available).
+ *
+ * When the SRP client is explicitly started through a successful call to `Start()`, the given SRP server address
+ * in `Start()` will continue to be used regardless of the state of auto-start mode and whether the same SRP
+ * server address is discovered or not in the Thread Network Data. In this case, only an explicit `Stop()` call
+ * will stop the client.
+ *
+ * @param[in] aCallback A callback to notify when client is auto-started/stopped. Can be `nullptr` if not needed.
+ * @param[in] aContext A context to be passed when invoking @p aCallback.
+ *
+ */
+ void EnableAutoStartMode(AutoStartCallback aCallback, void *aContext);
+
+ /**
+ * This method disables the auto-start mode.
+ *
+ * Disabling the auto-start mode will not stop the client if it is already running but the client stops monitoring
+ * the Thread Network Data to verify that the selected SRP server is still present in it.
+ *
+ * Note that a call to `Stop()` will also disable the auto-start mode.
+ *
+ */
+ void DisableAutoStartMode(void) { mAutoStartModeEnabled = false; }
+
+ /**
+ * This method indicates the current state of auto-start mode (enabled or disabled).
+ *
+ * @returns TRUE if the auto-start mode is enabled, FALSE otherwise.
+ *
+ */
+ bool IsAutoStartModeEnabled(void) const { return mAutoStartModeEnabled; }
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+
+ /**
+ * This method indicates whether the SRP client is running or not.
+ *
+ * @returns TRUE if the SRP client is running, FALSE otherwise.
+ *
+ */
+ bool IsRunning(void) const { return (mState != kStateStopped); }
+
+ /**
+ * This method gets the socket address (IPv6 address and port number) of the SRP server which is being used by SRP
+ * client.
+ *
+ * If the client is not running, the address is unspecified (all zero) with zero port number.
+ *
+ * @returns The SRP server's socket address.
+ *
+ */
+ const Ip6::SockAddr &GetServerAddress(void) const { return mSocket.GetPeerName(); }
+
+ /**
+ * This method sets the callback used to notify caller of events/changes.
+ *
+ * The SRP client allows a single callback to be registered. So consecutive calls to this method will overwrite any
+ * previously set callback functions.
+ *
+ * @param[in] aCallback The callback to notify of events and changes. Can be nullptr if not needed.
+ * @param[in] aContext An arbitrary context used with @p aCallback.
+ *
+ */
+ void SetCallback(Callback aCallback, void *aContext);
+
+ /**
+ * This method gets the lease interval used in SRP update requests.
+ *
+ * Note that this is lease duration that would be requested by the SRP client. Server may choose to accept a
+ * different lease interval.
+ *
+ * @returns The lease interval (in seconds).
+ *
+ */
+ uint32_t GetLeaseInterval(void) const { return mLeaseInterval; }
+
+ /**
+ * This method sets the lease interval used in SRP update requests.
+ *
+ * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
+ * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
+ *
+ * @param[in] The lease interval (in seconds). If zero, the default value `kDefaultLease` would be used.
+ *
+ */
+ void SetLeaseInterval(uint32_t aInterval) { mLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultLease); }
+
+ /**
+ * This method gets the key lease interval used in SRP update requests.
+ *
+ * @returns The key lease interval (in seconds).
+ *
+ */
+ uint32_t GetKeyLeaseInterval(void) const { return mKeyLeaseInterval; }
+
+ /**
+ * This method sets the key lease interval used in SRP update requests.
+ *
+ * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
+ * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
+ *
+ * @param[in] The key lease interval (in seconds). If zero, the default value `kDefaultKeyLease` would be used.
+ *
+ */
+ void SetKeyLeaseInterval(uint32_t aInterval)
+ {
+ mKeyLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultKeyLease);
+ }
+
+ /**
+ * This method gets the host info.
+ *
+ * @returns A reference to host info structure.
+ *
+ */
+ const HostInfo &GetHostInfo(void) const { return mHostInfo; }
+
+ /**
+ * This function sets the host name label.
+ *
+ * After a successful call to this function, `Callback` will be called to report the status of host info
+ * registration with SRP server.
+ *
+ * The host name can be set before client is started or after start but before host info is registered with server
+ * (host info should be in either `kToAdd` or `kRemoved`).
+ *
+ * @param[in] aName A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST
+ * persist and remain valid and constant after return from this function.
+ *
+ * @retval kErrorNone The host name label was set successfully.
+ * @retval kErrorInvalidArgs The @p aName is NULL.
+ * @retval kErrorInvalidState The host name is already set and registered with the server.
+ *
+ */
+ Error SetHostName(const char *aName);
+
+ /**
+ * This method sets/updates the list of host IPv6 address.
+ *
+ * Host IPv6 addresses can be set/changed before start or even during operation of SRP client (e.g. to add/remove
+ * or change a previously registered host address), except when the host info is being removed (client is busy
+ * handling a remove request from an earlier call to `RemoveHostAndServices()` and host info still being in either
+ * `kStateToRemove` or `kStateRemoving` states).
+ *
+ * After a successful call to this method, `Callback` will be called to report the status of the address
+ * registration with SRP server.
+ *
+ * @param[in] aAddresses A pointer to the an array containing the host IPv6 addresses.
+ * @param[in] aNumAddresses The number of addresses in the @p aAddresses array.
+ *
+ * @retval kErrorNone The host IPv6 address list change started successfully. The `Callback` will be
+ * called to report the status of registering addresses with server.
+ * @retval kErrorInvalidArgs The address list is invalid (e.g., must contain at least one address).
+ * @retval kErrorInvalidState Host is being removed and therefore cannot change host address.
+ *
+ */
+ Error SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
+
+ /**
+ * This method adds a service to be registered with server.
+ *
+ * After a successful call to this method, `Callback` will be called to report the status of the service
+ * addition/registration with SRP server.
+ *
+ * @param[in] aService A `Service` to add (the instance must persist and remain unchanged after
+ * successful return from this method).
+ *
+ * @retval kErrorNone The addition of service started successfully. The `Callback` will be called to
+ * report the status.
+ * @retval kErrorAlready The same service is already in the list.
+ * @retval kErrorInvalidArgs The service structure is invalid (e.g., bad service name or `TxEntry`).
+ *
+ */
+ Error AddService(Service &aService);
+
+ /**
+ * This method removes a service to be unregistered with server.
+ *
+ * @param[in] aService A `Service` to remove (the instance must persist and remain unchanged after
+ * successful return from this method).
+ *
+ * @retval kErrorNone The removal of service started successfully. The `Callback` will be called to report
+ * the status.
+ * @retval kErrorNotFound The service could not be found in the list.
+ *
+ */
+
+ Error RemoveService(Service &aService);
+
+ /**
+ * This method gets the list of services being managed by client.
+ *
+ * @returns The list of services.
+ *
+ */
+ const LinkedList<Service> &GetServices(void) const { return mServices; }
+
+ /**
+ * This method starts the remove process of the host info and all services.
+ *
+ * After retuning from this method, `Callback` will be called to report the status of remove request with
+ * SRP server.
+ *
+ * If the host info is to be permanently removed from server, @p aRemoveKeyLease should be set to `true` which
+ * removes the key lease associated with host on server. Otherwise, the key lease record is kept as before, which
+ * ensures that the server holds the host name in reserve for when the client once again able to provide and
+ * register its service(s).
+ *
+ * @param[in] aRemoveKeyLease A boolean indicating whether or not the host key lease should also be removed.
+ *
+ * @retval kErrorNone The removal of host and services started successfully. The `Callback` will be called
+ * to report the status.
+ * @retval kErrorAlready The host is already removed.
+ *
+ */
+ Error RemoveHostAndServices(bool aShouldRemoveKeyLease);
+
+ /**
+ * This method clears all host info and all the services.
+ *
+ * Unlike `RemoveHostAndServices()` which sends an update message to server to remove/unregister all the info, this
+ * method clears all the info immediately without any interaction with server.
+ *
+ */
+ void ClearHostAndServices(void);
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+ /**
+ * This method gets the domain name being used by SRP client.
+ *
+ * If domain name is not set, "default.service.arpa" will be used.
+ *
+ * @returns The domain name string.
+ *
+ */
+ const char *GetDomainName(void) const { return mDomainName; }
+
+ /**
+ * This method sets the domain name to be used by SRP client.
+ *
+ * This is an optional method. If not set "default.service.arpa" will be used.
+ *
+ * The domain name can be set before client is started or after start but before host info is registered with server
+ * (host info should be in either `kToAdd` or `kToRemove`).
+ *
+ * @param[in] aName A pointer to the domain name string. If NULL sets it to default "default.service.arpa".
+ *
+ * @retval kErrorNone The domain name label was set successfully.
+ * @retval kErrorInvalidState The host info is already registered with server.
+ *
+ */
+ Error SetDomainName(const char *aName);
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
+
+ /**
+ * This static method converts a `ItemState` to a string.
+ *
+ * @param[in] aState An `ItemState`.
+ *
+ * @returns A string representation of @p aState.
+ *
+ */
+ static const char *ItemStateToString(ItemState aState);
+
+private:
+ enum : uint8_t
+ {
+ kFastPollsAfterUpdateTx = 11, // Number of fast data polls after SRP Update tx (11x 188ms = ~2 seconds)
+ };
+
+ enum : uint16_t
+ {
+ kUdpPayloadSize = Ip6::Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header), // Max UDP payload size
+ };
+
+ enum : uint32_t
+ {
+ // -------------------------------
+ // Lease related constants
+
+ kDefaultLease = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE, // in seconds.
+ kDefaultKeyLease = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE, // in seconds.
+
+ // The guard interval determines how much earlier (relative to
+ // the lease expiration time) the client will send an update
+ // to renew the lease.
+ kLeaseRenewGuardInterval = OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL, // in seconds.
+
+ // Max allowed lease time to avoid timer roll-over (~24.8 days).
+ kMaxLease = (Timer::kMaxDelay / 1000) - 1,
+
+ // Opportunistic early refresh: When sending an SRP update, the
+ // services that are not yet expired but are close, are allowed
+ // to refresh early and are included in the SRP update. This
+ // helps place more services on the same lease refresh schedule
+ // reducing number of messages sent to the SRP server. The
+ // "early lease renewal interval" is used to determine if a
+ // service can renew early. The interval is calculated by
+ // multiplying the accepted lease interval by the"early lease
+ // renewal factor" which is given as a fraction (numerator and
+ // denominator).
+ //
+ // If the factor is set to zero (numerator=0, denominator=1),
+ // the opportunistic early refresh behavior is disabled. If
+ // denominator is set to zero (the factor is set to infinity),
+ // then all services (including previously registered ones)
+ // are always included in SRP update message.
+
+ kEarlyLeaseRenewFactorNumerator = OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR,
+ kEarlyLeaseRenewFactorDenominator = OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR,
+
+ // -------------------------------
+ // When there is a change (e.g., a new service is added/removed)
+ // that requires an update, the SRP client will wait for a short
+ // delay as specified by `kUpdateTxDelay` before sending an SRP
+ // update to server. This allows the user to provide more change
+ // that are then all sent in same update message.
+ kUpdateTxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_DELAY, // in msec.
+
+ // -------------------------------
+ // Retry related constants
+ //
+ // If the preparation or transmission of an SRP update message
+ // fails (e.g., no buffer to allocate the message), SRP client
+ // will retry after a short interval `kTxFailureRetryInterval`
+ // up to `kMaxTxFailureRetries` attempts. After this, the retry
+ // wait interval will be used (which keeps growing on each failure
+ // - please see bellow).
+ //
+ // If the update message is sent successfully but there is no
+ // response from server or if server rejects the update, the
+ // client will retransmit the update message after some wait
+ // interval. The wait interval starts from the minimum value and
+ // is increased by the growth factor on back-to-back failures up
+ // to the max value. The growth factor is given as a fraction
+ // (e.g., for 1.5, we can use 15 as the numerator and 10 as the
+ // denominator). A random jitter is added to the retry interval.
+ // If the current wait interval value is smaller than the jitter
+ // interval, then wait interval value itself is used as the
+ // jitter value. For example, with jitter interval of 2 seconds
+ // if the current retry interval is 800ms, then a random wait
+ // interval in [0,2*800] ms will be used.
+
+ kTxFailureRetryInterval = 250, // in ms
+ kMaxTxFailureRetries = 8, // num of quick retries after tx failure
+ kMinRetryWaitInterval = OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL, // in ms
+ kMaxRetryWaitInterval = OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL, // in ms
+ kRetryIntervalGrowthFactorNumerator = OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR,
+ kRetryIntervalGrowthFactorDenominator = OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR,
+ };
+
+ enum : uint16_t
+ {
+ kTxFailureRetryJitter = 10, // in ms
+ kRetryIntervalJitter = OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER, // in ms
+ };
+
+ static_assert(kDefaultLease <= static_cast<uint32_t>(kMaxLease), "kDefaultLease is larger than max");
+ static_assert(kDefaultKeyLease <= static_cast<uint32_t>(kMaxLease), "kDefaultKeyLease is larger than max");
+
+ enum State : uint8_t
+ {
+ kStateStopped, // Client is stopped.
+ kStatePaused, // Client is paused (due to device being detached).
+ kStateToUpdate, // Waiting to send SRP update
+ kStateUpdating, // SRP update is sent, waiting for response from server.
+ kStateUpdated, // SRP update response received from server.
+ kStateToRetry, // SRP update tx failed, waiting to retry.
+ };
+
+ enum : bool
+ {
+ kAutoStartDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE,
+ };
+
+ // This enumeration type is used by the private `Start()` and
+ // `Stop()` methods to indicate whether it is being requested by the
+ // user or by the auto-start feature.
+ enum Requester
+ {
+ kRequesterUser,
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ kRequesterAuto,
+#endif
+ };
+
+ struct Info : public Clearable<Info>
+ {
+ enum : uint16_t
+ {
+ kUnknownOffset = 0, // Unknown offset value (used when offset is not yet set).
+ };
+
+ uint16_t mDomainNameOffset; // Offset of domain name serialization
+ uint16_t mHostNameOffset; // Offset of host name serialization.
+ uint16_t mRecordCount; // Number of resource records in Update section.
+ Crypto::Ecdsa::P256::KeyPair mKeyPair; // The ECDSA key pair.
+ };
+
+ Error Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester);
+ void Stop(Requester aRequester);
+ void Resume(void);
+ void Pause(void);
+ void HandleNotifierEvents(Events aEvents);
+ void HandleRoleChanged(void);
+ void UpdateServiceStateToRemove(Service &aService);
+ State GetState(void) const { return mState; }
+ void SetState(State aState);
+ void ChangeHostAndServiceStates(const ItemState *aNewStates);
+ void InvokeCallback(Error aError) const;
+ void InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const;
+ void ClearHostInfoAndServices(void);
+ void HandleHostInfoOrServiceChange(void);
+ void SendUpdate(void);
+ Error PrepareUpdateMessage(Message &aMessage);
+ Error ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair);
+ Error AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo);
+ Error AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo) const;
+ Error AppendDeleteAllRrsets(Message &aMessage) const;
+ Error AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const;
+ Error AppendUpdateLeaseOptRecord(Message &aMessage) const;
+ Error AppendSignature(Message &aMessage, Info &aInfo);
+ void UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const;
+ static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+ void ProcessResponse(Message &aMessage);
+ void HandleUpdateDone(void);
+ void GetRemovedServices(LinkedList<Service> &aRemovedServices);
+ static Error ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord);
+ Error ProcessOptRecord(const Message &aMessage, uint16_t aOffset, const Dns::OptRecord &aOptRecord);
+ void UpdateState(void);
+ uint32_t GetRetryWaitInterval(void) const { return mRetryWaitInterval; }
+ void ResetRetryWaitInterval(void) { mRetryWaitInterval = kMinRetryWaitInterval; }
+ void GrowRetryWaitInterval(void);
+ uint32_t GetBoundedLeaseInterval(uint32_t aInterval, uint32_t aDefaultInterval) const;
+ bool ShouldRenewEarly(const Service &aService) const;
+ static void HandleTimer(Timer &aTimer);
+ void HandleTimer(void);
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ void ProcessAutoStart(void);
+#endif
+
+#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_SRP == 1)
+ static const char *StateToString(State aState);
+ void LogRetryWaitInterval(void) const;
+#else
+ void LogRetryWaitInterval(void) const {}
+#endif
+
+ static const char kDefaultDomainName[];
+
+ static_assert(kMaxTxFailureRetries < 16, "kMaxTxFailureRetries exceed the range of mTxFailureRetryCount (4-bit)");
+
+ State mState;
+ uint8_t mTxFailureRetryCount : 4;
+ bool mShouldRemoveKeyLease : 1;
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ bool mAutoStartModeEnabled : 1;
+ bool mAutoStartDidSelectServer : 1;
+#endif
+
+ uint16_t mUpdateMessageId;
+ uint32_t mRetryWaitInterval;
+
+ TimeMilli mLeaseRenewTime;
+ uint32_t mAcceptedLeaseInterval;
+ uint32_t mLeaseInterval;
+ uint32_t mKeyLeaseInterval;
+
+ Ip6::Udp::Socket mSocket;
+
+ Callback mCallback;
+ void * mCallbackContext;
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+ AutoStartCallback mAutoStartCallback;
+ void * mAutoStartContext;
+#endif
+
+ const char * mDomainName;
+ HostInfo mHostInfo;
+ LinkedList<Service> mServices;
+ TimerMilli mTimer;
+};
+
+} // namespace Srp
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+#endif // SRP_CLIENT_HPP_
diff --git a/src/core/net/srp_server.cpp b/src/core/net/srp_server.cpp
new file mode 100644
index 0000000..c60630e
--- /dev/null
+++ b/src/core/net/srp_server.cpp
@@ -0,0 +1,1703 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes implementation for SRP server.
+ */
+
+#include "srp_server.hpp"
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
+#include "common/new.hpp"
+#include "net/dns_types.hpp"
+#include "thread/network_data_service.hpp"
+#include "thread/thread_netif.hpp"
+
+namespace ot {
+namespace Srp {
+
+static const char kDefaultDomain[] = "default.service.arpa.";
+
+static Dns::UpdateHeader::Response ErrorToDnsResponseCode(Error aError)
+{
+ Dns::UpdateHeader::Response responseCode;
+
+ switch (aError)
+ {
+ case kErrorNone:
+ responseCode = Dns::UpdateHeader::kResponseSuccess;
+ break;
+ case kErrorNoBufs:
+ responseCode = Dns::UpdateHeader::kResponseServerFailure;
+ break;
+ case kErrorParse:
+ responseCode = Dns::UpdateHeader::kResponseFormatError;
+ break;
+ case kErrorDuplicated:
+ responseCode = Dns::UpdateHeader::kResponseNameExists;
+ break;
+ default:
+ responseCode = Dns::UpdateHeader::kResponseRefused;
+ break;
+ }
+
+ return responseCode;
+}
+
+Server::Server(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mSocket(aInstance)
+ , mServiceUpdateHandler(nullptr)
+ , mServiceUpdateHandlerContext(nullptr)
+ , mDomain(nullptr)
+ , mMinLease(kDefaultMinLease)
+ , mMaxLease(kDefaultMaxLease)
+ , mMinKeyLease(kDefaultMinKeyLease)
+ , mMaxKeyLease(kDefaultMaxKeyLease)
+ , mLeaseTimer(aInstance, HandleLeaseTimer)
+ , mOutstandingUpdatesTimer(aInstance, HandleOutstandingUpdatesTimer)
+ , mEnabled(false)
+{
+ IgnoreError(SetDomain(kDefaultDomain));
+}
+
+Server::~Server(void)
+{
+ Instance::HeapFree(mDomain);
+}
+
+void Server::SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler, void *aServiceHandlerContext)
+{
+ mServiceUpdateHandler = aServiceHandler;
+ mServiceUpdateHandlerContext = aServiceHandlerContext;
+}
+
+bool Server::IsRunning(void) const
+{
+ return mSocket.IsBound();
+}
+
+void Server::SetEnabled(bool aEnabled)
+{
+ VerifyOrExit(mEnabled != aEnabled);
+
+ mEnabled = aEnabled;
+
+ if (!mEnabled)
+ {
+ Stop();
+ }
+ else if (Get<Mle::MleRouter>().IsAttached())
+ {
+ Start();
+ }
+
+exit:
+ return;
+}
+
+Error Server::SetLeaseRange(uint32_t aMinLease, uint32_t aMaxLease, uint32_t aMinKeyLease, uint32_t aMaxKeyLease)
+{
+ Error error = kErrorNone;
+
+ // TODO: Support longer LEASE.
+ // We use milliseconds timer for LEASE & KEY-LEASE, this is to avoid overflow.
+ VerifyOrExit(aMaxKeyLease <= Time::MsecToSec(TimerMilli::kMaxDelay), error = kErrorInvalidArgs);
+ VerifyOrExit(aMinLease <= aMaxLease, error = kErrorInvalidArgs);
+ VerifyOrExit(aMinKeyLease <= aMaxKeyLease, error = kErrorInvalidArgs);
+ VerifyOrExit(aMinLease <= aMinKeyLease, error = kErrorInvalidArgs);
+ VerifyOrExit(aMaxLease <= aMaxKeyLease, error = kErrorInvalidArgs);
+
+ mMinLease = aMinLease;
+ mMaxLease = aMaxLease;
+ mMinKeyLease = aMinKeyLease;
+ mMaxKeyLease = aMaxKeyLease;
+
+exit:
+ return error;
+}
+
+uint32_t Server::GrantLease(uint32_t aLease) const
+{
+ OT_ASSERT(mMinLease <= mMaxLease);
+
+ return (aLease == 0) ? 0 : OT_MAX(mMinLease, OT_MIN(mMaxLease, aLease));
+}
+
+uint32_t Server::GrantKeyLease(uint32_t aKeyLease) const
+{
+ OT_ASSERT(mMinKeyLease <= mMaxKeyLease);
+
+ return (aKeyLease == 0) ? 0 : OT_MAX(mMinKeyLease, OT_MIN(mMaxKeyLease, aKeyLease));
+}
+
+const char *Server::GetDomain(void) const
+{
+ return mDomain;
+}
+
+Error Server::SetDomain(const char *aDomain)
+{
+ Error error = kErrorNone;
+ char * buf = nullptr;
+ size_t appendTrailingDot = 0;
+ size_t length = strlen(aDomain);
+
+ VerifyOrExit(!mEnabled, error = kErrorInvalidState);
+
+ VerifyOrExit(length > 0 && length < Dns::Name::kMaxNameSize, error = kErrorInvalidArgs);
+ if (aDomain[length - 1] != '.')
+ {
+ appendTrailingDot = 1;
+ }
+
+ buf = static_cast<char *>(Instance::HeapCAlloc(1, length + appendTrailingDot + 1));
+ VerifyOrExit(buf != nullptr, error = kErrorNoBufs);
+
+ strcpy(buf, aDomain);
+ if (appendTrailingDot)
+ {
+ buf[length] = '.';
+ buf[length + 1] = '\0';
+ }
+ Instance::HeapFree(mDomain);
+ mDomain = buf;
+
+exit:
+ if (error != kErrorNone)
+ {
+ Instance::HeapFree(buf);
+ }
+ return error;
+}
+
+const Server::Host *Server::GetNextHost(const Server::Host *aHost)
+{
+ return (aHost == nullptr) ? mHosts.GetHead() : aHost->GetNext();
+}
+
+// This method adds a SRP service host and takes ownership of it.
+// The caller MUST make sure that there is no existing host with the same hostname.
+void Server::AddHost(Host *aHost)
+{
+ OT_ASSERT(mHosts.FindMatching(aHost->GetFullName()) == nullptr);
+ IgnoreError(mHosts.Add(*aHost));
+}
+
+void Server::RemoveHost(Host *aHost, bool aRetainName, bool aNotifyServiceHandler)
+{
+ VerifyOrExit(aHost != nullptr);
+
+ aHost->mLease = 0;
+ aHost->ClearResources();
+
+ if (aRetainName)
+ {
+ otLogInfoSrp("[server] remove host '%s' (but retain its name)", aHost->mFullName);
+ }
+ else
+ {
+ aHost->mKeyLease = 0;
+ IgnoreError(mHosts.Remove(*aHost));
+ otLogInfoSrp("[server] fully remove host '%s'", aHost->mFullName);
+ }
+
+ if (aNotifyServiceHandler && mServiceUpdateHandler != nullptr)
+ {
+ mServiceUpdateHandler(aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
+ // We don't wait for the reply from the service update handler,
+ // but always remove the host (and its services) regardless of
+ // host/service update result. Because removing a host should fail
+ // only when there is system failure of the platform mDNS implementation
+ // and in which case the host is not expected to be still registered.
+ }
+
+ if (!aRetainName)
+ {
+ aHost->Free();
+ }
+
+exit:
+ return;
+}
+
+const Server::Service *Server::FindService(const char *aFullName) const
+{
+ const Service *service = nullptr;
+
+ for (const Host *host = mHosts.GetHead(); host != nullptr; host = host->GetNext())
+ {
+ service = host->FindService(aFullName);
+ if (service != nullptr)
+ {
+ break;
+ }
+ }
+
+ return service;
+}
+
+bool Server::HasNameConflictsWith(Host &aHost) const
+{
+ bool hasConflicts = false;
+ const Service *service = nullptr;
+ const Host * existingHost = mHosts.FindMatching(aHost.GetFullName());
+
+ if (existingHost != nullptr && *aHost.GetKey() != *existingHost->GetKey())
+ {
+ ExitNow(hasConflicts = true);
+ }
+
+ // Check not only services of this host but all hosts.
+ while ((service = aHost.GetNextService(service)) != nullptr)
+ {
+ const Service *existingService = FindService(service->mFullName);
+ if (existingService != nullptr && *service->GetHost().GetKey() != *existingService->GetHost().GetKey())
+ {
+ ExitNow(hasConflicts = true);
+ }
+ }
+
+exit:
+ return hasConflicts;
+}
+
+void Server::HandleServiceUpdateResult(const Host *aHost, Error aError)
+{
+ UpdateMetadata *update = mOutstandingUpdates.FindMatching(aHost);
+
+ if (update != nullptr)
+ {
+ HandleServiceUpdateResult(update, aError);
+ }
+ else
+ {
+ otLogInfoSrp("[server] delayed SRP host update result, the SRP update has been committed");
+ }
+}
+
+void Server::HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError)
+{
+ CommitSrpUpdate(aError, aUpdate->GetDnsHeader(), aUpdate->GetHost(), aUpdate->GetMessageInfo());
+
+ IgnoreError(mOutstandingUpdates.Remove(*aUpdate));
+ aUpdate->Free();
+
+ if (mOutstandingUpdates.IsEmpty())
+ {
+ mOutstandingUpdatesTimer.Stop();
+ }
+ else
+ {
+ mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
+ }
+}
+
+void Server::CommitSrpUpdate(Error aError,
+ const Dns::UpdateHeader &aDnsHeader,
+ Host & aHost,
+ const Ip6::MessageInfo & aMessageInfo)
+{
+ Host * existingHost;
+ uint32_t hostLease;
+ uint32_t hostKeyLease;
+ uint32_t grantedLease;
+ uint32_t grantedKeyLease;
+
+ SuccessOrExit(aError);
+
+ hostLease = aHost.GetLease();
+ hostKeyLease = aHost.GetKeyLease();
+ grantedLease = GrantLease(hostLease);
+ grantedKeyLease = GrantKeyLease(hostKeyLease);
+
+ aHost.SetLease(grantedLease);
+ aHost.SetKeyLease(grantedKeyLease);
+
+ existingHost = mHosts.FindMatching(aHost.GetFullName());
+
+ if (aHost.GetLease() == 0)
+ {
+ if (aHost.GetKeyLease() == 0)
+ {
+ otLogInfoSrp("[server] remove key of host %s", aHost.GetFullName());
+ RemoveHost(existingHost, /* aRetainName */ false, /* aNotifyServiceHandler */ false);
+ }
+ else if (existingHost != nullptr)
+ {
+ Service *service = nullptr;
+
+ existingHost->SetKeyLease(aHost.GetKeyLease());
+ RemoveHost(existingHost, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+ while ((service = existingHost->GetNextService(service)) != nullptr)
+ {
+ existingHost->RemoveService(service, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+ }
+ }
+
+ aHost.Free();
+ }
+ else if (existingHost != nullptr)
+ {
+ const Service *service = nullptr;
+
+ // Merge current updates into existing host.
+
+ otLogInfoSrp("[server] update host %s", existingHost->GetFullName());
+
+ existingHost->CopyResourcesFrom(aHost);
+ while ((service = aHost.GetNextService(service)) != nullptr)
+ {
+ Service *existingService = existingHost->FindService(service->mFullName);
+
+ if (service->mIsDeleted)
+ {
+ existingHost->RemoveService(existingService, /* aRetainName */ true, /* aNotifyServiceHandler */ false);
+ }
+ else
+ {
+ Service *newService = existingHost->AddService(service->mFullName);
+
+ VerifyOrExit(newService != nullptr, aError = kErrorNoBufs);
+ SuccessOrExit(aError = newService->CopyResourcesFrom(*service));
+ otLogInfoSrp("[server] %s service %s", (existingService != nullptr) ? "update existing" : "add new",
+ service->mFullName);
+ }
+ }
+
+ aHost.Free();
+ }
+ else
+ {
+ otLogInfoSrp("[server] add new host %s", aHost.GetFullName());
+ AddHost(&aHost);
+ }
+
+ // Re-schedule the lease timer.
+ HandleLeaseTimer();
+
+exit:
+ if (aError == kErrorNone && !(grantedLease == hostLease && grantedKeyLease == hostKeyLease))
+ {
+ SendResponse(aDnsHeader, grantedLease, grantedKeyLease, aMessageInfo);
+ }
+ else
+ {
+ SendResponse(aDnsHeader, ErrorToDnsResponseCode(aError), aMessageInfo);
+ }
+}
+
+void Server::Start(void)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(!IsRunning());
+
+ SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
+ SuccessOrExit(error = mSocket.Bind(kUdpPort, OT_NETIF_THREAD));
+
+ SuccessOrExit(error = PublishServerData());
+
+ otLogInfoSrp("[server] start listening on port %hu", mSocket.GetSockName().mPort);
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogCritSrp("[server] failed to start: %s", ErrorToString(error));
+ // Cleanup any resources we may have allocated.
+ Stop();
+ }
+}
+
+void Server::Stop(void)
+{
+ VerifyOrExit(IsRunning());
+
+ UnpublishServerData();
+
+ while (!mHosts.IsEmpty())
+ {
+ RemoveHost(mHosts.GetHead(), /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+ }
+
+ // TODO: We should cancel any oustanding service updates, but current
+ // OTBR mDNS publisher cannot properly handle it.
+ while (!mOutstandingUpdates.IsEmpty())
+ {
+ mOutstandingUpdates.Pop()->Free();
+ }
+
+ mLeaseTimer.Stop();
+ mOutstandingUpdatesTimer.Stop();
+
+ otLogInfoSrp("[server] stop listening on %hu", mSocket.GetSockName().mPort);
+ IgnoreError(mSocket.Close());
+
+exit:
+ return;
+}
+
+void Server::HandleNotifierEvents(Events aEvents)
+{
+ VerifyOrExit(mEnabled);
+ VerifyOrExit(aEvents.Contains(kEventThreadRoleChanged));
+
+ if (Get<Mle::MleRouter>().IsAttached())
+ {
+ Start();
+ }
+ else
+ {
+ Stop();
+ }
+
+exit:
+ return;
+}
+
+Error Server::PublishServerData(void)
+{
+ NetworkData::Service::SrpServer::ServerData serverData;
+
+ OT_ASSERT(mSocket.IsBound());
+
+ serverData.SetPort(mSocket.GetSockName().GetPort());
+
+ return Get<NetworkData::Service::Manager>().Add<NetworkData::Service::SrpServer>(serverData);
+}
+
+void Server::UnpublishServerData(void)
+{
+ Error error = Get<NetworkData::Service::Manager>().Remove<NetworkData::Service::SrpServer>();
+
+ if (error != kErrorNone)
+ {
+ otLogWarnSrp("[server] failed to unpublish SRP service: %s", ErrorToString(error));
+ }
+}
+
+const Server::UpdateMetadata *Server::FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo,
+ uint16_t aDnsMessageId)
+{
+ const UpdateMetadata *ret = nullptr;
+
+ for (const UpdateMetadata *update = mOutstandingUpdates.GetHead(); update != nullptr; update = update->GetNext())
+ {
+ if (aDnsMessageId == update->GetDnsHeader().GetMessageId() &&
+ aMessageInfo.GetPeerAddr() == update->GetMessageInfo().GetPeerAddr() &&
+ aMessageInfo.GetPeerPort() == update->GetMessageInfo().GetPeerPort())
+ {
+ ExitNow(ret = update);
+ }
+ }
+
+exit:
+ return ret;
+}
+
+void Server::HandleDnsUpdate(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t aOffset)
+{
+ Error error = kErrorNone;
+ Dns::Zone zone;
+ Host * host = nullptr;
+
+ otLogInfoSrp("[server] receive DNS update from %s", aMessageInfo.GetPeerAddr().ToString().AsCString());
+
+ SuccessOrExit(error = ProcessZoneSection(aMessage, aDnsHeader, aOffset, zone));
+
+ if (FindOutstandingUpdate(aMessageInfo, aDnsHeader.GetMessageId()) != nullptr)
+ {
+ otLogInfoSrp("[server] drop duplicated SRP update request: messageId=%hu", aDnsHeader.GetMessageId());
+
+ // Silently drop duplicate requests.
+ // This could rarely happen, because the outstanding SRP update timer should
+ // be shorter than the SRP update retransmission timer.
+ ExitNow(error = kErrorNone);
+ }
+
+ // Per 2.3.2 of SRP draft 6, no prerequisites should be included in a SRP update.
+ VerifyOrExit(aDnsHeader.GetPrerequisiteRecordCount() == 0, error = kErrorFailed);
+
+ host = Host::New(GetInstance());
+ VerifyOrExit(host != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = ProcessUpdateSection(*host, aMessage, aDnsHeader, zone, aOffset));
+
+ // Parse lease time and validate signature.
+ SuccessOrExit(error = ProcessAdditionalSection(host, aMessage, aDnsHeader, aOffset));
+
+ HandleUpdate(aDnsHeader, host, aMessageInfo);
+
+exit:
+ if (error != kErrorNone)
+ {
+ if (host != nullptr)
+ {
+ host->Free();
+ }
+ SendResponse(aDnsHeader, ErrorToDnsResponseCode(error), aMessageInfo);
+ }
+}
+
+Error Server::ProcessZoneSection(const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t & aOffset,
+ Dns::Zone & aZone) const
+{
+ Error error = kErrorNone;
+ char name[Dns::Name::kMaxNameSize];
+ Dns::Zone zone;
+
+ VerifyOrExit(aDnsHeader.GetZoneRecordCount() == 1, error = kErrorParse);
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ // TODO: return `Dns::kResponseNotAuth` for not authorized zone names.
+ VerifyOrExit(strcmp(name, GetDomain()) == 0, error = kErrorSecurity);
+ SuccessOrExit(error = aMessage.Read(aOffset, zone));
+ aOffset += sizeof(zone);
+
+ VerifyOrExit(zone.GetType() == Dns::ResourceRecord::kTypeSoa, error = kErrorParse);
+ aZone = zone;
+
+exit:
+ return error;
+}
+
+Error Server::ProcessUpdateSection(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t & aOffset) const
+{
+ Error error = kErrorNone;
+
+ // Process Service Discovery, Host and Service Description Instructions with
+ // 3 times iterations over all DNS update RRs. The order of those processes matters.
+
+ // 0. Enumerate over all Service Discovery Instructions before processing any other records.
+ // So that we will know whether a name is a hostname or service instance name when processing
+ // a "Delete All RRsets from a name" record.
+ error = ProcessServiceDiscoveryInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
+ SuccessOrExit(error);
+
+ // 1. Enumerate over all RRs to build the Host Description Instruction.
+ error = ProcessHostDescriptionInstruction(aHost, aMessage, aDnsHeader, aZone, aOffset);
+ SuccessOrExit(error);
+
+ // 2. Enumerate over all RRs to build the Service Description Insutructions.
+ error = ProcessServiceDescriptionInstructions(aHost, aMessage, aDnsHeader, aZone, aOffset);
+ SuccessOrExit(error);
+
+ // 3. Verify that there are no name conflicts.
+ VerifyOrExit(!HasNameConflictsWith(aHost), error = kErrorDuplicated);
+
+exit:
+ return error;
+}
+
+Error Server::ProcessHostDescriptionInstruction(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t aOffset) const
+{
+ Error error;
+
+ OT_ASSERT(aHost.GetFullName() == nullptr);
+
+ for (uint16_t i = 0; i < aDnsHeader.GetUpdateRecordCount(); ++i)
+ {
+ char name[Dns::Name::kMaxNameSize];
+ Dns::ResourceRecord record;
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ // TODO: return `Dns::kResponseNotZone` for names not in the zone.
+ VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
+ SuccessOrExit(error = aMessage.Read(aOffset, record));
+
+ if (record.GetClass() == Dns::ResourceRecord::kClassAny)
+ {
+ Service *service;
+
+ // Delete All RRsets from a name.
+ VerifyOrExit(IsValidDeleteAllRecord(record), error = kErrorFailed);
+
+ service = aHost.FindService(name);
+ if (service == nullptr)
+ {
+ // A "Delete All RRsets from a name" RR can only apply to a Service or Host Description.
+
+ if (aHost.GetFullName())
+ {
+ VerifyOrExit(aHost.Matches(name), error = kErrorFailed);
+ }
+ else
+ {
+ SuccessOrExit(error = aHost.SetFullName(name));
+ }
+ aHost.ClearResources();
+ }
+
+ aOffset += record.GetSize();
+ continue;
+ }
+
+ if (record.GetType() == Dns::ResourceRecord::kTypeAaaa)
+ {
+ Dns::AaaaRecord aaaaRecord;
+
+ VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+ if (aHost.GetFullName() == nullptr)
+ {
+ SuccessOrExit(error = aHost.SetFullName(name));
+ }
+ else
+ {
+ VerifyOrExit(aHost.Matches(name), error = kErrorFailed);
+ }
+
+ SuccessOrExit(error = aMessage.Read(aOffset, aaaaRecord));
+ VerifyOrExit(aaaaRecord.IsValid(), error = kErrorParse);
+
+ // Tolerate kErrorDrop for AAAA Resources.
+ VerifyOrExit(aHost.AddIp6Address(aaaaRecord.GetAddress()) != kErrorNoBufs, error = kErrorNoBufs);
+
+ aOffset += aaaaRecord.GetSize();
+ }
+ else if (record.GetType() == Dns::ResourceRecord::kTypeKey)
+ {
+ // We currently support only ECDSA P-256.
+ Dns::Ecdsa256KeyRecord key;
+
+ VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+ VerifyOrExit(aHost.GetKey() == nullptr, error = kErrorFailed);
+
+ SuccessOrExit(error = aMessage.Read(aOffset, key));
+ VerifyOrExit(key.IsValid(), error = kErrorParse);
+
+ aHost.SetKey(key);
+
+ aOffset += record.GetSize();
+ }
+ else
+ {
+ aOffset += record.GetSize();
+ }
+ }
+
+ // Verify that we have a complete Host Description Instruction.
+
+ VerifyOrExit(aHost.GetFullName() != nullptr, error = kErrorFailed);
+ VerifyOrExit(aHost.GetKey() != nullptr, error = kErrorFailed);
+ {
+ uint8_t hostAddressesNum;
+
+ aHost.GetAddresses(hostAddressesNum);
+
+ // There MUST be at least one valid address if we have nonzero lease.
+ VerifyOrExit(aHost.GetLease() > 0 || hostAddressesNum > 0, error = kErrorFailed);
+ }
+
+exit:
+ return error;
+}
+
+Error Server::ProcessServiceDiscoveryInstructions(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t aOffset) const
+{
+ Error error = kErrorNone;
+
+ for (uint16_t i = 0; i < aDnsHeader.GetUpdateRecordCount(); ++i)
+ {
+ char name[Dns::Name::kMaxNameSize];
+ Dns::ResourceRecord record;
+ char serviceName[Dns::Name::kMaxNameSize];
+ Service * service;
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
+ SuccessOrExit(error = aMessage.Read(aOffset, record));
+
+ aOffset += sizeof(record);
+
+ if (record.GetType() == Dns::ResourceRecord::kTypePtr)
+ {
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, serviceName, sizeof(serviceName)));
+ VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
+ }
+ else
+ {
+ aOffset += record.GetLength();
+ continue;
+ }
+
+ VerifyOrExit(record.GetClass() == Dns::ResourceRecord::kClassNone || record.GetClass() == aZone.GetClass(),
+ error = kErrorFailed);
+
+ // TODO: check if the RR name and the full service name matches.
+
+ service = aHost.FindService(serviceName);
+ VerifyOrExit(service == nullptr, error = kErrorFailed);
+ service = aHost.AddService(serviceName);
+ VerifyOrExit(service != nullptr, error = kErrorNoBufs);
+
+ // This RR is a "Delete an RR from an RRset" update when the CLASS is NONE.
+ service->mIsDeleted = (record.GetClass() == Dns::ResourceRecord::kClassNone);
+ }
+
+exit:
+ return error;
+}
+
+Error Server::ProcessServiceDescriptionInstructions(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t & aOffset) const
+{
+ Service *service;
+ Error error = kErrorNone;
+
+ for (uint16_t i = 0; i < aDnsHeader.GetUpdateRecordCount(); ++i)
+ {
+ char name[Dns::Name::kMaxNameSize];
+ Dns::ResourceRecord record;
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
+ SuccessOrExit(error = aMessage.Read(aOffset, record));
+
+ if (record.GetClass() == Dns::ResourceRecord::kClassAny)
+ {
+ // Delete All RRsets from a name.
+ VerifyOrExit(IsValidDeleteAllRecord(record), error = kErrorFailed);
+ service = aHost.FindService(name);
+ if (service != nullptr)
+ {
+ service->ClearResources();
+ }
+
+ aOffset += record.GetSize();
+ continue;
+ }
+
+ if (record.GetType() == Dns::ResourceRecord::kTypeSrv)
+ {
+ Dns::SrvRecord srvRecord;
+ char hostName[Dns::Name::kMaxNameSize];
+ uint16_t hostNameLength = sizeof(hostName);
+
+ VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+ SuccessOrExit(error = aMessage.Read(aOffset, srvRecord));
+ aOffset += sizeof(srvRecord);
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, hostName, hostNameLength));
+ VerifyOrExit(Dns::Name::IsSubDomainOf(name, GetDomain()), error = kErrorSecurity);
+ VerifyOrExit(aHost.Matches(hostName), error = kErrorFailed);
+
+ service = aHost.FindService(name);
+ VerifyOrExit(service != nullptr && !service->mIsDeleted, error = kErrorFailed);
+
+ // Make sure that this is the first SRV RR for this service.
+ VerifyOrExit(service->mPort == 0, error = kErrorFailed);
+ service->mPriority = srvRecord.GetPriority();
+ service->mWeight = srvRecord.GetWeight();
+ service->mPort = srvRecord.GetPort();
+ }
+ else if (record.GetType() == Dns::ResourceRecord::kTypeTxt)
+ {
+ VerifyOrExit(record.GetClass() == aZone.GetClass(), error = kErrorFailed);
+
+ service = aHost.FindService(name);
+ VerifyOrExit(service != nullptr && !service->mIsDeleted, error = kErrorFailed);
+
+ aOffset += sizeof(record);
+ SuccessOrExit(error = service->SetTxtDataFromMessage(aMessage, aOffset, record.GetLength()));
+ aOffset += record.GetLength();
+ }
+ else
+ {
+ aOffset += record.GetSize();
+ }
+ }
+
+ service = nullptr;
+ while ((service = aHost.GetNextService(service)) != nullptr)
+ {
+ VerifyOrExit(service->mIsDeleted || (service->mTxtData != nullptr && service->mPort != 0),
+ error = kErrorFailed);
+ }
+
+exit:
+ return error;
+}
+
+bool Server::IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord)
+{
+ return aRecord.GetClass() == Dns::ResourceRecord::kClassAny && aRecord.GetType() == Dns::ResourceRecord::kTypeAny &&
+ aRecord.GetTtl() == 0 && aRecord.GetLength() == 0;
+}
+
+Error Server::ProcessAdditionalSection(Host * aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t & aOffset) const
+{
+ Error error = kErrorNone;
+ Dns::OptRecord optRecord;
+ Dns::LeaseOption leaseOption;
+ Dns::SigRecord sigRecord;
+ char name[2]; // The root domain name (".") is expected.
+ uint16_t sigOffset;
+ uint16_t sigRdataOffset;
+ char signerName[Dns::Name::kMaxNameSize];
+ uint16_t signatureLength;
+
+ VerifyOrExit(aDnsHeader.GetAdditionalRecordCount() == 2, error = kErrorFailed);
+
+ // EDNS(0) Update Lease Option.
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ SuccessOrExit(error = aMessage.Read(aOffset, optRecord));
+ SuccessOrExit(error = aMessage.Read(aOffset + sizeof(optRecord), leaseOption));
+ VerifyOrExit(leaseOption.IsValid(), error = kErrorFailed);
+ VerifyOrExit(optRecord.GetSize() == sizeof(optRecord) + sizeof(leaseOption), error = kErrorParse);
+
+ aOffset += optRecord.GetSize();
+
+ aHost->SetLease(leaseOption.GetLeaseInterval());
+ aHost->SetKeyLease(leaseOption.GetKeyLeaseInterval());
+
+ // SIG(0).
+
+ sigOffset = aOffset;
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, name, sizeof(name)));
+ SuccessOrExit(error = aMessage.Read(aOffset, sigRecord));
+ VerifyOrExit(sigRecord.IsValid(), error = kErrorParse);
+
+ sigRdataOffset = aOffset + sizeof(Dns::ResourceRecord);
+ aOffset += sizeof(sigRecord);
+
+ // TODO: Verify that the signature doesn't expire. This is not
+ // implemented because the end device may not be able to get
+ // the synchronized date/time.
+
+ SuccessOrExit(error = Dns::Name::ReadName(aMessage, aOffset, signerName, sizeof(signerName)));
+
+ signatureLength = sigRecord.GetLength() - (aOffset - sigRdataOffset);
+ aOffset += signatureLength;
+
+ // Verify the signature. Currently supports only ECDSA.
+
+ VerifyOrExit(sigRecord.GetAlgorithm() == Dns::KeyRecord::kAlgorithmEcdsaP256Sha256, error = kErrorFailed);
+ VerifyOrExit(sigRecord.GetTypeCovered() == 0, error = kErrorFailed);
+ VerifyOrExit(signatureLength == Crypto::Ecdsa::P256::Signature::kSize, error = kErrorParse);
+
+ SuccessOrExit(error = VerifySignature(*aHost->GetKey(), aMessage, aDnsHeader, sigOffset, sigRdataOffset,
+ sigRecord.GetLength(), signerName));
+
+exit:
+ return error;
+}
+
+Error Server::VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
+ const Message & aMessage,
+ Dns::UpdateHeader aDnsHeader,
+ uint16_t aSigOffset,
+ uint16_t aSigRdataOffset,
+ uint16_t aSigRdataLength,
+ const char * aSignerName) const
+{
+ Error error;
+ uint16_t offset = aMessage.GetOffset();
+ uint16_t signatureOffset;
+ Crypto::Sha256 sha256;
+ Crypto::Sha256::Hash hash;
+ Crypto::Ecdsa::P256::Signature signature;
+ Message * signerNameMessage = nullptr;
+
+ VerifyOrExit(aSigRdataLength >= Crypto::Ecdsa::P256::Signature::kSize, error = kErrorInvalidArgs);
+
+ sha256.Start();
+
+ // SIG RDATA less signature.
+ sha256.Update(aMessage, aSigRdataOffset, sizeof(Dns::SigRecord) - sizeof(Dns::ResourceRecord));
+
+ // The uncompressed (canonical) form of the signer name should be used for signature
+ // verification. See https://tools.ietf.org/html/rfc2931#section-3.1 for details.
+ signerNameMessage = Get<Ip6::Udp>().NewMessage(0);
+ VerifyOrExit(signerNameMessage != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = Dns::Name::AppendName(aSignerName, *signerNameMessage));
+ sha256.Update(*signerNameMessage, signerNameMessage->GetOffset(), signerNameMessage->GetLength());
+
+ // We need the DNS header before appending the SIG RR.
+ aDnsHeader.SetAdditionalRecordCount(aDnsHeader.GetAdditionalRecordCount() - 1);
+ sha256.Update(aDnsHeader);
+ sha256.Update(aMessage, offset + sizeof(aDnsHeader), aSigOffset - offset - sizeof(aDnsHeader));
+
+ sha256.Finish(hash);
+
+ signatureOffset = aSigRdataOffset + aSigRdataLength - Crypto::Ecdsa::P256::Signature::kSize;
+ SuccessOrExit(error = aMessage.Read(signatureOffset, signature));
+
+ error = aKey.GetKey().Verify(hash, signature);
+
+exit:
+ FreeMessage(signerNameMessage);
+ return error;
+}
+
+void Server::HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host *aHost, const Ip6::MessageInfo &aMessageInfo)
+{
+ Error error = kErrorNone;
+
+ if (aHost->GetLease() == 0)
+ {
+ Host *existingHost = mHosts.FindMatching(aHost->GetFullName());
+
+ aHost->ClearResources();
+
+ // The client may not include all services it has registered and we should append
+ // those services for current SRP update.
+ if (existingHost != nullptr)
+ {
+ Service *existingService = nullptr;
+
+ while ((existingService = existingHost->GetNextService(existingService)) != nullptr)
+ {
+ if (!existingService->mIsDeleted)
+ {
+ Service *service = aHost->AddService(existingService->mFullName);
+ VerifyOrExit(service != nullptr, error = kErrorNoBufs);
+ service->mIsDeleted = true;
+ }
+ }
+ }
+ }
+
+exit:
+ if (error != kErrorNone)
+ {
+ CommitSrpUpdate(error, aDnsHeader, *aHost, aMessageInfo);
+ }
+ else if (mServiceUpdateHandler != nullptr)
+ {
+ UpdateMetadata *update = UpdateMetadata::New(GetInstance(), aDnsHeader, aHost, aMessageInfo);
+
+ IgnoreError(mOutstandingUpdates.Add(*update));
+ mOutstandingUpdatesTimer.StartAt(mOutstandingUpdates.GetTail()->GetExpireTime(), 0);
+
+ mServiceUpdateHandler(aHost, kDefaultEventsHandlerTimeout, mServiceUpdateHandlerContext);
+ }
+ else
+ {
+ CommitSrpUpdate(kErrorNone, aDnsHeader, *aHost, aMessageInfo);
+ }
+}
+
+void Server::SendResponse(const Dns::UpdateHeader & aHeader,
+ Dns::UpdateHeader::Response aResponseCode,
+ const Ip6::MessageInfo & aMessageInfo)
+{
+ Error error;
+ Message * response = nullptr;
+ Dns::UpdateHeader header;
+
+ response = mSocket.NewMessage(0);
+ VerifyOrExit(response != nullptr, error = kErrorNoBufs);
+
+ header.SetMessageId(aHeader.GetMessageId());
+ header.SetType(Dns::UpdateHeader::kTypeResponse);
+ header.SetQueryType(aHeader.GetQueryType());
+ header.SetResponseCode(aResponseCode);
+ SuccessOrExit(error = response->Append(header));
+
+ SuccessOrExit(error = mSocket.SendTo(*response, aMessageInfo));
+
+ if (aResponseCode != Dns::UpdateHeader::kResponseSuccess)
+ {
+ otLogInfoSrp("[server] send fail response: %d", aResponseCode);
+ }
+ else
+ {
+ otLogInfoSrp("[server] send success response");
+ }
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogWarnSrp("[server] failed to send response: %s", ErrorToString(error));
+ FreeMessage(response);
+ }
+}
+
+void Server::SendResponse(const Dns::UpdateHeader &aHeader,
+ uint32_t aLease,
+ uint32_t aKeyLease,
+ const Ip6::MessageInfo & aMessageInfo)
+{
+ Error error;
+ Message * response = nullptr;
+ Dns::UpdateHeader header;
+ Dns::OptRecord optRecord;
+ Dns::LeaseOption leaseOption;
+
+ response = mSocket.NewMessage(0);
+ VerifyOrExit(response != nullptr, error = kErrorNoBufs);
+
+ header.SetMessageId(aHeader.GetMessageId());
+ header.SetType(Dns::UpdateHeader::kTypeResponse);
+ header.SetQueryType(aHeader.GetQueryType());
+ header.SetResponseCode(Dns::UpdateHeader::kResponseSuccess);
+ header.SetAdditionalRecordCount(1);
+ SuccessOrExit(error = response->Append(header));
+
+ // Append the root domain (".").
+ SuccessOrExit(error = Dns::Name::AppendTerminator(*response));
+
+ optRecord.Init();
+ optRecord.SetUdpPayloadSize(kUdpPayloadSize);
+ optRecord.SetDnsSecurityFlag();
+ optRecord.SetLength(sizeof(Dns::LeaseOption));
+ SuccessOrExit(error = response->Append(optRecord));
+
+ leaseOption.Init();
+ leaseOption.SetLeaseInterval(aLease);
+ leaseOption.SetKeyLeaseInterval(aKeyLease);
+ SuccessOrExit(error = response->Append(leaseOption));
+
+ SuccessOrExit(error = mSocket.SendTo(*response, aMessageInfo));
+
+ otLogInfoSrp("[server] send response with granted lease: %u and key lease: %u", aLease, aKeyLease);
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogWarnSrp("[server] failed to send response: %s", ErrorToString(error));
+ FreeMessage(response);
+ }
+}
+
+void Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
+{
+ static_cast<Server *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
+ *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
+}
+
+void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+{
+ Error error;
+ Dns::UpdateHeader dnsHeader;
+ uint16_t offset = aMessage.GetOffset();
+
+ SuccessOrExit(error = aMessage.Read(offset, dnsHeader));
+ offset += sizeof(dnsHeader);
+
+ // Handles only queries.
+ VerifyOrExit(dnsHeader.GetType() == Dns::UpdateHeader::Type::kTypeQuery, error = kErrorDrop);
+
+ switch (dnsHeader.GetQueryType())
+ {
+ case Dns::UpdateHeader::kQueryTypeUpdate:
+ HandleDnsUpdate(aMessage, aMessageInfo, dnsHeader, offset);
+ break;
+ default:
+ error = kErrorDrop;
+ break;
+ }
+
+exit:
+ if (error != kErrorNone)
+ {
+ otLogInfoSrp("[server] failed to handle DNS message: %s", ErrorToString(error));
+ }
+}
+
+void Server::HandleLeaseTimer(Timer &aTimer)
+{
+ aTimer.Get<Server>().HandleLeaseTimer();
+}
+
+void Server::HandleLeaseTimer(void)
+{
+ TimeMilli now = TimerMilli::GetNow();
+ TimeMilli earliestExpireTime = now.GetDistantFuture();
+ Host * host = mHosts.GetHead();
+
+ while (host != nullptr)
+ {
+ Host *nextHost = host->GetNext();
+
+ if (host->GetKeyExpireTime() <= now)
+ {
+ otLogInfoSrp("[server] KEY LEASE of host %s expired", host->GetFullName());
+
+ // Removes the whole host and all services if the KEY RR expired.
+ RemoveHost(host, /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+ }
+ else if (host->IsDeleted())
+ {
+ // The host has been deleted, but the hostname & service instance names retain.
+
+ Service *service;
+
+ earliestExpireTime = OT_MIN(earliestExpireTime, host->GetKeyExpireTime());
+
+ // Check if any service instance name expired.
+ service = host->GetNextService(nullptr);
+ while (service != nullptr)
+ {
+ OT_ASSERT(service->mIsDeleted);
+
+ Service *nextService = service->GetNext();
+
+ if (service->GetKeyExpireTime() <= now)
+ {
+ otLogInfoSrp("[server] KEY LEASE of service %s expired", service->mFullName);
+ host->RemoveService(service, /* aRetainName */ false, /* aNotifyServiceHandler */ true);
+ }
+ else
+ {
+ earliestExpireTime = OT_MIN(earliestExpireTime, service->GetKeyExpireTime());
+ }
+
+ service = nextService;
+ }
+ }
+ else if (host->GetExpireTime() <= now)
+ {
+ Service *service = nullptr;
+
+ otLogInfoSrp("[server] LEASE of host %s expired", host->GetFullName());
+
+ // If the host expired, delete all resources of this host and its services.
+ RemoveHost(host, /* aRetainName */ true, /* aNotifyServiceHandler */ true);
+ while ((service = host->GetNextService(service)) != nullptr)
+ {
+ host->RemoveService(service, /* aRetainName */ true, /* aNotifyServiceHandler */ true);
+ }
+
+ earliestExpireTime = OT_MIN(earliestExpireTime, host->GetKeyExpireTime());
+ }
+ else
+ {
+ // The host doesn't expire, check if any service expired or is explicitly removed.
+
+ OT_ASSERT(!host->IsDeleted());
+
+ Service *service = host->GetNextService(nullptr);
+
+ earliestExpireTime = OT_MIN(earliestExpireTime, host->GetExpireTime());
+
+ while (service != nullptr)
+ {
+ Service *nextService = service->GetNext();
+
+ if (service->mIsDeleted)
+ {
+ // The service has been deleted but the name retains.
+ earliestExpireTime = OT_MIN(earliestExpireTime, service->GetKeyExpireTime());
+ }
+ else if (service->GetExpireTime() <= now)
+ {
+ otLogInfoSrp("[server] LEASE of service %s expired", service->mFullName);
+
+ // The service is expired, delete it.
+ host->RemoveService(service, /* aRetainName */ true, /* aNotifyServiceHandler */ true);
+ earliestExpireTime = OT_MIN(earliestExpireTime, service->GetKeyExpireTime());
+ }
+ else
+ {
+ earliestExpireTime = OT_MIN(earliestExpireTime, service->GetExpireTime());
+ }
+
+ service = nextService;
+ }
+ }
+
+ host = nextHost;
+ }
+
+ if (earliestExpireTime != now.GetDistantFuture())
+ {
+ if (!mLeaseTimer.IsRunning() || earliestExpireTime <= mLeaseTimer.GetFireTime())
+ {
+ otLogInfoSrp("[server] lease timer is scheduled for %u seconds", Time::MsecToSec(earliestExpireTime - now));
+ mLeaseTimer.StartAt(earliestExpireTime, 0);
+ }
+ }
+ else
+ {
+ otLogInfoSrp("[server] lease timer is stopped");
+ mLeaseTimer.Stop();
+ }
+}
+
+void Server::HandleOutstandingUpdatesTimer(Timer &aTimer)
+{
+ aTimer.Get<Server>().HandleOutstandingUpdatesTimer();
+}
+
+void Server::HandleOutstandingUpdatesTimer(void)
+{
+ otLogInfoSrp("[server] outstanding service update timeout");
+ while (!mOutstandingUpdates.IsEmpty() && mOutstandingUpdates.GetTail()->GetExpireTime() <= TimerMilli::GetNow())
+ {
+ HandleServiceUpdateResult(mOutstandingUpdates.GetTail(), kErrorResponseTimeout);
+ }
+}
+
+Server::Service *Server::Service::New(const char *aFullName)
+{
+ void * buf;
+ Service *service = nullptr;
+
+ buf = Instance::HeapCAlloc(1, sizeof(Service));
+ VerifyOrExit(buf != nullptr);
+
+ service = new (buf) Service();
+ if (service->SetFullName(aFullName) != kErrorNone)
+ {
+ service->Free();
+ service = nullptr;
+ }
+
+exit:
+ return service;
+}
+
+void Server::Service::Free(void)
+{
+ Instance::HeapFree(mFullName);
+ Instance::HeapFree(mTxtData);
+ Instance::HeapFree(this);
+}
+
+Server::Service::Service(void)
+ : mFullName(nullptr)
+ , mPriority(0)
+ , mWeight(0)
+ , mPort(0)
+ , mTxtLength(0)
+ , mTxtData(nullptr)
+ , mHost(nullptr)
+ , mNext(nullptr)
+ , mTimeLastUpdate(TimerMilli::GetNow())
+{
+}
+
+Error Server::Service::SetFullName(const char *aFullName)
+{
+ OT_ASSERT(aFullName != nullptr);
+
+ Error error = kErrorNone;
+ char *nameCopy = static_cast<char *>(Instance::HeapCAlloc(1, strlen(aFullName) + 1));
+
+ VerifyOrExit(nameCopy != nullptr, error = kErrorNoBufs);
+ strcpy(nameCopy, aFullName);
+
+ Instance::HeapFree(mFullName);
+ mFullName = nameCopy;
+
+exit:
+ return error;
+}
+
+TimeMilli Server::Service::GetExpireTime(void) const
+{
+ OT_ASSERT(!mIsDeleted);
+ OT_ASSERT(!GetHost().IsDeleted());
+
+ return mTimeLastUpdate + Time::SecToMsec(GetHost().GetLease());
+}
+
+TimeMilli Server::Service::GetKeyExpireTime(void) const
+{
+ return mTimeLastUpdate + Time::SecToMsec(GetHost().GetKeyLease());
+}
+
+Error Server::Service::SetTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength)
+{
+ Error error = kErrorNone;
+ uint8_t *txtData;
+
+ txtData = static_cast<uint8_t *>(Instance::HeapCAlloc(1, aTxtDataLength));
+ VerifyOrExit(txtData != nullptr, error = kErrorNoBufs);
+
+ memcpy(txtData, aTxtData, aTxtDataLength);
+
+ Instance::HeapFree(mTxtData);
+ mTxtData = txtData;
+ mTxtLength = aTxtDataLength;
+
+ // If a TXT RR is associated to this service, the service will retain.
+ mIsDeleted = false;
+
+exit:
+ return error;
+}
+
+Error Server::Service::SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
+{
+ Error error = kErrorNone;
+ uint8_t *txtData;
+
+ txtData = static_cast<uint8_t *>(Instance::HeapCAlloc(1, aLength));
+ VerifyOrExit(txtData != nullptr, error = kErrorNoBufs);
+ VerifyOrExit(aMessage.ReadBytes(aOffset, txtData, aLength) == aLength, error = kErrorParse);
+ VerifyOrExit(Dns::TxtRecord::VerifyTxtData(txtData, aLength), error = kErrorParse);
+
+ Instance::HeapFree(mTxtData);
+ mTxtData = txtData;
+ mTxtLength = aLength;
+
+ mIsDeleted = false;
+
+exit:
+ if (error != kErrorNone)
+ {
+ Instance::HeapFree(txtData);
+ }
+
+ return error;
+}
+
+void Server::Service::ClearResources(void)
+{
+ mPort = 0;
+ Instance::HeapFree(mTxtData);
+ mTxtData = nullptr;
+ mTxtLength = 0;
+}
+
+Error Server::Service::CopyResourcesFrom(const Service &aService)
+{
+ Error error;
+
+ SuccessOrExit(error = SetTxtData(aService.mTxtData, aService.mTxtLength));
+ mPriority = aService.mPriority;
+ mWeight = aService.mWeight;
+ mPort = aService.mPort;
+
+ mIsDeleted = false;
+ mTimeLastUpdate = TimerMilli::GetNow();
+
+exit:
+ return error;
+}
+
+bool Server::Service::Matches(const char *aFullName) const
+{
+ return (mFullName != nullptr) && (strcmp(mFullName, aFullName) == 0);
+}
+
+bool Server::Service::MatchesServiceName(const char *aServiceName) const
+{
+ uint8_t i = static_cast<uint8_t>(strlen(mFullName));
+ uint8_t j = static_cast<uint8_t>(strlen(aServiceName));
+
+ while (i > 0 && j > 0 && mFullName[i - 1] == aServiceName[j - 1])
+ {
+ i--;
+ j--;
+ }
+
+ return j == 0 && i > 0 && mFullName[i - 1] == '.';
+}
+
+Server::Host *Server::Host::New(Instance &aInstance)
+{
+ void *buf;
+ Host *host = nullptr;
+
+ buf = Instance::HeapCAlloc(1, sizeof(Host));
+ VerifyOrExit(buf != nullptr);
+
+ host = new (buf) Host(aInstance);
+
+exit:
+ return host;
+}
+
+void Server::Host::Free(void)
+{
+ FreeAllServices();
+ Instance::HeapFree(mFullName);
+ Instance::HeapFree(this);
+}
+
+Server::Host::Host(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mFullName(nullptr)
+ , mAddressesNum(0)
+ , mNext(nullptr)
+ , mLease(0)
+ , mKeyLease(0)
+ , mTimeLastUpdate(TimerMilli::GetNow())
+{
+ mKey.Clear();
+}
+
+Error Server::Host::SetFullName(const char *aFullName)
+{
+ OT_ASSERT(aFullName != nullptr);
+
+ Error error = kErrorNone;
+ char *nameCopy = static_cast<char *>(Instance::HeapCAlloc(1, strlen(aFullName) + 1));
+
+ VerifyOrExit(nameCopy != nullptr, error = kErrorNoBufs);
+ strcpy(nameCopy, aFullName);
+
+ if (mFullName != nullptr)
+ {
+ Instance::HeapFree(mFullName);
+ }
+ mFullName = nameCopy;
+
+exit:
+ return error;
+}
+
+void Server::Host::SetKey(Dns::Ecdsa256KeyRecord &aKey)
+{
+ OT_ASSERT(aKey.IsValid());
+
+ mKey = aKey;
+}
+
+void Server::Host::SetLease(uint32_t aLease)
+{
+ mLease = aLease;
+}
+
+void Server::Host::SetKeyLease(uint32_t aKeyLease)
+{
+ mKeyLease = aKeyLease;
+}
+
+TimeMilli Server::Host::GetExpireTime(void) const
+{
+ OT_ASSERT(!IsDeleted());
+
+ return mTimeLastUpdate + Time::SecToMsec(mLease);
+}
+
+TimeMilli Server::Host::GetKeyExpireTime(void) const
+{
+ return mTimeLastUpdate + Time::SecToMsec(mKeyLease);
+}
+
+// Add a new service entry to the host, do nothing if there is already
+// such services with the same name.
+Server::Service *Server::Host::AddService(const char *aFullName)
+{
+ Service *service = FindService(aFullName);
+
+ VerifyOrExit(service == nullptr);
+
+ service = Service::New(aFullName);
+ if (service != nullptr)
+ {
+ IgnoreError(mServices.Add(*service));
+ service->mHost = this;
+ }
+
+exit:
+ return service;
+}
+
+void Server::Host::RemoveService(Service *aService, bool aRetainName, bool aNotifyServiceHandler)
+{
+ const Server &server = Get<Server>();
+
+ VerifyOrExit(aService != nullptr);
+
+ aService->mIsDeleted = true;
+
+ if (aRetainName)
+ {
+ aService->ClearResources();
+ otLogInfoSrp("[server] remove service '%s' (but retain its name)", aService->mFullName);
+ }
+ else
+ {
+ otLogInfoSrp("[server] fully remove service '%s'", aService->mFullName);
+ }
+
+ IgnoreError(mServices.Remove(*aService));
+
+ if (aNotifyServiceHandler && server.mServiceUpdateHandler != nullptr)
+ {
+ LinkedList<Service> remainingServices = mServices;
+
+ mServices.Clear();
+ IgnoreError(mServices.Add(*aService));
+
+ server.mServiceUpdateHandler(this, kDefaultEventsHandlerTimeout, server.mServiceUpdateHandlerContext);
+ // We don't wait for the reply from the service update handler,
+ // but always remove the service regardless of service update result.
+ // Because removing a service should fail only when there is system
+ // failure of the platform mDNS implementation and in which case the
+ // service is not expected to be still registered.
+
+ mServices = remainingServices;
+ }
+
+ if (aRetainName)
+ {
+ IgnoreError(mServices.Add(*aService));
+ }
+ else
+ {
+ aService->Free();
+ }
+
+exit:
+ return;
+}
+
+void Server::Host::FreeAllServices(void)
+{
+ while (!mServices.IsEmpty())
+ {
+ RemoveService(mServices.GetHead(), /* aRetainName */ false, /* aNotifyServiceHandler */ false);
+ }
+}
+
+void Server::Host::ClearResources(void)
+{
+ mAddressesNum = 0;
+}
+
+void Server::Host::CopyResourcesFrom(const Host &aHost)
+{
+ memcpy(mAddresses, aHost.mAddresses, aHost.mAddressesNum * sizeof(mAddresses[0]));
+ mAddressesNum = aHost.mAddressesNum;
+ mKey = aHost.mKey;
+ mLease = aHost.mLease;
+ mKeyLease = aHost.mKeyLease;
+
+ mTimeLastUpdate = TimerMilli::GetNow();
+}
+
+Server::Service *Server::Host::FindService(const char *aFullName)
+{
+ return mServices.FindMatching(aFullName);
+}
+
+const Server::Service *Server::Host::FindService(const char *aFullName) const
+{
+ return const_cast<Host *>(this)->FindService(aFullName);
+}
+
+Error Server::Host::AddIp6Address(const Ip6::Address &aIp6Address)
+{
+ Error error = kErrorNone;
+
+ if (aIp6Address.IsMulticast() || aIp6Address.IsUnspecified() || aIp6Address.IsLoopback())
+ {
+ // We don't like those address because they cannot be used
+ // for communication with exterior devices.
+ ExitNow(error = kErrorDrop);
+ }
+
+ for (const Ip6::Address &addr : mAddresses)
+ {
+ if (aIp6Address == addr)
+ {
+ // Drop duplicate addresses.
+ ExitNow(error = kErrorDrop);
+ }
+ }
+
+ if (mAddressesNum >= kMaxAddressesNum)
+ {
+ otLogWarnSrp("[server] too many addresses for host %s", GetFullName());
+ ExitNow(error = kErrorNoBufs);
+ }
+
+ mAddresses[mAddressesNum++] = aIp6Address;
+
+exit:
+ return error;
+}
+
+bool Server::Host::Matches(const char *aName) const
+{
+ return mFullName != nullptr && strcmp(mFullName, aName) == 0;
+}
+
+Server::UpdateMetadata *Server::UpdateMetadata::New(Instance & aInstance,
+ const Dns::UpdateHeader &aHeader,
+ Host * aHost,
+ const Ip6::MessageInfo & aMessageInfo)
+{
+ void * buf;
+ UpdateMetadata *update = nullptr;
+
+ buf = aInstance.HeapCAlloc(1, sizeof(UpdateMetadata));
+ VerifyOrExit(buf != nullptr);
+
+ update = new (buf) UpdateMetadata(aInstance, aHeader, aHost, aMessageInfo);
+
+exit:
+ return update;
+}
+
+void Server::UpdateMetadata::Free(void)
+{
+ Instance::HeapFree(this);
+}
+
+Server::UpdateMetadata::UpdateMetadata(Instance & aInstance,
+ const Dns::UpdateHeader &aHeader,
+ Host * aHost,
+ const Ip6::MessageInfo & aMessageInfo)
+ : InstanceLocator(aInstance)
+ , mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
+ , mDnsHeader(aHeader)
+ , mHost(aHost)
+ , mMessageInfo(aMessageInfo)
+ , mNext(nullptr)
+{
+}
+
+} // namespace Srp
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
diff --git a/src/core/net/srp_server.hpp b/src/core/net/srp_server.hpp
new file mode 100644
index 0000000..6efb04d
--- /dev/null
+++ b/src/core/net/srp_server.hpp
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions for SRP server.
+ */
+
+#ifndef NET_SRP_SERVER_HPP_
+#define NET_SRP_SERVER_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+
+#if !OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+#error "OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
+#endif
+
+#if !OPENTHREAD_CONFIG_ECDSA_ENABLE
+#error "OPENTHREAD_CONFIG_ECDSA_ENABLE is required for OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
+#endif
+
+#include <openthread/ip6.h>
+#include <openthread/srp_server.h>
+
+#include "common/clearable.hpp"
+#include "common/linked_list.hpp"
+#include "common/locator.hpp"
+#include "common/non_copyable.hpp"
+#include "common/notifier.hpp"
+#include "common/timer.hpp"
+#include "crypto/ecdsa.hpp"
+#include "net/dns_types.hpp"
+#include "net/ip6.hpp"
+#include "net/ip6_address.hpp"
+#include "net/udp6.hpp"
+
+namespace ot {
+namespace Srp {
+
+/**
+ * This class implements the SRP server.
+ *
+ */
+class Server : public InstanceLocator, private NonCopyable
+{
+ friend class ot::Notifier;
+
+public:
+ enum : uint16_t
+ {
+ kUdpPort = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT, ///< The SRP Server UDP listening port.
+ };
+
+ class Host;
+ class Service;
+
+ /**
+ * This class implements a server-side SRP service.
+ *
+ */
+ class Service : public LinkedListEntry<Service>, private NonCopyable
+ {
+ friend class LinkedListEntry<Service>;
+ friend class Server;
+
+ public:
+ /**
+ * This method creates a new Service object with given full name.
+ *
+ * @param[in] aFullName The full name of the service instance.
+ *
+ * @returns A pointer to the newly created Service object, nullptr if
+ * cannot allocate memory for the object.
+ *
+ */
+ static Service *New(const char *aFullName);
+
+ /**
+ * This method frees the Service object.
+ *
+ */
+ void Free(void);
+
+ /**
+ * This method tells if the SRP service has been deleted.
+ *
+ * A SRP service can be deleted but retains its name for future uses.
+ * In this case, the service instance is not removed from the SRP server/registry.
+ * It is guaranteed that all services are deleted if the host is deleted.
+ *
+ * @returns TRUE if the service has been deleted, FALSE if not.
+ *
+ */
+ bool IsDeleted(void) const { return mIsDeleted; }
+
+ /**
+ * This method returns the full name of the service.
+ *
+ * @returns A pointer to the null-terminated service name string.
+ *
+ */
+ const char *GetFullName(void) const { return mFullName; }
+
+ /**
+ * This method returns the port of the service instance.
+ *
+ * @returns The port of the service.
+ *
+ */
+ uint16_t GetPort(void) const { return mPort; }
+
+ /**
+ * This method returns the weight of the service instance.
+ *
+ * @returns The weight of the service.
+ *
+ */
+ uint16_t GetWeight(void) const { return mWeight; }
+
+ /**
+ * This method returns the priority of the service instance.
+ *
+ * @param[in] aService A pointer to the SRP service.
+ *
+ * @returns The priority of the service.
+ *
+ */
+ uint16_t GetPriority(void) const { return mPriority; }
+
+ /**
+ * This method returns the TXT record data of the service instance.
+ *
+ * @returns A pointer to the buffer containing the TXT record data.
+ *
+ */
+ const uint8_t *GetTxtData(void) const { return mTxtData; }
+
+ /**
+ * This method returns the TXT recored data length of the service instance.
+ *
+ * @return The TXT record data length (number of bytes in buffer returned from `GetTxtData()`).
+ *
+ */
+ uint16_t GetTxtDataLength(void) const { return mTxtLength; }
+
+ /**
+ * This method returns the host which the service instance reside on.
+ *
+ * @returns A reference to the host instance.
+ *
+ */
+ const Host &GetHost(void) const { return *static_cast<const Host *>(mHost); }
+
+ /**
+ * This method returns the expire time (in milliseconds) of the service.
+ *
+ * @returns The service expire time in milliseconds.
+ *
+ */
+ TimeMilli GetExpireTime(void) const;
+
+ /**
+ * This method returns the key expire time (in milliseconds) of the service.
+ *
+ * @returns The service key expire time in milliseconds.
+ *
+ */
+ TimeMilli GetKeyExpireTime(void) const;
+
+ /**
+ * This method tells whether this service matches a given full name.
+ *
+ * @param[in] aFullName The full name.
+ *
+ * @returns TRUE if the servce matches the full name, FALSE if doesn't match.
+ *
+ */
+ bool Matches(const char *aFullName) const;
+
+ /**
+ * This method tells whether this service matches a given service name <Service>.<Domain>.
+ *
+ * @param[in] aServiceName The full service name to match.
+ *
+ * @retval TRUE If the service matches the full service name.
+ * @retval FALSE If the service does not match the full service name.
+ *
+ */
+ bool MatchesServiceName(const char *aServiceName) const;
+
+ private:
+ explicit Service(void);
+ Error SetFullName(const char *aFullName);
+ Error SetTxtData(const uint8_t *aTxtData, uint16_t aTxtDataLength);
+ Error SetTxtDataFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
+ Error CopyResourcesFrom(const Service &aService);
+ void ClearResources(void);
+
+ char * mFullName;
+ uint16_t mPriority;
+ uint16_t mWeight;
+ uint16_t mPort;
+ uint16_t mTxtLength;
+ uint8_t * mTxtData;
+ otSrpServerHost *mHost;
+ Service * mNext;
+ TimeMilli mTimeLastUpdate;
+ bool mIsDeleted;
+ };
+
+ /**
+ * This class implements the Host which registers services on the SRP server.
+ *
+ */
+ class Host : public LinkedListEntry<Host>, public InstanceLocator, private NonCopyable
+ {
+ friend class LinkedListEntry<Host>;
+ friend class Server;
+
+ public:
+ /**
+ * This method creates a new Host object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ * @returns A pointer to the newly created Host object, nullptr if
+ * cannot allocate memory for the object.
+ *
+ */
+ static Host *New(Instance &aInstance);
+
+ /**
+ * This method Frees the Host object.
+ *
+ */
+ void Free(void);
+
+ /**
+ * This method tells whether the Host object has been deleted.
+ *
+ * The Host object retains event if the host has been deleted by the SRP client,
+ * because the host name may retain.
+ *
+ * @returns TRUE if the host is deleted, FALSE if the host is not deleted.
+ *
+ */
+ bool IsDeleted(void) const { return (mLease == 0); }
+
+ /**
+ * This method returns the full name of the host.
+ *
+ * @returns A pointer to the null-terminated full host name.
+ *
+ */
+ const char *GetFullName(void) const { return mFullName; }
+
+ /**
+ * This method returns adrersses of the host.
+ *
+ * @param[out] aAddressesNum The number of the addresses.
+ *
+ * @returns A pointer to the addresses array.
+ *
+ */
+ const Ip6::Address *GetAddresses(uint8_t &aAddressesNum) const
+ {
+ aAddressesNum = mAddressesNum;
+ return mAddresses;
+ }
+
+ /**
+ * This method returns the LEASE time of the host.
+ *
+ * @returns The LEASE time in seconds.
+ *
+ */
+ uint32_t GetLease(void) const { return mLease; }
+
+ /**
+ * This method returns the KEY-LEASE time of the key of the host.
+ *
+ * @returns The KEY-LEASE time in seconds.
+ *
+ */
+ uint32_t GetKeyLease(void) const { return mKeyLease; }
+
+ /**
+ * This method returns the KEY resource of the host.
+ *
+ * @returns A pointer to the ECDSA P 256 public key if there is valid one.
+ * nullptr if no valid key exists.
+ *
+ */
+ const Dns::Ecdsa256KeyRecord *GetKey(void) const { return mKey.IsValid() ? &mKey : nullptr; }
+
+ /**
+ * This method returns the expire time (in milliseconds) of the host.
+ *
+ * @returns The expire time in milliseconds.
+ *
+ */
+ TimeMilli GetExpireTime(void) const;
+
+ /**
+ * This method returns the expire time (in milliseconds) of the key of the host.
+ *
+ * @returns The expire time of the key in milliseconds.
+ *
+ */
+ TimeMilli GetKeyExpireTime(void) const;
+
+ /**
+ * This method returns the next service of the host.
+ *
+ * @param[in] aService A pointer to current service.
+ *
+ * @returns A pointer to the next service or NULL if no more services exist.
+ *
+ */
+ const Service *GetNextService(const Service *aService) const
+ {
+ return aService ? aService->GetNext() : mServices.GetHead();
+ }
+
+ /**
+ * This method tells whether the host matches a given full name.
+ *
+ * @param[in] aFullName The full name.
+ *
+ * @returns A boolean that indicates whether the host matches the given name.
+ *
+ */
+ bool Matches(const char *aName) const;
+
+ private:
+ enum : uint8_t
+ {
+ kMaxAddressesNum = OPENTHREAD_CONFIG_SRP_SERVER_MAX_ADDRESSES_NUM,
+ };
+
+ explicit Host(Instance &aInstance);
+ Error SetFullName(const char *aFullName);
+ void SetKey(Dns::Ecdsa256KeyRecord &aKey);
+ void SetLease(uint32_t aLease);
+ void SetKeyLease(uint32_t aKeyLease);
+ Service *GetNextService(Service *aService) { return aService ? aService->GetNext() : mServices.GetHead(); }
+ Service *AddService(const char *aFullName);
+ void RemoveService(Service *aService, bool aRetainName, bool aNotifyServiceHandler);
+ void FreeAllServices(void);
+ void ClearResources(void);
+ void CopyResourcesFrom(const Host &aHost);
+ Service *FindService(const char *aFullName);
+ const Service *FindService(const char *aFullName) const;
+ Error AddIp6Address(const Ip6::Address &aIp6Address);
+
+ char * mFullName;
+ Ip6::Address mAddresses[kMaxAddressesNum];
+ uint8_t mAddressesNum;
+ Host * mNext;
+
+ Dns::Ecdsa256KeyRecord mKey;
+ uint32_t mLease; // The LEASE time in seconds.
+ uint32_t mKeyLease; // The KEY-LEASE time in seconds.
+ TimeMilli mTimeLastUpdate;
+ LinkedList<Service> mServices;
+ };
+
+ /**
+ * This constructor initializes the SRP server object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ */
+ explicit Server(Instance &aInstance);
+ ~Server(void);
+
+ /**
+ * This method sets the SRP service events handler.
+ *
+ * @param[in] aServiceHandler A service events handler.
+ * @param[in] aServiceHandlerContext A pointer to arbitrary context information.
+ *
+ * @note The handler SHOULD call HandleServiceUpdateResult to report the result of its processing.
+ * Otherwise, a SRP update will be considered failed.
+ *
+ * @sa HandleServiceUpdateResult
+ *
+ */
+ void SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler, void *aServiceHandlerContext);
+
+ /**
+ * This method returns the domain authorized to the SRP server.
+ *
+ * If the domain if not set by SetDomain, "default.service.arpa." will be returned.
+ * A trailing dot is always appended even if the domain is set without it.
+ *
+ * @returns A pointer to the dot-joined domain string.
+ *
+ */
+ const char *GetDomain(void) const;
+
+ /**
+ * This method sets the domain on the SRP server.
+ *
+ * A trailing dot will be appended to @p aDomain if it is not already there.
+ * This method should only be called before the SRP server is enabled.
+ *
+ * @param[in] aDomain The domain to be set. MUST NOT be nullptr.
+ *
+ * @retval kErrorNone Successfully set the domain to @p aDomain.
+ * @retval kErrorInvalidState The SRP server is already enabled and the Domain cannot be changed.
+ * @retval kErrorInvalidArgs The argument @p aDomain is not a valid DNS domain name.
+ * @retval kErrorNoBufs There is no memory to store content of @p aDomain.
+ *
+ */
+ Error SetDomain(const char *aDomain);
+
+ /**
+ * This method tells whether the SRP server is currently running.
+ *
+ * @returns A boolean that indicates whether the server is running.
+ *
+ */
+ bool IsRunning(void) const;
+
+ /**
+ * This method enables/disables the SRP server.
+ *
+ * @param[in] aEnabled A boolean to enable/disable the SRP server.
+ *
+ */
+ void SetEnabled(bool aEnabled);
+
+ /**
+ * This method sets LEASE & KEY-LEASE range that is acceptable by the SRP server.
+ *
+ * When a LEASE time is requested from a client, the granted value will be
+ * limited in range [aMinLease, aMaxLease]; and a KEY-LEASE will be granted
+ * in range [aMinKeyLease, aMaxKeyLease].
+ *
+ * @param[in] aMinLease The minimum LEASE interval in seconds.
+ * @param[in] aMaxLease The maximum LEASE interval in seconds.
+ * @param[in] aMinKeyLease The minimum KEY-LEASE interval in seconds.
+ * @param[in] aMaxKeyLease The maximum KEY-LEASE interval in seconds.
+ *
+ * @retval kErrorNone Successfully set the LEASE and KEY-LEASE ranges.
+ * @retval kErrorInvalidArgs The LEASE or KEY-LEASE range is not valid.
+ *
+ */
+ Error SetLeaseRange(uint32_t aMinLease, uint32_t aMaxLease, uint32_t aMinKeyLease, uint32_t aMaxKeyLease);
+
+ /**
+ * This method returns the next registered SRP host.
+ *
+ * @param[in] aHost The current SRP host; use nullptr to get the first SRP host.
+ *
+ * @returns A pointer to the next SRP host or nullptr if no more SRP hosts can be found.
+ *
+ */
+ const Host *GetNextHost(const Host *aHost);
+
+ /**
+ * This method receives the service update result from service handler set by
+ * SetServiceHandler.
+ *
+ * @param[in] aHost A pointer to the Host object which contains the SRP service updates.
+ * @param[in] aError The service update result.
+ *
+ */
+ void HandleServiceUpdateResult(const Host *aHost, Error aError);
+
+private:
+ enum : uint16_t
+ {
+ kUdpPayloadSize = Ip6::Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header), // Max UDP payload size
+ };
+
+ enum : uint32_t
+ {
+ kDefaultMinLease = 60u * 30, // Default minimum lease time, 30 min (in seconds).
+ kDefaultMaxLease = 3600u * 2, // Default maximum lease time, 2 hours (in seconds).
+ kDefaultMinKeyLease = 3600u * 24, // Default minimum key-lease time, 1 day (in seconds).
+ kDefaultMaxKeyLease = 3600u * 24 * 14, // Default maximum key-lease time, 14 days (in seconds).
+ kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT,
+ };
+
+ /**
+ * This class includes metadata for processing a SRP update (register, deregister)
+ * and sending DNS response to the client.
+ *
+ */
+ class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
+ {
+ friend class LinkedListEntry<UpdateMetadata>;
+
+ public:
+ static UpdateMetadata * New(Instance & aInstance,
+ const Dns::UpdateHeader &aHeader,
+ Host * aHost,
+ const Ip6::MessageInfo & aMessageInfo);
+ void Free(void);
+ TimeMilli GetExpireTime(void) const { return mExpireTime; }
+ const Dns::UpdateHeader &GetDnsHeader(void) const { return mDnsHeader; }
+ Host & GetHost(void) { return *mHost; }
+ const Ip6::MessageInfo & GetMessageInfo(void) const { return mMessageInfo; }
+ bool Matches(const Host *aHost) const { return mHost == aHost; }
+
+ private:
+ UpdateMetadata(Instance & aInstance,
+ const Dns::UpdateHeader &aHeader,
+ Host * aHost,
+ const Ip6::MessageInfo & aMessageInfo);
+
+ TimeMilli mExpireTime;
+ Dns::UpdateHeader mDnsHeader;
+ Host * mHost; // The host will be updated. The UpdateMetadata has no ownership of this host.
+ Ip6::MessageInfo mMessageInfo; // The message info of the DNS update request.
+ UpdateMetadata * mNext;
+ };
+
+ void Start(void);
+ void Stop(void);
+ void HandleNotifierEvents(Events aEvents);
+ Error PublishServerData(void);
+ void UnpublishServerData(void);
+ uint32_t GrantLease(uint32_t aLease) const;
+ uint32_t GrantKeyLease(uint32_t aKeyLease) const;
+
+ void CommitSrpUpdate(Error aError,
+ const Dns::UpdateHeader &aDnsHeader,
+ Host & aHost,
+ const Ip6::MessageInfo & aMessageInfo);
+ void HandleDnsUpdate(Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t aOffset);
+ Error ProcessUpdateSection(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t & aOffset) const;
+ Error ProcessAdditionalSection(Host * aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t & aOffset) const;
+ Error VerifySignature(const Dns::Ecdsa256KeyRecord &aKey,
+ const Message & aMessage,
+ Dns::UpdateHeader aDnsHeader,
+ uint16_t aSigOffset,
+ uint16_t aSigRdataOffset,
+ uint16_t aSigRdataLength,
+ const char * aSignerName) const;
+ Error ProcessZoneSection(const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ uint16_t & aOffset,
+ Dns::Zone & aZone) const;
+ Error ProcessHostDescriptionInstruction(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t aOffset) const;
+ Error ProcessServiceDiscoveryInstructions(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t aOffset) const;
+ Error ProcessServiceDescriptionInstructions(Host & aHost,
+ const Message & aMessage,
+ const Dns::UpdateHeader &aDnsHeader,
+ const Dns::Zone & aZone,
+ uint16_t & aOffset) const;
+
+ static bool IsValidDeleteAllRecord(const Dns::ResourceRecord &aRecord);
+ const Service *FindService(const char *aFullName) const;
+
+ void HandleUpdate(const Dns::UpdateHeader &aDnsHeader, Host *aHost, const Ip6::MessageInfo &aMessageInfo);
+ void AddHost(Host *aHost);
+ void RemoveHost(Host *aHost, bool aRetainName, bool aNotifyServiceHandler);
+ bool HasNameConflictsWith(Host &aHost) const;
+ void SendResponse(const Dns::UpdateHeader & aHeader,
+ Dns::UpdateHeader::Response aResponseCode,
+ const Ip6::MessageInfo & aMessageInfo);
+ void SendResponse(const Dns::UpdateHeader &aHeader,
+ uint32_t aLease,
+ uint32_t aKeyLease,
+ const Ip6::MessageInfo & aMessageInfo);
+ static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
+ void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static void HandleLeaseTimer(Timer &aTimer);
+ void HandleLeaseTimer(void);
+ static void HandleOutstandingUpdatesTimer(Timer &aTimer);
+ void HandleOutstandingUpdatesTimer(void);
+
+ void HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
+ const UpdateMetadata *FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo, uint16_t aDnsMessageId);
+
+ Ip6::Udp::Socket mSocket;
+ otSrpServerServiceUpdateHandler mServiceUpdateHandler;
+ void * mServiceUpdateHandlerContext;
+
+ char *mDomain;
+
+ uint32_t mMinLease; // The minimum lease time in seconds.
+ uint32_t mMaxLease; // The maximum lease time in seconds.
+ uint32_t mMinKeyLease; // The minimum key-lease time in seconds.
+ uint32_t mMaxKeyLease; // The maximum key-lease time in seconds.
+
+ LinkedList<Host> mHosts;
+ TimerMilli mLeaseTimer;
+
+ TimerMilli mOutstandingUpdatesTimer;
+ LinkedList<UpdateMetadata> mOutstandingUpdates;
+
+ bool mEnabled;
+};
+
+} // namespace Srp
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+#endif // NET_SRP_SERVER_HPP_
diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp
index af2f962..a015041 100644
--- a/src/core/net/udp6.cpp
+++ b/src/core/net/udp6.cpp
@@ -82,70 +82,50 @@
return Get<Udp>().NewMessage(aReserved, aSettings);
}
-otError Udp::Socket::Open(otUdpReceive aHandler, void *aContext)
+Error Udp::Socket::Open(otUdpReceive aHandler, void *aContext)
{
return Get<Udp>().Open(*this, aHandler, aContext);
}
-otError Udp::Socket::Bind(const SockAddr &aSockAddr)
+Error Udp::Socket::Bind(const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier)
{
- return Get<Udp>().Bind(*this, aSockAddr);
+ return Get<Udp>().Bind(*this, aSockAddr, aNetifIdentifier);
}
-otError Udp::Socket::Bind(uint16_t aPort)
+Error Udp::Socket::Bind(uint16_t aPort, otNetifIdentifier aNetifIdentifier)
{
- return Bind(SockAddr(aPort));
+ return Bind(SockAddr(aPort), aNetifIdentifier);
}
-otError Udp::Socket::BindToNetif(otNetifIdentifier aNetifIdentifier)
-{
- OT_UNUSED_VARIABLE(aNetifIdentifier);
-
- otError error = OT_ERROR_NONE;
-
-#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
- SuccessOrExit(error = otPlatUdpBindToNetif(this, aNetifIdentifier));
-#endif
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- Get<Udp>().BindToNetif(*this, aNetifIdentifier);
-#endif
-
-#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
-exit:
-#endif
- return error;
-}
-
-otError Udp::Socket::Connect(const SockAddr &aSockAddr)
+Error Udp::Socket::Connect(const SockAddr &aSockAddr)
{
return Get<Udp>().Connect(*this, aSockAddr);
}
-otError Udp::Socket::Connect(uint16_t aPort)
+Error Udp::Socket::Connect(uint16_t aPort)
{
return Connect(SockAddr(aPort));
}
-otError Udp::Socket::Close(void)
+Error Udp::Socket::Close(void)
{
return Get<Udp>().Close(*this);
}
-otError Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
+Error Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
{
return Get<Udp>().SendTo(*this, aMessage, aMessageInfo);
}
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-otError Udp::Socket::JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
+Error Udp::Socket::JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
{
OT_UNUSED_VARIABLE(aNetifIdentifier);
OT_UNUSED_VARIABLE(aAddress);
- otError error = OT_ERROR_NOT_IMPLEMENTED;
+ Error error = kErrorNotImplemented;
- VerifyOrExit(aAddress.IsMulticast(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpJoinMulticastGroup(this, aNetifIdentifier, &aAddress);
@@ -155,14 +135,14 @@
return error;
}
-otError Udp::Socket::LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
+Error Udp::Socket::LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress)
{
OT_UNUSED_VARIABLE(aNetifIdentifier);
OT_UNUSED_VARIABLE(aAddress);
- otError error = OT_ERROR_NOT_IMPLEMENTED;
+ Error error = kErrorNotImplemented;
- VerifyOrExit(aAddress.IsMulticast(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aAddress.IsMulticast(), error = kErrorInvalidArgs);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpLeaveMulticastGroup(this, aNetifIdentifier, &aAddress);
@@ -186,14 +166,14 @@
{
}
-otError Udp::AddReceiver(Receiver &aReceiver)
+Error Udp::AddReceiver(Receiver &aReceiver)
{
return mReceivers.Add(aReceiver);
}
-otError Udp::RemoveReceiver(Receiver &aReceiver)
+Error Udp::RemoveReceiver(Receiver &aReceiver)
{
- otError error;
+ Error error;
SuccessOrExit(error = mReceivers.Remove(aReceiver));
aReceiver.SetNext(nullptr);
@@ -202,9 +182,9 @@
return error;
}
-otError Udp::Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext)
+Error Udp::Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
aSocket.GetSockName().Clear();
aSocket.GetPeerName().Clear();
@@ -222,12 +202,25 @@
return error;
}
-otError Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr)
+Error Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier)
{
- otError error = OT_ERROR_NONE;
+ OT_UNUSED_VARIABLE(aNetifIdentifier);
+
+ Error error = kErrorNone;
+
+#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
+ SuccessOrExit(error = otPlatUdpBindToNetif(&aSocket, aNetifIdentifier));
+#endif
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+ if (aNetifIdentifier == OT_NETIF_BACKBONE)
+ {
+ SetBackboneSocket(aSocket);
+ }
+#endif
VerifyOrExit(aSockAddr.GetAddress().IsUnspecified() || Get<ThreadNetif>().HasUnicastAddress(aSockAddr.GetAddress()),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
aSocket.mSockName = aSockAddr;
@@ -239,7 +232,7 @@
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpBind(&aSocket);
#endif
- } while (error != OT_ERROR_NONE);
+ } while (error != kErrorNone);
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
else if (ShouldUsePlatformUdp(aSocket))
@@ -253,14 +246,6 @@
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-void Udp::BindToNetif(SocketHandle &aSocket, otNetifIdentifier aNetifIdentifier)
-{
- if (aNetifIdentifier == OT_NETIF_BACKBONE)
- {
- SetBackboneSocket(aSocket);
- }
-}
-
void Udp::SetBackboneSocket(SocketHandle &aSocket)
{
RemoveSocket(aSocket);
@@ -297,15 +282,15 @@
}
#endif
-otError Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
+Error Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
aSocket.mPeerName = aSockAddr;
if (!aSocket.IsBound())
{
- SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName()));
+ SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName(), OT_NETIF_THREAD));
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
@@ -319,9 +304,9 @@
return error;
}
-otError Udp::Close(SocketHandle &aSocket)
+Error Udp::Close(SocketHandle &aSocket)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpClose(&aSocket);
@@ -336,26 +321,26 @@
return error;
}
-otError Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo)
+Error Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MessageInfo messageInfoLocal;
VerifyOrExit((aMessageInfo.GetSockPort() == 0) || (aSocket.GetSockName().mPort == aMessageInfo.GetSockPort()),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
messageInfoLocal = aMessageInfo;
if (messageInfoLocal.GetPeerAddr().IsUnspecified())
{
- VerifyOrExit(!aSocket.GetPeerName().GetAddress().IsUnspecified(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aSocket.GetPeerName().GetAddress().IsUnspecified(), error = kErrorInvalidArgs);
messageInfoLocal.SetPeerAddr(aSocket.GetPeerName().GetAddress());
}
if (messageInfoLocal.mPeerPort == 0)
{
- VerifyOrExit(aSocket.GetPeerName().mPort != 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aSocket.GetPeerName().mPort != 0, error = kErrorInvalidArgs);
messageInfoLocal.mPeerPort = aSocket.GetPeerName().mPort;
}
@@ -366,7 +351,7 @@
if (!aSocket.IsBound())
{
- SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName()));
+ SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName(), OT_NETIF_THREAD));
}
messageInfoLocal.SetSockPort(aSocket.GetSockName().mPort);
@@ -374,15 +359,6 @@
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (ShouldUsePlatformUdp(aSocket))
{
- // Replace anycast address with a valid unicast address since response messages typically copy the peer address
- if (Get<Mle::Mle>().IsAnycastLocator(messageInfoLocal.GetSockAddr()))
- {
- const NetifUnicastAddress *netifAddr = Get<Ip6>().SelectSourceAddress(messageInfoLocal);
-
- VerifyOrExit(netifAddr != nullptr, error = OT_ERROR_INVALID_ARGS);
- messageInfoLocal.SetSockAddr(netifAddr->GetAddress());
- }
-
SuccessOrExit(error = otPlatUdpSend(&aSocket, &aMessage, &messageInfoLocal));
}
else
@@ -450,14 +426,14 @@
return Get<Ip6>().NewMessage(sizeof(Header) + aReserved, aSettings);
}
-otError Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
+Error Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
if (aMessageInfo.IsHostInterface())
{
- VerifyOrExit(mUdpForwarder != nullptr, error = OT_ERROR_NO_ROUTE);
+ VerifyOrExit(mUdpForwarder != nullptr, error = kErrorNoRoute);
mUdpForwarder(&aMessage, aMessageInfo.mPeerPort, &aMessageInfo.GetPeerAddr(), aMessageInfo.mSockPort,
mUdpForwarderContext);
// message is consumed by the callback
@@ -482,10 +458,10 @@
return error;
}
-otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
+Error Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
- Header udpHeader;
+ Error error = kErrorNone;
+ Header udpHeader;
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader));
@@ -548,7 +524,6 @@
return;
}
-#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
bool Udp::ShouldUsePlatformUdp(uint16_t aPort) const
{
return (aPort != Mle::kUdpPort && aPort != Tmf::kUdpPort
@@ -558,6 +533,7 @@
);
}
+#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
bool Udp::ShouldUsePlatformUdp(const Udp::SocketHandle &aSocket) const
{
return (ShouldUsePlatformUdp(aSocket.mSockName.mPort)
@@ -566,7 +542,7 @@
#endif
);
}
-#endif
+#endif // OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
} // namespace Ip6
} // namespace ot
diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp
index cd201ae..1992cb4 100644
--- a/src/core/net/udp6.hpp
+++ b/src/core/net/udp6.hpp
@@ -60,6 +60,10 @@
*
*/
+#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE && OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
+#error "OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE and OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE must not both be set."
+#endif
+
/**
* This class implements core UDP message handling.
*
@@ -161,94 +165,85 @@
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully opened the socket.
- * @retval OT_ERROR_FAILED Failed to open the socket.
+ * @retval kErrorNone Successfully opened the socket.
+ * @retval kErrorFailed Failed to open the socket.
*
*/
- otError Open(otUdpReceive aHandler, void *aContext);
+ Error Open(otUdpReceive aHandler, void *aContext);
/**
* This method binds the UDP socket.
*
- * @param[in] aSockAddr A reference to the socket address.
- *
- * @retval OT_ERROR_NONE Successfully bound the socket.
- * @retval OT_ERROR_INVALID_ARGS Unable to bind to Thread network interface with the given address.
- * @retval OT_ERROR_FAILED Failed to bind UDP Socket.
- *
- */
- otError Bind(const SockAddr &aSockAddr);
-
- /**
- * This method binds the UDP socket to a specified network interface.
- *
+ * @param[in] aSockAddr A reference to the socket address.
* @param[in] aNetifIdentifier The network interface identifier.
*
- * @retval OT_ERROR_NONE Successfully bound to the network interface.
- * @retval OT_ERROR_FAILED Failed to bind to the network interface.
+ * @retval kErrorNone Successfully bound the socket.
+ * @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address.
+ * @retval kErrorFailed Failed to bind UDP Socket.
*
*/
- otError BindToNetif(otNetifIdentifier aNetifIdentifier);
+ Error Bind(const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier = OT_NETIF_THREAD);
/**
* This method binds the UDP socket.
*
- * @param[in] aPort A port number.
+ * @param[in] aPort A port number.
+ * @param[in] aNetifIdentifier The network interface identifier.
*
- * @retval OT_ERROR_NONE Successfully bound the socket.
- * @retval OT_ERROR_FAILED Failed to bind UDP Socket.
+ * @retval kErrorNone Successfully bound the socket.
+ * @retval kErrorFailed Failed to bind UDP Socket.
*
*/
- otError Bind(uint16_t aPort);
+ Error Bind(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_THREAD);
/**
* This method binds the UDP socket.
*
- * @retval OT_ERROR_NONE Successfully bound the socket.
- * @retval OT_ERROR_FAILED Failed to bind UDP Socket.
+ * @retval kErrorNone Successfully bound the socket.
+ * @retval kErrorFailed Failed to bind UDP Socket.
*
*/
- otError Bind(void) { return Bind(0); }
+ Error Bind(void) { return Bind(0); }
/**
* This method connects the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
- * @retval OT_ERROR_NONE Successfully connected the socket.
- * @retval OT_ERROR_FAILED Failed to connect UDP Socket.
+ * @retval kErrorNone Successfully connected the socket.
+ * @retval kErrorFailed Failed to connect UDP Socket.
*
*/
- otError Connect(const SockAddr &aSockAddr);
+ Error Connect(const SockAddr &aSockAddr);
/**
* This method connects the UDP socket.
*
* @param[in] aPort A port number.
*
- * @retval OT_ERROR_NONE Successfully connected the socket.
- * @retval OT_ERROR_FAILED Failed to connect UDP Socket.
+ * @retval kErrorNone Successfully connected the socket.
+ * @retval kErrorFailed Failed to connect UDP Socket.
*
*/
- otError Connect(uint16_t aPort);
+ Error Connect(uint16_t aPort);
/**
* This method connects the UDP socket.
*
- * @retval OT_ERROR_NONE Successfully connected the socket.
- * @retval OT_ERROR_FAILED Failed to connect UDP Socket.
+ * @retval kErrorNone Successfully connected the socket.
+ * @retval kErrorFailed Failed to connect UDP Socket.
*
*/
- otError Connect(void) { return Connect(0); }
+ Error Connect(void) { return Connect(0); }
/**
* This method closes the UDP socket.
*
- * @retval OT_ERROR_NONE Successfully closed the UDP socket.
- * @retval OT_ERROR_FAILED Failed to close UDP Socket.
+ * @retval kErrorNone Successfully closed the UDP socket.
+ * @retval kErrorFailed Failed to close UDP Socket.
*
*/
- otError Close(void);
+ Error Close(void);
/**
* This method sends a UDP message.
@@ -256,12 +251,12 @@
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
- * @retval OT_ERROR_NONE Successfully sent the UDP message.
- * @retval OT_ERROR_INVALID_ARGS If no peer is specified in @p aMessageInfo or by Connect().
- * @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
+ * @retval kErrorNone Successfully sent the UDP message.
+ * @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect().
+ * @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
- otError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
+ Error SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
/**
@@ -270,11 +265,11 @@
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
- * @retval OT_ERROR_NONE Successfully joined the multicast group.
- * @retval OT_ERROR_FAILED Failed to join the multicast group.
+ * @retval kErrorNone Successfully joined the multicast group.
+ * @retval kErrorFailed Failed to join the multicast group.
*
*/
- otError JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
+ Error JoinNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
/**
* This method configures the UDP socket to leave a multicast group on a Host network interface.
@@ -282,11 +277,11 @@
* @param[in] aNetifIdentifier The network interface identifier.
* @param[in] aAddress The multicast group address.
*
- * @retval OT_ERROR_NONE Successfully left the multicast group.
- * @retval OT_ERROR_FAILED Failed to leave the multicast group.
+ * @retval kErrorNone Successfully left the multicast group.
+ * @retval kErrorFailed Failed to leave the multicast group.
*
*/
- otError LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
+ Error LeaveNetifMulticastGroup(otNetifIdentifier aNetifIdentifier, const Address &aAddress);
#endif
};
@@ -421,22 +416,22 @@
*
* @param[in] aReceiver A reference to the UDP receiver.
*
- * @retval OT_ERROR_NONE Successfully added the UDP receiver.
- * @retval OT_ERROR_ALREADY The UDP receiver was already added.
+ * @retval kErrorNone Successfully added the UDP receiver.
+ * @retval kErrorAlready The UDP receiver was already added.
*
*/
- otError AddReceiver(Receiver &aReceiver);
+ Error AddReceiver(Receiver &aReceiver);
/**
* This method removes a UDP receiver.
*
* @param[in] aReceiver A reference to the UDP receiver.
*
- * @retval OT_ERROR_NONE Successfully removed the UDP receiver.
- * @retval OT_ERROR_NOT_FOUND The UDP receiver was not added.
+ * @retval kErrorNone Successfully removed the UDP receiver.
+ * @retval kErrorNotFound The UDP receiver was not added.
*
*/
- otError RemoveReceiver(Receiver &aReceiver);
+ Error RemoveReceiver(Receiver &aReceiver);
/**
* This method opens a UDP socket.
@@ -445,33 +440,25 @@
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully opened the socket.
- * @retval OT_ERROR_FAILED Failed to open the socket.
+ * @retval kErrorNone Successfully opened the socket.
+ * @retval kErrorFailed Failed to open the socket.
*
*/
- otError Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext);
+ Error Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext);
/**
* This method binds a UDP socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
+ * @param[in] aNetifIdentifier The network interface identifier.
*
- * @retval OT_ERROR_NONE Successfully bound the socket.
- * @retval OT_ERROR_INVALID_ARGS Unable to bind to Thread network interface with the given address.
- * @retval OT_ERROR_FAILED Failed to bind UDP Socket.
+ * @retval kErrorNone Successfully bound the socket.
+ * @retval kErrorInvalidArgs Unable to bind to Thread network interface with the given address.
+ * @retval kErrorFailed Failed to bind UDP Socket.
*
*/
- otError Bind(SocketHandle &aSocket, const SockAddr &aSockAddr);
-
- /**
- * This method binds a UDP socket to the Network interface.
- *
- * @param[in] aSocket A reference to the socket.
- * @param[in] aNetifIdentifier The network interface identifier.
- *
- */
- void BindToNetif(SocketHandle &aSocket, otNetifIdentifier aNetifIdentifier);
+ Error Bind(SocketHandle &aSocket, const SockAddr &aSockAddr, otNetifIdentifier aNetifIdentifier);
/**
* This method connects a UDP socket.
@@ -479,22 +466,22 @@
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
*
- * @retval OT_ERROR_NONE Successfully connected the socket.
- * @retval OT_ERROR_FAILED Failed to connect UDP Socket.
+ * @retval kErrorNone Successfully connected the socket.
+ * @retval kErrorFailed Failed to connect UDP Socket.
*
*/
- otError Connect(SocketHandle &aSocket, const SockAddr &aSockAddr);
+ Error Connect(SocketHandle &aSocket, const SockAddr &aSockAddr);
/**
* This method closes the UDP socket.
*
* @param[in] aSocket A reference to the socket.
*
- * @retval OT_ERROR_NONE Successfully closed the UDP socket.
- * @retval OT_ERROR_FAILED Failed to close UDP Socket.
+ * @retval kErrorNone Successfully closed the UDP socket.
+ * @retval kErrorFailed Failed to close UDP Socket.
*
*/
- otError Close(SocketHandle &aSocket);
+ Error Close(SocketHandle &aSocket);
/**
* This method sends a UDP message using a socket.
@@ -503,12 +490,12 @@
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
- * @retval OT_ERROR_NONE Successfully sent the UDP message.
- * @retval OT_ERROR_INVALID_ARGS If no peer is specified in @p aMessageInfo or by Connect().
- * @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
+ * @retval kErrorNone Successfully sent the UDP message.
+ * @retval kErrorInvalidArgs If no peer is specified in @p aMessageInfo or by Connect().
+ * @retval kErrorNoBufs Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
- otError SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo);
+ Error SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo);
/**
* This method returns a new ephemeral port.
@@ -536,11 +523,11 @@
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aIpProto The Internet Protocol value.
*
- * @retval OT_ERROR_NONE Successfully enqueued the message into an output interface.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the IPv6 headers.
+ * @retval kErrorNone Successfully enqueued the message into an output interface.
+ * @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers.
*
*/
- otError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
+ Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
/**
* This method handles a received UDP message.
@@ -548,11 +535,11 @@
* @param[in] aMessage A reference to the UDP message to process.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
- * @retval OT_ERROR_NONE Successfully processed the UDP message.
- * @retval OT_ERROR_DROP Could not fully process the UDP message.
+ * @retval kErrorNone Successfully processed the UDP message.
+ * @retval kErrorDrop Could not fully process the UDP message.
*
*/
- otError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
+ Error HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
/**
* This method handles a received UDP message with offset set to the payload.
@@ -586,6 +573,17 @@
}
#endif
+ /**
+ * This method returns whether a udp port belongs to the platform or the stack.
+ *
+ * @param[in] aPort The udp port
+ *
+ * @retval True when the port belongs to the platform.
+ * @retval False when the port belongs to the stack.
+ *
+ */
+ bool ShouldUsePlatformUdp(uint16_t aPort) const;
+
private:
enum
{
@@ -596,7 +594,6 @@
void AddSocket(SocketHandle &aSocket);
void RemoveSocket(SocketHandle &aSocket);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
- bool ShouldUsePlatformUdp(uint16_t aPort) const;
bool ShouldUsePlatformUdp(const SocketHandle &aSocket) const;
#endif
diff --git a/src/core/openthread-core-config.h b/src/core/openthread-core-config.h
index 18f8245..4e86be6 100644
--- a/src/core/openthread-core-config.h
+++ b/src/core/openthread-core-config.h
@@ -47,7 +47,7 @@
#endif
#ifndef OPENTHREAD_CONFIG_THREAD_VERSION
-#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_1
+#define OPENTHREAD_CONFIG_THREAD_VERSION OT_THREAD_VERSION_1_2
#endif
#include "config/openthread-core-default-config.h"
@@ -65,6 +65,8 @@
#include "config/dhcp6_server.h"
#include "config/diag.h"
#include "config/dns_client.h"
+#include "config/dnssd_server.h"
+#include "config/dtls.h"
#include "config/ip6.h"
#include "config/joiner.h"
#include "config/link_quality.h"
@@ -73,19 +75,15 @@
#include "config/mac.h"
#include "config/mle.h"
#include "config/parent_search.h"
+#include "config/ping_sender.h"
#include "config/platform.h"
#include "config/radio_link.h"
#include "config/sntp_client.h"
+#include "config/srp_client.h"
+#include "config/srp_server.h"
#include "config/time_sync.h"
#include "config/tmf.h"
-#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || \
- OPENTHREAD_CONFIG_COMMISSIONER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE
-#define OPENTHREAD_CONFIG_DTLS_ENABLE 1
-#else
-#define OPENTHREAD_CONFIG_DTLS_ENABLE 0
-#endif
-
#undef OPENTHREAD_CORE_CONFIG_H_IN
#include "config/openthread-core-config-check.h"
diff --git a/src/core/radio.cmake b/src/core/radio.cmake
index 1a78f10..ffa0c7b 100644
--- a/src/core/radio.cmake
+++ b/src/core/radio.cmake
@@ -47,11 +47,13 @@
target_sources(openthread-radio PRIVATE
api/diags_api.cpp
+ api/error_api.cpp
api/instance_api.cpp
api/link_raw_api.cpp
api/logging_api.cpp
api/random_noncrypto_api.cpp
api/tasklet_api.cpp
+ common/error.cpp
common/instance.cpp
common/logging.cpp
common/random_manager.cpp
diff --git a/src/core/radio/radio.cpp b/src/core/radio/radio.cpp
index 9ac0f96..b519e54 100644
--- a/src/core/radio/radio.cpp
+++ b/src/core/radio/radio.cpp
@@ -53,7 +53,7 @@
#endif
}
-otError Radio::Transmit(Mac::TxFrame &aFrame)
+Error Radio::Transmit(Mac::TxFrame &aFrame)
{
#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE
Get<Utils::Otns>().EmitTransmit(aFrame);
diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp
index bdec579..3af3fb1 100644
--- a/src/core/radio/radio.hpp
+++ b/src/core/radio/radio.hpp
@@ -117,12 +117,12 @@
* This callback method handles a "Receive Done" event from radio platform.
*
* @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received,
- * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received,
+ * kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
- void HandleReceiveDone(Mac::RxFrame *aFrame, otError aError);
+ void HandleReceiveDone(Mac::RxFrame *aFrame, Error aError);
/**
* This callback method handles a "Transmit Started" event from radio platform.
@@ -137,13 +137,13 @@
*
* @param[in] aFrame The frame that was transmitted.
* @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on the
- * channel, OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx could not take place due to activity on the
+ * channel, kErrorAbort when transmission was aborted for other reasons.
*
*/
- void HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, otError aError);
+ void HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, Error aError);
/**
* This callback method handles "Energy Scan Done" event from radio platform.
@@ -162,24 +162,24 @@
* This callback method handles a "Receive Done" event from radio platform when diagnostics mode is enabled.
*
* @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
- * @param[in] aError OT_ERROR_NONE when successfully received a frame,
- * OT_ERROR_ABORT when reception was aborted and a frame was not received,
- * OT_ERROR_NO_BUFS when a frame could not be received due to lack of rx buffer space.
+ * @param[in] aError kErrorNone when successfully received a frame,
+ * kErrorAbort when reception was aborted and a frame was not received,
+ * kErrorNoBufs when a frame could not be received due to lack of rx buffer space.
*
*/
- void HandleDiagsReceiveDone(Mac::RxFrame *aFrame, otError aError);
+ void HandleDiagsReceiveDone(Mac::RxFrame *aFrame, Error aError);
/**
* This callback method handles a "Transmit Done" event from radio platform when diagnostics mode is enabled.
*
* @param[in] aFrame The frame that was transmitted.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx could not take place due to activity on the
- * channel, OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx could not take place due to activity on the
+ * channel, kErrorAbort when transmission was aborted for other reasons.
*
*/
- void HandleDiagsTransmitDone(Mac::TxFrame &aFrame, otError aError);
+ void HandleDiagsTransmitDone(Mac::TxFrame &aFrame, Error aError);
#endif
private:
@@ -289,44 +289,44 @@
*
* @param[out] aPower A reference to output the transmit power in dBm.
*
- * @retval OT_ERROR_NONE Successfully retrieved the transmit power.
- * @retval OT_ERROR_NOT_IMPLEMENTED Transmit power configuration via dBm is not implemented.
+ * @retval kErrorNone Successfully retrieved the transmit power.
+ * @retval kErrorNotImplemented Transmit power configuration via dBm is not implemented.
*
*/
- otError GetTransmitPower(int8_t &aPower);
+ Error GetTransmitPower(int8_t &aPower);
/**
* This method sets the radio's transmit power in dBm.
*
* @param[in] aPower The transmit power in dBm.
*
- * @retval OT_ERROR_NONE Successfully set the transmit power.
- * @retval OT_ERROR_NOT_IMPLEMENTED Transmit power configuration via dBm is not implemented.
+ * @retval kErrorNone Successfully set the transmit power.
+ * @retval kErrorNotImplemented Transmit power configuration via dBm is not implemented.
*
*/
- otError SetTransmitPower(int8_t aPower);
+ Error SetTransmitPower(int8_t aPower);
/**
* This method gets the radio's CCA ED threshold in dBm.
*
* @param[in] aThreshold The CCA ED threshold in dBm.
*
- * @retval OT_ERROR_NONE A reference to output the CCA ED threshold in dBm.
- * @retval OT_ERROR_NOT_IMPLEMENTED CCA ED threshold configuration via dBm is not implemented.
+ * @retval kErrorNone A reference to output the CCA ED threshold in dBm.
+ * @retval kErrorNotImplemented CCA ED threshold configuration via dBm is not implemented.
*
*/
- otError GetCcaEnergyDetectThreshold(int8_t &aThreshold);
+ Error GetCcaEnergyDetectThreshold(int8_t &aThreshold);
/**
* This method sets the radio's CCA ED threshold in dBm.
*
* @param[in] aThreshold The CCA ED threshold in dBm.
*
- * @retval OT_ERROR_NONE Successfully set the CCA ED threshold.
- * @retval OT_ERROR_NOT_IMPLEMENTED CCA ED threshold configuration via dBm is not implemented.
+ * @retval kErrorNone Successfully set the CCA ED threshold.
+ * @retval kErrorNotImplemented CCA ED threshold configuration via dBm is not implemented.
*
*/
- otError SetCcaEnergyDetectThreshold(int8_t aThreshold);
+ Error SetCcaEnergyDetectThreshold(int8_t aThreshold);
/**
* This method gets the status of promiscuous mode.
@@ -360,20 +360,20 @@
/**
* This method enables the radio.
*
- * @retval OT_ERROR_NONE Successfully enabled.
- * @retval OT_ERROR_FAILED The radio could not be enabled.
+ * @retval kErrorNone Successfully enabled.
+ * @retval kErrorFailed The radio could not be enabled.
*
*/
- otError Enable(void);
+ Error Enable(void);
/**
* This method disables the radio.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Disabled.
- * @retval OT_ERROR_INVALID_STATE The radio was not in sleep state.
+ * @retval kErrorNone Successfully transitioned to Disabled.
+ * @retval kErrorInvalidState The radio was not in sleep state.
*
*/
- otError Disable(void);
+ Error Disable(void);
/**
* This method indicates whether radio is enabled or not.
@@ -386,23 +386,23 @@
/**
* This method transitions the radio from Receive to Sleep (turn off the radio).
*
- * @retval OT_ERROR_NONE Successfully transitioned to Sleep.
- * @retval OT_ERROR_BUSY The radio was transmitting.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled.
+ * @retval kErrorNone Successfully transitioned to Sleep.
+ * @retval kErrorBusy The radio was transmitting.
+ * @retval kErrorInvalidState The radio was disabled.
*
*/
- otError Sleep(void);
+ Error Sleep(void);
/**
* This method transitions the radio from Sleep to Receive (turn on the radio).
*
* @param[in] aChannel The channel to use for receiving.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Receive.
- * @retval OT_ERROR_INVALID_STATE The radio was disabled or transmitting.
+ * @retval kErrorNone Successfully transitioned to Receive.
+ * @retval kErrorInvalidState The radio was disabled or transmitting.
*
*/
- otError Receive(uint8_t aChannel);
+ Error Receive(uint8_t aChannel);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
@@ -419,12 +419,12 @@
* @param[in] aExtAddr The extended source address of CSL receiver's parent device (when the platforms
* generate enhanced ack, platforms may need to know acks to which address should include CSL IE).
*
- * @retval OT_ERROR_NOT_SUPPORTED Radio driver doesn't support CSL.
- * @retval OT_ERROR_FAILED Other platform specific errors.
- * @retval OT_ERROR_NONE Successfully enabled or disabled CSL.
+ * @retval kErrorNotImplemented Radio driver doesn't support CSL.
+ * @retval kErrorFailed Other platform specific errors.
+ * @retval kErrorNone Successfully enabled or disabled CSL.
*
*/
- otError EnableCsl(uint32_t aCslPeriod, const otExtAddress *aExtAddr);
+ Error EnableCsl(uint32_t aCslPeriod, const otExtAddress *aExtAddr);
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
@@ -445,11 +445,11 @@
*
* @param[in] aFrame A reference to the frame to be transmitted.
*
- * @retval OT_ERROR_NONE Successfully transitioned to Transmit.
- * @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
+ * @retval kErrorNone Successfully transitioned to Transmit.
+ * @retval kErrorInvalidState The radio was not in the Receive state.
*
*/
- otError Transmit(Mac::TxFrame &aFrame);
+ Error Transmit(Mac::TxFrame &aFrame);
/**
* This method gets the most recent RSSI measurement.
@@ -467,11 +467,11 @@
* @param[in] aScanChannel The channel to perform the energy scan on.
* @param[in] aScanDuration The duration, in milliseconds, for the channel to be scanned.
*
- * @retval OT_ERROR_NONE Successfully started scanning the channel.
- * @retval OT_ERROR_NOT_IMPLEMENTED The radio doesn't support energy scanning.
+ * @retval kErrorNone Successfully started scanning the channel.
+ * @retval kErrorNotImplemented The radio doesn't support energy scanning.
*
*/
- otError EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
+ Error EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration);
/**
* This method enables/disables source address match feature.
@@ -497,44 +497,44 @@
*
* @param[in] aShortAddress The short address to be added.
*
- * @retval OT_ERROR_NONE Successfully added short address to the source match table.
- * @retval OT_ERROR_NO_BUFS No available entry in the source match table.
+ * @retval kErrorNone Successfully added short address to the source match table.
+ * @retval kErrorNoBufs No available entry in the source match table.
*
*/
- otError AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
+ Error AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
/**
* This method adds an extended address to the source address match table.
*
* @param[in] aExtAddress The extended address to be added stored in little-endian byte order.
*
- * @retval OT_ERROR_NONE Successfully added extended address to the source match table.
- * @retval OT_ERROR_NO_BUFS No available entry in the source match table.
+ * @retval kErrorNone Successfully added extended address to the source match table.
+ * @retval kErrorNoBufs No available entry in the source match table.
*
*/
- otError AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
+ Error AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
/**
* This method removes a short address from the source address match table.
*
* @param[in] aShortAddress The short address to be removed.
*
- * @retval OT_ERROR_NONE Successfully removed short address from the source match table.
- * @retval OT_ERROR_NO_ADDRESS The short address is not in source address match table.
+ * @retval kErrorNone Successfully removed short address from the source match table.
+ * @retval kErrorNoAddress The short address is not in source address match table.
*
*/
- otError ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
+ Error ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress);
/**
* This method removes an extended address from the source address match table.
*
* @param[in] aExtAddress The extended address to be removed stored in little-endian byte order.
*
- * @retval OT_ERROR_NONE Successfully removed the extended address from the source match table.
- * @retval OT_ERROR_NO_ADDRESS The extended address is not in source address match table.
+ * @retval kErrorNone Successfully removed the extended address from the source match table.
+ * @retval kErrorNoAddress The extended address is not in source address match table.
*
*/
- otError ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
+ Error ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress);
/**
* This method clears all short addresses from the source address match table.
@@ -580,15 +580,15 @@
* @param[in] aShortAddr The short address of the the probing Initiator.
* @param[in] aExtAddr The extended source address of the probing Initiator.
*
- * @retval OT_ERROR_NONE Successfully enable/disable or update Enhanced-ACK Based Probing for a specific
- * Initiator.
- * @retval OT_ERROR_INVALID_ARGS @p aDataLength or @p aExtAddr is not valid.
- * @retval OT_ERROR_NOT_SUPPORTED Radio driver doesn't support Enhanced-ACK Probing.
+ * @retval kErrorNone Successfully enable/disable or update Enhanced-ACK Based Probing for a specific
+ * Initiator.
+ * @retval kErrorInvalidArgs @p aDataLength or @p aExtAddr is not valid.
+ * @retval kErrorNotImplemented Radio driver doesn't support Enhanced-ACK Probing.
*
*/
- otError ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics,
- const Mac::ShortAddress &aShortAddress,
- const Mac::ExtAddress & aExtAddress)
+ Error ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics,
+ const Mac::ShortAddress &aShortAddress,
+ const Mac::ExtAddress & aExtAddress)
{
return otPlatRadioConfigureEnhAckProbing(GetInstancePtr(), aLinkMetrics, aShortAddress, &aExtAddress);
}
@@ -665,22 +665,22 @@
otPlatRadioSetMacKey(GetInstancePtr(), aKeyIdMode, aKeyId, &aPrevKey, &aCurrKey, &aNextKey);
}
-inline otError Radio::GetTransmitPower(int8_t &aPower)
+inline Error Radio::GetTransmitPower(int8_t &aPower)
{
return otPlatRadioGetTransmitPower(GetInstancePtr(), &aPower);
}
-inline otError Radio::SetTransmitPower(int8_t aPower)
+inline Error Radio::SetTransmitPower(int8_t aPower)
{
return otPlatRadioSetTransmitPower(GetInstancePtr(), aPower);
}
-inline otError Radio::GetCcaEnergyDetectThreshold(int8_t &aThreshold)
+inline Error Radio::GetCcaEnergyDetectThreshold(int8_t &aThreshold)
{
return otPlatRadioGetCcaEnergyDetectThreshold(GetInstancePtr(), &aThreshold);
}
-inline otError Radio::SetCcaEnergyDetectThreshold(int8_t aThreshold)
+inline Error Radio::SetCcaEnergyDetectThreshold(int8_t aThreshold)
{
return otPlatRadioSetCcaEnergyDetectThreshold(GetInstancePtr(), aThreshold);
}
@@ -700,12 +700,12 @@
return otPlatRadioGetState(GetInstancePtr());
}
-inline otError Radio::Enable(void)
+inline Error Radio::Enable(void)
{
return otPlatRadioEnable(GetInstancePtr());
}
-inline otError Radio::Disable(void)
+inline Error Radio::Disable(void)
{
return otPlatRadioDisable(GetInstancePtr());
}
@@ -715,12 +715,12 @@
return otPlatRadioIsEnabled(GetInstancePtr());
}
-inline otError Radio::Sleep(void)
+inline Error Radio::Sleep(void)
{
return otPlatRadioSleep(GetInstancePtr());
}
-inline otError Radio::Receive(uint8_t aChannel)
+inline Error Radio::Receive(uint8_t aChannel)
{
return otPlatRadioReceive(GetInstancePtr(), aChannel);
}
@@ -731,7 +731,7 @@
otPlatRadioUpdateCslSampleTime(GetInstancePtr(), aCslSampleTime);
}
-inline otError Radio::EnableCsl(uint32_t aCslPeriod, const otExtAddress *aExtAddr)
+inline Error Radio::EnableCsl(uint32_t aCslPeriod, const otExtAddress *aExtAddr)
{
return otPlatRadioEnableCsl(GetInstancePtr(), aCslPeriod, aExtAddr);
}
@@ -747,7 +747,7 @@
return otPlatRadioGetRssi(GetInstancePtr());
}
-inline otError Radio::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
+inline Error Radio::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
return otPlatRadioEnergyScan(GetInstancePtr(), aScanChannel, aScanDuration);
}
@@ -757,22 +757,22 @@
otPlatRadioEnableSrcMatch(GetInstancePtr(), aEnable);
}
-inline otError Radio::AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
+inline Error Radio::AddSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
{
return otPlatRadioAddSrcMatchShortEntry(GetInstancePtr(), aShortAddress);
}
-inline otError Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
+inline Error Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
{
return otPlatRadioAddSrcMatchExtEntry(GetInstancePtr(), &aExtAddress);
}
-inline otError Radio::ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
+inline Error Radio::ClearSrcMatchShortEntry(Mac::ShortAddress aShortAddress)
{
return otPlatRadioClearSrcMatchShortEntry(GetInstancePtr(), aShortAddress);
}
-inline otError Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
+inline Error Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &aExtAddress)
{
return otPlatRadioClearSrcMatchExtEntry(GetInstancePtr(), &aExtAddress);
}
@@ -815,24 +815,24 @@
{
}
-inline otError Radio::GetTransmitPower(int8_t &)
+inline Error Radio::GetTransmitPower(int8_t &)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
-inline otError Radio::SetTransmitPower(int8_t)
+inline Error Radio::SetTransmitPower(int8_t)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
-inline otError Radio::GetCcaEnergyDetectThreshold(int8_t &)
+inline Error Radio::GetCcaEnergyDetectThreshold(int8_t &)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
-inline otError Radio::SetCcaEnergyDetectThreshold(int8_t)
+inline Error Radio::SetCcaEnergyDetectThreshold(int8_t)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
inline bool Radio::GetPromiscuous(void)
@@ -849,14 +849,14 @@
return OT_RADIO_STATE_DISABLED;
}
-inline otError Radio::Enable(void)
+inline Error Radio::Enable(void)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-inline otError Radio::Disable(void)
+inline Error Radio::Disable(void)
{
- return OT_ERROR_INVALID_STATE;
+ return kErrorInvalidState;
}
inline bool Radio::IsEnabled(void)
@@ -864,14 +864,14 @@
return true;
}
-inline otError Radio::Sleep(void)
+inline Error Radio::Sleep(void)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-inline otError Radio::Receive(uint8_t)
+inline Error Radio::Receive(uint8_t)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
@@ -879,9 +879,9 @@
{
}
-inline otError Radio::EnableCsl(uint32_t, const otExtAddress *)
+inline Error Radio::EnableCsl(uint32_t, const otExtAddress *)
{
- return OT_ERROR_NOT_SUPPORTED;
+ return kErrorNotImplemented;
}
#endif
@@ -890,9 +890,9 @@
return *static_cast<Mac::TxFrame *>(otPlatRadioGetTransmitBuffer(GetInstancePtr()));
}
-inline otError Radio::Transmit(Mac::TxFrame &)
+inline Error Radio::Transmit(Mac::TxFrame &)
{
- return OT_ERROR_ABORT;
+ return kErrorAbort;
}
inline int8_t Radio::GetRssi(void)
@@ -900,33 +900,33 @@
return OT_RADIO_RSSI_INVALID;
}
-inline otError Radio::EnergyScan(uint8_t, uint16_t)
+inline Error Radio::EnergyScan(uint8_t, uint16_t)
{
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
inline void Radio::EnableSrcMatch(bool)
{
}
-inline otError Radio::AddSrcMatchShortEntry(Mac::ShortAddress)
+inline Error Radio::AddSrcMatchShortEntry(Mac::ShortAddress)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-inline otError Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &)
+inline Error Radio::AddSrcMatchExtEntry(const Mac::ExtAddress &)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-inline otError Radio::ClearSrcMatchShortEntry(Mac::ShortAddress)
+inline Error Radio::ClearSrcMatchShortEntry(Mac::ShortAddress)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-inline otError Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &)
+inline Error Radio::ClearSrcMatchExtEntry(const Mac::ExtAddress &)
{
- return OT_ERROR_NONE;
+ return kErrorNone;
}
inline void Radio::ClearSrcMatchShortEntries(void)
diff --git a/src/core/radio/radio_callbacks.cpp b/src/core/radio/radio_callbacks.cpp
index 11d713c..55b231b 100644
--- a/src/core/radio/radio_callbacks.cpp
+++ b/src/core/radio/radio_callbacks.cpp
@@ -38,7 +38,7 @@
namespace ot {
-void Radio::Callbacks::HandleReceiveDone(Mac::RxFrame *aFrame, otError aError)
+void Radio::Callbacks::HandleReceiveDone(Mac::RxFrame *aFrame, Error aError)
{
Get<Mac::SubMac>().HandleReceiveDone(aFrame, aError);
}
@@ -48,7 +48,7 @@
Get<Mac::SubMac>().HandleTransmitStarted(aFrame);
}
-void Radio::Callbacks::HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, otError aError)
+void Radio::Callbacks::HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, Error aError)
{
Get<Mac::SubMac>().HandleTransmitDone(aFrame, aAckFrame, aError);
}
@@ -59,7 +59,7 @@
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
-void Radio::Callbacks::HandleDiagsReceiveDone(Mac::RxFrame *aFrame, otError aError)
+void Radio::Callbacks::HandleDiagsReceiveDone(Mac::RxFrame *aFrame, Error aError)
{
#if OPENTHREAD_RADIO
// Pass it to notify OpenThread `Diags` module on host side.
@@ -69,7 +69,7 @@
#endif
}
-void Radio::Callbacks::HandleDiagsTransmitDone(Mac::TxFrame &aFrame, otError aError)
+void Radio::Callbacks::HandleDiagsTransmitDone(Mac::TxFrame &aFrame, Error aError)
{
#if OPENTHREAD_RADIO
// Pass it to notify OpenThread `Diags` module on host side.
diff --git a/src/core/radio/radio_platform.cpp b/src/core/radio/radio_platform.cpp
index 76d19e0..c5c6328 100644
--- a/src/core/radio/radio_platform.cpp
+++ b/src/core/radio/radio_platform.cpp
@@ -44,7 +44,7 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
-extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
{
Instance & instance = *static_cast<Instance *>(aInstance);
Mac::RxFrame *rxFrame = static_cast<Mac::RxFrame *>(aFrame);
@@ -81,7 +81,7 @@
return;
}
-extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
+extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, Error aError)
{
Instance & instance = *static_cast<Instance *>(aInstance);
Mac::TxFrame &txFrame = *static_cast<Mac::TxFrame *>(aFrame);
@@ -116,7 +116,7 @@
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
-extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
{
Instance & instance = *static_cast<Instance *>(aInstance);
Mac::RxFrame *rxFrame = static_cast<Mac::RxFrame *>(aFrame);
@@ -131,7 +131,7 @@
instance.Get<Radio::Callbacks>().HandleDiagsReceiveDone(rxFrame, aError);
}
-extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, Error aError)
{
Instance & instance = *static_cast<Instance *>(aInstance);
Mac::TxFrame &txFrame = *static_cast<Mac::TxFrame *>(aFrame);
@@ -146,7 +146,7 @@
#else // #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
-extern "C" void otPlatRadioReceiveDone(otInstance *, otRadioFrame *, otError)
+extern "C" void otPlatRadioReceiveDone(otInstance *, otRadioFrame *, Error)
{
}
@@ -154,7 +154,7 @@
{
}
-extern "C" void otPlatRadioTxDone(otInstance *, otRadioFrame *, otRadioFrame *, otError)
+extern "C" void otPlatRadioTxDone(otInstance *, otRadioFrame *, otRadioFrame *, Error)
{
}
@@ -163,11 +163,11 @@
}
#if OPENTHREAD_CONFIG_DIAG_ENABLE
-extern "C" void otPlatDiagRadioReceiveDone(otInstance *, otRadioFrame *, otError)
+extern "C" void otPlatDiagRadioReceiveDone(otInstance *, otRadioFrame *, Error)
{
}
-extern "C" void otPlatDiagRadioTransmitDone(otInstance *, otRadioFrame *, otError)
+extern "C" void otPlatDiagRadioTransmitDone(otInstance *, otRadioFrame *, Error)
{
}
#endif
@@ -242,27 +242,43 @@
return 0;
}
-OT_TOOL_WEAK otError otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
+OT_TOOL_WEAK Error otPlatRadioGetFemLnaGain(otInstance *aInstance, int8_t *aGain)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aGain);
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
-OT_TOOL_WEAK otError otPlatRadioSetFemLnaGain(otInstance *aInstance, int8_t aGain)
+OT_TOOL_WEAK Error otPlatRadioSetFemLnaGain(otInstance *aInstance, int8_t aGain)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aGain);
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
}
-OT_TOOL_WEAK otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower)
+OT_TOOL_WEAK Error otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aChannel);
OT_UNUSED_VARIABLE(aMaxPower);
- return OT_ERROR_NOT_IMPLEMENTED;
+ return kErrorNotImplemented;
+}
+
+OT_TOOL_WEAK Error otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aRegionCode);
+
+ return kErrorNotImplemented;
+}
+
+OT_TOOL_WEAK Error otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aRegionCode);
+
+ return kErrorNotImplemented;
}
diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp
index 5de95be..8c75621 100644
--- a/src/core/radio/trel_interface.cpp
+++ b/src/core/radio/trel_interface.cpp
@@ -81,7 +81,7 @@
return;
}
-otError Interface::Send(const Packet &aPacket)
+Error Interface::Send(const Packet &aPacket)
{
Ip6::Address destIp6Address;
@@ -131,7 +131,7 @@
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aEnable);
- return OT_ERROR_NOT_IMPLEMENTED;
+ return ot::kErrorNotImplemented;
}
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
diff --git a/src/core/radio/trel_interface.hpp b/src/core/radio/trel_interface.hpp
index 843b546..ebdd40d 100644
--- a/src/core/radio/trel_interface.hpp
+++ b/src/core/radio/trel_interface.hpp
@@ -92,11 +92,11 @@
*
* @param[in] aPacket A packet to send.
*
- * @retval OT_ERROR_NONE The frame was sent successfully.
- * @retval OT_ERROR_ABORT The interface is not ready and send was aborted.
+ * @retval kErrorNone The frame was sent successfully.
+ * @retval kErrorAbort The interface is not ready and send was aborted.
*
*/
- otError Send(const Packet &aPacket);
+ Error Send(const Packet &aPacket);
/**
* This method is a callback from platform layer to handle a received packet over the interface.
diff --git a/src/core/radio/trel_link.cpp b/src/core/radio/trel_link.cpp
index 2d935f4..e2e9d56 100644
--- a/src/core/radio/trel_link.cpp
+++ b/src/core/radio/trel_link.cpp
@@ -49,8 +49,8 @@
, mRxChannel(0)
, mPanId(Mac::kPanIdBroadcast)
, mTxPacketNumber(0)
- , mTxTasklet(aInstance, HandleTxTasklet, this)
- , mTimer(aInstance, HandleTimer, this)
+ , mTxTasklet(aInstance, HandleTxTasklet)
+ , mTimer(aInstance, HandleTimer)
, mInterface(aInstance)
{
memset(&mTxFrame, 0, sizeof(mTxFrame));
@@ -115,7 +115,7 @@
void Link::HandleTxTasklet(Tasklet &aTasklet)
{
- aTasklet.GetOwner<Link>().HandleTxTasklet();
+ aTasklet.Get<Link>().HandleTxTasklet();
}
void Link::HandleTxTasklet(void)
@@ -143,7 +143,7 @@
// continue to rx on same channel
mRxChannel = mTxFrame.GetChannel();
- VerifyOrExit(!mTxFrame.IsEmpty(), InvokeSendDone(OT_ERROR_ABORT));
+ VerifyOrExit(!mTxFrame.IsEmpty(), InvokeSendDone(kErrorAbort));
IgnoreError(mTxFrame.GetDstAddr(destAddr));
@@ -171,7 +171,7 @@
}
}
- if (mTxFrame.GetDstPanId(destPanId) != OT_ERROR_NONE)
+ if (mTxFrame.GetDstPanId(destPanId) != kErrorNone)
{
destPanId = Mac::kPanIdBroadcast;
}
@@ -203,7 +203,7 @@
otLogDebgMac("Trel: BeginTransmit() [%s] plen:%d", txPacket.GetHeader().ToString().AsCString(),
txPacket.GetPayloadLength());
- VerifyOrExit(mInterface.Send(txPacket) == OT_ERROR_NONE, InvokeSendDone(OT_ERROR_ABORT));
+ VerifyOrExit(mInterface.Send(txPacket) == kErrorNone, InvokeSendDone(kErrorAbort));
if (mTxFrame.GetAckRequest())
{
@@ -232,13 +232,13 @@
ackFrame = &mRxFrame;
}
- InvokeSendDone(OT_ERROR_NONE, ackFrame);
+ InvokeSendDone(kErrorNone, ackFrame);
exit:
return;
}
-void Link::InvokeSendDone(otError aError, Mac::RxFrame *aAckFrame)
+void Link::InvokeSendDone(Error aError, Mac::RxFrame *aAckFrame)
{
SetState(kStateReceive);
@@ -248,7 +248,7 @@
void Link::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Link>().HandleTimer();
+ aTimer.Get<Link>().HandleTimer();
}
void Link::HandleTimer(void)
@@ -284,7 +284,7 @@
case Mle::kRoleChild:
HandleTimer(Get<Mle::MleRouter>().GetParent());
- // Fall through
+ OT_FALL_THROUGH;
case Mle::kRoleRouter:
case Mle::kRoleLeader:
@@ -303,7 +303,7 @@
{
aNeighbor.mTrelPreviousPendingAcks--;
- ReportDeferredAckStatus(aNeighbor, OT_ERROR_NO_ACK);
+ ReportDeferredAckStatus(aNeighbor, kErrorNoAck);
VerifyOrExit(!aNeighbor.IsStateInvalid());
}
@@ -372,7 +372,7 @@
mRxFrame.mInfo.mRxInfo.mLqi = OT_RADIO_LQI_NONE;
mRxFrame.mInfo.mRxInfo.mAckedWithFramePending = true;
- Get<Mac::Mac>().HandleReceivedFrame(&mRxFrame, OT_ERROR_NONE);
+ Get<Mac::Mac>().HandleReceivedFrame(&mRxFrame, kErrorNone);
exit:
return;
@@ -380,7 +380,7 @@
void Link::HandleAck(Packet &aAckPacket)
{
- otError ackError;
+ Error ackError;
Mac::Address srcAddress;
Neighbor * neighbor;
uint32_t ackNumber;
@@ -404,14 +404,14 @@
// expected one. If it does not, it indicates that some of
// packets missed their acks.
- ackError = (ackNumber == neighbor->GetExpectedTrelAckNumber()) ? OT_ERROR_NONE : OT_ERROR_NO_ACK;
+ ackError = (ackNumber == neighbor->GetExpectedTrelAckNumber()) ? kErrorNone : kErrorNoAck;
neighbor->DecrementPendingTrelAckCount();
ReportDeferredAckStatus(*neighbor, ackError);
VerifyOrExit(!neighbor->IsStateInvalid());
- } while (ackError == OT_ERROR_NO_ACK);
+ } while (ackError == kErrorNoAck);
exit:
return;
@@ -436,10 +436,10 @@
IgnoreError(mInterface.Send(ackPacket));
}
-void Link::ReportDeferredAckStatus(Neighbor &aNeighbor, otError aError)
+void Link::ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError)
{
otLogDebgMac("Trel: ReportDeferredAckStatus(): %s for %s", aNeighbor.GetExtAddress().ToString().AsCString(),
- otThreadErrorToString(aError));
+ ErrorToString(aError));
Get<MeshForwarder>().HandleDeferredAck(aNeighbor, aError);
}
diff --git a/src/core/radio/trel_link.hpp b/src/core/radio/trel_link.hpp
index 825bb33..4f597ff 100644
--- a/src/core/radio/trel_link.hpp
+++ b/src/core/radio/trel_link.hpp
@@ -168,12 +168,12 @@
void SetState(State aState);
void BeginTransmit(void);
- void InvokeSendDone(otError aError) { InvokeSendDone(aError, nullptr); }
- void InvokeSendDone(otError aError, Mac::RxFrame *aAckFrame);
+ void InvokeSendDone(Error aError) { InvokeSendDone(aError, nullptr); }
+ void InvokeSendDone(Error aError, Mac::RxFrame *aAckFrame);
void ProcessReceivedPacket(Packet &aPacket);
void HandleAck(Packet &aAckPacket);
void SendAck(Packet &aRxPacket);
- void ReportDeferredAckStatus(Neighbor &aNeighbor, otError aError);
+ void ReportDeferredAckStatus(Neighbor &aNeighbor, Error aError);
void HandleTimer(Neighbor &aNeighbor);
static void HandleTxTasklet(Tasklet &aTasklet);
diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp
index 7d2f0e7..14f1314 100644
--- a/src/core/thread/address_resolver.cpp
+++ b/src/core/thread/address_resolver.cpp
@@ -78,7 +78,7 @@
{
if (list == &mQueryList)
{
- Get<MeshForwarder>().HandleResolved(entry->GetTarget(), OT_ERROR_DROP);
+ Get<MeshForwarder>().HandleResolved(entry->GetTarget(), kErrorDrop);
}
mCacheEntryPool.Free(*entry);
@@ -86,9 +86,9 @@
}
}
-otError AddressResolver::GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const
+Error AddressResolver::GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const CacheEntryList *list;
const CacheEntry * entry;
@@ -115,7 +115,7 @@
}
else
{
- ExitNow(error = OT_ERROR_NOT_FOUND);
+ ExitNow(error = kErrorNotFound);
}
entry = list->GetHead();
@@ -323,21 +323,21 @@
if (&aList == &mQueryList)
{
- Get<MeshForwarder>().HandleResolved(aEntry.GetTarget(), OT_ERROR_DROP);
+ Get<MeshForwarder>().HandleResolved(aEntry.GetTarget(), kErrorDrop);
}
LogCacheEntryChange(kEntryRemoved, aReason, aEntry, &aList);
}
-otError AddressResolver::UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16)
+Error AddressResolver::UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
CacheEntryList *list;
CacheEntry * entry;
CacheEntry * prev;
entry = FindCacheEntry(aEid, list, prev);
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(entry != nullptr, error = kErrorNotFound);
if ((list == &mCachedList) || (list == &mSnoopedList))
{
@@ -356,7 +356,7 @@
entry->MarkLastTransactionTimeAsInvalid();
mCachedList.Push(*entry);
- Get<MeshForwarder>().HandleResolved(aEid, OT_ERROR_NONE);
+ Get<MeshForwarder>().HandleResolved(aEid, kErrorNone);
}
LogCacheEntryChange(kEntryUpdated, kReasonSnoop, *entry);
@@ -436,9 +436,9 @@
}
}
-otError AddressResolver::Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery)
+Error AddressResolver::Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
CacheEntry * entry;
CacheEntry * prev = nullptr;
CacheEntryList *list;
@@ -451,10 +451,10 @@
// allocate a new entry and perform address query. We do not
// allow first-time address query entries to be evicted till
// timeout.
- VerifyOrExit(aAllowAddressQuery, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aAllowAddressQuery, error = kErrorNotFound);
entry = NewCacheEntry(/* aSnoopedEntry */ false);
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
entry->SetTarget(aEid);
entry->SetRloc16(Mac::kShortAddrInvalid);
@@ -483,11 +483,11 @@
// Note that if `aAllowAddressQuery` is `false` then the `entry` is definitely already in a list, i.e., we cannot
// not get here with `aAllowAddressQuery` being `false` and `entry` being a newly allocated one, due to the
// `VerifyOrExit` check that `aAllowAddressQuery` is `true` before allocating a new cache entry.
- VerifyOrExit(aAllowAddressQuery, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aAllowAddressQuery, error = kErrorNotFound);
if (list == &mQueryList)
{
- ExitNow(error = OT_ERROR_ADDRESS_QUERY);
+ ExitNow(error = kErrorAddressQuery);
}
if (list == &mQueryRetryList)
@@ -496,14 +496,14 @@
// Query again only if the timeout (retry delay interval) is
// expired.
- VerifyOrExit(entry->IsTimeoutZero(), error = OT_ERROR_DROP);
+ VerifyOrExit(entry->IsTimeoutZero(), error = kErrorDrop);
mQueryRetryList.PopAfter(prev);
}
entry->SetTimeout(kAddressQueryTimeout);
error = SendAddressQuery(aEid);
- VerifyOrExit(error == OT_ERROR_NONE, mCacheEntryPool.Free(*entry));
+ VerifyOrExit(error == kErrorNone, mCacheEntryPool.Free(*entry));
if (list == nullptr)
{
@@ -511,19 +511,19 @@
}
mQueryList.Push(*entry);
- error = OT_ERROR_ADDRESS_QUERY;
+ error = kErrorAddressQuery;
exit:
return error;
}
-otError AddressResolver::SendAddressQuery(const Ip6::Address &aEid)
+Error AddressResolver::SendAddressQuery(const Ip6::Address &aEid)
{
- otError error;
+ Error error;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
message->InitAsNonConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kAddressQuery));
@@ -583,9 +583,9 @@
switch (Tlv::Find<ThreadLastTransactionTimeTlv>(aMessage, lastTransactionTime))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
lastTransactionTime = 0;
break;
default:
@@ -622,12 +622,12 @@
LogCacheEntryChange(kEntryUpdated, kReasonReceivedNotification, *entry);
- if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == OT_ERROR_NONE)
+ if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
{
otLogInfoArp("Sending address notification acknowledgment");
}
- Get<MeshForwarder>().HandleResolved(target, OT_ERROR_NONE);
+ Get<MeshForwarder>().HandleResolved(target, kErrorNone);
exit:
return;
@@ -637,11 +637,11 @@
const Ip6::InterfaceIdentifier &aMeshLocalIid,
const Ip6::Address * aDestination)
{
- otError error;
+ Error error;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
message->Init(aDestination == nullptr ? Coap::kTypeNonConfirmable : Coap::kTypeConfirmable, Coap::kCodePost);
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kAddressError));
@@ -668,10 +668,10 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeMessage(message);
- otLogInfoArp("Failed to send address error: %s", otThreadErrorToString(error));
+ otLogInfoArp("Failed to send address error: %s", ErrorToString(error));
}
}
@@ -683,19 +683,19 @@
void AddressResolver::HandleAddressError(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address target;
Ip6::InterfaceIdentifier meshLocalIid;
Mac::ExtAddress extAddr;
Ip6::Address destination;
- VerifyOrExit(aMessage.IsPostRequest(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessage.IsPostRequest(), error = kErrorDrop);
otLogInfoArp("Received address error notification");
if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
{
- if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == OT_ERROR_NONE)
+ if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
{
otLogInfoArp("Sent address error notification acknowledgment");
}
@@ -738,7 +738,7 @@
// Mesh Local EID differs, so check whether Target EID
// matches a child address and if so remove it.
- if (child.RemoveIp6Address(target) == OT_ERROR_NONE)
+ if (child.RemoveIp6Address(target) == kErrorNone)
{
SuccessOrExit(error = Get<Mle::Mle>().GetLocatorAddress(destination, child.GetRloc16()));
@@ -750,9 +750,9 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnArp("Error while processing address error notification: %s", otThreadErrorToString(error));
+ otLogWarnArp("Error while processing address error notification: %s", ErrorToString(error));
}
}
@@ -816,11 +816,11 @@
const uint32_t * aLastTransactionTime,
const Ip6::Address & aDestination)
{
- otError error;
+ Error error;
Coap::Message * message;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
message->InitAsConfirmablePost();
SuccessOrExit(error = message->AppendUriPathOptions(UriPath::kAddressNotify));
@@ -912,7 +912,7 @@
otLogInfoArp("Timed out waiting for address notification for %s, retry: %d",
entry->GetTarget().ToString().AsCString(), entry->GetTimeout());
- Get<MeshForwarder>().HandleResolved(entry->GetTarget(), OT_ERROR_DROP);
+ Get<MeshForwarder>().HandleResolved(entry->GetTarget(), kErrorDrop);
// When the entry is removed from `mQueryList`
// we keep the `prev` pointer same as before.
diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp
index bccf1be..13f0d70 100644
--- a/src/core/thread/address_resolver.hpp
+++ b/src/core/thread/address_resolver.hpp
@@ -99,11 +99,11 @@
* To get the first entry, initialize the iterator by setting all its fields to zero.
* e.g., `memset` the the iterator structure to zero.
*
- * @retval OT_ERROR_NONE Successfully populated @p aInfo with the info for the next EID cache entry.
- * @retval OT_ERROR_NOT_FOUND No more entries in the address cache table.
+ * @retval kErrorNone Successfully populated @p aInfo with the info for the next EID cache entry.
+ * @retval kErrorNotFound No more entries in the address cache table.
*
*/
- otError GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const;
+ Error GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const;
/**
* This method removes the EID-to-RLOC cache entries corresponding to an RLOC16.
@@ -135,11 +135,11 @@
* @param[in] aEid A reference to the EID.
* @param[in] aRloc16 The RLOC16 corresponding to @p aEid.
*
- * @retval OT_ERROR_NONE Successfully updates an existing cache entry.
- * @retval OT_ERROR_NOT_FOUND No cache entry with @p aEid.
+ * @retval kErrorNone Successfully updates an existing cache entry.
+ * @retval kErrorNotFound No cache entry with @p aEid.
*
*/
- otError UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16);
+ Error UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16);
/**
* This method adds a snooped cache entry for a given EID.
@@ -161,14 +161,14 @@
* @param[out] aRloc16 The RLOC16 corresponding to @p aEid.
* @param[in] aAllowAddressQuery Allow to initiate Address Query if the mapping is not known.
*
- * @retval OT_ERROR_NONE Successfully provided the RLOC16.
- * @retval OT_ERROR_ADDRESS_QUERY Initiated an Address Query if allowed.
- * @retval OT_ERROR_DROP Earlier Address Query for the EID timed out. In retry timeout interval.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to send Address Query.
- * @retval OT_ERROR_NOT_FOUND The mapping was not found and Address Query was not allowed.
+ * @retval kErrorNone Successfully provided the RLOC16.
+ * @retval kErrorAddressQuery Initiated an Address Query if allowed.
+ * @retval kErrorDrop Earlier Address Query for the EID timed out. In retry timeout interval.
+ * @retval kErrorNoBufs Insufficient buffer space available to send Address Query.
+ * @retval kErrorNotFound The mapping was not found and Address Query was not allowed.
*
*/
- otError Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery = true);
+ Error Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery = true);
/**
* This method restarts any ongoing address queries.
@@ -312,7 +312,7 @@
CacheEntry *NewCacheEntry(bool aSnoopedEntry);
void RemoveCacheEntry(CacheEntry &aEntry, CacheEntryList &aList, CacheEntry *aPrevEntry, Reason aReason);
- otError SendAddressQuery(const Ip6::Address &aEid);
+ Error SendAddressQuery(const Ip6::Address &aEid);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
diff --git a/src/core/thread/announce_begin_server.cpp b/src/core/thread/announce_begin_server.cpp
index 9183df4..1023980 100644
--- a/src/core/thread/announce_begin_server.cpp
+++ b/src/core/thread/announce_begin_server.cpp
@@ -92,7 +92,7 @@
void AnnounceBeginServer::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<AnnounceBeginServer>().AnnounceSenderBase::HandleTimer();
+ aTimer.Get<AnnounceBeginServer>().AnnounceSenderBase::HandleTimer();
}
} // namespace ot
diff --git a/src/core/thread/announce_begin_server.hpp b/src/core/thread/announce_begin_server.hpp
index 054e54a..66be807 100644
--- a/src/core/thread/announce_begin_server.hpp
+++ b/src/core/thread/announce_begin_server.hpp
@@ -64,7 +64,7 @@
* @param[in] aCount The number of transmissions per channel.
* @param[in] aPeriod The time between transmissions (milliseconds).
*
- * @retval OT_ERROR_NONE Successfully started the transmission process.
+ * @retval kErrorNone Successfully started the transmission process.
*
*/
void SendAnnounce(uint32_t aChannelMask, uint8_t aCount = kDefaultCount, uint16_t aPeriod = kDefaultPeriod);
diff --git a/src/core/thread/announce_sender.cpp b/src/core/thread/announce_sender.cpp
index f8b5495..b9787dd 100644
--- a/src/core/thread/announce_sender.cpp
+++ b/src/core/thread/announce_sender.cpp
@@ -52,7 +52,7 @@
, mJitter(0)
, mCount(0)
, mChannel(0)
- , mTimer(aInstance, aHandler, this)
+ , mTimer(aInstance, aHandler)
{
}
@@ -81,11 +81,11 @@
void AnnounceSenderBase::HandleTimer(void)
{
- otError error;
+ Error error;
error = mChannelMask.GetNextChannel(mChannel);
- if (error == OT_ERROR_NOT_FOUND)
+ if (error == kErrorNotFound)
{
if (mCount != 0)
{
@@ -97,7 +97,7 @@
error = mChannelMask.GetNextChannel(mChannel);
}
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
Get<Mle::MleRouter>().SendAnnounce(mChannel, false);
@@ -116,7 +116,7 @@
void AnnounceSender::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<AnnounceSender>().AnnounceSenderBase::HandleTimer();
+ aTimer.Get<AnnounceSender>().AnnounceSenderBase::HandleTimer();
}
void AnnounceSender::CheckState(void)
@@ -142,7 +142,7 @@
}
#endif
- // fall through
+ OT_FALL_THROUGH;
case Mle::kRoleDisabled:
case Mle::kRoleDetached:
@@ -150,7 +150,7 @@
ExitNow();
}
- VerifyOrExit(Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) == OT_ERROR_NONE, Stop());
+ VerifyOrExit(Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) == kErrorNone, Stop());
period = interval / channelMask.GetNumberOfChannels();
diff --git a/src/core/thread/child_table.cpp b/src/core/thread/child_table.cpp
index 43f5cb5..9df285a 100644
--- a/src/core/thread/child_table.cpp
+++ b/src/core/thread/child_table.cpp
@@ -43,17 +43,17 @@
ChildTable::Iterator::Iterator(Instance &aInstance, Child::StateFilter aFilter)
: InstanceLocator(aInstance)
+ , ItemPtrIterator(nullptr)
, mFilter(aFilter)
- , mChild(nullptr)
{
Reset();
}
void ChildTable::Iterator::Reset(void)
{
- mChild = &Get<ChildTable>().mChildren[0];
+ mItem = &Get<ChildTable>().mChildren[0];
- if (!mChild->MatchesFilter(mFilter))
+ if (!mItem->MatchesFilter(mFilter))
{
Advance();
}
@@ -61,13 +61,13 @@
void ChildTable::Iterator::Advance(void)
{
- VerifyOrExit(mChild != nullptr);
+ VerifyOrExit(mItem != nullptr);
do
{
- mChild++;
- VerifyOrExit(mChild < &Get<ChildTable>().mChildren[Get<ChildTable>().mMaxChildrenAllowed], mChild = nullptr);
- } while (!mChild->MatchesFilter(mFilter));
+ mItem++;
+ VerifyOrExit(mItem < &Get<ChildTable>().mChildren[Get<ChildTable>().mMaxChildrenAllowed], mItem = nullptr);
+ } while (!mItem->MatchesFilter(mFilter));
exit:
return;
@@ -168,12 +168,12 @@
return numChildren;
}
-otError ChildTable::SetMaxChildrenAllowed(uint16_t aMaxChildren)
+Error ChildTable::SetMaxChildrenAllowed(uint16_t aMaxChildren)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aMaxChildren > 0 && aMaxChildren <= kMaxChildren, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(!HasChildren(Child::kInStateAnyExceptInvalid), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aMaxChildren > 0 && aMaxChildren <= kMaxChildren, error = kErrorInvalidArgs);
+ VerifyOrExit(!HasChildren(Child::kInStateAnyExceptInvalid), error = kErrorInvalidState);
mMaxChildrenAllowed = aMaxChildren;
@@ -181,9 +181,9 @@
return error;
}
-otError ChildTable::GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo)
+Error ChildTable::GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Child * child;
uint16_t rloc16;
@@ -194,7 +194,7 @@
rloc16 = Get<Mac::Mac>().GetShortAddress() | aChildId;
child = FindChild(rloc16, Child::kInStateValidOrRestoring);
- VerifyOrExit(child != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(child != nullptr, error = kErrorNotFound);
aChildInfo.SetFrom(*child);
@@ -202,13 +202,13 @@
return error;
}
-otError ChildTable::GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo)
+Error ChildTable::GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo)
{
- otError error = OT_ERROR_NONE;
- Child * child = nullptr;
+ Error error = kErrorNone;
+ Child *child = nullptr;
child = GetChildAtIndex(aChildIndex);
- VerifyOrExit((child != nullptr) && child->IsStateValidOrRestoring(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit((child != nullptr) && child->IsStateValidOrRestoring(), error = kErrorNotFound);
aChildInfo.SetFrom(*child);
@@ -218,7 +218,7 @@
void ChildTable::Restore(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
bool foundDuplicate = false;
uint16_t numChildren = 0;
@@ -230,7 +230,7 @@
if (child == nullptr)
{
- VerifyOrExit((child = GetNewChild()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((child = GetNewChild()) != nullptr, error = kErrorNoBufs);
}
else
{
@@ -253,7 +253,7 @@
exit:
- if (foundDuplicate || (numChildren > GetMaxChildren()) || (error != OT_ERROR_NONE))
+ if (foundDuplicate || (numChildren > GetMaxChildren()) || (error != kErrorNone))
{
// If there is any error, e.g., there are more saved children
// in non-volatile settings than could be restored or there are
@@ -277,7 +277,7 @@
}
}
-otError ChildTable::StoreChild(const Child &aChild)
+Error ChildTable::StoreChild(const Child &aChild)
{
Settings::ChildInfo childInfo;
diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp
index dfc9055..fe7ff73 100644
--- a/src/core/thread/child_table.hpp
+++ b/src/core/thread/child_table.hpp
@@ -38,6 +38,7 @@
#if OPENTHREAD_FTD
+#include "common/iterator_utils.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "thread/topology.hpp"
@@ -58,8 +59,9 @@
* This class represents an iterator for iterating through the child entries in the child table.
*
*/
- class Iterator : public InstanceLocator
+ class Iterator : public InstanceLocator, public ItemPtrIterator<Child, Iterator>
{
+ friend class ItemPtrIterator<Child, Iterator>;
friend class IteratorBuilder;
public:
@@ -79,99 +81,23 @@
void Reset(void);
/**
- * This method indicates whether there are no more `Child` entries in the list (iterator has reached end of
- * the list).
- *
- * @retval TRUE There are no more entries in the list (reached end of the list).
- * @retval FALSE The current entry is valid.
- *
- */
- bool IsDone(void) const { return (mChild == nullptr); }
-
- /**
- * This method overloads `++` operator (pre-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
- * If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
- * `GetChild()` returns `nullptr` and `IsDone()` returns `true`).
- *
- */
- void operator++(void) { Advance(); }
-
- /**
- * This method overloads `++` operator (post-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
- * If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
- * `GetChild()` returns `nullptr` and `IsDone()` returns `true`).
- *
- */
- void operator++(int) { Advance(); }
-
- /**
* This method gets the `Child` entry to which the iterator is currently pointing.
*
* @returns A pointer to the `Child` entry, or `nullptr` if the iterator is done and/or empty.
*
*/
- Child *GetChild(void) { return mChild; }
-
- /**
- * This method overloads the `*` dereference operator and gets a reference to `Child` entry to which the
- * iterator is currently pointing.
- *
- * This method MUST be used when the iterator is not empty/finished (i.e., `IsDone()` returns `false`).
- *
- * @returns A reference to the `Child` entry currently pointed by the iterator.
- *
- */
- Child &operator*(void) { return *mChild; }
-
- /**
- * This method overloads the `->` dereference operator and gets a pointer to `Child` entry to which the iterator
- * is currently pointing.
- *
- * @returns A pointer to the `Child` entry associated with the iterator, or `nullptr` if iterator is empty/done.
- *
- */
- Child *operator->(void) { return mChild; }
-
- /**
- * This method overloads operator `==` to evaluate whether or not two `Iterator` instances point to the same
- * child entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `Iterator` objects point to the same child entry or both are done.
- * @retval FALSE If the two `Iterator` objects do not point to the same child entry.
- *
- */
- bool operator==(const Iterator &aOther) const { return mChild == aOther.mChild; }
-
- /**
- * This method overloads operator `!=` to evaluate whether or not two `Iterator` instances point to the same
- * child entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `Iterator` objects do not point to the same child entry.
- * @retval FALSE If the two `Iterator` objects point to the same child entry or both are done.
- *
- */
- bool operator!=(const Iterator &aOther) const { return mChild != aOther.mChild; }
+ Child *GetChild(void) { return mItem; }
private:
explicit Iterator(Instance &aInstance)
: InstanceLocator(aInstance)
, mFilter(Child::StateFilter::kInStateValid)
- , mChild(nullptr)
{
}
void Advance(void);
Child::StateFilter mFilter;
- Child * mChild;
};
/**
@@ -300,12 +226,12 @@
*
* @param[in] aMaxChildren Maximum number of children allowed.
*
- * @retval OT_ERROR_NONE The number of allowed children changed successfully.
- * @retval OT_ERROR_INVALID_ARGS If @p aMaxChildren is not in the range [1, Max supported children].
- * @retval OT_ERROR_INVALID_STATE The child table is not empty.
+ * @retval kErrorNone The number of allowed children changed successfully.
+ * @retval kErrorInvalidArgs If @p aMaxChildren is not in the range [1, Max supported children].
+ * @retval kErrorInvalidState The child table is not empty.
*
*/
- otError SetMaxChildrenAllowed(uint16_t aMaxChildren);
+ Error SetMaxChildrenAllowed(uint16_t aMaxChildren);
/**
* This method enables range-based `for` loop iteration over all child entries in the child table matching a given
@@ -329,7 +255,7 @@
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
- otError GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo);
+ Error GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo);
/**
* This method retains diagnostic information for an attached child by the internal table index.
@@ -338,7 +264,7 @@
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
- otError GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo);
+ Error GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo);
/**
* This method restores child table from non-volatile memory.
@@ -359,11 +285,11 @@
*
* @param[in] aChild A reference to the child to store.
*
- * @retval OT_ERROR_NONE Successfully store child.
- * @retval OT_ERROR_NO_BUFS Insufficient available buffers to store child.
+ * @retval kErrorNone Successfully store child.
+ * @retval kErrorNoBufs Insufficient available buffers to store child.
*
*/
- otError StoreChild(const Child &aChild);
+ Error StoreChild(const Child &aChild);
/**
* This method indicates whether the child table contains any sleepy child (in states valid or restoring) with a
diff --git a/src/core/thread/csl_tx_scheduler.cpp b/src/core/thread/csl_tx_scheduler.cpp
index 613003e..9b72a53 100644
--- a/src/core/thread/csl_tx_scheduler.cpp
+++ b/src/core/thread/csl_tx_scheduler.cpp
@@ -28,7 +28,7 @@
#include "csl_tx_scheduler.hpp"
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
@@ -42,16 +42,16 @@
{
}
-inline otError CslTxScheduler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame,
- FrameContext &aContext,
- Child & aChild)
+inline Error CslTxScheduler::Callbacks::PrepareFrameForChild(Mac::TxFrame &aFrame,
+ FrameContext &aContext,
+ Child & aChild)
{
return Get<IndirectSender>().PrepareFrameForChild(aFrame, aContext, aChild);
}
inline void CslTxScheduler::Callbacks::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
- otError aError,
+ Error aError,
Child & aChild)
{
Get<IndirectSender>().HandleSentFrameToChild(aFrame, aContext, aError, aChild);
@@ -163,23 +163,22 @@
return static_cast<uint32_t>(nextTxWindow - radioNow - mCslFrameRequestAheadUs);
}
+#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+
Mac::TxFrame *CslTxScheduler::HandleFrameRequest(Mac::TxFrames &aTxFrames)
{
Mac::TxFrame *frame = nullptr;
-
-#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
- uint32_t txDelay;
+ uint32_t txDelay;
VerifyOrExit(mCslTxChild != nullptr);
#if OPENTHREAD_CONFIG_MULTI_RADIO
- frame = &aTxFrames.GetTxFrame(kRadioTypeIeee802154);
+ frame = &aTxFrames.GetTxFrame(Mac::kRadioTypeIeee802154);
#else
frame = &aTxFrames.GetTxFrame();
#endif
- VerifyOrExit(mCallbacks.PrepareFrameForChild(*frame, mFrameContext, *mCslTxChild) == OT_ERROR_NONE,
- frame = nullptr);
+ VerifyOrExit(mCallbacks.PrepareFrameForChild(*frame, mFrameContext, *mCslTxChild) == kErrorNone, frame = nullptr);
mCslTxMessage = mCslTxChild->GetIndirectMessage();
VerifyOrExit(mCslTxMessage != nullptr, frame = nullptr);
@@ -213,11 +212,19 @@
frame->SetCsmaCaEnabled(false);
exit:
-#endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
return frame;
}
-void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError)
+#else // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+
+Mac::TxFrame *CslTxScheduler::HandleFrameRequest(Mac::TxFrames &)
+{
+ return nullptr;
+}
+
+#endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+
+void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError)
{
Child *child = mCslTxChild;
@@ -232,16 +239,16 @@
return;
}
-void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError, Child &aChild)
+void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild)
{
switch (aError)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
aChild.ResetCslTxAttempts();
aChild.ResetIndirectTxAttempts();
break;
- case OT_ERROR_NO_ACK:
+ case kErrorNoAck:
aChild.IncrementCslTxAttempts();
otLogInfoMac("CSL tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(), aChild.GetCslTxAttempts(),
@@ -254,9 +261,10 @@
aChild.ResetCslTxAttempts();
}
- // Fall through
- case OT_ERROR_CHANNEL_ACCESS_FAILURE:
- case OT_ERROR_ABORT:
+ OT_FALL_THROUGH;
+
+ case kErrorChannelAccessFailure:
+ case kErrorAbort:
// Even if CSL tx attempts count reaches max, the message won't be
// dropped until indirect tx attempts count reaches max. So here it
@@ -295,4 +303,4 @@
} // namespace ot
-#endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
diff --git a/src/core/thread/csl_tx_scheduler.hpp b/src/core/thread/csl_tx_scheduler.hpp
index 645315c..718aed3 100644
--- a/src/core/thread/csl_tx_scheduler.hpp
+++ b/src/core/thread/csl_tx_scheduler.hpp
@@ -50,7 +50,7 @@
* @{
*/
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
class Child;
@@ -142,27 +142,27 @@
* @param[out] aContext A reference to a `FrameContext` where the context for the new frame would be placed.
* @param[in] aChild The child for which to prepare the frame.
*
- * @retval OT_ERROR_NONE Frame was prepared successfully.
- * @retval OT_ERROR_ABORT CSL transmission should be aborted (no frame for the child).
+ * @retval kErrorNone Frame was prepared successfully.
+ * @retval kErrorAbort CSL transmission should be aborted (no frame for the child).
*
*/
- otError PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
+ Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
/**
* This callback method notifies the end of CSL frame transmission to a child.
*
* @param[in] aFrame The transmitted frame.
* @param[in] aContext The context associated with the frame when it was prepared.
- * @param[in] aError OT_ERROR_NONE when the frame was transmitted successfully,
- * OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
- * OT_ERROR_CHANNEL_ACCESS_FAILURE tx failed due to activity on the channel,
- * OT_ERROR_ABORT when transmission was aborted for other reasons.
+ * @param[in] aError kErrorNone when the frame was transmitted successfully,
+ * kErrorNoAck when the frame was transmitted but no ACK was received,
+ * kErrorChannelAccessFailure tx failed due to activity on the channel,
+ * kErrorAbort when transmission was aborted for other reasons.
* @param[in] aChild The child to which the frame was transmitted.
*
*/
void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
- otError aError,
+ Error aError,
Child & aChild);
};
/**
@@ -197,9 +197,9 @@
// Callbacks from `Mac`
Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames);
- void HandleSentFrame(const Mac::TxFrame &aFrame, otError aError);
+ void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError);
- void HandleSentFrame(const Mac::TxFrame &aFrame, otError aError, Child &aChild);
+ void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, Child &aChild);
uint32_t mCslFrameRequestAheadUs;
Child * mCslTxChild;
@@ -208,7 +208,7 @@
Callbacks mCallbacks;
};
-#endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
/**
* @}
diff --git a/src/core/thread/discover_scanner.cpp b/src/core/thread/discover_scanner.cpp
index 3e5720a..072e9d1 100644
--- a/src/core/thread/discover_scanner.cpp
+++ b/src/core/thread/discover_scanner.cpp
@@ -48,7 +48,7 @@
: InstanceLocator(aInstance)
, mHandler(nullptr)
, mHandlerContext(nullptr)
- , mTimer(aInstance, DiscoverScanner::HandleTimer, this)
+ , mTimer(aInstance, DiscoverScanner::HandleTimer)
, mFilterIndexes()
, mState(kStateIdle)
, mScanChannel(0)
@@ -58,22 +58,22 @@
{
}
-otError DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
- uint16_t aPanId,
- bool aJoiner,
- bool aEnableFiltering,
- const FilterIndexes * aFilterIndexes,
- Handler aCallback,
- void * aContext)
+Error DiscoverScanner::Discover(const Mac::ChannelMask &aScanChannels,
+ uint16_t aPanId,
+ bool aJoiner,
+ bool aEnableFiltering,
+ const FilterIndexes * aFilterIndexes,
+ Handler aCallback,
+ void * aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message = nullptr;
Tlv tlv;
Ip6::Address destination;
MeshCoP::DiscoveryRequestTlv discoveryRequest;
MeshCoP::JoinerAdvertisementTlv joinerAdvertisement;
- VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
+ VerifyOrExit(mState == kStateIdle, error = kErrorBusy);
mEnableFiltering = aEnableFiltering;
@@ -103,7 +103,7 @@
mScanChannels.Intersect(aScanChannels);
}
- VerifyOrExit((message = Get<Mle>().NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Mle>().NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleDiscoverRequest);
message->SetPanId(aPanId);
SuccessOrExit(error = Get<Mle>().AppendHeader(*message, Mle::kCommandDiscoveryRequest));
@@ -151,7 +151,7 @@
}
mScanChannel = Mac::ChannelMask::kChannelIteratorFirst;
- mState = (mScanChannels.GetNextChannel(mScanChannel) == OT_ERROR_NONE) ? kStateScanning : kStateScanDone;
+ mState = (mScanChannels.GetNextChannel(mScanChannel) == kErrorNone) ? kStateScanning : kStateScanDone;
Mle::Log(Mle::kMessageSend, Mle::kTypeDiscoveryRequest, destination);
@@ -160,13 +160,13 @@
return error;
}
-otError DiscoverScanner::SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength)
+Error DiscoverScanner::SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit((aAdvData != nullptr) && (aAdvDataLength != 0) &&
(aAdvDataLength <= MeshCoP::JoinerAdvertisementTlv::kAdvDataMaxLength) && (aOui <= kMaxOui),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
mOui = aOui;
mAdvDataLength = aAdvDataLength;
@@ -234,7 +234,7 @@
mTimer.Stop();
Get<MeshForwarder>().ResumeMessageTransmissions();
- // Fall through
+ OT_FALL_THROUGH;
case kStateScanDone:
Get<Mac::Mac>().ClearTemporaryChannel();
@@ -258,7 +258,7 @@
void DiscoverScanner::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<DiscoverScanner>().HandleTimer();
+ aTimer.Get<DiscoverScanner>().HandleTimer();
}
void DiscoverScanner::HandleTimer(void)
@@ -272,7 +272,7 @@
// frame tx is aborted from `PrepareDiscoveryRequestFrame()` and
// then wraps up the scan (invoking handler callback).
- if (mScanChannels.GetNextChannel(mScanChannel) != OT_ERROR_NONE)
+ if (mScanChannels.GetNextChannel(mScanChannel) != kErrorNone)
{
mState = kStateScanDone;
}
@@ -285,7 +285,7 @@
void DiscoverScanner::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const ThreadLinkInfo * linkInfo = aMessageInfo.GetThreadLinkInfo();
Tlv tlv;
MeshCoP::Tlv meshcopTlv;
@@ -298,10 +298,10 @@
Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aMessageInfo.GetPeerAddr());
- VerifyOrExit(mState == kStateScanning, error = OT_ERROR_DROP);
+ VerifyOrExit(mState == kStateScanning, error = kErrorDrop);
// Find MLE Discovery TLV
- VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == OT_ERROR_NONE, error = OT_ERROR_PARSE);
+ VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
IgnoreError(aMessage.Read(offset, tlv));
offset += sizeof(tlv);
@@ -324,7 +324,7 @@
{
case MeshCoP::Tlv::kDiscoveryResponse:
IgnoreError(aMessage.Read(offset, discoveryResponse));
- VerifyOrExit(discoveryResponse.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(discoveryResponse.IsValid(), error = kErrorParse);
result.mVersion = discoveryResponse.GetVersion();
result.mIsNative = discoveryResponse.IsNativeCommissioner();
break;
diff --git a/src/core/thread/discover_scanner.hpp b/src/core/thread/discover_scanner.hpp
index e72d8d2..e05dae7 100644
--- a/src/core/thread/discover_scanner.hpp
+++ b/src/core/thread/discover_scanner.hpp
@@ -114,18 +114,18 @@
* @param[in] aHandler A pointer to a function that is called on receiving an MLE Discovery Response.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully started a Thread Discovery Scan.
- * @retval OT_ERROR_NO_BUFS Could not allocate message for Discovery Request.
- * @retval OT_ERROR_BUSY Thread Discovery Scan is already in progress.
+ * @retval kErrorNone Successfully started a Thread Discovery Scan.
+ * @retval kErrorNoBufs Could not allocate message for Discovery Request.
+ * @retval kErrorBusy Thread Discovery Scan is already in progress.
*
*/
- otError Discover(const Mac::ChannelMask &aScanChannels,
- Mac::PanId aPanId,
- bool aJoiner,
- bool aEnableFiltering,
- const FilterIndexes * aFilterIndexes,
- Handler aCallback,
- void * aContext);
+ Error Discover(const Mac::ChannelMask &aScanChannels,
+ Mac::PanId aPanId,
+ bool aJoiner,
+ bool aEnableFiltering,
+ const FilterIndexes * aFilterIndexes,
+ Handler aCallback,
+ void * aContext);
/**
* This method indicates whether or not an MLE Thread Discovery Scan is currently in progress.
@@ -142,11 +142,11 @@
* @param[in] aAdvData A pointer to AdvData for Joiner Advertisement.
* @param[in] aAdvDataLength The length of AdvData.
*
- * @retval OT_ERROR_NONE Successfully set Joiner Advertisement.
- * @retval OT_ERROR_INVALID_ARGS Invalid AdvData.
+ * @retval kErrorNone Successfully set Joiner Advertisement.
+ * @retval kErrorInvalidArgs Invalid AdvData.
*
*/
- otError SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength);
+ Error SetJoinerAdvertisement(uint32_t aOui, const uint8_t *aAdvData, uint8_t aAdvDataLength);
private:
enum State
diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp
index a9503a1..7bc809f 100644
--- a/src/core/thread/dua_manager.cpp
+++ b/src/core/thread/dua_manager.cpp
@@ -51,7 +51,7 @@
DuaManager::DuaManager(Instance &aInstance)
: InstanceLocator(aInstance)
- , mRegistrationTask(aInstance, DuaManager::HandleRegistrationTask, this)
+ , mRegistrationTask(aInstance, DuaManager::HandleRegistrationTask)
, mDuaNotification(UriPath::kDuaRegistrationNotify, &DuaManager::HandleDuaNotification, this)
, mIsDuaPending(false)
#if OPENTHREAD_CONFIG_DUA_ENABLE
@@ -110,7 +110,8 @@
// In case removed for some reason e.g. the kDuaInvalid response from PBBR forcely
VerifyOrExit(!Get<ThreadNetif>().HasUnicastAddress(GetDomainUnicastAddress()));
- // fall through
+ OT_FALL_THROUGH;
+
case BackboneRouter::Leader::kDomainPrefixRefreshed:
case BackboneRouter::Leader::kDomainPrefixAdded:
{
@@ -143,12 +144,12 @@
}
#if OPENTHREAD_CONFIG_DUA_ENABLE
-otError DuaManager::GenerateDomainUnicastAddressIid(void)
+Error DuaManager::GenerateDomainUnicastAddressIid(void)
{
- otError error;
+ Error error;
uint8_t dadCounter = mDadCounter;
- if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, nullptr, 0, &dadCounter)) == OT_ERROR_NONE)
+ if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, nullptr, 0, &dadCounter)) == kErrorNone)
{
if (dadCounter != mDadCounter)
{
@@ -160,17 +161,17 @@
}
else
{
- otLogWarnDua("Generate DUA: %s", otThreadErrorToString(error));
+ otLogWarnDua("Generate DUA: %s", ErrorToString(error));
}
return error;
}
-otError DuaManager::SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid)
+Error DuaManager::SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!aIid.IsReserved(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aIid.IsReserved(), error = kErrorInvalidArgs);
VerifyOrExit(mFixedDuaInterfaceIdentifier.IsUnspecified() || mFixedDuaInterfaceIdentifier != aIid);
mFixedDuaInterfaceIdentifier = aIid;
@@ -197,7 +198,7 @@
{
RemoveDomainUnicastAddress();
- if (GenerateDomainUnicastAddressIid() == OT_ERROR_NONE)
+ if (GenerateDomainUnicastAddressIid() == kErrorNone)
{
AddDomainUnicastAddress();
}
@@ -221,7 +222,7 @@
return;
}
-otError DuaManager::Store(void)
+Error DuaManager::Store(void)
{
Settings::DadInfo dadInfo;
@@ -264,7 +265,7 @@
RemoveDomainUnicastAddress();
mDadCounter++;
- if (GenerateDomainUnicastAddressIid() == OT_ERROR_NONE)
+ if (GenerateDomainUnicastAddressIid() == kErrorNone)
{
AddDomainUnicastAddress();
}
@@ -276,7 +277,7 @@
uint16_t delay = 0;
otBackboneRouterConfig config;
- VerifyOrExit(Get<BackboneRouter::Leader>().GetConfig(config) == OT_ERROR_NONE);
+ VerifyOrExit(Get<BackboneRouter::Leader>().GetConfig(config) == kErrorNone);
delay = config.mReregistrationDelay > 1 ? Random::NonCrypto::GetUint16InRange(1, config.mReregistrationDelay) : 1;
@@ -395,6 +396,11 @@
UpdateTimeTickerRegistration();
}
+void DuaManager::HandleRegistrationTask(Tasklet &aTasklet)
+{
+ aTasklet.Get<DuaManager>().PerformNextRegistration();
+}
+
void DuaManager::UpdateTimeTickerRegistration(void)
{
if (mDelay.mValue == 0)
@@ -409,34 +415,41 @@
void DuaManager::PerformNextRegistration(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mle::MleRouter & mle = Get<Mle::MleRouter>();
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
Ip6::Address dua;
- VerifyOrExit(mle.IsAttached(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mle.IsAttached(), error = kErrorInvalidState);
+ VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorInvalidState);
// Only allow one outgoing DUA.req
- VerifyOrExit(!mIsDuaPending, error = OT_ERROR_BUSY);
+ VerifyOrExit(!mIsDuaPending, error = kErrorBusy);
// Only send DUA.req when necessary
#if OPENTHREAD_CONFIG_DUA_ENABLE
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
- VerifyOrExit(mle.IsRouterOrLeader() || !mle.IsExpectedToBecomeRouter(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit((mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0) ||
- (mChildDuaMask.HasAny() && mChildDuaMask != mChildDuaRegisteredMask),
- error = OT_ERROR_NOT_FOUND);
-#else
- VerifyOrExit(mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0, error = OT_ERROR_NOT_FOUND);
-#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
-
- VerifyOrExit(mle.IsFullThreadDevice() || mle.GetParent().IsThreadVersion1p1(), error = OT_ERROR_INVALID_STATE);
+#if OPENTHREAD_FTD
+ VerifyOrExit(mle.IsRouterOrLeader() || !mle.IsExpectedToBecomeRouter(), error = kErrorInvalidState);
+#endif
+ VerifyOrExit(mle.IsFullThreadDevice() || mle.GetParent().IsThreadVersion1p1(), error = kErrorInvalidState);
#endif // OPENTHREAD_CONFIG_DUA_ENABLE
+ {
+ bool needReg = false;
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+ needReg = (mDuaState == kToRegister && mDelay.mFields.mRegistrationDelay == 0);
+#endif
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
+ needReg = needReg || (mChildDuaMask.HasAny() && mChildDuaMask != mChildDuaRegisteredMask);
+#endif
+ VerifyOrExit(needReg, error = kErrorNotFound);
+ }
+
// Prepare DUA.req
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDuaRegistrationRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -508,60 +521,61 @@
mIsDuaPending = true;
mRegisteringDua = dua;
- // TODO: (DUA) need update when CSL is enabled.
+ // Generally Thread 1.2 Router would send DUA.req on behalf for DUA registered by its MTD child.
+ // When Thread 1.2 MTD attaches to Thread 1.1 parent, 1.2 MTD should send DUA.req to PBBR itself.
+ // In this case, Thread 1.2 sleepy end device relies on fast data poll to fetch the response timely.
if (!Get<Mle::Mle>().IsRxOnWhenIdle())
{
Get<DataPollSender>().SendFastPolls();
}
exit:
- if (error == OT_ERROR_NO_BUFS)
+ if (error == kErrorNoBufs)
{
UpdateCheckDelay(Mle::kNoBufDelay);
}
FreeMessageOnError(message, error);
- otLogInfoDua("Sent DUA.req for DUA %s: %s", dua.ToString().AsCString(), otThreadErrorToString(error));
+ otLogInfoDua("Sent DUA.req for DUA %s: %s", dua.ToString().AsCString(), ErrorToString(error));
}
-void DuaManager::HandleDuaResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, otError aResult)
+void DuaManager::HandleDuaResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error;
+ Error error;
mIsDuaPending = false;
- if (aResult == OT_ERROR_RESPONSE_TIMEOUT)
+ if (aResult == kErrorResponseTimeout)
{
UpdateCheckDelay(Mle::KResponseTimeoutDelay);
ExitNow(error = aResult);
}
- VerifyOrExit(aResult == OT_ERROR_NONE, error = OT_ERROR_PARSE);
+ VerifyOrExit(aResult == kErrorNone, error = kErrorParse);
VerifyOrExit(aMessage.GetCode() == Coap::kCodeChanged || aMessage.GetCode() >= Coap::kCodeBadRequest,
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
error = ProcessDuaResponse(aMessage);
exit:
- if (error != OT_ERROR_RESPONSE_TIMEOUT)
+ if (error != kErrorResponseTimeout)
{
mRegistrationTask.Post();
}
- otLogInfoDua("Received DUA.req: %s", otThreadErrorToString(error));
+ otLogInfoDua("Received DUA.req: %s", ErrorToString(error));
}
void DuaManager::HandleDuaNotification(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error;
- OT_UNUSED_VARIABLE(error);
+ Error error;
- VerifyOrExit(aMessage.IsPostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessage.IsPostRequest(), error = kErrorParse);
- if (aMessage.IsConfirmable() && Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == OT_ERROR_NONE)
+ if (aMessage.IsConfirmable() && Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
{
otLogInfoDua("Sent DUA.ntf acknowledgment");
}
@@ -569,12 +583,13 @@
error = ProcessDuaResponse(aMessage);
exit:
- otLogInfoDua("Received DUA.ntf: %d", otThreadErrorToString(error));
+ OT_UNUSED_VARIABLE(error);
+ otLogInfoDua("Received DUA.ntf: %d", ErrorToString(error));
}
-otError DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
+Error DuaManager::ProcessDuaResponse(Coap::Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address target;
uint8_t status;
@@ -622,8 +637,8 @@
{
Child *child = Get<ChildTable>().GetChildAtIndex(mChildIndexDuaRegistering);
- VerifyOrExit(child != nullptr, error = OT_ERROR_NOT_FOUND);
- VerifyOrExit(child->HasIp6Address(target), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(child != nullptr, error = kErrorNotFound);
+ VerifyOrExit(child->HasIp6Address(target), error = kErrorNotFound);
mRegisterCurrentChildIndex = false;
@@ -665,9 +680,9 @@
{
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- otError error;
+ Error error;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDuaRegistrationNotify));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -685,13 +700,13 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
FreeMessage(message);
// TODO: (DUA) (P4) may enhance to guarantee the delivery of DUA.ntf
otLogWarnDua("Sent ADDR_NTF for child %04x DUA %s Error %s", aChild.GetRloc16(),
- aAddress.ToString().AsCString(), otThreadErrorToString(error));
+ aAddress.ToString().AsCString(), ErrorToString(error));
}
}
diff --git a/src/core/thread/dua_manager.hpp b/src/core/thread/dua_manager.hpp
index ac46c6b..db83d3b 100644
--- a/src/core/thread/dua_manager.hpp
+++ b/src/core/thread/dua_manager.hpp
@@ -38,6 +38,10 @@
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
+#if OPENTHREAD_CONFIG_DUA_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_DUA_ENABLE"
+#endif
+
#include "backbone_router/bbr_leader.hpp"
#include "coap/coap.hpp"
#include "coap/coap_message.hpp"
@@ -119,11 +123,11 @@
*
* @param[in] aIid A reference to the Interface Identifier to set.
*
- * @retval OT_ERROR_NONE Successfully set the Interface Identifier.
- * @retval OT_ERROR_INVALID_ARGS The specified Interface Identifier is reserved.
+ * @retval kErrorNone Successfully set the Interface Identifier.
+ * @retval kErrorInvalidArgs The specified Interface Identifier is reserved.
*
*/
- otError SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid);
+ Error SetFixedDuaInterfaceIdentifier(const Ip6::InterfaceIdentifier &aIid);
/**
* This method clears the Interface Identifier manually specified for the Thread Domain Unicast Address.
@@ -174,8 +178,8 @@
};
#if OPENTHREAD_CONFIG_DUA_ENABLE
- otError GenerateDomainUnicastAddressIid(void);
- otError Store(void);
+ Error GenerateDomainUnicastAddressIid(void);
+ Error Store(void);
void AddDomainUnicastAddress(void);
void RemoveDomainUnicastAddress(void);
@@ -190,20 +194,17 @@
void HandleTimeTick(void);
- static void HandleRegistrationTask(Tasklet &aTasklet) { aTasklet.GetOwner<DuaManager>().PerformNextRegistration(); }
+ static void HandleRegistrationTask(Tasklet &aTasklet);
void UpdateTimeTickerRegistration(void);
- static void HandleDuaResponse(void * aContext,
- otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- otError aResult)
+ static void HandleDuaResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult)
{
static_cast<DuaManager *>(aContext)->HandleDuaResponse(
*static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
}
- void HandleDuaResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, otError aResult);
+ void HandleDuaResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aResult);
static void HandleDuaNotification(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
@@ -211,8 +212,8 @@
*static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
- void HandleDuaNotification(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- otError ProcessDuaResponse(Coap::Message &aMessage);
+ void HandleDuaNotification(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ Error ProcessDuaResponse(Coap::Message &aMessage);
void PerformNextRegistration(void);
void UpdateReregistrationDelay(void);
diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp
index e6d1e7d..dbf8598 100644
--- a/src/core/thread/energy_scan_server.cpp
+++ b/src/core/thread/energy_scan_server.cpp
@@ -55,7 +55,7 @@
, mCount(0)
, mActive(false)
, mScanResultsLength(0)
- , mTimer(aInstance, EnergyScanServer::HandleTimer, this)
+ , mTimer(aInstance, EnergyScanServer::HandleTimer)
, mEnergyScan(UriPath::kEnergyScan, &EnergyScanServer::HandleRequest, this)
{
Get<Tmf::TmfAgent>().AddResource(mEnergyScan);
@@ -106,7 +106,7 @@
void EnergyScanServer::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<EnergyScanServer>().HandleTimer();
+ aTimer.Get<EnergyScanServer>().HandleTimer();
}
void EnergyScanServer::HandleTimer(void)
@@ -169,13 +169,13 @@
void EnergyScanServer::SendReport(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::ChannelMaskTlv channelMask;
MeshCoP::EnergyListTlv energyList;
Ip6::MessageInfo messageInfo;
Coap::Message * message;
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kEnergyReport));
SuccessOrExit(error = message->SetPayloadMarker());
diff --git a/src/core/thread/indirect_sender.cpp b/src/core/thread/indirect_sender.cpp
index 1ad113c..bea9817 100644
--- a/src/core/thread/indirect_sender.cpp
+++ b/src/core/thread/indirect_sender.cpp
@@ -65,7 +65,7 @@
, mEnabled(false)
, mSourceMatchController(aInstance)
, mDataPollHandler(aInstance)
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
, mCslTxScheduler(aInstance)
#endif
{
@@ -82,7 +82,7 @@
}
mDataPollHandler.Clear();
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Clear();
#endif
@@ -109,6 +109,7 @@
if (supervisionMessage != nullptr)
{
IgnoreError(RemoveMessageFromSleepyChild(*supervisionMessage, aChild));
+ Get<MeshForwarder>().RemoveMessageIfNoPendingTx(*supervisionMessage);
}
}
@@ -118,12 +119,12 @@
return;
}
-otError IndirectSender::RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild)
+Error IndirectSender::RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
- VerifyOrExit(aMessage.GetChildMask(childIndex), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aMessage.GetChildMask(childIndex), error = kErrorNotFound);
aMessage.ClearChildMask(childIndex);
mSourceMatchController.DecrementMessageCount(aChild);
@@ -147,23 +148,14 @@
message->ClearChildMask(Get<ChildTable>().GetChildIndex(aChild));
- if (!message->IsChildPending() && !message->GetDirectTransmission())
- {
- if (Get<MeshForwarder>().mSendMessage == message)
- {
- Get<MeshForwarder>().mSendMessage = nullptr;
- }
-
- Get<MeshForwarder>().mSendQueue.Dequeue(*message);
- message->Free();
- }
+ Get<MeshForwarder>().RemoveMessageIfNoPendingTx(*message);
}
aChild.SetIndirectMessage(nullptr);
mSourceMatchController.ResetMessageCount(aChild);
mDataPollHandler.RequestFrameChange(DataPollHandler::kPurgeFrame, aChild);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
@@ -208,7 +200,7 @@
mSourceMatchController.ResetMessageCount(aChild);
mDataPollHandler.RequestFrameChange(DataPollHandler::kPurgeFrame, aChild);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
}
@@ -263,7 +255,7 @@
aChild.SetWaitingForMessageUpdate(true);
mDataPollHandler.RequestFrameChange(DataPollHandler::kPurgeFrame, aChild);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
@@ -295,7 +287,7 @@
aChild.SetWaitingForMessageUpdate(true);
mDataPollHandler.RequestFrameChange(DataPollHandler::kReplaceFrame, aChild);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
@@ -321,7 +313,7 @@
aChild.SetIndirectFragmentOffset(0);
aChild.SetIndirectTxSuccess(true);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
@@ -332,20 +324,21 @@
mDataPollHandler.HandleNewFrame(aChild);
aChild.GetMacAddress(childAddress);
- Get<MeshForwarder>().LogMessage(MeshForwarder::kMessagePrepareIndirect, *message, &childAddress, OT_ERROR_NONE);
+ Get<MeshForwarder>().LogMessage(MeshForwarder::kMessagePrepareIndirect, *message, &childAddress, kErrorNone);
}
}
-otError IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild)
+Error IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = aChild.GetIndirectMessage();
- VerifyOrExit(mEnabled, error = OT_ERROR_ABORT);
+ VerifyOrExit(mEnabled, error = kErrorAbort);
if (message == nullptr)
{
PrepareEmptyFrame(aFrame, aChild, /* aAckRequest */ true);
+ aContext.mMessageNextOffset = 0;
ExitNow();
}
@@ -422,7 +415,7 @@
void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
const FrameContext &aContext,
- otError aError,
+ Error aError,
Child & aChild)
{
Message *message = aChild.GetIndirectMessage();
@@ -430,15 +423,33 @@
VerifyOrExit(mEnabled);
+ if (aError == kErrorNone)
+ {
+ Get<Utils::ChildSupervisor>().UpdateOnSend(aChild);
+ }
+
+ // A zero `nextOffset` indicates that the sent frame is an empty
+ // frame generated by `PrepareFrameForChild()` when there was no
+ // indirect message in the send queue for the child. This can happen
+ // in the (not common) case where the radio platform does not
+ // support the "source address match" feature and always includes
+ // "frame pending" flag in acks to data poll frames. In such a case,
+ // `IndirectSender` prepares and sends an empty frame to the child
+ // after it sends a data poll. Here in `HandleSentFrameToChild()` we
+ // exit quickly if we detect the "send done" is for the empty frame
+ // to ensure we do not update any newly added indirect message after
+ // preparing the empty frame.
+
+ VerifyOrExit(nextOffset != 0);
+
switch (aError)
{
- case OT_ERROR_NONE:
- Get<Utils::ChildSupervisor>().UpdateOnSend(aChild);
+ case kErrorNone:
break;
- case OT_ERROR_NO_ACK:
- case OT_ERROR_CHANNEL_ACCESS_FAILURE:
- case OT_ERROR_ABORT:
+ case kErrorNoAck:
+ case kErrorChannelAccessFailure:
+ case kErrorAbort:
aChild.SetIndirectTxSuccess(false);
@@ -463,7 +474,7 @@
{
aChild.SetIndirectFragmentOffset(nextOffset);
mDataPollHandler.HandleNewFrame(aChild);
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mCslTxScheduler.Update();
#endif
ExitNow();
@@ -473,7 +484,7 @@
{
// The indirect tx of this message to the child is done.
- otError txError = aError;
+ Error txError = aError;
uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
Mac::Address macDest;
@@ -501,9 +512,9 @@
// represents the error status of the last fragment frame
// transmission.
- if (!aChild.GetIndirectTxSuccess() && (txError == OT_ERROR_NONE))
+ if (!aChild.GetIndirectTxSuccess() && (txError == kErrorNone))
{
- txError = OT_ERROR_FAILED;
+ txError = kErrorFailed;
}
#endif
@@ -531,11 +542,7 @@
mSourceMatchController.DecrementMessageCount(aChild);
}
- if (!message->GetDirectTransmission() && !message->IsChildPending())
- {
- Get<MeshForwarder>().mSendQueue.Dequeue(*message);
- message->Free();
- }
+ Get<MeshForwarder>().RemoveMessageIfNoPendingTx(*message);
}
UpdateIndirectMessage(aChild);
diff --git a/src/core/thread/indirect_sender.hpp b/src/core/thread/indirect_sender.hpp
index f0bca76..53cb7f1 100644
--- a/src/core/thread/indirect_sender.hpp
+++ b/src/core/thread/indirect_sender.hpp
@@ -67,7 +67,7 @@
{
friend class Instance;
friend class DataPollHandler::Callbacks;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
friend class CslTxScheduler::Callbacks;
#endif
@@ -168,11 +168,11 @@
* @param[in] aMessage The message to update.
* @param[in] aChild The (sleepy) child for indirect transmission.
*
- * @retval OT_ERROR_NONE Successfully removed the message for indirect transmission.
- * @retval OT_ERROR_NOT_FOUND The message was not scheduled for indirect transmission to the child.
+ * @retval kErrorNone Successfully removed the message for indirect transmission.
+ * @retval kErrorNotFound The message was not scheduled for indirect transmission to the child.
*
*/
- otError RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild);
+ Error RemoveMessageFromSleepyChild(Message &aMessage, Child &aChild);
/**
* This method removes all added messages for a specific child and frees message (with no indirect/direct tx).
@@ -211,12 +211,9 @@
};
// Callbacks from DataPollHandler
- otError PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
- void HandleSentFrameToChild(const Mac::TxFrame &aFrame,
- const FrameContext &aContext,
- otError aError,
- Child & aChild);
- void HandleFrameChangeDone(Child &aChild);
+ Error PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &aContext, Child &aChild);
+ void HandleSentFrameToChild(const Mac::TxFrame &aFrame, const FrameContext &aContext, Error aError, Child &aChild);
+ void HandleFrameChangeDone(Child &aChild);
void UpdateIndirectMessage(Child &aChild);
Message *FindIndirectMessage(Child &aChild, bool aSupervisionTypeOnly = false);
@@ -228,7 +225,7 @@
bool mEnabled;
SourceMatchController mSourceMatchController;
DataPollHandler mDataPollHandler;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
CslTxScheduler mCslTxScheduler;
#endif
};
diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp
index aa46902..ce8a19a 100644
--- a/src/core/thread/key_manager.cpp
+++ b/src/core/thread/key_manager.cpp
@@ -48,25 +48,6 @@
'T', 'h', 'r', 'e', 'a', 'd',
};
-const otMasterKey KeyManager::kDefaultMasterKey = {{
- 0x00,
- 0x11,
- 0x22,
- 0x33,
- 0x44,
- 0x55,
- 0x66,
- 0x77,
- 0x88,
- 0x99,
- 0xaa,
- 0xbb,
- 0xcc,
- 0xdd,
- 0xee,
- 0xff,
-}};
-
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
const uint8_t KeyManager::kHkdfExtractSaltString[] = {'T', 'h', 'r', 'e', 'a', 'd', 'S', 'e', 'q', 'u', 'e', 'n',
'c', 'e', 'M', 'a', 's', 't', 'e', 'r', 'K', 'e', 'y'};
@@ -85,13 +66,17 @@
, mKeyRotationTime(kDefaultKeyRotationTime)
, mKeySwitchGuardTime(kDefaultKeySwitchGuardTime)
, mKeySwitchGuardEnabled(false)
- , mKeyRotationTimer(aInstance, KeyManager::HandleKeyRotationTimer, this)
+ , mKeyRotationTimer(aInstance, KeyManager::HandleKeyRotationTimer)
, mKekFrameCounter(0)
, mSecurityPolicyFlags(kDefaultSecurityPolicyFlags)
, mIsPskcSet(false)
{
+ Error error = mMasterKey.GenerateRandom();
+
+ OT_ASSERT(error == kErrorNone);
+ OT_UNUSED_VARIABLE(error);
+
mMacFrameCounters.Reset();
- mMasterKey = static_cast<const MasterKey &>(kDefaultMasterKey);
mPskc.Clear();
}
@@ -114,9 +99,9 @@
}
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
-otError KeyManager::SetMasterKey(const MasterKey &aKey)
+Error KeyManager::SetMasterKey(const MasterKey &aKey)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Router *parent;
SuccessOrExit(Get<Notifier>().Update(mMasterKey, aKey, kEventMasterKeyChanged));
@@ -163,8 +148,8 @@
hmac.Start(mMasterKey.m8, sizeof(mMasterKey.m8));
Encoding::BigEndian::WriteUint32(aKeySequence, keySequenceBytes);
- hmac.Update(keySequenceBytes, sizeof(keySequenceBytes));
- hmac.Update(kThreadString, sizeof(kThreadString));
+ hmac.Update(keySequenceBytes);
+ hmac.Update(kThreadString);
hmac.Finish(aHashKeys.mHash);
}
@@ -313,11 +298,11 @@
mKekFrameCounter = 0;
}
-otError KeyManager::SetKeyRotation(uint32_t aKeyRotation)
+Error KeyManager::SetKeyRotation(uint32_t aKeyRotation)
{
- otError result = OT_ERROR_NONE;
+ Error result = kErrorNone;
- VerifyOrExit(aKeyRotation >= static_cast<uint32_t>(kMinKeyRotationTime), result = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aKeyRotation >= static_cast<uint32_t>(kMinKeyRotationTime), result = kErrorInvalidArgs);
mKeyRotationTime = aKeyRotation;
@@ -338,7 +323,7 @@
void KeyManager::HandleKeyRotationTimer(Timer &aTimer)
{
- aTimer.GetOwner<KeyManager>().HandleKeyRotationTimer();
+ aTimer.Get<KeyManager>().HandleKeyRotationTimer();
}
void KeyManager::HandleKeyRotationTimer(void)
diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp
index d73d9c0..9e661ff 100644
--- a/src/core/thread/key_manager.hpp
+++ b/src/core/thread/key_manager.hpp
@@ -73,11 +73,11 @@
/**
* This method generates a cryptographically secure random sequence to populate the Thread Master Key.
*
- * @retval OT_ERROR_NONE Successfully generated a random Thread Master Key.
- * @retval OT_ERROR_FAILED Failed to generate random sequence.
+ * @retval kErrorNone Successfully generated a random Thread Master Key.
+ * @retval kErrorFailed Failed to generate random sequence.
*
*/
- otError GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
+ Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
#endif
} OT_TOOL_PACKED_END;
@@ -93,10 +93,10 @@
/**
* This method generates a cryptographically secure random sequence to populate the Thread PSKc.
*
- * @retval OT_ERROR_NONE Successfully generated a random Thread PSKc.
+ * @retval kErrorNone Successfully generated a random Thread PSKc.
*
*/
- otError GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(Pskc)); }
+ Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(Pskc)); }
#endif
} OT_TOOL_PACKED_END;
@@ -158,11 +158,11 @@
*
* @param[in] aKey A Thread Master Key.
*
- * @retval OT_ERROR_NONE Successfully set the Thread Master Key.
- * @retval OT_ERROR_INVALID_ARGS The @p aKeyLength value was invalid.
+ * @retval kErrorNone Successfully set the Thread Master Key.
+ * @retval kErrorInvalidArgs The @p aKeyLength value was invalid.
*
*/
- otError SetMasterKey(const MasterKey &aKey);
+ Error SetMasterKey(const MasterKey &aKey);
#if OPENTHREAD_FTD || OPENTHREAD_MTD
/**
@@ -382,11 +382,11 @@
*
* @param[in] aKeyRotation The KeyRotation value in hours.
*
- * @retval OT_ERROR_NONE KeyRotation time updated.
- * @retval OT_ERROR_INVALID_ARGS @p aKeyRotation is out of range.
+ * @retval kErrorNone KeyRotation time updated.
+ * @retval kErrorInvalidArgs @p aKeyRotation is out of range.
*
*/
- otError SetKeyRotation(uint32_t aKeyRotation);
+ Error SetKeyRotation(uint32_t aKeyRotation);
/**
* This method returns the KeySwitchGuardTime.
@@ -531,8 +531,7 @@
static void HandleKeyRotationTimer(Timer &aTimer);
void HandleKeyRotationTimer(void);
- static const uint8_t kThreadString[];
- static const otMasterKey kDefaultMasterKey;
+ static const uint8_t kThreadString[];
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
static const uint8_t kHkdfExtractSaltString[];
diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp
index 95f6bea..d6d98d3 100644
--- a/src/core/thread/link_metrics.cpp
+++ b/src/core/thread/link_metrics.cpp
@@ -112,17 +112,17 @@
{
}
-otError LinkMetrics::LinkMetricsQuery(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const otLinkMetrics *aLinkMetricsFlags)
+Error LinkMetrics::LinkMetricsQuery(const Ip6::Address & aDestination,
+ uint8_t aSeriesId,
+ const otLinkMetrics *aLinkMetricsFlags)
{
- otError error;
+ Error error;
LinkMetricsTypeIdFlags typeIdFlags[kMaxTypeIdFlags];
uint8_t typeIdFlagsCount = 0;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_UNKNOWN_NEIGHBOR);
- VerifyOrExit(neighbor->IsThreadVersion1p2(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
+ VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
if (aLinkMetricsFlags != nullptr)
{
@@ -131,7 +131,7 @@
if (aSeriesId != 0)
{
- VerifyOrExit(typeIdFlagsCount == 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(typeIdFlagsCount == 0, error = kErrorInvalidArgs);
}
error = SendLinkMetricsQuery(aDestination, aSeriesId, typeIdFlags, typeIdFlagsCount);
@@ -140,12 +140,12 @@
return error;
}
-otError LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const otLinkMetricsSeriesFlags &aSeriesFlags,
- const otLinkMetrics * aLinkMetricsFlags)
+Error LinkMetrics::SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
+ uint8_t aSeriesId,
+ const otLinkMetricsSeriesFlags &aSeriesFlags,
+ const otLinkMetrics * aLinkMetricsFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t subTlvs[sizeof(Tlv) + sizeof(uint8_t) * 2 + sizeof(LinkMetricsTypeIdFlags) * kMaxTypeIdFlags];
Tlv * forwardProbingRegistrationSubTlv = reinterpret_cast<Tlv *>(subTlvs);
SeriesFlags *seriesFlags = reinterpret_cast<SeriesFlags *>(subTlvs + sizeof(Tlv) + sizeof(aSeriesId));
@@ -153,8 +153,8 @@
uint8_t typeIdFlagsCount = 0;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_UNKNOWN_NEIGHBOR);
- VerifyOrExit(neighbor->IsThreadVersion1p2(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
+ VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
// Directly transform `aLinkMetricsFlags` into LinkMetricsTypeIdFlags and put them into `subTlvs`
if (aLinkMetricsFlags != nullptr)
@@ -163,7 +163,7 @@
reinterpret_cast<LinkMetricsTypeIdFlags *>(subTlvs + typeIdFlagsOffset), *aLinkMetricsFlags);
}
- VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aSeriesId > kQueryIdSingleProbe, error = kErrorInvalidArgs);
forwardProbingRegistrationSubTlv->SetType(kForwardProbingRegistration);
forwardProbingRegistrationSubTlv->SetLength(
@@ -179,26 +179,25 @@
forwardProbingRegistrationSubTlv->GetSize());
exit:
- otLogDebgMle("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", otThreadErrorToString(error),
- aSeriesId);
+ otLogDebgMle("SendMgmtRequestForwardTrackingSeries, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
return error;
}
-otError LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
- const otLinkMetricsEnhAckFlags aEnhAckFlags,
- const otLinkMetrics * aLinkMetricsFlags)
+Error LinkMetrics::SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
+ const otLinkMetricsEnhAckFlags aEnhAckFlags,
+ const otLinkMetrics * aLinkMetricsFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
EnhAckLinkMetricsConfigurationSubTlv enhAckLinkMetricsConfigurationSubTlv;
Mac::Address macAddress;
Neighbor * neighbor = GetNeighborFromLinkLocalAddr(aDestination);
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_UNKNOWN_NEIGHBOR);
- VerifyOrExit(neighbor->IsThreadVersion1p2(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
+ VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
if (aEnhAckFlags == OT_LINK_METRICS_ENH_ACK_CLEAR)
{
- VerifyOrExit(aLinkMetricsFlags == nullptr, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aLinkMetricsFlags == nullptr, error = kErrorInvalidArgs);
}
enhAckLinkMetricsConfigurationSubTlv.SetEnhAckFlags(aEnhAckFlags);
@@ -227,28 +226,28 @@
return error;
}
-otError LinkMetrics::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength)
+Error LinkMetrics::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t buf[kLinkProbeMaxLen];
Neighbor *neighbor = GetNeighborFromLinkLocalAddr(aDestination);
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_UNKNOWN_NEIGHBOR);
- VerifyOrExit(neighbor->IsThreadVersion1p2(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(neighbor != nullptr, error = kErrorUnknownNeighbor);
+ VerifyOrExit(neighbor->IsThreadVersion1p2(), error = kErrorNotCapable);
VerifyOrExit(aLength <= LinkMetrics::kLinkProbeMaxLen && aSeriesId != kQueryIdSingleProbe &&
aSeriesId != kSeriesIdAllSeries,
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
error = Get<Mle::MleRouter>().SendLinkProbe(aDestination, aSeriesId, buf, aLength);
exit:
- otLogDebgMle("SendLinkProbe, error:%s, Series ID:%u", otThreadErrorToString(error), aSeriesId);
+ otLogDebgMle("SendLinkProbe, error:%s, Series ID:%u", ErrorToString(error), aSeriesId);
return error;
}
-otError LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor)
+Error LinkMetrics::AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Tlv tlv;
uint8_t queryId;
bool hasQueryId = false;
@@ -289,7 +288,7 @@
offset += tlv.GetSize();
}
- VerifyOrExit(hasQueryId, error = OT_ERROR_PARSE);
+ VerifyOrExit(hasQueryId, error = kErrorParse);
// Link Metrics Report TLV
tlv.SetType(Mle::Tlv::kLinkMetricsReport);
@@ -339,15 +338,15 @@
aMessage.Write(startOffset, tlv);
exit:
- otLogDebgMle("AppendLinkMetricsReport, error:%s", otThreadErrorToString(error));
+ otLogDebgMle("AppendLinkMetricsReport, error:%s", ErrorToString(error));
return error;
}
-otError LinkMetrics::HandleLinkMetricsManagementRequest(const Message & aMessage,
- Neighbor & aNeighbor,
- LinkMetricsStatus &aStatus)
+Error LinkMetrics::HandleLinkMetricsManagementRequest(const Message & aMessage,
+ Neighbor & aNeighbor,
+ LinkMetricsStatus &aStatus)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Tlv tlv;
uint8_t seriesId;
SeriesFlags seriesFlags;
@@ -371,8 +370,8 @@
switch (tlv.GetType())
{
case kForwardProbingRegistration:
- VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = OT_ERROR_PARSE);
- VerifyOrExit(tlv.GetLength() >= sizeof(seriesId) + sizeof(seriesFlags), error = OT_ERROR_PARSE);
+ VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = kErrorParse);
+ VerifyOrExit(tlv.GetLength() >= sizeof(seriesId) + sizeof(seriesFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, seriesId));
pos += sizeof(seriesId);
SuccessOrExit(aMessage.Read(pos, seriesFlags));
@@ -383,8 +382,8 @@
break;
case kEnhancedACKConfiguration:
- VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = OT_ERROR_PARSE);
- VerifyOrExit(tlv.GetLength() >= sizeof(LinkMetricsEnhAckFlags), error = OT_ERROR_PARSE);
+ VerifyOrExit(!hasForwardProbingRegistrationTlv && !hasEnhAckProbingTlv, error = kErrorParse);
+ VerifyOrExit(tlv.GetLength() >= sizeof(LinkMetricsEnhAckFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, enhAckFlags));
pos += sizeof(enhAckFlags);
SuccessOrExit(error = ReadTypeIdFlagsFromMessage(
@@ -412,9 +411,9 @@
return error;
}
-otError LinkMetrics::HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
+Error LinkMetrics::HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Tlv tlv;
uint16_t offset;
uint16_t length;
@@ -433,8 +432,8 @@
switch (tlv.GetType())
{
case kLinkMetricsStatus:
- VerifyOrExit(!hasStatus, error = OT_ERROR_PARSE);
- VerifyOrExit(tlv.GetLength() == sizeof(status), error = OT_ERROR_PARSE);
+ VerifyOrExit(!hasStatus, error = kErrorParse);
+ VerifyOrExit(tlv.GetLength() == sizeof(status), error = kErrorParse);
SuccessOrExit(aMessage.Read(offset + index + sizeof(tlv), status));
hasStatus = true;
break;
@@ -446,7 +445,7 @@
index += tlv.GetSize();
}
- VerifyOrExit(hasStatus, error = OT_ERROR_PARSE);
+ VerifyOrExit(hasStatus, error = kErrorParse);
mLinkMetricsMgmtResponseCallback(&aAddress, status, mLinkMetricsMgmtResponseCallbackContext);
@@ -459,7 +458,7 @@
uint16_t aLength,
const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
otLinkMetricsValues metricsValues;
uint8_t metricsRawValue;
uint16_t pos = aOffset;
@@ -482,14 +481,14 @@
VerifyOrExit(tlv.GetType() == kLinkMetricsReportSub);
pos += sizeof(Tlv);
- VerifyOrExit(pos + tlv.GetLength() <= endPos, error = OT_ERROR_PARSE);
+ VerifyOrExit(pos + tlv.GetLength() <= endPos, error = kErrorParse);
switch (tlv.GetType())
{
case kLinkMetricsStatus:
VerifyOrExit(!hasStatus && !hasReport,
- error = OT_ERROR_DROP); // There should be either: one Status TLV or some Report-Sub TLVs
- VerifyOrExit(tlv.GetLength() == sizeof(status), error = OT_ERROR_PARSE);
+ error = kErrorDrop); // There should be either: one Status TLV or some Report-Sub TLVs
+ VerifyOrExit(tlv.GetLength() == sizeof(status), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, status));
hasStatus = true;
pos += sizeof(status);
@@ -497,8 +496,8 @@
case kLinkMetricsReportSub:
VerifyOrExit(!hasStatus,
- error = OT_ERROR_DROP); // There shouldn't be any Report-Sub TLV when there's a Status TLV
- VerifyOrExit(tlv.GetLength() == sizeof(typeIdFlags), error = OT_ERROR_PARSE);
+ error = kErrorDrop); // There shouldn't be any Report-Sub TLV when there's a Status TLV
+ VerifyOrExit(tlv.GetLength() > sizeof(typeIdFlags), error = kErrorParse);
SuccessOrExit(aMessage.Read(pos, typeIdFlags));
if (typeIdFlags.IsExtendedFlagSet())
{
@@ -560,20 +559,20 @@
}
exit:
- otLogDebgMle("HandleLinkMetricsReport, error:%s", otThreadErrorToString(error));
+ otLogDebgMle("HandleLinkMetricsReport, error:%s", ErrorToString(error));
return;
}
-otError LinkMetrics::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId)
+Error LinkMetrics::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t offset;
uint16_t length;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length));
- VerifyOrExit(length >= sizeof(aSeriesId), error = OT_ERROR_PARSE);
+ VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offset, aSeriesId));
- VerifyOrExit(aSeriesId >= kQueryIdSingleProbe && aSeriesId <= kSeriesIdAllSeries, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aSeriesId >= kQueryIdSingleProbe && aSeriesId <= kSeriesIdAllSeries, error = kErrorInvalidArgs);
exit:
return error;
@@ -628,12 +627,12 @@
return;
}
-otError LinkMetrics::SendLinkMetricsQuery(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const LinkMetricsTypeIdFlags *aTypeIdFlags,
- uint8_t aTypeIdFlagsCount)
+Error LinkMetrics::SendLinkMetricsQuery(const Ip6::Address & aDestination,
+ uint8_t aSeriesId,
+ const LinkMetricsTypeIdFlags *aTypeIdFlags,
+ uint8_t aTypeIdFlagsCount)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
LinkMetricsQueryOptionsTlv linkMetricsQueryOptionsTlv;
uint8_t length = 0;
static const uint8_t tlvs[] = {Mle::Tlv::kLinkMetricsReport};
@@ -719,7 +718,7 @@
Neighbor & aNeighbor)
{
LinkMetricsStatus status = kLinkMetricsStatusSuccess;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(!aLinkMetrics.mReserved, status = kLinkMetricsStatusCannotSupportNewSeries);
@@ -744,7 +743,7 @@
status = kLinkMetricsStatusOtherError;
}
- VerifyOrExit(error == OT_ERROR_NONE, status = kLinkMetricsStatusOtherError);
+ VerifyOrExit(error == kErrorNone, status = kLinkMetricsStatusOtherError);
exit:
return status;
@@ -763,12 +762,12 @@
return neighbor;
}
-otError LinkMetrics::ReadTypeIdFlagsFromMessage(const Message &aMessage,
- uint8_t aStartPos,
- uint8_t aEndPos,
- otLinkMetrics &aLinkMetrics)
+Error LinkMetrics::ReadTypeIdFlagsFromMessage(const Message &aMessage,
+ uint8_t aStartPos,
+ uint8_t aEndPos,
+ otLinkMetrics &aLinkMetrics)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
memset(&aLinkMetrics, 0, sizeof(aLinkMetrics));
@@ -781,22 +780,22 @@
switch (typeIdFlags.GetRawValue())
{
case kTypeIdFlagPdu:
- VerifyOrExit(!aLinkMetrics.mPduCount, error = OT_ERROR_PARSE);
+ VerifyOrExit(!aLinkMetrics.mPduCount, error = kErrorParse);
aLinkMetrics.mPduCount = true;
break;
case kTypeIdFlagLqi:
- VerifyOrExit(!aLinkMetrics.mLqi, error = OT_ERROR_PARSE);
+ VerifyOrExit(!aLinkMetrics.mLqi, error = kErrorParse);
aLinkMetrics.mLqi = true;
break;
case kTypeIdFlagLinkMargin:
- VerifyOrExit(!aLinkMetrics.mLinkMargin, error = OT_ERROR_PARSE);
+ VerifyOrExit(!aLinkMetrics.mLinkMargin, error = kErrorParse);
aLinkMetrics.mLinkMargin = true;
break;
case kTypeIdFlagRssi:
- VerifyOrExit(!aLinkMetrics.mRssi, error = OT_ERROR_PARSE);
+ VerifyOrExit(!aLinkMetrics.mRssi, error = kErrorParse);
aLinkMetrics.mRssi = true;
break;
@@ -817,11 +816,9 @@
return error;
}
-otError LinkMetrics::AppendReportSubTlvToMessage(Message & aMessage,
- uint8_t & aLength,
- const otLinkMetricsValues &aValues)
+Error LinkMetrics::AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const otLinkMetricsValues &aValues)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
LinkMetricsReportSubTlv metric;
aLength = 0;
@@ -867,10 +864,10 @@
return error;
}
-otError LinkMetrics::AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus)
+Error LinkMetrics::AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus)
{
- otError error = OT_ERROR_NONE;
- Tlv statusTlv;
+ Error error = kErrorNone;
+ Tlv statusTlv;
statusTlv.SetType(kLinkMetricsStatus);
statusTlv.SetLength(sizeof(uint8_t));
diff --git a/src/core/thread/link_metrics.hpp b/src/core/thread/link_metrics.hpp
index e2d1c37..2ccd2e1 100644
--- a/src/core/thread/link_metrics.hpp
+++ b/src/core/thread/link_metrics.hpp
@@ -38,6 +38,10 @@
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+#if (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE."
+#endif
+
#include <openthread/ip6.h>
#include <openthread/link.h>
@@ -194,15 +198,13 @@
* @param[in] aSeriesId The Series ID to query, 0 for single probe.
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query.
*
- * @retval OT_ERROR_NONE Successfully sent a Link Metrics query message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Data Request message.
- * @retval OT_ERROR_INVALID_ARGS TypeIdFlags are not valid or exceed the count limit.
- * @retval OT_ERROR_UNKNOWN_NEIGHBOR @p aDestination is not link-local or the neighbor is not found.
+ * @retval kErrorNone Successfully sent a Link Metrics query message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
+ * @retval kErrorInvalidArgs TypeIdFlags are not valid or exceed the count limit.
+ * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
- otError LinkMetricsQuery(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const otLinkMetrics *aLinkMetricsFlags);
+ Error LinkMetricsQuery(const Ip6::Address &aDestination, uint8_t aSeriesId, const otLinkMetrics *aLinkMetricsFlags);
/**
* This method sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series.
@@ -213,17 +215,16 @@
* accounted.
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query.
*
- * @retval OT_ERROR_NONE Successfully sent a Link Metrics Management Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Link Metrics Management Request
- * message.
- * @retval OT_ERROR_INVALID_ARGS @p aSeriesId is not within the valid range.
- * @retval OT_ERROR_UNKNOWN_NEIGHBOR @p aDestination is not link-local or the neighbor is not found.
+ * @retval kErrorNone Successfully sent a Link Metrics Management Request message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
+ * @retval kErrorInvalidArgs @p aSeriesId is not within the valid range.
+ * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
- otError SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const otLinkMetricsSeriesFlags &aSeriesFlags,
- const otLinkMetrics * aLinkMetricsFlags);
+ Error SendMgmtRequestForwardTrackingSeries(const Ip6::Address & aDestination,
+ uint8_t aSeriesId,
+ const otLinkMetricsSeriesFlags &aSeriesFlags,
+ const otLinkMetrics * aLinkMetricsFlags);
/**
* This method sends an MLE Link Metrics Management Request to configure/clear a Enhanced-ACK Based Probing.
@@ -234,16 +235,15 @@
* @param[in] aLinkMetricsFlags A pointer to flags specifying what metrics to query. Should be `NULL` when
* `aEnhAckFlags` is `0`.
*
- * @retval OT_ERROR_NONE Successfully sent a Link Metrics Management Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Link Metrics Management Request
- * message.
- * @retval OT_ERROR_INVALID_ARGS @p aEnhAckFlags is not a valid value or @p aLinkMetricsFlags isn't correct.
- * @retval OT_ERROR_UNKNOWN_NEIGHBOR @p aDestination is not link-local or the neighbor is not found.
+ * @retval kErrorNone Successfully sent a Link Metrics Management Request message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
+ * @retval kErrorInvalidArgs @p aEnhAckFlags is not a valid value or @p aLinkMetricsFlags isn't correct.
+ * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
- otError SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
- otLinkMetricsEnhAckFlags aEnhAckFlags,
- const otLinkMetrics * aLinkMetricsFlags);
+ Error SendMgmtRequestEnhAckProbing(const Ip6::Address & aDestination,
+ otLinkMetricsEnhAckFlags aEnhAckFlags,
+ const otLinkMetrics * aLinkMetricsFlags);
/**
* This method sends an MLE Link Probe message.
@@ -252,13 +252,13 @@
* @param[in] aSeriesId The Series ID which the Probe message targets at.
* @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64].
*
- * @retval OT_ERROR_NONE Successfully sent a Link Probe message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Link Probe message.
- * @retval OT_ERROR_INVALID_ARGS @p aSeriesId or @p aLength is not within the valid range.
- * @retval OT_ERROR_UNKNOWN_NEIGHBOR @p aDestination is not link-local or the neighbor is not found.
+ * @retval kErrorNone Successfully sent a Link Probe message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Probe message.
+ * @retval kErrorInvalidArgs @p aSeriesId or @p aLength is not within the valid range.
+ * @retval kErrorUnknownNeighbor @p aDestination is not link-local or the neighbor is not found.
*
*/
- otError SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength);
+ Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t aLength);
/**
* This method appends a Link Metrics Report to a message according to the Link Metrics query.
@@ -267,12 +267,12 @@
* @param[in] aRequestMessage A reference to the message of the Data Request.
* @param[in] aNeighbor A reference to the neighbor who queries the report.
*
- * @retval OT_ERROR_NONE Successfully appended the Thread Discovery TLV.
- * @retval OT_ERROR_PARSE Cannot parse query sub TLV successfully.
- * @retval OT_ERROR_INVALID_ARGS QueryId is invalid or any Type ID is invalid.
+ * @retval kErrorNone Successfully appended the Thread Discovery TLV.
+ * @retval kErrorParse Cannot parse query sub TLV successfully.
+ * @retval kErrorInvalidArgs QueryId is invalid or any Type ID is invalid.
*
*/
- otError AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor);
+ Error AppendLinkMetricsReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor);
/**
* This method handles the received Link Metrics Management Request contained in @p aMessage and return a status.
@@ -281,13 +281,11 @@
* @param[in] aNeighbor A reference to the neighbor who sends the request.
* @param[out] aStatus A reference to the status which indicates the handling result.
*
- * @retval OT_ERROR_NONE Successfully handled the Link Metrics Management Request.
- * @retval OT_ERROR_PARSE Cannot parse sub-TLVs from @p aMessage successfully.
+ * @retval kErrorNone Successfully handled the Link Metrics Management Request.
+ * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully.
*
*/
- otError HandleLinkMetricsManagementRequest(const Message & aMessage,
- Neighbor & aNeighbor,
- LinkMetricsStatus &aStatus);
+ Error HandleLinkMetricsManagementRequest(const Message &aMessage, Neighbor &aNeighbor, LinkMetricsStatus &aStatus);
/**
* This method handles the received Link Metrics Management Response contained in @p aMessage.
@@ -295,11 +293,11 @@
* @param[in] aMessage A reference to the message that contains the Link Metrics Management Response.
* @param[in] aAddress A reference to the source address of the message.
*
- * @retval OT_ERROR_NONE Successfully handled the Link Metrics Management Response.
- * @retval OT_ERROR_PARSE Cannot parse sub-TLVs from @p aMessage successfully.
+ * @retval kErrorNone Successfully handled the Link Metrics Management Response.
+ * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully.
*
*/
- otError HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress);
+ Error HandleLinkMetricsManagementResponse(const Message &aMessage, const Ip6::Address &aAddress);
/**
* This method handles the received Link Metrics report contained in @p aMessage.
@@ -321,11 +319,11 @@
* @param[in] aMessage A reference to the message that contains the Link Probe Message.
* @param[out] aSeriesId A reference to Series ID that parsed from the message.
*
- * @retval OT_ERROR_NONE Successfully handled the Link Metrics Management Response.
- * @retval OT_ERROR_PARSE Cannot parse sub-TLVs from @p aMessage successfully.
+ * @retval kErrorNone Successfully handled the Link Metrics Management Response.
+ * @retval kErrorParse Cannot parse sub-TLVs from @p aMessage successfully.
*
*/
- otError HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId);
+ Error HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId);
/**
* This method registers a callback to handle Link Metrics report received.
@@ -383,10 +381,10 @@
Pool<LinkMetricsSeriesInfo, kMaxSeriesSupported> mLinkMetricsSeriesInfoPool;
- otError SendLinkMetricsQuery(const Ip6::Address & aDestination,
- uint8_t aSeriesId,
- const LinkMetricsTypeIdFlags *aTypeIdFlags,
- uint8_t aTypeIdFlagsCount);
+ Error SendLinkMetricsQuery(const Ip6::Address & aDestination,
+ uint8_t aSeriesId,
+ const LinkMetricsTypeIdFlags *aTypeIdFlags,
+ uint8_t aTypeIdFlagsCount);
LinkMetricsStatus ConfigureForwardTrackingSeries(uint8_t aSeriesId,
const SeriesFlags & aSeriesFlags,
@@ -399,14 +397,14 @@
Neighbor *GetNeighborFromLinkLocalAddr(const Ip6::Address &aDestination);
- static otError ReadTypeIdFlagsFromMessage(const Message &aMessage,
- uint8_t aStartPos,
- uint8_t aEndPos,
- otLinkMetrics &aLinkMetrics);
+ static Error ReadTypeIdFlagsFromMessage(const Message &aMessage,
+ uint8_t aStartPos,
+ uint8_t aEndPos,
+ otLinkMetrics &aLinkMetrics);
- static otError AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const otLinkMetricsValues &aValues);
+ static Error AppendReportSubTlvToMessage(Message &aMessage, uint8_t &aLength, const otLinkMetricsValues &aValues);
- static otError AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus);
+ static Error AppendStatusSubTlvToMessage(Message &aMessage, uint8_t &aLength, LinkMetricsStatus aStatus);
};
/**
diff --git a/src/core/thread/link_quality.cpp b/src/core/thread/link_quality.cpp
index e8a2ac1..0dc65a6 100644
--- a/src/core/thread/link_quality.cpp
+++ b/src/core/thread/link_quality.cpp
@@ -58,12 +58,12 @@
mFailureRate = static_cast<uint16_t>(((oldAverage * (n - 1)) + newValue + (n / 2)) / n);
}
-otError RssAverager::Add(int8_t aRss)
+Error RssAverager::Add(int8_t aRss)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t newValue;
- VerifyOrExit(aRss != OT_RADIO_RSSI_INVALID, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aRss != OT_RADIO_RSSI_INVALID, error = kErrorInvalidArgs);
// Restrict the RSS value to the closed range [0, -128] so the RSS times precision multiple can fit in 11 bits.
if (aRss > 0)
@@ -234,17 +234,17 @@
case 0:
threshold1 += kHysteresisThreshold;
- // fall-through
+ OT_FALL_THROUGH;
case 1:
threshold2 += kHysteresisThreshold;
- // fall-through
+ OT_FALL_THROUGH;
case 2:
threshold3 += kHysteresisThreshold;
- // fall-through
+ OT_FALL_THROUGH;
default:
break;
diff --git a/src/core/thread/link_quality.hpp b/src/core/thread/link_quality.hpp
index 10d06a4..91e41d2 100644
--- a/src/core/thread/link_quality.hpp
+++ b/src/core/thread/link_quality.hpp
@@ -134,16 +134,16 @@
/**
* This method adds a received signal strength (RSS) value to the average.
*
- * If @p aRss is OT_RADIO_RSSI_INVALID, it is ignored and error status OT_ERROR_INVALID_ARGS is returned.
+ * If @p aRss is OT_RADIO_RSSI_INVALID, it is ignored and error status kErrorInvalidArgs is returned.
* The value of RSS is capped at 0dBm (i.e., for any given RSS value higher than 0dBm, 0dBm is used instead).
*
* @param[in] aRss Received signal strength value (in dBm) to be added to the average.
*
- * @retval OT_ERROR_NONE New RSS value added to average successfully.
- * @retval OT_ERROR_INVALID_ARGS Value of @p aRss is OT_RADIO_RSSI_INVALID.
+ * @retval kErrorNone New RSS value added to average successfully.
+ * @retval kErrorInvalidArgs Value of @p aRss is OT_RADIO_RSSI_INVALID.
*
*/
- otError Add(int8_t aRss);
+ Error Add(int8_t aRss);
/**
* This method returns the current average signal strength value maintained by the averager.
diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp
index 27e181d..a617d2b 100644
--- a/src/core/thread/lowpan.cpp
+++ b/src/core/thread/lowpan.cpp
@@ -60,9 +60,9 @@
aAddress.SetPrefix(aContext.mPrefix);
}
-otError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress)
+Error Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
switch (aMacAddr.GetType())
{
@@ -75,7 +75,7 @@
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
if (aContext.mPrefix.GetLength() > 64)
@@ -91,13 +91,13 @@
return error;
}
-otError Lowpan::CompressSourceIid(const Mac::Address &aMacAddr,
- const Ip6::Address &aIpAddr,
- const Context & aContext,
- uint16_t & aHcCtl,
- BufferWriter & aBuf)
+Error Lowpan::CompressSourceIid(const Mac::Address &aMacAddr,
+ const Ip6::Address &aIpAddr,
+ const Context & aContext,
+ uint16_t & aHcCtl,
+ BufferWriter & aBuf)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BufferWriter buf = aBuf;
Ip6::Address ipaddr;
Mac::Address tmp;
@@ -126,7 +126,7 @@
}
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
aBuf = buf;
}
@@ -134,13 +134,13 @@
return error;
}
-otError Lowpan::CompressDestinationIid(const Mac::Address &aMacAddr,
- const Ip6::Address &aIpAddr,
- const Context & aContext,
- uint16_t & aHcCtl,
- BufferWriter & aBuf)
+Error Lowpan::CompressDestinationIid(const Mac::Address &aMacAddr,
+ const Ip6::Address &aIpAddr,
+ const Context & aContext,
+ uint16_t & aHcCtl,
+ BufferWriter & aBuf)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BufferWriter buf = aBuf;
Ip6::Address ipaddr;
Mac::Address tmp;
@@ -169,7 +169,7 @@
}
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
aBuf = buf;
}
@@ -177,9 +177,9 @@
return error;
}
-otError Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf)
+Error Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BufferWriter buf = aBuf;
Context multicastContext;
@@ -212,7 +212,7 @@
else
{
// Check if multicast address can be compressed using Context ID 0.
- if (Get<NetworkData::Leader>().GetContext(0, multicastContext) == OT_ERROR_NONE &&
+ if (Get<NetworkData::Leader>().GetContext(0, multicastContext) == kErrorNone &&
multicastContext.mPrefix.GetLength() == aIpAddr.mFields.m8[3] &&
memcmp(multicastContext.mPrefix.GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0)
{
@@ -231,7 +231,7 @@
}
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
aBuf = buf;
}
@@ -239,29 +239,29 @@
return error;
}
-otError Lowpan::Compress(Message & aMessage,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- BufferWriter & aBuf)
+Error Lowpan::Compress(Message & aMessage,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ BufferWriter & aBuf)
{
- otError error;
+ Error error;
uint8_t headerDepth = 0xff;
do
{
error = Compress(aMessage, aMacSource, aMacDest, aBuf, headerDepth);
- } while ((error != OT_ERROR_NONE) && (headerDepth > 0));
+ } while ((error != kErrorNone) && (headerDepth > 0));
return error;
}
-otError Lowpan::Compress(Message & aMessage,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- BufferWriter & aBuf,
- uint8_t & aHeaderDepth)
+Error Lowpan::Compress(Message & aMessage,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ BufferWriter & aBuf,
+ uint8_t & aHeaderDepth)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
NetworkData::Leader &networkData = Get<NetworkData::Leader>();
uint16_t startOffset = aMessage.GetOffset();
BufferWriter buf = aBuf;
@@ -279,7 +279,7 @@
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), ip6Header));
srcContextValid =
- (networkData.GetContext(ip6Header.GetSource(), srcContext) == OT_ERROR_NONE && srcContext.mCompressFlag);
+ (networkData.GetContext(ip6Header.GetSource(), srcContext) == kErrorNone && srcContext.mCompressFlag);
if (!srcContextValid)
{
@@ -287,7 +287,7 @@
}
dstContextValid =
- (networkData.GetContext(ip6Header.GetDestination(), dstContext) == OT_ERROR_NONE && dstContext.mCompressFlag);
+ (networkData.GetContext(ip6Header.GetDestination(), dstContext) == kErrorNone && dstContext.mCompressFlag);
if (!dstContextValid)
{
@@ -350,7 +350,7 @@
hcCtl |= kHcNextHeader;
break;
}
- // fall through
+ OT_FALL_THROUGH;
default:
SuccessOrExit(error = buf.Write(static_cast<uint8_t>(ip6Header.GetNextHeader())));
@@ -439,7 +439,7 @@
error = Compress(aMessage, aMacSource, aMacDest, buf);
- // fall through
+ OT_FALL_THROUGH;
default:
ExitNow();
@@ -451,7 +451,7 @@
exit:
aHeaderDepth = headerDepth;
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
IgnoreError(aBuf.Write(hcCtl >> 8));
IgnoreError(aBuf.Write(hcCtl & 0xff));
@@ -465,9 +465,9 @@
return error;
}
-otError Lowpan::CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader)
+Error Lowpan::CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BufferWriter buf = aBuf;
uint16_t startOffset = aMessage.GetOffset();
Ip6::ExtensionHeader extHeader;
@@ -498,7 +498,7 @@
len = (extHeader.GetLength() + 1) * 8 - sizeof(extHeader);
// RFC 6282 does not support compressing large extension headers
- VerifyOrExit(len <= kExtHdrMaxLength, error = OT_ERROR_FAILED);
+ VerifyOrExit(len <= kExtHdrMaxLength, error = kErrorFailed);
// RFC 6282 says: "IPv6 Hop-by-Hop and Destination Options Headers may use a trailing
// Pad1 or PadN to achieve 8-octet alignment. When there is a single trailing Pad1 or PadN
@@ -536,7 +536,7 @@
len -= padLength;
}
- VerifyOrExit(aMessage.GetOffset() + len + padLength <= aMessage.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessage.GetOffset() + len + padLength <= aMessage.GetLength(), error = kErrorParse);
aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
@@ -545,7 +545,7 @@
aMessage.MoveOffset(len + padLength);
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
aBuf = buf;
}
@@ -557,9 +557,9 @@
return error;
}
-otError Lowpan::CompressUdp(Message &aMessage, BufferWriter &aBuf)
+Error Lowpan::CompressUdp(Message &aMessage, BufferWriter &aBuf)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BufferWriter buf = aBuf;
uint16_t startOffset = aMessage.GetOffset();
Ip6::Udp::Header udpHeader;
@@ -602,7 +602,7 @@
aMessage.MoveOffset(sizeof(udpHeader));
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
aBuf = buf;
}
@@ -614,9 +614,9 @@
return error;
}
-otError Lowpan::DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader)
+Error Lowpan::DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if ((aDispatch & kExtHdrDispatchMask) == kExtHdrDispatch)
{
@@ -649,7 +649,7 @@
ExitNow();
}
- error = OT_ERROR_PARSE;
+ error = kErrorParse;
exit:
return error;
@@ -663,7 +663,7 @@
uint16_t aBufLength)
{
NetworkData::Leader &networkData = Get<NetworkData::Leader>();
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
const uint8_t * cur = aBuf;
const uint8_t * end = aBuf + aBufLength;
uint16_t hcCtl;
@@ -687,12 +687,12 @@
{
VerifyOrExit(cur < end);
- if (networkData.GetContext(cur[0] >> 4, srcContext) != OT_ERROR_NONE)
+ if (networkData.GetContext(cur[0] >> 4, srcContext) != kErrorNone)
{
srcContextValid = false;
}
- if (networkData.GetContext(cur[0] & 0xf, dstContext) != OT_ERROR_NONE)
+ if (networkData.GetContext(cur[0] & 0xf, dstContext) != kErrorNone)
{
dstContextValid = false;
}
@@ -924,15 +924,15 @@
aIp6Header.SetNextHeader(nextHeader);
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
- return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
+ return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
}
int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
const uint8_t * cur = aBuf;
const uint8_t * end = aBuf + aBufLength;
uint8_t hdr[2];
@@ -1001,15 +1001,15 @@
aMessage.MoveOffset(padLength);
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
- return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
+ return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
}
int Lowpan::DecompressUdpHeader(Ip6::Udp::Header &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
const uint8_t *cur = aBuf;
const uint8_t *end = aBuf + aBufLength;
uint8_t udpCtl;
@@ -1066,10 +1066,10 @@
cur += 2;
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
- return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
+ return (error == kErrorNone) ? static_cast<int>(cur - aBuf) : -1;
}
int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength)
@@ -1090,7 +1090,7 @@
udpHeader.SetLength(aDatagramLength - aMessage.GetOffset());
}
- VerifyOrExit(aMessage.Append(udpHeader) == OT_ERROR_NONE, headerLen = -1);
+ VerifyOrExit(aMessage.Append(udpHeader) == kErrorNone, headerLen = -1);
aMessage.MoveOffset(sizeof(udpHeader));
exit:
@@ -1104,7 +1104,7 @@
uint16_t aBufLength,
uint16_t aDatagramLength)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
Ip6::Header ip6Header;
const uint8_t *cur = aBuf;
uint16_t remaining = aBufLength;
@@ -1173,10 +1173,10 @@
aMessage.Write(currentOffset + Ip6::Header::kPayloadLengthFieldOffset, ip6PayloadLength);
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
- return (error == OT_ERROR_NONE) ? static_cast<int>(compressedLength) : -1;
+ return (error == kErrorNone) ? static_cast<int>(compressedLength) : -1;
}
//---------------------------------------------------------------------------------------------------------------------
@@ -1194,9 +1194,9 @@
return (aFrameLength >= kMinHeaderLength) && ((*aFrame & kDispatchMask) == kDispatch);
}
-otError MeshHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
+Error MeshHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
uint8_t dispatch;
VerifyOrExit(aFrameLength >= kMinHeaderLength);
@@ -1220,20 +1220,20 @@
mSource = ReadUint16(aFrame);
mDestination = ReadUint16(aFrame + 2);
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
}
-otError MeshHeader::ParseFrom(const Message &aMessage)
+Error MeshHeader::ParseFrom(const Message &aMessage)
{
uint16_t headerLength;
return ParseFrom(aMessage, headerLength);
}
-otError MeshHeader::ParseFrom(const Message &aMessage, uint16_t &aHeaderLength)
+Error MeshHeader::ParseFrom(const Message &aMessage, uint16_t &aHeaderLength)
{
uint8_t frame[kDeepHopsHeaderLength];
uint16_t frameLength;
@@ -1306,9 +1306,9 @@
return (aFrameLength >= kFirstFragmentHeaderSize) && ((*aFrame & kDispatchMask) == kDispatch);
}
-otError FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
+Error FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
VerifyOrExit(IsFragmentHeader(aFrame, aFrameLength));
@@ -1327,13 +1327,13 @@
aHeaderLength = kFirstFragmentHeaderSize;
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
}
-otError FragmentHeader::ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength)
+Error FragmentHeader::ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength)
{
uint8_t frame[kSubsequentFragmentHeaderSize];
uint16_t frameLength;
diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp
index dbb1901..e80542d 100644
--- a/src/core/thread/lowpan.hpp
+++ b/src/core/thread/lowpan.hpp
@@ -121,15 +121,15 @@
*
* @param[in] aLength Number of bytes to advance.
*
- * @retval OT_ERROR_NONE Enough buffer space is available to advance the requested number of bytes.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to advance the requested number of bytes.
+ * @retval kErrorNone Enough buffer space is available to advance the requested number of bytes.
+ * @retval kErrorNoBufs Insufficient buffer space to advance the requested number of bytes.
*
*/
- otError Advance(uint8_t aLength)
+ Error Advance(uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
mWritePointer += aLength;
exit:
@@ -141,15 +141,15 @@
*
* @param[in] aByte Byte to write.
*
- * @retval OT_ERROR_NONE Successfully wrote the byte and updated the pointer.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte.
+ * @retval kErrorNone Successfully wrote the byte and updated the pointer.
+ * @retval kErrorNoBufs Insufficient buffer space to write the byte.
*
*/
- otError Write(uint8_t aByte)
+ Error Write(uint8_t aByte)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(CanWrite(sizeof(aByte)), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanWrite(sizeof(aByte)), error = kErrorNoBufs);
*mWritePointer++ = aByte;
@@ -163,15 +163,15 @@
* @param[in] aBuf A pointer to the byte sequence.
* @param[in] aLength Number of bytes to write.
*
- * @retval OT_ERROR_NONE Successfully wrote the byte sequence and updated the pointer.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte sequence.
+ * @retval kErrorNone Successfully wrote the byte sequence and updated the pointer.
+ * @retval kErrorNoBufs Insufficient buffer space to write the byte sequence.
*
*/
- otError Write(const void *aBuf, uint8_t aLength)
+ Error Write(const void *aBuf, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
memcpy(mWritePointer, aBuf, aLength);
mWritePointer += aLength;
@@ -188,18 +188,18 @@
* @param[in] aMessage A message buffer.
* @param[in] aLength Number of bytes to write.
*
- * @retval OT_ERROR_NONE Successfully wrote the byte sequence and updated the pointer.
- * @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte sequence.
+ * @retval kErrorNone Successfully wrote the byte sequence and updated the pointer.
+ * @retval kErrorNoBufs Insufficient buffer space to write the byte sequence.
*
*/
- otError Write(const Message &aMessage, uint8_t aLength)
+ Error Write(const Message &aMessage, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
- int rval;
+ Error error = kErrorNone;
+ int rval;
OT_UNUSED_VARIABLE(rval);
- VerifyOrExit(CanWrite(aLength), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanWrite(aLength), error = kErrorNoBufs);
rval = aMessage.ReadBytes(aMessage.GetOffset(), mWritePointer, aLength);
OT_ASSERT(rval == aLength);
@@ -254,10 +254,7 @@
* @returns The size of the compressed header in bytes.
*
*/
- otError Compress(Message & aMessage,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- BufferWriter & aBuf);
+ Error Compress(Message &aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest, BufferWriter &aBuf);
/**
* This method decompresses a LOWPAN_IPHC header.
@@ -361,32 +358,32 @@
kUdpPortMask = 3 << 0,
};
- otError Compress(Message & aMessage,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- BufferWriter & aBuf,
- uint8_t & aHeaderDepth);
+ Error Compress(Message & aMessage,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ BufferWriter & aBuf,
+ uint8_t & aHeaderDepth);
- otError CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader);
- otError CompressSourceIid(const Mac::Address &aMacAddr,
- const Ip6::Address &aIpAddr,
- const Context & aContext,
- uint16_t & aHcCtl,
- BufferWriter & aBuf);
- otError CompressDestinationIid(const Mac::Address &aMacAddr,
- const Ip6::Address &aIpAddr,
- const Context & aContext,
- uint16_t & aHcCtl,
- BufferWriter & aBuf);
- otError CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf);
- otError CompressUdp(Message &aMessage, BufferWriter &aBuf);
+ Error CompressExtensionHeader(Message &aMessage, BufferWriter &aBuf, uint8_t &aNextHeader);
+ Error CompressSourceIid(const Mac::Address &aMacAddr,
+ const Ip6::Address &aIpAddr,
+ const Context & aContext,
+ uint16_t & aHcCtl,
+ BufferWriter & aBuf);
+ Error CompressDestinationIid(const Mac::Address &aMacAddr,
+ const Ip6::Address &aIpAddr,
+ const Context & aContext,
+ uint16_t & aHcCtl,
+ BufferWriter & aBuf);
+ Error CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, BufferWriter &aBuf);
+ Error CompressUdp(Message &aMessage, BufferWriter &aBuf);
- int DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength);
- int DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength);
- otError DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader);
+ int DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength);
+ int DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength);
+ Error DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader);
- static void CopyContext(const Context &aContext, Ip6::Address &aAddress);
- static otError ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress);
+ static void CopyContext(const Context &aContext, Ip6::Address &aAddress);
+ static Error ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress);
};
/**
@@ -431,11 +428,11 @@
* @param[in] aFrameLength The length of the frame.
* @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success).
*
- * @retval OT_ERROR_NONE Mesh Header parsed successfully.
- * @retval OT_ERROR_PARSE Mesh Header could not be parsed.
+ * @retval kErrorNone Mesh Header parsed successfully.
+ * @retval kErrorParse Mesh Header could not be parsed.
*
*/
- otError ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
+ Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
/**
* This method parses the Mesh Header from a given message.
@@ -444,11 +441,11 @@
*
* @param[in] aMessage The message to read from.
*
- * @retval OT_ERROR_NONE Mesh Header parsed successfully.
- * @retval OT_ERROR_PARSE Mesh Header could not be parsed.
+ * @retval kErrorNone Mesh Header parsed successfully.
+ * @retval kErrorParse Mesh Header could not be parsed.
*
*/
- otError ParseFrom(const Message &aMessage);
+ Error ParseFrom(const Message &aMessage);
/**
* This method parses the Mesh Header from a given message.
@@ -458,11 +455,11 @@
* @param[in] aMessage The message to read from.
* @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success).
*
- * @retval OT_ERROR_NONE Mesh Header parsed successfully.
- * @retval OT_ERROR_PARSE Mesh Header could not be parsed.
+ * @retval kErrorNone Mesh Header parsed successfully.
+ * @retval kErrorParse Mesh Header could not be parsed.
*
*/
- otError ParseFrom(const Message &aMessage, uint16_t &aHeaderLength);
+ Error ParseFrom(const Message &aMessage, uint16_t &aHeaderLength);
/**
* This method returns the the Mesh Header length when written to a frame.
@@ -606,11 +603,11 @@
* @param[in] aFrameLength The length of the frame.
* @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success).
*
- * @retval OT_ERROR_NONE Fragment Header parsed successfully.
- * @retval OT_ERROR_PARSE Fragment header could not be parsed from @p aFrame.
+ * @retval kErrorNone Fragment Header parsed successfully.
+ * @retval kErrorParse Fragment header could not be parsed from @p aFrame.
*
*/
- otError ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
+ Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
/**
* This method parses the Fragment Header from a message.
@@ -619,11 +616,11 @@
* @param[in] aOffset The offset within the message to start reading from.
* @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success).
*
- * @retval OT_ERROR_NONE Fragment Header parsed successfully.
- * @retval OT_ERROR_PARSE Fragment header could not be parsed from @p aFrame.
+ * @retval kErrorNone Fragment Header parsed successfully.
+ * @retval kErrorParse Fragment header could not be parsed from @p aFrame.
*
*/
- otError ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength);
+ Error ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength);
/**
* This method returns the Datagram Size value.
diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp
index a1339fe..09505cc 100644
--- a/src/core/thread/mesh_forwarder.cpp
+++ b/src/core/thread/mesh_forwarder.cpp
@@ -58,7 +58,7 @@
{
Clear();
- if (OT_ERROR_NONE != aFrame.GetSrcPanId(mPanId))
+ if (kErrorNone != aFrame.GetSrcPanId(mPanId))
{
IgnoreError(aFrame.GetDstPanId(mPanId));
}
@@ -89,7 +89,7 @@
, mEnabled(false)
, mTxPaused(false)
, mSendBusy(false)
- , mScheduleTransmissionTask(aInstance, MeshForwarder::ScheduleTransmissionTask, this)
+ , mScheduleTransmissionTask(aInstance, MeshForwarder::ScheduleTransmissionTask)
#if OPENTHREAD_FTD
, mIndirectSender(aInstance)
#endif
@@ -154,7 +154,8 @@
void MeshForwarder::PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest)
{
- uint16_t fcf = 0;
+ uint16_t fcf = 0;
+ bool iePresent = CalcIePresent(nullptr);
Mac::Address macSource;
macSource.SetShort(Get<Mac::Mac>().GetShortAddress());
@@ -166,6 +167,13 @@
fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfSecurityEnabled;
+ if (iePresent)
+ {
+ fcf |= Mac::Frame::kFcfIePresent;
+ }
+
+ fcf |= CalcFrameVersion(Get<NeighborTable>().FindNeighbor(aMacDest), iePresent);
+
if (aAckRequest)
{
fcf |= Mac::Frame::kFcfAckRequest;
@@ -173,7 +181,6 @@
fcf |= (aMacDest.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt;
fcf |= (macSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt;
- Get<Mac::Mac>().UpdateFrameControlField(Get<NeighborTable>().FindNeighbor(aMacDest), false, fcf);
aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32);
@@ -187,7 +194,10 @@
aFrame.SetSrcAddr(macSource);
aFrame.SetFramePending(false);
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
- IgnoreError(Get<Mac::Mac>().AppendHeaderIe(false, aFrame));
+ if (iePresent)
+ {
+ AppendHeaderIe(nullptr, aFrame);
+ }
#endif
aFrame.SetPayloadLength(0);
}
@@ -214,7 +224,7 @@
}
queue->Dequeue(aMessage);
- LogMessage(kMessageEvict, aMessage, nullptr, OT_ERROR_NO_BUFS);
+ LogMessage(kMessageEvict, aMessage, nullptr, kErrorNoBufs);
aMessage.Free();
}
@@ -229,7 +239,7 @@
void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
{
- aTasklet.GetOwner<MeshForwarder>().ScheduleTransmissionTask();
+ aTasklet.Get<MeshForwarder>().ScheduleTransmissionTask();
}
void MeshForwarder::ScheduleTransmissionTask(void)
@@ -253,7 +263,7 @@
Message *MeshForwarder::GetDirectTransmission(void)
{
Message *curMessage, *nextMessage;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
for (curMessage = mSendQueue.GetHead(); curMessage; curMessage = nextMessage)
{
@@ -281,12 +291,12 @@
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
case Message::kTypeMacEmptyData:
- error = OT_ERROR_NONE;
+ error = kErrorNone;
break;
#endif
default:
- error = OT_ERROR_DROP;
+ error = kErrorDrop;
break;
}
@@ -297,12 +307,12 @@
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
ExitNow();
#if OPENTHREAD_FTD
- case OT_ERROR_ADDRESS_QUERY:
+ case kErrorAddressQuery:
mSendQueue.Dequeue(*curMessage);
mResolvingQueue.Enqueue(*curMessage);
continue;
@@ -321,17 +331,17 @@
return curMessage;
}
-otError MeshForwarder::UpdateIp6Route(Message &aMessage)
+Error MeshForwarder::UpdateIp6Route(Message &aMessage)
{
Mle::MleRouter &mle = Get<Mle::MleRouter>();
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Header ip6Header;
mAddMeshHeader = false;
IgnoreError(aMessage.Read(0, ip6Header));
- VerifyOrExit(!ip6Header.GetSource().IsMulticast(), error = OT_ERROR_DROP);
+ VerifyOrExit(!ip6Header.GetSource().IsMulticast(), error = kErrorDrop);
GetMacSourceAddress(ip6Header.GetSource(), mMacSource);
@@ -343,7 +353,7 @@
}
else
{
- error = OT_ERROR_DROP;
+ error = kErrorDrop;
}
ExitNow();
@@ -432,33 +442,33 @@
}
}
-otError MeshForwarder::DecompressIp6Header(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- Ip6::Header & aIp6Header,
- uint8_t & aHeaderLength,
- bool & aNextHeaderCompressed)
+Error MeshForwarder::DecompressIp6Header(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ Ip6::Header & aIp6Header,
+ uint8_t & aHeaderLength,
+ bool & aNextHeaderCompressed)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const uint8_t * start = aFrame;
Lowpan::FragmentHeader fragmentHeader;
uint16_t fragmentHeaderLength;
int headerLength;
- if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == OT_ERROR_NONE)
+ if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
{
// Only the first fragment header is followed by a LOWPAN_IPHC header
- VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
aFrame += fragmentHeaderLength;
aFrameLength -= fragmentHeaderLength;
}
- VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound);
headerLength = Get<Lowpan::Lowpan>().DecompressBaseHeader(aIp6Header, aNextHeaderCompressed, aMacSource, aMacDest,
aFrame, aFrameLength);
- VerifyOrExit(headerLength > 0, error = OT_ERROR_PARSE);
+ VerifyOrExit(headerLength > 0, error = kErrorParse);
aHeaderLength = static_cast<uint8_t>(aFrame - start) + static_cast<uint8_t>(headerLength);
exit:
@@ -542,7 +552,7 @@
// queue for it. The message would be then converted to a
// direct tx.
- // Fall through
+ OT_FALL_THROUGH;
#endif
default:
@@ -585,17 +595,23 @@
uint16_t dstpan;
uint8_t secCtl;
uint16_t nextOffset;
+ bool iePresent = CalcIePresent(&aMessage);
start:
// Initialize MAC header
fcf = Mac::Frame::kFcfFrameData;
- Get<Mac::Mac>().UpdateFrameControlField(Get<NeighborTable>().FindNeighbor(aMacDest), aMessage.IsTimeSync(), fcf);
-
fcf |= (aMacDest.IsShort()) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt;
fcf |= (aMacSource.IsShort()) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt;
+ if (iePresent)
+ {
+ fcf |= Mac::Frame::kFcfIePresent;
+ }
+
+ fcf |= CalcFrameVersion(Get<NeighborTable>().FindNeighbor(aMacDest), iePresent);
+
// All unicast frames request ACK
if (aMacDest.IsExtended() || !aMacDest.IsBroadcast())
{
@@ -663,7 +679,10 @@
aFrame.SetSrcAddr(aMacSource);
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
- IgnoreError(Get<Mac::Mac>().AppendHeaderIe(aMessage.IsTimeSync(), aFrame));
+ if (iePresent)
+ {
+ AppendHeaderIe(&aMessage, aFrame);
+ }
#endif
payload = aFrame.GetPayload();
@@ -742,7 +761,7 @@
maxPayloadLength - headerLength - Lowpan::FragmentHeader::kFirstFragmentHeaderSize);
uint8_t hcLength;
Mac::Address meshSource, meshDest;
- otError error;
+ Error error;
OT_UNUSED_VARIABLE(error);
@@ -758,7 +777,7 @@
}
error = Get<Lowpan::Lowpan>().Compress(aMessage, meshSource, meshDest, buffer);
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
hcLength = static_cast<uint8_t>(buffer.GetWritePointer() - payload);
headerLength += hcLength;
@@ -854,7 +873,7 @@
return nextOffset;
}
-Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError aError, const Mac::Address &aMacDest)
+Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, Error aError, const Mac::Address &aMacDest)
{
Neighbor *neighbor = nullptr;
@@ -873,7 +892,7 @@
if (aFrame.GetRadioType() == Mac::kRadioTypeTrel)
#endif
{
- VerifyOrExit(aError != OT_ERROR_NONE);
+ VerifyOrExit(aError != kErrorNone);
}
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
@@ -883,15 +902,15 @@
return neighbor;
}
-void MeshForwarder::UpdateNeighborLinkFailures(Neighbor &aNeighbor, otError aError, bool aAllowNeighborRemove)
+void MeshForwarder::UpdateNeighborLinkFailures(Neighbor &aNeighbor, Error aError, bool aAllowNeighborRemove)
{
// Update neighbor `LinkFailures` counter on ack error.
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
aNeighbor.ResetLinkFailures();
}
- else if (aError == OT_ERROR_NO_ACK)
+ else if (aError == kErrorNoAck)
{
aNeighbor.IncrementLinkFailures();
@@ -904,13 +923,13 @@
}
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-void MeshForwarder::HandleDeferredAck(Neighbor &aNeighbor, otError aError)
+void MeshForwarder::HandleDeferredAck(Neighbor &aNeighbor, Error aError)
{
bool allowNeighborRemove = true;
VerifyOrExit(mEnabled);
- if (aError == OT_ERROR_NO_ACK)
+ if (aError == kErrorNoAck)
{
otLogInfoMac("Deferred ack timeout on trel for neighbor %s rloc16:0x%04x",
aNeighbor.GetExtAddress().ToString().AsCString(), aNeighbor.GetRloc16());
@@ -929,13 +948,13 @@
}
#endif // #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-void MeshForwarder::HandleSentFrame(Mac::TxFrame &aFrame, otError aError)
+void MeshForwarder::HandleSentFrame(Mac::TxFrame &aFrame, Error aError)
{
Neighbor * neighbor = nullptr;
Mac::Address macDest;
- OT_ASSERT((aError == OT_ERROR_NONE) || (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE) || (aError == OT_ERROR_ABORT) ||
- (aError == OT_ERROR_NO_ACK));
+ OT_ASSERT((aError == kErrorNone) || (aError == kErrorChannelAccessFailure) || (aError == kErrorAbort) ||
+ (aError == kErrorNoAck));
mSendBusy = false;
@@ -953,13 +972,15 @@
return;
}
-void MeshForwarder::UpdateSendMessage(otError aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor)
+void MeshForwarder::UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor)
{
+ Error txError = aFrameTxError;
+
VerifyOrExit(mSendMessage != nullptr);
OT_ASSERT(mSendMessage->GetDirectTransmission());
- if (aFrameTxError != OT_ERROR_NONE)
+ if (aFrameTxError != kErrorNone)
{
// If the transmission of any fragment frame fails,
// the overall message transmission is considered
@@ -979,57 +1000,58 @@
if (mMessageNextOffset < mSendMessage->GetLength())
{
mSendMessage->SetOffset(mMessageNextOffset);
+ ExitNow();
}
- else
+
+ txError = aFrameTxError;
+
+ mSendMessage->ClearDirectTransmission();
+ mSendMessage->SetOffset(0);
+
+ if (aNeighbor != nullptr)
{
- otError txError = aFrameTxError;
-
- mSendMessage->ClearDirectTransmission();
- mSendMessage->SetOffset(0);
-
- if (aNeighbor != nullptr)
- {
- aNeighbor->GetLinkInfo().AddMessageTxStatus(mSendMessage->GetTxSuccess());
- }
+ aNeighbor->GetLinkInfo().AddMessageTxStatus(mSendMessage->GetTxSuccess());
+ }
#if !OPENTHREAD_CONFIG_DROP_MESSAGE_ON_FRAGMENT_TX_FAILURE
- // When `CONFIG_DROP_MESSAGE_ON_FRAGMENT_TX_FAILURE` is
- // disabled, all fragment frames of a larger message are
- // sent even if the transmission of an earlier fragment fail.
- // Note that `GetTxSuccess() tracks the tx success of the
- // entire message, while `aFrameTxError` represents the error
- // status of the last fragment frame transmission.
+ // When `CONFIG_DROP_MESSAGE_ON_FRAGMENT_TX_FAILURE` is
+ // disabled, all fragment frames of a larger message are
+ // sent even if the transmission of an earlier fragment fail.
+ // Note that `GetTxSuccess() tracks the tx success of the
+ // entire message, while `aFrameTxError` represents the error
+ // status of the last fragment frame transmission.
- if (!mSendMessage->GetTxSuccess() && (txError == OT_ERROR_NONE))
- {
- txError = OT_ERROR_FAILED;
- }
+ if (!mSendMessage->GetTxSuccess() && (txError == kErrorNone))
+ {
+ txError = kErrorFailed;
+ }
#endif
- LogMessage(kMessageTransmit, *mSendMessage, &aMacDest, txError);
+ LogMessage(kMessageTransmit, *mSendMessage, &aMacDest, txError);
- if (mSendMessage->GetType() == Message::kTypeIp6)
+ if (mSendMessage->GetType() == Message::kTypeIp6)
+ {
+ if (mSendMessage->GetTxSuccess())
{
- if (mSendMessage->GetTxSuccess())
- {
- mIpCounters.mTxSuccess++;
- }
- else
- {
- mIpCounters.mTxFailure++;
- }
+ mIpCounters.mTxSuccess++;
+ }
+ else
+ {
+ mIpCounters.mTxFailure++;
}
}
- if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
+ switch (mSendMessage->GetSubType())
{
+ case Message::kSubTypeMleDiscoverRequest:
+ // Note that `HandleDiscoveryRequestFrameTxDone()` may update
+ // `mSendMessage` and mark it again for direct transmission.
Get<Mle::DiscoverScanner>().HandleDiscoveryRequestFrameTxDone(*mSendMessage);
- }
+ break;
- if (!mSendMessage->GetDirectTransmission() && !mSendMessage->IsChildPending())
- {
- if (mSendMessage->GetSubType() == Message::kSubTypeMleChildIdRequest && mSendMessage->IsLinkSecurityEnabled())
+ case Message::kSubTypeMleChildIdRequest:
+ if (mSendMessage->IsLinkSecurityEnabled())
{
// If the Child ID Request requires fragmentation and therefore
// link layer security, the frame transmission will be aborted.
@@ -1041,14 +1063,33 @@
Get<Mle::Mle>().RequestShorterChildIdRequest();
}
- mSendQueue.Dequeue(*mSendMessage);
- mSendMessage->Free();
+ break;
+
+ default:
+ break;
+ }
+
+ RemoveMessageIfNoPendingTx(*mSendMessage);
+
+exit:
+ mScheduleTransmissionTask.Post();
+}
+
+void MeshForwarder::RemoveMessageIfNoPendingTx(Message &aMessage)
+{
+ VerifyOrExit(!aMessage.GetDirectTransmission() && !aMessage.IsChildPending());
+
+ if (mSendMessage == &aMessage)
+ {
mSendMessage = nullptr;
mMessageNextOffset = 0;
}
+ mSendQueue.Dequeue(aMessage);
+ aMessage.Free();
+
exit:
- mScheduleTransmissionTask.Post();
+ return;
}
void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
@@ -1058,9 +1099,9 @@
Mac::Address macSource;
uint8_t * payload;
uint16_t payloadLength;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mEnabled, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mEnabled, error = kErrorInvalidState);
SuccessOrExit(error = aFrame.GetSrcAddr(macSource));
SuccessOrExit(error = aFrame.GetDstAddr(macDest));
@@ -1091,9 +1132,9 @@
}
else
{
- VerifyOrExit(payloadLength == 0, error = OT_ERROR_NOT_LOWPAN_DATA_FRAME);
+ VerifyOrExit(payloadLength == 0, error = kErrorNotLowpanDataFrame);
- LogFrame("Received empty payload frame", aFrame, OT_ERROR_NONE);
+ LogFrame("Received empty payload frame", aFrame, kErrorNone);
}
break;
@@ -1102,13 +1143,13 @@
break;
default:
- error = OT_ERROR_DROP;
+ error = kErrorDrop;
break;
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
LogFrame("Dropping rx frame", aFrame, error);
}
@@ -1120,7 +1161,7 @@
const Mac::Address & aMacDest,
const ThreadLinkInfo &aLinkInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Lowpan::FragmentHeader fragmentHeader;
uint16_t fragmentHeaderLength;
Message * message = nullptr;
@@ -1142,11 +1183,11 @@
if (neighbor->IsLastRxFragmentTagSet())
{
- VerifyOrExit(!neighbor->IsLastRxFragmentTagAfter(tag), error = OT_ERROR_DUPLICATED);
+ VerifyOrExit(!neighbor->IsLastRxFragmentTagAfter(tag), error = kErrorDuplicated);
if (neighbor->GetLastRxFragmentTag() == tag)
{
- VerifyOrExit(fragmentHeader.GetDatagramOffset() != 0, error = OT_ERROR_DUPLICATED);
+ VerifyOrExit(fragmentHeader.GetDatagramOffset() != 0, error = kErrorDuplicated);
// Duplication suppression for a "next fragment" is handled
// by the code below where the the datagram offset is
@@ -1172,7 +1213,7 @@
error = FrameToMessage(aFrame, aFrameLength, datagramSize, aMacSource, aMacDest, message);
SuccessOrExit(error);
- VerifyOrExit(datagramSize >= message->GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(datagramSize >= message->GetLength(), error = kErrorParse);
error = message->SetLength(datagramSize);
SuccessOrExit(error);
@@ -1180,7 +1221,7 @@
message->SetTimeout(kReassemblyTimeout);
message->SetLinkInfo(aLinkInfo);
- VerifyOrExit(Get<Ip6::Filter>().Accept(*message), error = OT_ERROR_DROP);
+ VerifyOrExit(Get<Ip6::Filter>().Accept(*message), error = kErrorDrop);
#if OPENTHREAD_FTD
SendIcmpErrorIfDstUnreach(*message, aMacSource, aMacDest);
@@ -1225,7 +1266,7 @@
ClearReassemblyList();
}
- VerifyOrExit(message != nullptr, error = OT_ERROR_DROP);
+ VerifyOrExit(message != nullptr, error = kErrorDrop);
message->WriteBytes(message->GetOffset(), aFrame, aFrameLength);
message->MoveOffset(aFrameLength);
@@ -1238,7 +1279,7 @@
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
if (message->GetOffset() >= message->GetLength())
{
@@ -1264,7 +1305,7 @@
next = message->GetNext();
mReassemblyList.Dequeue(*message);
- LogMessage(kMessageReassemblyDrop, *message, nullptr, OT_ERROR_NO_FRAME_RECEIVED);
+ LogMessage(kMessageReassemblyDrop, *message, nullptr, kErrorNoFrameReceived);
if (message->GetType() == Message::kTypeIp6)
{
@@ -1307,7 +1348,7 @@
{
mReassemblyList.Dequeue(*message);
- LogMessage(kMessageReassemblyDrop, *message, nullptr, OT_ERROR_REASSEMBLY_TIMEOUT);
+ LogMessage(kMessageReassemblyDrop, *message, nullptr, kErrorReassemblyTimeout);
if (message->GetType() == Message::kTypeIp6)
{
mIpCounters.mRxFailure++;
@@ -1320,14 +1361,14 @@
return mReassemblyList.GetHead() != nullptr;
}
-otError MeshForwarder::FrameToMessage(const uint8_t * aFrame,
- uint16_t aFrameLength,
- uint16_t aDatagramSize,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- Message *& aMessage)
+Error MeshForwarder::FrameToMessage(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ uint16_t aDatagramSize,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ Message *& aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
int headerLength;
Message::Priority priority;
@@ -1335,11 +1376,11 @@
SuccessOrExit(error);
aMessage = Get<MessagePool>().New(Message::kTypeIp6, 0, priority);
- VerifyOrExit(aMessage, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aMessage, error = kErrorNoBufs);
headerLength =
Get<Lowpan::Lowpan>().Decompress(*aMessage, aMacSource, aMacDest, aFrame, aFrameLength, aDatagramSize);
- VerifyOrExit(headerLength > 0, error = OT_ERROR_PARSE);
+ VerifyOrExit(headerLength > 0, error = kErrorParse);
aFrame += headerLength;
aFrameLength -= static_cast<uint16_t>(headerLength);
@@ -1358,7 +1399,7 @@
const Mac::Address & aMacDest,
const ThreadLinkInfo &aLinkInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = nullptr;
#if OPENTHREAD_FTD
@@ -1369,7 +1410,7 @@
message->SetLinkInfo(aLinkInfo);
- VerifyOrExit(Get<Ip6::Filter>().Accept(*message), error = OT_ERROR_DROP);
+ VerifyOrExit(Get<Ip6::Filter>().Accept(*message), error = kErrorDrop);
#if OPENTHREAD_FTD
SendIcmpErrorIfDstUnreach(*message, aMacSource, aMacDest);
@@ -1377,7 +1418,7 @@
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
IgnoreError(HandleDatagram(*message, aLinkInfo, aMacSource));
}
@@ -1388,13 +1429,11 @@
}
}
-otError MeshForwarder::HandleDatagram(Message & aMessage,
- const ThreadLinkInfo &aLinkInfo,
- const Mac::Address & aMacSource)
+Error MeshForwarder::HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource)
{
ThreadNetif &netif = Get<ThreadNetif>();
- LogMessage(kMessageReceive, aMessage, &aMacSource, OT_ERROR_NONE);
+ LogMessage(kMessageReceive, aMessage, &aMacSource, kErrorNone);
if (aMessage.GetType() == Message::kTypeIp6)
{
@@ -1404,13 +1443,13 @@
return Get<Ip6::Ip6>().HandleDatagram(aMessage, &netif, &aLinkInfo, false);
}
-otError MeshForwarder::GetFramePriority(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- Message::Priority & aPriority)
+Error MeshForwarder::GetFramePriority(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ Message::Priority & aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Header ip6Header;
uint16_t dstPort;
uint8_t headerLength;
@@ -1427,7 +1466,7 @@
{
case Ip6::kProtoIcmp6:
- VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = OT_ERROR_PARSE);
+ VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = kErrorParse);
// Only ICMPv6 error messages are prioritized.
if (reinterpret_cast<const Ip6::Icmp::Header *>(aFrame)->IsError())
@@ -1444,13 +1483,13 @@
Ip6::Udp::Header udpHeader;
VerifyOrExit(Get<Lowpan::Lowpan>().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0,
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
dstPort = udpHeader.GetDestinationPort();
}
else
{
- VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = OT_ERROR_PARSE);
+ VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = kErrorParse);
dstPort = reinterpret_cast<const Ip6::Udp::Header *>(aFrame)->GetDestinationPort();
}
@@ -1470,38 +1509,111 @@
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError MeshForwarder::SendEmptyMessage(void)
+Error MeshForwarder::SendEmptyMessage(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message = nullptr;
VerifyOrExit(mEnabled && !Get<Mac::Mac>().GetRxOnWhenIdle() &&
Get<Mle::MleRouter>().GetParent().IsStateValidOrRestoring(),
- error = OT_ERROR_INVALID_STATE);
+ error = kErrorInvalidState);
message = Get<MessagePool>().New(Message::kTypeMacEmptyData, 0);
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = SendMessage(*message));
exit:
FreeMessageOnError(message, error);
- otLogDebgMac("Send empty message, error:%s", otThreadErrorToString(error));
+ otLogDebgMac("Send empty message, error:%s", ErrorToString(error));
return error;
}
#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+bool MeshForwarder::CalcIePresent(const Message *aMessage)
+{
+ bool iePresent = false;
+
+ OT_UNUSED_VARIABLE(aMessage);
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+ iePresent |= (aMessage != nullptr && aMessage->IsTimeSync());
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ iePresent |= Get<Mac::Mac>().IsCslEnabled();
+#endif
+
+ return iePresent;
+}
+
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+void MeshForwarder::AppendHeaderIe(const Message *aMessage, Mac::Frame &aFrame)
+{
+ uint8_t index = 0;
+ bool iePresent = false;
+ bool payloadPresent =
+ (aFrame.GetType() == Mac::Frame::kFcfFrameMacCmd) || (aMessage != nullptr && aMessage->GetLength() != 0);
+
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+ if (aMessage != nullptr && aMessage->IsTimeSync())
+ {
+ IgnoreError(aFrame.AppendHeaderIeAt<Mac::TimeIe>(index));
+ iePresent = true;
+ }
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ if (Get<Mac::Mac>().IsCslEnabled())
+ {
+ IgnoreError(aFrame.AppendHeaderIeAt<Mac::CslIe>(index));
+ iePresent = true;
+ }
+#endif
+
+ if (iePresent && payloadPresent)
+ {
+ // Assume no Payload IE in current implementation
+ IgnoreError(aFrame.AppendHeaderIeAt<Mac::Termination2Ie>(index));
+ }
+}
+#endif
+
+uint16_t MeshForwarder::CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent)
+{
+ uint16_t version = Mac::Frame::kFcfFrameVersion2006;
+ OT_UNUSED_VARIABLE(aNeighbor);
+
+ if (aIePresent)
+ {
+ version = Mac::Frame::kFcfFrameVersion2015;
+ }
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+ else if (aNeighbor != nullptr && !Mle::MleRouter::IsActiveRouter(aNeighbor->GetRloc16()) &&
+ static_cast<const Child *>(aNeighbor)->IsCslSynchronized())
+ {
+ version = Mac::Frame::kFcfFrameVersion2015;
+ }
+#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ else if (aNeighbor != nullptr && aNeighbor->IsEnhAckProbingActive())
+ {
+ version = Mac::Frame::kFcfFrameVersion2015; ///< Set version to 2015 to fetch Link Metrics data in Enh-ACK.
+ }
+#endif
+
+ return version;
+}
+
// LCOV_EXCL_START
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
-otError MeshForwarder::ParseIp6UdpTcpHeader(const Message &aMessage,
- Ip6::Header & aIp6Header,
- uint16_t & aChecksum,
- uint16_t & aSourcePort,
- uint16_t & aDestPort)
+Error MeshForwarder::ParseIp6UdpTcpHeader(const Message &aMessage,
+ Ip6::Header & aIp6Header,
+ uint16_t & aChecksum,
+ uint16_t & aSourcePort,
+ uint16_t & aDestPort)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
union
{
Ip6::Udp::Header udp;
@@ -1535,70 +1647,36 @@
break;
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
}
-const char *MeshForwarder::MessageActionToString(MessageAction aAction, otError aError)
+const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aError)
{
- const char *actionText = "";
+ static const char *const kMessageActionStrings[] = {
+ "Received", // (0) kMessageReceive
+ "Sent", // (1) kMessageTransmit
+ "Prepping indir tx", // (2) kMessagePrepareIndirect
+ "Dropping", // (3) kMessageDrop
+ "Dropping (reassembly queue)", // (4) kMessageReassemblyDrop
+ "Evicting", // (5) kMessageEvict
+ };
- switch (aAction)
- {
- case kMessageReceive:
- actionText = "Received";
- break;
+ static_assert(kMessageReceive == 0, "kMessageReceive value is incorrect");
+ static_assert(kMessageTransmit == 1, "kMessageTransmit value is incorrect");
+ static_assert(kMessagePrepareIndirect == 2, "kMessagePrepareIndirect value is incorrect");
+ static_assert(kMessageDrop == 3, "kMessageDrop value is incorrect");
+ static_assert(kMessageReassemblyDrop == 4, "kMessageReassemblyDrop value is incorrect");
+ static_assert(kMessageEvict == 5, "kMessageEvict value is incorrect");
- case kMessageTransmit:
- actionText = (aError == OT_ERROR_NONE) ? "Sent" : "Failed to send";
- break;
-
- case kMessagePrepareIndirect:
- actionText = "Prepping indir tx";
- break;
-
- case kMessageDrop:
- actionText = "Dropping";
- break;
-
- case kMessageReassemblyDrop:
- actionText = "Dropping (reassembly queue)";
- break;
-
- case kMessageEvict:
- actionText = "Evicting";
- break;
- }
-
- return actionText;
+ return (aError == kErrorNone) ? kMessageActionStrings[aAction] : "Failed to send";
}
const char *MeshForwarder::MessagePriorityToString(const Message &aMessage)
{
- const char *priorityText = "unknown";
-
- switch (aMessage.GetPriority())
- {
- case Message::kPriorityNet:
- priorityText = "net";
- break;
-
- case Message::kPriorityHigh:
- priorityText = "high";
- break;
-
- case Message::kPriorityNormal:
- priorityText = "normal";
- break;
-
- case Message::kPriorityLow:
- priorityText = "low";
- break;
- }
-
- return priorityText;
+ return Message::PriorityToString(aMessage.GetPriority());
}
#if OPENTHREAD_CONFIG_LOG_SRC_DST_IP_ADDRESSES
@@ -1634,7 +1712,7 @@
void MeshForwarder::LogIp6Message(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
- otError aError,
+ Error aError,
otLogLevel aLogLevel)
{
Ip6::Header ip6Header;
@@ -1659,10 +1737,11 @@
aMessage.GetLength(), checksum,
(aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
(aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(),
- aMessage.IsLinkSecurityEnabled() ? "yes" : "no", (aError == OT_ERROR_NONE) ? "" : ", error:",
- (aError == OT_ERROR_NONE) ? "" : otThreadErrorToString(aError), MessagePriorityToString(aMessage),
- shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "",
- shouldLogRadio ? ", radio:" : "", radioString);
+ aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
+ (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
+ MessagePriorityToString(aMessage), shouldLogRss ? ", rss:" : "",
+ shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "", shouldLogRadio ? ", radio:" : "",
+ radioString);
if (aAction != kMessagePrepareIndirect)
{
@@ -1676,7 +1755,7 @@
void MeshForwarder::LogMessage(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
- otError aError)
+ Error aError)
{
otLogLevel logLevel = OT_LOG_LEVEL_INFO;
@@ -1685,7 +1764,7 @@
case kMessageReceive:
case kMessageTransmit:
case kMessagePrepareIndirect:
- logLevel = (aError == OT_ERROR_NONE) ? OT_LOG_LEVEL_INFO : OT_LOG_LEVEL_NOTE;
+ logLevel = (aError == kErrorNone) ? OT_LOG_LEVEL_INFO : OT_LOG_LEVEL_NOTE;
break;
case kMessageDrop:
@@ -1717,12 +1796,11 @@
return;
}
-void MeshForwarder::LogFrame(const char *aActionText, const Mac::Frame &aFrame, otError aError)
+void MeshForwarder::LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError)
{
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
- otLogNoteMac("%s, aError:%s, %s", aActionText, otThreadErrorToString(aError),
- aFrame.ToInfoString().AsCString());
+ otLogNoteMac("%s, aError:%s, %s", aActionText, ErrorToString(aError), aFrame.ToInfoString().AsCString());
}
else
{
@@ -1730,7 +1808,7 @@
}
}
-void MeshForwarder::LogFragmentFrameDrop(otError aError,
+void MeshForwarder::LogFragmentFrameDrop(Error aError,
uint16_t aFrameLength,
const Mac::Address & aMacSource,
const Mac::Address & aMacDest,
@@ -1738,33 +1816,33 @@
bool aIsSecure)
{
otLogNoteMac("Dropping rx frag frame, error:%s, len:%d, src:%s, dst:%s, tag:%d, offset:%d, dglen:%d, sec:%s",
- otThreadErrorToString(aError), aFrameLength, aMacSource.ToString().AsCString(),
+ ErrorToString(aError), aFrameLength, aMacSource.ToString().AsCString(),
aMacDest.ToString().AsCString(), aFragmentHeader.GetDatagramTag(), aFragmentHeader.GetDatagramOffset(),
aFragmentHeader.GetDatagramSize(), aIsSecure ? "yes" : "no");
}
-void MeshForwarder::LogLowpanHcFrameDrop(otError aError,
+void MeshForwarder::LogLowpanHcFrameDrop(Error aError,
uint16_t aFrameLength,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
bool aIsSecure)
{
- otLogNoteMac("Dropping rx lowpan HC frame, error:%s, len:%d, src:%s, dst:%s, sec:%s", otThreadErrorToString(aError),
+ otLogNoteMac("Dropping rx lowpan HC frame, error:%s, len:%d, src:%s, dst:%s, sec:%s", ErrorToString(aError),
aFrameLength, aMacSource.ToString().AsCString(), aMacDest.ToString().AsCString(),
aIsSecure ? "yes" : "no");
}
#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
-void MeshForwarder::LogMessage(MessageAction, const Message &, const Mac::Address *, otError)
+void MeshForwarder::LogMessage(MessageAction, const Message &, const Mac::Address *, Error)
{
}
-void MeshForwarder::LogFrame(const char *, const Mac::Frame &, otError)
+void MeshForwarder::LogFrame(const char *, const Mac::Frame &, Error)
{
}
-void MeshForwarder::LogFragmentFrameDrop(otError,
+void MeshForwarder::LogFragmentFrameDrop(Error,
uint16_t,
const Mac::Address &,
const Mac::Address &,
@@ -1773,7 +1851,7 @@
{
}
-void MeshForwarder::LogLowpanHcFrameDrop(otError, uint16_t, const Mac::Address &, const Mac::Address &, bool)
+void MeshForwarder::LogLowpanHcFrameDrop(Error, uint16_t, const Mac::Address &, const Mac::Address &, bool)
{
}
diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp
index 6a54d58..3758de4 100644
--- a/src/core/thread/mesh_forwarder.hpp
+++ b/src/core/thread/mesh_forwarder.hpp
@@ -44,6 +44,7 @@
#include "mac/channel_mask.hpp"
#include "mac/data_poll_sender.hpp"
#include "mac/mac.hpp"
+#include "mac/mac_frame.hpp"
#include "net/ip6.hpp"
#include "thread/address_resolver.hpp"
#include "thread/indirect_sender.hpp"
@@ -180,33 +181,33 @@
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully enqueued the message.
- * @retval OT_ERROR_ALREADY The message was already enqueued.
- * @retval OT_ERROR_DROP The message could not be sent and should be dropped.
+ * @retval kErrorNone Successfully enqueued the message.
+ * @retval kErrorAlready The message was already enqueued.
+ * @retval kErrorDrop The message could not be sent and should be dropped.
*
*/
- otError SendMessage(Message &aMessage);
+ Error SendMessage(Message &aMessage);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
* This method sends an empty data frame to the parent.
*
- * @retval OT_ERROR_NONE Successfully enqueued an empty message.
- * @retval OT_ERROR_INVALID_STATE Device is not in Rx-Off-When-Idle mode or it has no parent.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers available.
+ * @retval kErrorNone Successfully enqueued an empty message.
+ * @retval kErrorInvalidState Device is not in Rx-Off-When-Idle mode or it has no parent.
+ * @retval kErrorNoBufs Insufficient message buffers available.
*
*/
- otError SendEmptyMessage(void);
+ Error SendEmptyMessage(void);
#endif
/**
* This method is called by the address resolver when an EID-to-RLOC mapping has been resolved.
*
* @param[in] aEid A reference to the EID that has been resolved.
- * @param[in] aError OT_ERROR_NONE on success and OT_ERROR_DROP otherwise.
+ * @param[in] aError kErrorNone on success and kErrorDrop otherwise.
*
*/
- void HandleResolved(const Ip6::Address &aEid, otError aError);
+ void HandleResolved(const Ip6::Address &aEid, Error aError);
/**
* This method indicates whether or not rx-on-when-idle mode is enabled.
@@ -235,12 +236,6 @@
void SetDiscoverParameters(const Mac::ChannelMask &aScanChannels);
/**
- * This method frees any indirect messages queued for children that are no longer attached.
- *
- */
- void UpdateIndirectMessages(void);
-
- /**
* This method frees any messages queued for an existing child.
*
* @param[in] aChild A reference to the child.
@@ -261,11 +256,11 @@
*
* @param[in] aPriority The highest priority level of the evicted message.
*
- * @retval OT_ERROR_NONE Successfully evicted a low priority message.
- * @retval OT_ERROR_NOT_FOUND No low priority messages available to evict.
+ * @retval kErrorNone Successfully evicted a low priority message.
+ * @retval kErrorNotFound No low priority messages available to evict.
*
*/
- otError EvictMessage(Message::Priority aPriority);
+ Error EvictMessage(Message::Priority aPriority);
/**
* This method returns a reference to the send queue.
@@ -317,11 +312,11 @@
* on the radio link.
*
* @param[in] aNeighbor The neighbor for which the deferred ack status is being reported.
- * @param[in] aTxError The deferred ack error status: `OT_ERROR_NONE` to indicate a deferred ack was received,
- * `OT_ERROR_NO_ACK` to indicate an ack timeout.
+ * @param[in] aTxError The deferred ack error status: `kErrorNone` to indicate a deferred ack was received,
+ * `kErrorNoAck` to indicate an ack timeout.
*
*/
- void HandleDeferredAck(Neighbor &aNeighbor, otError aTxError);
+ void HandleDeferredAck(Neighbor &aNeighbor, Error aTxError);
#endif
private:
@@ -332,7 +327,7 @@
kMeshHeaderFrameFcsSize = sizeof(uint16_t), // Frame FCS size for Mesh Header frame.
};
- enum MessageAction ///< Defines the action parameter in `LogMessageInfo()` method.
+ enum MessageAction : uint8_t ///< Defines the action parameter in `LogMessageInfo()` method.
{
kMessageReceive, ///< Indicates that the message was received.
kMessageTransmit, ///< Indicates that the message was sent.
@@ -382,32 +377,32 @@
};
#endif // OPENTHREAD_FTD
- void SendIcmpErrorIfDstUnreach(const Message & aMessage,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest);
- otError CheckReachability(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest);
- void UpdateRoutes(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest);
+ void SendIcmpErrorIfDstUnreach(const Message & aMessage,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest);
+ Error CheckReachability(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest);
+ void UpdateRoutes(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest);
- otError DecompressIp6Header(const uint8_t * aFrame,
+ Error DecompressIp6Header(const uint8_t * aFrame,
uint16_t aFrameLength,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
Ip6::Header & aIp6Header,
uint8_t & aHeaderLength,
bool & aNextHeaderCompressed);
- otError FrameToMessage(const uint8_t * aFrame,
+ Error FrameToMessage(const uint8_t * aFrame,
uint16_t aFrameLength,
uint16_t aDatagramSize,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
Message *& aMessage);
- otError GetIp6Header(const uint8_t * aFrame,
+ Error GetIp6Header(const uint8_t * aFrame,
uint16_t aFrameLength,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
@@ -439,101 +434,108 @@
bool aAddFragHeader = false);
void PrepareEmptyFrame(Mac::TxFrame &aFrame, const Mac::Address &aMacDest, bool aAckRequest);
- void SendMesh(Message &aMessage, Mac::TxFrame &aFrame);
- void SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage);
- otError UpdateIp6Route(Message &aMessage);
- otError UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage);
- otError UpdateMeshRoute(Message &aMessage);
- bool UpdateReassemblyList(void);
- void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
- uint16_t aFragmentLength,
- uint16_t aSrcRloc16,
- Message::Priority aPriority);
- otError HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource);
- void ClearReassemblyList(void);
- void RemoveMessage(Message &aMessage);
- void HandleDiscoverComplete(void);
+ void SendMesh(Message &aMessage, Mac::TxFrame &aFrame);
+ void SendDestinationUnreachable(uint16_t aMeshSource, const Message &aMessage);
+ Error UpdateIp6Route(Message &aMessage);
+ Error UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage);
+ Error UpdateMeshRoute(Message &aMessage);
+ bool UpdateReassemblyList(void);
+ void UpdateFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
+ uint16_t aFragmentLength,
+ uint16_t aSrcRloc16,
+ Message::Priority aPriority);
+ Error HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLinkInfo, const Mac::Address &aMacSource);
+ void ClearReassemblyList(void);
+ void RemoveMessage(Message &aMessage);
+ void HandleDiscoverComplete(void);
void HandleReceivedFrame(Mac::RxFrame &aFrame);
Mac::TxFrame *HandleFrameRequest(Mac::TxFrames &aTxFrames);
- Neighbor * UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError aError, const Mac::Address &aMacDest);
- void UpdateNeighborLinkFailures(Neighbor &aNeighbor, otError aError, bool aAllowNeighborRemove);
- void HandleSentFrame(Mac::TxFrame &aFrame, otError aError);
- void UpdateSendMessage(otError aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor);
+ Neighbor * UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, Error aError, const Mac::Address &aMacDest);
+ void UpdateNeighborLinkFailures(Neighbor &aNeighbor, Error aError, bool aAllowNeighborRemove);
+ void HandleSentFrame(Mac::TxFrame &aFrame, Error aError);
+ void UpdateSendMessage(Error aFrameTxError, Mac::Address &aMacDest, Neighbor *aNeighbor);
+ void RemoveMessageIfNoPendingTx(Message &aMessage);
void HandleTimeTick(void);
static void ScheduleTransmissionTask(Tasklet &aTasklet);
void ScheduleTransmissionTask(void);
- otError GetFramePriority(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- Message::Priority & aPriority);
- otError GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
- uint16_t aSrcRloc16,
- Message::Priority & aPriority);
- void GetForwardFramePriority(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest,
- Message::Priority & aPriority);
+ Error GetFramePriority(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ Message::Priority & aPriority);
+ Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
+ uint16_t aSrcRloc16,
+ Message::Priority & aPriority);
+ void GetForwardFramePriority(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest,
+ Message::Priority & aPriority);
- otError GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest);
+ Error GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest);
+
+ bool CalcIePresent(const Message *aMessage);
+ uint16_t CalcFrameVersion(const Neighbor *aNeighbor, bool aIePresent);
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+ void AppendHeaderIe(const Message *aMessage, Mac::Frame &aFrame);
+#endif
void PauseMessageTransmissions(void) { mTxPaused = true; }
void ResumeMessageTransmissions(void);
- void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, otError aError);
- void LogFrame(const char *aActionText, const Mac::Frame &aFrame, otError aError);
- void LogFragmentFrameDrop(otError aError,
+ void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, Error aError);
+ void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError);
+ void LogFragmentFrameDrop(Error aError,
uint16_t aFrameLength,
const Mac::Address & aMacSource,
const Mac::Address & aMacDest,
const Lowpan::FragmentHeader &aFragmentHeader,
bool aIsSecure);
- void LogLowpanHcFrameDrop(otError aError,
+ void LogLowpanHcFrameDrop(Error aError,
uint16_t aFrameLength,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
bool aIsSecure);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
- const char *MessageActionToString(MessageAction aAction, otError aError);
+ const char *MessageActionToString(MessageAction aAction, Error aError);
const char *MessagePriorityToString(const Message &aMessage);
- otError ParseIp6UdpTcpHeader(const Message &aMessage,
- Ip6::Header & aIp6Header,
- uint16_t & aChecksum,
- uint16_t & aSourcePort,
- uint16_t & aDestPort);
+ Error ParseIp6UdpTcpHeader(const Message &aMessage,
+ Ip6::Header & aIp6Header,
+ uint16_t & aChecksum,
+ uint16_t & aSourcePort,
+ uint16_t & aDestPort);
#if OPENTHREAD_FTD
- otError DecompressIp6UdpTcpHeader(const Message & aMessage,
- uint16_t aOffset,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest,
- Ip6::Header & aIp6Header,
- uint16_t & aChecksum,
- uint16_t & aSourcePort,
- uint16_t & aDestPort);
- otError LogMeshFragmentHeader(MessageAction aAction,
- const Message & aMessage,
- const Mac::Address *aMacAddress,
- otError aError,
- uint16_t & aOffset,
- Mac::Address & aMeshSource,
- Mac::Address & aMeshDest,
- otLogLevel aLogLevel);
- void LogMeshIpHeader(const Message & aMessage,
- uint16_t aOffset,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest,
- otLogLevel aLogLevel);
- void LogMeshMessage(MessageAction aAction,
- const Message & aMessage,
- const Mac::Address *aAddress,
- otError aError,
- otLogLevel aLogLevel);
+ Error DecompressIp6UdpTcpHeader(const Message & aMessage,
+ uint16_t aOffset,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest,
+ Ip6::Header & aIp6Header,
+ uint16_t & aChecksum,
+ uint16_t & aSourcePort,
+ uint16_t & aDestPort);
+ Error LogMeshFragmentHeader(MessageAction aAction,
+ const Message & aMessage,
+ const Mac::Address *aMacAddress,
+ Error aError,
+ uint16_t & aOffset,
+ Mac::Address & aMeshSource,
+ Mac::Address & aMeshDest,
+ otLogLevel aLogLevel);
+ void LogMeshIpHeader(const Message & aMessage,
+ uint16_t aOffset,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest,
+ otLogLevel aLogLevel);
+ void LogMeshMessage(MessageAction aAction,
+ const Message & aMessage,
+ const Mac::Address *aAddress,
+ Error aError,
+ otLogLevel aLogLevel);
#endif
void LogIp6SourceDestAddresses(Ip6::Header &aIp6Header,
uint16_t aSourcePort,
@@ -542,7 +544,7 @@
void LogIp6Message(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aAddress,
- otError aError,
+ Error aError,
otLogLevel aLogLevel);
#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp
index 4d87316..0ce2f4d 100644
--- a/src/core/thread/mesh_forwarder_ftd.cpp
+++ b/src/core/thread/mesh_forwarder_ftd.cpp
@@ -44,10 +44,10 @@
namespace ot {
-otError MeshForwarder::SendMessage(Message &aMessage)
+Error MeshForwarder::SendMessage(Message &aMessage)
{
Mle::MleRouter &mle = Get<Mle::MleRouter>();
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Neighbor * neighbor;
aMessage.SetOffset(0);
@@ -135,7 +135,7 @@
return error;
}
-void MeshForwarder::HandleResolved(const Ip6::Address &aEid, otError aError)
+void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
{
Message * cur, *next;
Ip6::Address ip6Dst;
@@ -156,7 +156,7 @@
{
mResolvingQueue.Dequeue(*cur);
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
mSendQueue.Enqueue(*cur);
enqueuedMessage = true;
@@ -175,9 +175,9 @@
}
}
-otError MeshForwarder::EvictMessage(Message::Priority aPriority)
+Error MeshForwarder::EvictMessage(Message::Priority aPriority)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
PriorityQueue *queues[] = {&mResolvingQueue, &mSendQueue};
Message * evict = nullptr;
@@ -208,7 +208,7 @@
if (evict != nullptr)
{
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
for (uint8_t priority = aPriority; priority < Message::kNumPriorities; priority++)
@@ -229,14 +229,14 @@
if (message->IsChildPending())
{
evict = message;
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
}
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
RemoveMessage(*evict);
}
@@ -257,7 +257,7 @@
continue;
}
- if (mIndirectSender.RemoveMessageFromSleepyChild(*message, aChild) != OT_ERROR_NONE)
+ if (mIndirectSender.RemoveMessageFromSleepyChild(*message, aChild) != kErrorNone)
{
switch (message->GetType())
{
@@ -294,16 +294,7 @@
}
}
- if (!message->IsChildPending() && !message->GetDirectTransmission())
- {
- if (mSendMessage == message)
- {
- mSendMessage = nullptr;
- }
-
- mSendQueue.Dequeue(*message);
- message->Free();
- }
+ RemoveMessageIfNoPendingTx(*message);
}
}
@@ -334,7 +325,7 @@
}
mSendQueue.Dequeue(*message);
- LogMessage(kMessageDrop, *message, nullptr, OT_ERROR_NONE);
+ LogMessage(kMessageDrop, *message, nullptr, kErrorNone);
message->Free();
}
}
@@ -342,29 +333,28 @@
void MeshForwarder::SendMesh(Message &aMessage, Mac::TxFrame &aFrame)
{
uint16_t fcf;
+ bool iePresent = CalcIePresent(&aMessage);
// initialize MAC header
fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfDstAddrShort |
Mac::Frame::kFcfSrcAddrShort | Mac::Frame::kFcfAckRequest | Mac::Frame::kFcfSecurityEnabled;
- Get<Mac::Mac>().UpdateFrameControlField(nullptr, aMessage.IsTimeSync(), fcf);
+
+ if (iePresent)
+ {
+ fcf |= Mac::Frame::kFcfIePresent;
+ }
+
+ fcf |= CalcFrameVersion(Get<NeighborTable>().FindNeighbor(mMacDest), iePresent);
aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32);
aFrame.SetDstPanId(Get<Mac::Mac>().GetPanId());
aFrame.SetDstAddr(mMacDest.GetShort());
aFrame.SetSrcAddr(mMacSource.GetShort());
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
- if (Get<Mac::Mac>().IsCslEnabled())
+#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+ if (iePresent)
{
- Mac::HeaderIe ieList[2]; // CSL + Termination
-
- ieList[0].Init();
- ieList[0].SetId(Mac::Frame::kHeaderIeCsl);
- ieList[0].SetLength(sizeof(Mac::CslIe));
- ieList[1].Init();
- ieList[1].SetId(Mac::Frame::kHeaderIeTermination2);
- ieList[1].SetLength(0);
- IgnoreError(aFrame.AppendHeaderIe(ieList, 2));
+ AppendHeaderIe(&aMessage, aFrame);
}
#endif
@@ -376,9 +366,9 @@
mMessageNextOffset = aMessage.GetLength();
}
-otError MeshForwarder::UpdateMeshRoute(Message &aMessage)
+Error MeshForwarder::UpdateMeshRoute(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Lowpan::MeshHeader meshHeader;
Neighbor * neighbor;
uint16_t nextHop;
@@ -398,7 +388,7 @@
if (neighbor == nullptr)
{
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
mMacDest.SetShort(neighbor->GetRloc16());
@@ -412,10 +402,10 @@
return error;
}
-otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage)
+Error MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage)
{
Mle::MleRouter &mle = Get<Mle::MleRouter>();
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Neighbor * neighbor;
if (aMessage.GetOffset() > 0)
@@ -425,7 +415,7 @@
else if (mle.IsRoutingLocator(ip6Header.GetDestination()))
{
uint16_t rloc16 = ip6Header.GetDestination().GetIid().GetLocator();
- VerifyOrExit(mle.IsRouterIdValid(Mle::Mle::RouterIdFromRloc16(rloc16)), error = OT_ERROR_DROP);
+ VerifyOrExit(mle.IsRouterIdValid(Mle::Mle::RouterIdFromRloc16(rloc16)), error = kErrorDrop);
mMeshDest = rloc16;
}
else if (mle.IsAnycastLocator(ip6Header.GetDestination()))
@@ -441,8 +431,8 @@
uint16_t agentRloc16;
uint8_t routerId;
VerifyOrExit((Get<NetworkData::Leader>().GetRlocByContextId(
- static_cast<uint8_t>(aloc16 & Mle::kAloc16DhcpAgentMask), agentRloc16) == OT_ERROR_NONE),
- error = OT_ERROR_DROP);
+ static_cast<uint8_t>(aloc16 & Mle::kAloc16DhcpAgentMask), agentRloc16) == kErrorNone),
+ error = kErrorDrop);
routerId = Mle::Mle::RouterIdFromRloc16(agentRloc16);
@@ -469,14 +459,14 @@
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
else if (aloc16 == Mle::kAloc16BackboneRouterPrimary)
{
- VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = OT_ERROR_DROP);
+ VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorDrop);
mMeshDest = Get<BackboneRouter::Leader>().GetServer16();
}
#endif
else
{
// TODO: support for Neighbor Discovery Agent ALOC
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
}
else if ((neighbor = Get<NeighborTable>().FindNeighbor(ip6Header.GetDestination())) != nullptr)
@@ -493,7 +483,7 @@
&mMeshDest));
}
- VerifyOrExit(mMeshDest != Mac::kShortAddrInvalid, error = OT_ERROR_DROP);
+ VerifyOrExit(mMeshDest != Mac::kShortAddrInvalid, error = kErrorDrop);
mMeshSource = Get<Mac::Mac>().GetShortAddress();
@@ -512,11 +502,11 @@
return error;
}
-otError MeshForwarder::GetIp6Header(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMacSource,
- const Mac::Address &aMacDest,
- Ip6::Header & aIp6Header)
+Error MeshForwarder::GetIp6Header(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMacSource,
+ const Mac::Address &aMacDest,
+ Ip6::Header & aIp6Header)
{
uint8_t headerLength;
bool nextHeaderCompressed;
@@ -529,7 +519,7 @@
const Mac::Address &aMacSource,
const Mac::Address &aMacDest)
{
- otError error;
+ Error error;
Ip6::Header ip6header;
Child * child;
@@ -544,7 +534,7 @@
error = Get<Mle::MleRouter>().CheckReachability(aMacDest.GetShort(), ip6header);
- if (error == OT_ERROR_NO_ROUTE)
+ if (error == kErrorNoRoute)
{
SendDestinationUnreachable(aMacSource.GetShort(), aMessage);
}
@@ -553,29 +543,29 @@
return;
}
-otError MeshForwarder::CheckReachability(const uint8_t * aFrame,
- uint16_t aFrameLength,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest)
+Error MeshForwarder::CheckReachability(const uint8_t * aFrame,
+ uint16_t aFrameLength,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Header ip6Header;
Message * message = nullptr;
Lowpan::FragmentHeader fragmentHeader;
uint16_t fragmentHeaderLength;
uint16_t datagramSize = 0;
- if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == OT_ERROR_NONE)
+ if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
{
// Only the first fragment header is followed by a LOWPAN_IPHC header
- VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = kErrorNotFound);
aFrame += fragmentHeaderLength;
aFrameLength -= fragmentHeaderLength;
datagramSize = fragmentHeader.GetDatagramSize();
}
- VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = kErrorNotFound);
error = FrameToMessage(aFrame, aFrameLength, datagramSize, aMeshSource, aMeshDest, message);
SuccessOrExit(error);
@@ -584,12 +574,12 @@
error = Get<Mle::MleRouter>().CheckReachability(aMeshDest.GetShort(), ip6Header);
exit:
- if (error == OT_ERROR_NOT_FOUND)
+ if (error == kErrorNotFound)
{
// the message may not contain an IPv6 header
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
- else if (error == OT_ERROR_NO_ROUTE)
+ else if (error == kErrorNoRoute)
{
SendDestinationUnreachable(aMeshSource.GetShort(), *message);
}
@@ -615,7 +605,7 @@
const Mac::Address & aMacSource,
const ThreadLinkInfo &aLinkInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message = nullptr;
Mac::Address meshDest;
Mac::Address meshSource;
@@ -623,7 +613,7 @@
uint16_t headerLength;
// Security Check: only process Mesh Header frames that had security enabled.
- VerifyOrExit(aLinkInfo.IsLinkSecurityEnabled(), error = OT_ERROR_SECURITY);
+ VerifyOrExit(aLinkInfo.IsLinkSecurityEnabled(), error = kErrorSecurity);
SuccessOrExit(error = meshHeader.ParseFrom(aFrame, aFrameLength, headerLength));
@@ -648,7 +638,7 @@
}
else
{
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
}
else if (meshHeader.GetHopsLeft() > 0)
@@ -664,7 +654,7 @@
GetForwardFramePriority(aFrame, aFrameLength, meshSource, meshDest, priority);
message = Get<MessagePool>().New(Message::kType6lowpan, priority);
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(message != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetLength(meshHeader.GetHeaderLength() + aFrameLength));
offset += meshHeader.WriteTo(*message, offset);
@@ -677,7 +667,7 @@
message->SetRadioType(static_cast<Mac::RadioType>(aLinkInfo.mRadioType));
#endif
- LogMessage(kMessageReceive, *message, &aMacSource, OT_ERROR_NONE);
+ LogMessage(kMessageReceive, *message, &aMacSource, kErrorNone);
#if OPENTHREAD_CONFIG_MULTI_RADIO
// Since the message will be forwarded, we clear the radio
@@ -692,10 +682,10 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogInfoMac("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", otThreadErrorToString(error),
- aFrameLength, aMacSource.ToString().AsCString(), aLinkInfo.IsLinkSecurityEnabled() ? "yes" : "no");
+ otLogInfoMac("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error), aFrameLength,
+ aMacSource.ToString().AsCString(), aLinkInfo.IsLinkSecurityEnabled() ? "yes" : "no");
FreeMessage(message);
}
}
@@ -714,8 +704,7 @@
if (!ip6Header.GetSource().GetIid().IsLocator() &&
Get<NetworkData::Leader>().IsOnMesh(ip6Header.GetSource()) /* only for on mesh address which may require AQ */)
{
- if (Get<AddressResolver>().UpdateCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort()) ==
- OT_ERROR_NOT_FOUND)
+ if (Get<AddressResolver>().UpdateCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort()) == kErrorNotFound)
{
// Thread 1.1 Specification 5.5.2.2: FTDs MAY add/update
// EID-to-RLOC Map Cache entries by inspecting packets
@@ -836,15 +825,15 @@
return newEntry;
}
-otError MeshForwarder::GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
- uint16_t aSrcRloc16,
- Message::Priority & aPriority)
+Error MeshForwarder::GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
+ uint16_t aSrcRloc16,
+ Message::Priority & aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
FragmentPriorityList::Entry *entry;
entry = mFragmentPriorityList.FindEntry(aSrcRloc16, aFragmentHeader.GetDatagramTag());
- VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(entry != nullptr, error = kErrorNotFound);
aPriority = entry->GetPriority();
exit:
@@ -857,12 +846,12 @@
const Mac::Address &aMeshDest,
Message::Priority & aPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
bool isFragment = false;
Lowpan::FragmentHeader fragmentHeader;
uint16_t fragmentHeaderLength;
- if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == OT_ERROR_NONE)
+ if (fragmentHeader.ParseFrom(aFrame, aFrameLength, fragmentHeaderLength) == kErrorNone)
{
isFragment = true;
aFrame += fragmentHeaderLength;
@@ -879,11 +868,10 @@
error = GetFramePriority(aFrame, aFrameLength, aMeshSource, aMeshDest, aPriority);
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogNoteMac("Failed to get forwarded frame priority, error:%s, len:%d, src:%d, dst:%s",
- otThreadErrorToString(error), aFrameLength, aMeshSource.ToString().AsCString(),
- aMeshDest.ToString().AsCString());
+ otLogNoteMac("Failed to get forwarded frame priority, error:%s, len:%d, src:%d, dst:%s", ErrorToString(error),
+ aFrameLength, aMeshSource.ToString().AsCString(), aMeshDest.ToString().AsCString());
}
else if (isFragment)
{
@@ -893,9 +881,9 @@
return;
}
-otError MeshForwarder::GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest)
+Error MeshForwarder::GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t serviceId = Mle::Mle::ServiceIdFromAloc(aServiceAloc);
const NetworkData::ServiceTlv *serviceTlv = Get<NetworkData::Leader>().FindServiceById(serviceId);
@@ -972,13 +960,13 @@
else
{
// ServiceTLV without ServerTLV? Can't forward packet anywhere.
- ExitNow(error = OT_ERROR_NO_ROUTE);
+ ExitNow(error = kErrorNoRoute);
}
}
else
{
// Unknown service, can't forward
- ExitNow(error = OT_ERROR_NO_ROUTE);
+ ExitNow(error = kErrorNoRoute);
}
exit:
@@ -989,16 +977,16 @@
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
-otError MeshForwarder::LogMeshFragmentHeader(MessageAction aAction,
- const Message & aMessage,
- const Mac::Address *aMacAddress,
- otError aError,
- uint16_t & aOffset,
- Mac::Address & aMeshSource,
- Mac::Address & aMeshDest,
- otLogLevel aLogLevel)
+Error MeshForwarder::LogMeshFragmentHeader(MessageAction aAction,
+ const Message & aMessage,
+ const Mac::Address *aMacAddress,
+ Error aError,
+ uint16_t & aOffset,
+ Mac::Address & aMeshSource,
+ Mac::Address & aMeshDest,
+ otLogLevel aLogLevel)
{
- otError error = OT_ERROR_FAILED;
+ Error error = kErrorFailed;
bool hasFragmentHeader = false;
bool shouldLogRss;
Lowpan::MeshHeader meshHeader;
@@ -1014,7 +1002,7 @@
aOffset = headerLength;
- if (fragmentHeader.ParseFrom(aMessage, aOffset, headerLength) == OT_ERROR_NONE)
+ if (fragmentHeader.ParseFrom(aMessage, aOffset, headerLength) == kErrorNone)
{
hasFragmentHeader = true;
aOffset += headerLength;
@@ -1027,16 +1015,15 @@
radioString = aMessage.IsRadioTypeSet() ? RadioTypeToString(aMessage.GetRadioType()) : "all";
#endif
- otLogMac(
- aLogLevel, "%s mesh frame, len:%d%s%s, msrc:%s, mdst:%s, hops:%d, frag:%s, sec:%s%s%s%s%s%s%s",
- MessageActionToString(aAction, aError), aMessage.GetLength(),
- (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
- (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(), aMeshSource.ToString().AsCString(),
- aMeshDest.ToString().AsCString(), meshHeader.GetHopsLeft() + ((aAction == kMessageReceive) ? 1 : 0),
- hasFragmentHeader ? "yes" : "no", aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
- (aError == OT_ERROR_NONE) ? "" : ", error:", (aError == OT_ERROR_NONE) ? "" : otThreadErrorToString(aError),
- shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "",
- shouldLogRadio ? ", radio:" : "", radioString);
+ otLogMac(aLogLevel, "%s mesh frame, len:%d%s%s, msrc:%s, mdst:%s, hops:%d, frag:%s, sec:%s%s%s%s%s%s%s",
+ MessageActionToString(aAction, aError), aMessage.GetLength(),
+ (aMacAddress == nullptr) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
+ (aMacAddress == nullptr) ? "" : aMacAddress->ToString().AsCString(), aMeshSource.ToString().AsCString(),
+ aMeshDest.ToString().AsCString(), meshHeader.GetHopsLeft() + ((aAction == kMessageReceive) ? 1 : 0),
+ hasFragmentHeader ? "yes" : "no", aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
+ (aError == kErrorNone) ? "" : ", error:", (aError == kErrorNone) ? "" : ErrorToString(aError),
+ shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "",
+ shouldLogRadio ? ", radio:" : "", radioString);
if (hasFragmentHeader)
{
@@ -1046,22 +1033,22 @@
VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0);
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
}
-otError MeshForwarder::DecompressIp6UdpTcpHeader(const Message & aMessage,
- uint16_t aOffset,
- const Mac::Address &aMeshSource,
- const Mac::Address &aMeshDest,
- Ip6::Header & aIp6Header,
- uint16_t & aChecksum,
- uint16_t & aSourcePort,
- uint16_t & aDestPort)
+Error MeshForwarder::DecompressIp6UdpTcpHeader(const Message & aMessage,
+ uint16_t aOffset,
+ const Mac::Address &aMeshSource,
+ const Mac::Address &aMeshDest,
+ Ip6::Header & aIp6Header,
+ uint16_t & aChecksum,
+ uint16_t & aSourcePort,
+ uint16_t & aDestPort)
{
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
int headerLength;
bool nextHeaderCompressed;
uint8_t frameBuffer[sizeof(Ip6::Header)];
@@ -1118,7 +1105,7 @@
break;
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
@@ -1150,7 +1137,7 @@
void MeshForwarder::LogMeshMessage(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
- otError aError,
+ Error aError,
otLogLevel aLogLevel)
{
uint16_t offset;
diff --git a/src/core/thread/mesh_forwarder_mtd.cpp b/src/core/thread/mesh_forwarder_mtd.cpp
index a11fc6b..6771791 100644
--- a/src/core/thread/mesh_forwarder_mtd.cpp
+++ b/src/core/thread/mesh_forwarder_mtd.cpp
@@ -37,7 +37,7 @@
namespace ot {
-otError MeshForwarder::SendMessage(Message &aMessage)
+Error MeshForwarder::SendMessage(Message &aMessage)
{
aMessage.SetDirectTransmission();
aMessage.SetOffset(0);
@@ -46,12 +46,12 @@
mSendQueue.Enqueue(aMessage);
mScheduleTransmissionTask.Post();
- return OT_ERROR_NONE;
+ return kErrorNone;
}
-otError MeshForwarder::EvictMessage(Message::Priority aPriority)
+Error MeshForwarder::EvictMessage(Message::Priority aPriority)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Message *message;
VerifyOrExit((message = mSendQueue.GetTail()) != nullptr);
@@ -59,7 +59,7 @@
if (message->GetPriority() < static_cast<uint8_t>(aPriority))
{
RemoveMessage(*message);
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
exit:
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index feaa4d6..d696a07 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -71,9 +71,9 @@
, mReattachState(kReattachStop)
, mAttachCounter(0)
, mAnnounceDelay(kAnnounceTimeout)
- , mAttachTimer(aInstance, Mle::HandleAttachTimer, this)
- , mDelayedResponseTimer(aInstance, Mle::HandleDelayedResponseTimer, this)
- , mMessageTransmissionTimer(aInstance, Mle::HandleMessageTransmissionTimer, this)
+ , mAttachTimer(aInstance, Mle::HandleAttachTimer)
+ , mDelayedResponseTimer(aInstance, Mle::HandleDelayedResponseTimer)
+ , mMessageTransmissionTimer(aInstance, Mle::HandleMessageTransmissionTimer)
, mParentLeaderCost(0)
, mParentRequestMode(kAttachAny)
, mParentPriority(0)
@@ -101,7 +101,7 @@
, mParentSearchBackoffWasCanceled(false)
, mParentSearchRecentlyDetached(false)
, mParentSearchBackoffCancelTime(0)
- , mParentSearchTimer(aInstance, Mle::HandleParentSearchTimer, this)
+ , mParentSearchTimer(aInstance, Mle::HandleParentSearchTimer)
#endif
, mAnnounceChannel(0)
, mAlternateChannel(0)
@@ -160,9 +160,9 @@
// to the Link- and Realm-Local All Thread Nodes multicast addresses.
}
-otError Mle::Enable(void)
+Error Mle::Enable(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
UpdateLinkLocalAddress();
SuccessOrExit(error = mSocket.Open(&Mle::HandleUdpReceive, this));
@@ -181,9 +181,9 @@
ScheduleMessageTransmissionTimer();
}
-otError Mle::Disable(void)
+Error Mle::Disable(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Stop(false);
SuccessOrExit(error = mSocket.Close());
@@ -193,13 +193,13 @@
return error;
}
-otError Mle::Start(bool aAnnounceAttach)
+Error Mle::Start(bool aAnnounceAttach)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
// cannot bring up the interface if IEEE 802.15.4 promiscuous mode is enabled
- VerifyOrExit(!Get<Radio>().GetPromiscuous(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(Get<ThreadNetif>().IsUp(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!Get<Radio>().GetPromiscuous(), error = kErrorInvalidState);
+ VerifyOrExit(Get<ThreadNetif>().IsUp(), error = kErrorInvalidState);
if (Get<Mac::Mac>().GetPanId() == Mac::kPanIdBroadcast)
{
@@ -227,7 +227,7 @@
#if OPENTHREAD_FTD
else if (IsActiveRouter(GetRloc16()))
{
- if (Get<MleRouter>().BecomeRouter(ThreadStatusTlv::kTooFewRouters) != OT_ERROR_NONE)
+ if (Get<MleRouter>().BecomeRouter(ThreadStatusTlv::kTooFewRouters) != kErrorNone)
{
IgnoreError(BecomeChild(kAttachAny));
}
@@ -313,9 +313,9 @@
return;
}
-otError Mle::Restore(void)
+Error Mle::Restore(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Settings::NetworkInfo networkInfo;
Settings::ParentInfo parentInfo;
@@ -361,7 +361,7 @@
{
error = Get<Settings>().ReadParentInfo(parentInfo);
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
// If the restored RLOC16 corresponds to an end-device, it
// is expected that the `ParentInfo` settings to be valid
@@ -402,9 +402,9 @@
return error;
}
-otError Mle::Store(void)
+Error Mle::Store(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Settings::NetworkInfo networkInfo;
networkInfo.Init();
@@ -464,11 +464,11 @@
return error;
}
-otError Mle::BecomeDetached(void)
+Error Mle::BecomeDetached(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
// In case role is already detached and attach state is `kAttachStateStart`
// (i.e., waiting to start an attach attempt), there is no need to make any
@@ -495,16 +495,21 @@
return error;
}
-otError Mle::BecomeChild(AttachMode aMode)
+Error Mle::BecomeChild(AttachMode aMode)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsAttaching(), error = OT_ERROR_BUSY);
+ VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
+ VerifyOrExit(!IsAttaching(), error = kErrorBusy);
+
+ if (!IsDetached())
+ {
+ mAttachCounter = 0;
+ }
if (mReattachState == kReattachStart)
{
- if (Get<MeshCoP::ActiveDataset>().Restore() == OT_ERROR_NONE)
+ if (Get<MeshCoP::ActiveDataset>().Restore() == kErrorNone)
{
mReattachState = kReattachActive;
}
@@ -523,7 +528,7 @@
#if OPENTHREAD_FTD
if (IsFullThreadDevice())
{
- Get<MleRouter>().StopAdvertiseTimer();
+ Get<MleRouter>().StopAdvertiseTrickleTimer();
}
#endif
}
@@ -652,8 +657,7 @@
SetRloc16(aRloc16);
SetRole(kRoleChild);
SetAttachState(kAttachStateIdle);
- mAttachTimer.Stop();
- mAttachCounter = 0;
+ mAttachTimer.Start(kAttachBackoffDelayToResetCounter);
mReattachState = kReattachStop;
mChildUpdateAttempts = 0;
mDataRequestAttempts = 0;
@@ -731,12 +735,12 @@
return;
}
-otError Mle::SetDeviceMode(DeviceMode aDeviceMode)
+Error Mle::SetDeviceMode(DeviceMode aDeviceMode)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
DeviceMode oldMode = mDeviceMode;
- VerifyOrExit(aDeviceMode.IsValid(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aDeviceMode.IsValid(), error = kErrorInvalidArgs);
VerifyOrExit(mDeviceMode != aDeviceMode);
mDeviceMode = aDeviceMode;
@@ -930,11 +934,11 @@
mLeaderData.SetLeaderRouterId(aLeaderRouterId);
}
-otError Mle::GetLeaderAddress(Ip6::Address &aAddress) const
+Error Mle::GetLeaderAddress(Ip6::Address &aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = OT_ERROR_DETACHED);
+ VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
aAddress.SetToRoutingLocator(GetMeshLocalPrefix(), Rloc16FromRouterId(mLeaderData.GetLeaderRouterId()));
@@ -942,11 +946,11 @@
return error;
}
-otError Mle::GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const
+Error Mle::GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = OT_ERROR_DETACHED);
+ VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
memcpy(&aAddress, &mMeshLocal16.GetAddress(), 14);
aAddress.GetIid().SetLocator(aLocator);
@@ -955,11 +959,11 @@
return error;
}
-otError Mle::GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const
+Error Mle::GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = OT_ERROR_DETACHED);
+ VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
aAddress.SetToAnycastLocator(GetMeshLocalPrefix(), ServiceAlocFromId(aServiceId));
exit:
@@ -988,10 +992,10 @@
return message;
}
-otError Mle::AppendHeader(Message &aMessage, Command aCommand)
+Error Mle::AppendHeader(Message &aMessage, Command aCommand)
{
- otError error = OT_ERROR_NONE;
- Header header;
+ Error error = kErrorNone;
+ Header header;
header.Init();
@@ -1012,49 +1016,49 @@
return error;
}
-otError Mle::AppendSourceAddress(Message &aMessage) const
+Error Mle::AppendSourceAddress(Message &aMessage) const
{
return Tlv::Append<SourceAddressTlv>(aMessage, GetRloc16());
}
-otError Mle::AppendStatus(Message &aMessage, StatusTlv::Status aStatus)
+Error Mle::AppendStatus(Message &aMessage, StatusTlv::Status aStatus)
{
return Tlv::Append<StatusTlv>(aMessage, aStatus);
}
-otError Mle::AppendMode(Message &aMessage, DeviceMode aMode)
+Error Mle::AppendMode(Message &aMessage, DeviceMode aMode)
{
return Tlv::Append<ModeTlv>(aMessage, aMode.Get());
}
-otError Mle::AppendTimeout(Message &aMessage, uint32_t aTimeout)
+Error Mle::AppendTimeout(Message &aMessage, uint32_t aTimeout)
{
return Tlv::Append<TimeoutTlv>(aMessage, aTimeout);
}
-otError Mle::AppendChallenge(Message &aMessage, const Challenge &aChallenge)
+Error Mle::AppendChallenge(Message &aMessage, const Challenge &aChallenge)
{
return Tlv::Append<ChallengeTlv>(aMessage, aChallenge.mBuffer, aChallenge.mLength);
}
-otError Mle::AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength)
+Error Mle::AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength)
{
return Tlv::Append<ChallengeTlv>(aMessage, aChallenge, aChallengeLength);
}
-otError Mle::AppendResponse(Message &aMessage, const Challenge &aResponse)
+Error Mle::AppendResponse(Message &aMessage, const Challenge &aResponse)
{
return Tlv::Append<ResponseTlv>(aMessage, aResponse.mBuffer, aResponse.mLength);
}
-otError Mle::ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer)
+Error Mle::ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer)
{
- otError error;
+ Error error;
uint16_t offset;
uint16_t length;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, aTlvType, offset, length));
- VerifyOrExit(length >= kMinChallengeSize, error = OT_ERROR_PARSE);
+ VerifyOrExit(length >= kMinChallengeSize, error = kErrorParse);
if (length > kMaxChallengeSize)
{
@@ -1068,17 +1072,17 @@
return error;
}
-otError Mle::ReadChallenge(const Message &aMessage, Challenge &aChallenge)
+Error Mle::ReadChallenge(const Message &aMessage, Challenge &aChallenge)
{
return ReadChallengeOrResponse(aMessage, Tlv::kChallenge, aChallenge);
}
-otError Mle::ReadResponse(const Message &aMessage, Challenge &aResponse)
+Error Mle::ReadResponse(const Message &aMessage, Challenge &aResponse)
{
return ReadChallengeOrResponse(aMessage, Tlv::kResponse, aResponse);
}
-otError Mle::AppendLinkFrameCounter(Message &aMessage)
+Error Mle::AppendLinkFrameCounter(Message &aMessage)
{
uint32_t counter;
@@ -1096,26 +1100,26 @@
return Tlv::Append<LinkFrameCounterTlv>(aMessage, counter);
}
-otError Mle::AppendMleFrameCounter(Message &aMessage)
+Error Mle::AppendMleFrameCounter(Message &aMessage)
{
return Tlv::Append<MleFrameCounterTlv>(aMessage, Get<KeyManager>().GetMleFrameCounter());
}
-otError Mle::ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const
+Error Mle::ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const
{
- otError error;
+ Error error;
SuccessOrExit(error = Tlv::Find<LinkFrameCounterTlv>(aMessage, aLinkFrameCounter));
switch (Tlv::Find<MleFrameCounterTlv>(aMessage, aMleFrameCounter))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
aMleFrameCounter = aLinkFrameCounter;
break;
default:
- error = OT_ERROR_PARSE;
+ error = kErrorParse;
break;
}
@@ -1123,12 +1127,12 @@
return error;
}
-otError Mle::AppendAddress16(Message &aMessage, uint16_t aRloc16)
+Error Mle::AppendAddress16(Message &aMessage, uint16_t aRloc16)
{
return Tlv::Append<Address16Tlv>(aMessage, aRloc16);
}
-otError Mle::AppendLeaderData(Message &aMessage)
+Error Mle::AppendLeaderData(Message &aMessage)
{
LeaderDataTlv leaderDataTlv;
@@ -1141,26 +1145,26 @@
return leaderDataTlv.AppendTo(aMessage);
}
-otError Mle::ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData)
+Error Mle::ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData)
{
- otError error;
+ Error error;
LeaderDataTlv leaderDataTlv;
SuccessOrExit(error = Tlv::FindTlv(aMessage, leaderDataTlv));
- VerifyOrExit(leaderDataTlv.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(leaderDataTlv.IsValid(), error = kErrorParse);
leaderDataTlv.Get(aLeaderData);
exit:
return error;
}
-otError Mle::AppendNetworkData(Message &aMessage, bool aStableOnly)
+Error Mle::AppendNetworkData(Message &aMessage, bool aStableOnly)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t networkData[NetworkData::NetworkData::kMaxSize];
uint8_t length;
- VerifyOrExit(!mRetrieveNewNetworkData, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!mRetrieveNewNetworkData, error = kErrorInvalidState);
length = sizeof(networkData);
IgnoreError(Get<NetworkData::Leader>().GetNetworkData(aStableOnly, networkData, length));
@@ -1171,14 +1175,14 @@
return error;
}
-otError Mle::AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength)
+Error Mle::AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength)
{
return Tlv::Append<TlvRequestTlv>(aMessage, aTlvs, aTlvsLength);
}
-otError Mle::FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs)
+Error Mle::FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs)
{
- otError error;
+ Error error;
uint16_t offset;
uint16_t length;
@@ -1196,17 +1200,17 @@
return error;
}
-otError Mle::AppendScanMask(Message &aMessage, uint8_t aScanMask)
+Error Mle::AppendScanMask(Message &aMessage, uint8_t aScanMask)
{
return Tlv::Append<ScanMaskTlv>(aMessage, aScanMask);
}
-otError Mle::AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin)
+Error Mle::AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin)
{
return Tlv::Append<LinkMarginTlv>(aMessage, aLinkMargin);
}
-otError Mle::AppendVersion(Message &aMessage)
+Error Mle::AppendVersion(Message &aMessage)
{
return Tlv::Append<VersionTlv>(aMessage, kThreadVersion);
}
@@ -1239,9 +1243,9 @@
return retval;
}
-otError Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode)
+Error Mle::AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Tlv tlv;
AddressRegistrationEntry entry;
Lowpan::Context context;
@@ -1273,7 +1277,7 @@
{
error = Get<NetworkData::Leader>().GetContext(domainUnicastAddress, context);
- OT_ASSERT(error == OT_ERROR_NONE);
+ OT_ASSERT(error == kErrorNone);
// Prioritize DUA, compressed entry
entry.SetContextId(context.mContextId);
@@ -1300,7 +1304,7 @@
}
#endif
- if (Get<NetworkData::Leader>().GetContext(addr->GetAddress(), context) == OT_ERROR_NONE)
+ if (Get<NetworkData::Leader>().GetContext(addr->GetAddress(), context) == kErrorNone)
{
// compressed entry
entry.SetContextId(context.mContextId);
@@ -1355,7 +1359,7 @@
exit:
- if (error == OT_ERROR_NONE && length > 0)
+ if (error == kErrorNone && length > 0)
{
tlv.SetLength(length);
aMessage.Write(startOffset, tlv);
@@ -1365,13 +1369,13 @@
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-otError Mle::AppendTimeRequest(Message &aMessage)
+Error Mle::AppendTimeRequest(Message &aMessage)
{
// `TimeRequestTlv` has no value.
return Tlv::Append<TimeRequestTlv>(aMessage, nullptr, 0);
}
-otError Mle::AppendTimeParameter(Message &aMessage)
+Error Mle::AppendTimeParameter(Message &aMessage)
{
TimeParameterTlv tlv;
@@ -1382,20 +1386,20 @@
return tlv.AppendTo(aMessage);
}
-otError Mle::AppendXtalAccuracy(Message &aMessage)
+Error Mle::AppendXtalAccuracy(Message &aMessage)
{
return Tlv::Append<XtalAccuracyTlv>(aMessage, otPlatTimeGetXtalAccuracy());
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-otError Mle::AppendActiveTimestamp(Message &aMessage)
+Error Mle::AppendActiveTimestamp(Message &aMessage)
{
- otError error;
+ Error error;
ActiveTimestampTlv timestampTlv;
const MeshCoP::Timestamp *timestamp;
timestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
- VerifyOrExit(timestamp, error = OT_ERROR_NONE);
+ VerifyOrExit(timestamp, error = kErrorNone);
timestampTlv.Init();
*static_cast<MeshCoP::Timestamp *>(×tampTlv) = *timestamp;
@@ -1405,14 +1409,14 @@
return error;
}
-otError Mle::AppendPendingTimestamp(Message &aMessage)
+Error Mle::AppendPendingTimestamp(Message &aMessage)
{
- otError error;
+ Error error;
PendingTimestampTlv timestampTlv;
const MeshCoP::Timestamp *timestamp;
timestamp = Get<MeshCoP::PendingDataset>().GetTimestamp();
- VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = OT_ERROR_NONE);
+ VerifyOrExit(timestamp && timestamp->GetSeconds() != 0, error = kErrorNone);
timestampTlv.Init();
*static_cast<MeshCoP::Timestamp *>(×tampTlv) = *timestamp;
@@ -1423,9 +1427,9 @@
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
-otError Mle::AppendCslChannel(Message &aMessage)
+Error Mle::AppendCslChannel(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
CslChannelTlv cslChannel;
// In current implementation, it's allowed to set CSL Channel unspecified. As `0` is not valid for Channel value
@@ -1444,7 +1448,7 @@
return error;
}
-otError Mle::AppendCslTimeout(Message &aMessage)
+Error Mle::AppendCslTimeout(Message &aMessage)
{
OT_ASSERT(Get<Mac::Mac>().IsCslEnabled());
return Tlv::Append<CslTimeoutTlv>(aMessage, Get<Mac::Mac>().GetCslTimeout() == 0 ? mTimeout
@@ -1586,7 +1590,7 @@
}
// Now add any missing service alocs which should be there, if there is enough space in mServiceAlocs
- while (Get<NetworkData::Leader>().GetNextServiceId(serviceIterator, rloc, serviceId) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextServiceId(serviceIterator, rloc, serviceId) == kErrorNone)
{
for (i = 0; i < serviceAlocsLength; i++)
{
@@ -1622,7 +1626,7 @@
void Mle::HandleAttachTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mle>().HandleAttachTimer();
+ aTimer.Get<Mle>().HandleAttachTimer();
}
void Mle::HandleAttachTimer(void)
@@ -1656,7 +1660,7 @@
if ((linkQuality == 3 || mAttachState != kAttachStateParentRequestRouter) &&
mParentCandidate.IsStateParentResponse() &&
(!IsChild() || mReceivedResponseFromParent || mParentRequestMode == kAttachBetter) &&
- SendChildIdRequest() == OT_ERROR_NONE)
+ SendChildIdRequest() == kErrorNone)
{
SetAttachState(kAttachStateChildIdRequest);
delay = kParentRequestReedTimeout;
@@ -1667,8 +1671,8 @@
switch (mAttachState)
{
case kAttachStateIdle:
- OT_ASSERT(false);
- OT_UNREACHABLE_CODE(break);
+ mAttachCounter = 0;
+ break;
case kAttachStateProcessAnnounce:
ProcessAnnounce();
@@ -1726,19 +1730,19 @@
break;
}
- // fall through
+ OT_FALL_THROUGH;
case kAttachStateAnnounce:
if (shouldAnnounce)
{
- if (SendOrphanAnnounce() == OT_ERROR_NONE)
+ if (SendOrphanAnnounce() == kErrorNone)
{
delay = mAnnounceDelay;
break;
}
}
- // fall through
+ OT_FALL_THROUGH;
case kAttachStateChildIdRequest:
SetAttachState(kAttachStateIdle);
@@ -1763,7 +1767,7 @@
VerifyOrExit(!IsChild() && (mReattachState == kReattachStop) &&
(Get<MeshCoP::ActiveDataset>().IsPartiallyComplete() || !IsFullThreadDevice()));
- if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != OT_ERROR_NONE)
+ if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != kErrorNone)
{
channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
}
@@ -1787,7 +1791,7 @@
if (mReattachState == kReattachActive)
{
- if (Get<MeshCoP::PendingDataset>().Restore() == OT_ERROR_NONE)
+ if (Get<MeshCoP::PendingDataset>().Restore() == kErrorNone)
{
IgnoreError(Get<MeshCoP::PendingDataset>().ApplyConfiguration());
mReattachState = kReattachPending;
@@ -1820,7 +1824,7 @@
IgnoreError(BecomeDetached());
}
#if OPENTHREAD_FTD
- else if (IsFullThreadDevice() && Get<MleRouter>().BecomeLeader() == OT_ERROR_NONE)
+ else if (IsFullThreadDevice() && Get<MleRouter>().BecomeLeader() == kErrorNone)
{
// do nothing
}
@@ -1858,7 +1862,7 @@
void Mle::HandleDelayedResponseTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mle>().HandleDelayedResponseTimer();
+ aTimer.Get<Mle>().HandleDelayedResponseTimer();
}
void Mle::HandleDelayedResponseTimer(void)
@@ -1887,7 +1891,7 @@
mDelayedResponses.Dequeue(*message);
metadata.RemoveFrom(*message);
- if (SendMessage(*message, metadata.mDestination) == OT_ERROR_NONE)
+ if (SendMessage(*message, metadata.mDestination) == kErrorNone)
{
Log(kMessageSend, kTypeGenericDelayed, metadata.mDestination);
@@ -1937,9 +1941,9 @@
}
}
-otError Mle::SendParentRequest(ParentRequestType aType)
+Error Mle::SendParentRequest(ParentRequestType aType)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message;
uint8_t scanMask = 0;
Ip6::Address destination;
@@ -1957,7 +1961,7 @@
break;
}
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandParentRequest));
SuccessOrExit(error = AppendMode(*message, mDeviceMode));
SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
@@ -1995,9 +1999,9 @@
}
}
-otError Mle::SendChildIdRequest(void)
+Error Mle::SendChildIdRequest(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t tlvs[] = {Tlv::kAddress16, Tlv::kNetworkData, Tlv::kRoute};
uint8_t tlvsLen = sizeof(tlvs);
Message * message = nullptr;
@@ -2008,7 +2012,7 @@
if (IsChild())
{
otLogInfoMle("Already attached to candidate parent");
- ExitNow(error = OT_ERROR_ALREADY);
+ ExitNow(error = kErrorAlready);
}
else
{
@@ -2021,7 +2025,7 @@
}
}
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleChildIdRequest);
SuccessOrExit(error = AppendHeader(*message, kCommandChildIdRequest));
SuccessOrExit(error = AppendResponse(*message, mParentCandidateChallenge));
@@ -2063,20 +2067,20 @@
return error;
}
-otError Mle::SendDataRequest(const Ip6::Address &aDestination,
- const uint8_t * aTlvs,
- uint8_t aTlvsLength,
- uint16_t aDelay,
- const uint8_t * aExtraTlvs,
- uint8_t aExtraTlvsLength)
+Error Mle::SendDataRequest(const Ip6::Address &aDestination,
+ const uint8_t * aTlvs,
+ uint8_t aTlvsLength,
+ uint16_t aDelay,
+ const uint8_t * aExtraTlvs,
+ uint8_t aExtraTlvsLength)
{
OT_UNUSED_VARIABLE(aExtraTlvs);
OT_UNUSED_VARIABLE(aExtraTlvsLength);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandDataRequest));
SuccessOrExit(error = AppendTlvRequest(*message, aTlvs, aTlvsLength));
SuccessOrExit(error = AppendActiveTimestamp(*message));
@@ -2174,7 +2178,7 @@
void Mle::HandleMessageTransmissionTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mle>().HandleMessageTransmissionTimer();
+ aTimer.Get<Mle>().HandleMessageTransmissionTimer();
}
void Mle::HandleMessageTransmissionTimer(void)
@@ -2198,7 +2202,7 @@
destination.SetToLinkLocalAddress(mParent.GetExtAddress());
- if (SendDataRequest(destination, tlvs, sizeof(tlvs), 0) == OT_ERROR_NONE)
+ if (SendDataRequest(destination, tlvs, sizeof(tlvs), 0) == kErrorNone)
{
mDataRequestAttempts++;
}
@@ -2229,7 +2233,7 @@
VerifyOrExit(mChildUpdateAttempts < kMaxChildKeepAliveAttempts, IgnoreError(BecomeDetached()));
- if (SendChildUpdateRequest() == OT_ERROR_NONE)
+ if (SendChildUpdateRequest() == kErrorNone)
{
mChildUpdateAttempts++;
}
@@ -2238,9 +2242,9 @@
return;
}
-otError Mle::SendChildUpdateRequest(void)
+Error Mle::SendChildUpdateRequest(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message = nullptr;
AddressRegistrationMode mode = kAppendAllAddresses;
@@ -2255,7 +2259,7 @@
mChildUpdateRequestState = kChildUpdateRequestActive;
ScheduleMessageTransmissionTimer();
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleChildUpdateRequest);
SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateRequest));
SuccessOrExit(error = AppendMode(*message, mDeviceMode));
@@ -2317,14 +2321,14 @@
return error;
}
-otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge)
+Error Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message;
bool checkAddress = false;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
@@ -2395,13 +2399,13 @@
void Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Address &aDestination)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ChannelTlv channel;
ActiveTimestampTlv activeTimestamp;
Message * message = nullptr;
- VerifyOrExit(Get<Mac::Mac>().GetSupportedChannelMask().ContainsChannel(aChannel), error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(Get<Mac::Mac>().GetSupportedChannelMask().ContainsChannel(aChannel), error = kErrorInvalidArgs);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetLinkSecurityEnabled(true);
message->SetSubType(Message::kSubTypeMleAnnounce);
message->SetChannel(aChannel);
@@ -2435,12 +2439,12 @@
FreeMessageOnError(message, error);
}
-otError Mle::SendOrphanAnnounce(void)
+Error Mle::SendOrphanAnnounce(void)
{
- otError error;
+ Error error;
Mac::ChannelMask channelMask;
- if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != OT_ERROR_NONE)
+ if (Get<MeshCoP::ActiveDataset>().GetChannelMask(channelMask) != kErrorNone)
{
channelMask = Get<Mac::Mac>().GetSupportedChannelMask();
}
@@ -2454,14 +2458,14 @@
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
-otError Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus)
+Error Mle::SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
Tlv tlv;
ot::Tlv statusSubTlv;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandLinkMetricsManagementResponse));
tlv.SetType(Tlv::kLinkMetricsManagement);
@@ -2478,13 +2482,13 @@
return error;
}
-otError Mle::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength)
+Error Mle::SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
Tlv tlv;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandLinkProbe));
tlv.SetType(Tlv::kLinkProbe);
@@ -2500,9 +2504,9 @@
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
-otError Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination)
+Error Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
uint32_t keySequence;
uint8_t nonce[Crypto::AesCcm::kNonceSize];
@@ -2561,9 +2565,9 @@
return error;
}
-otError Mle::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
+Error Mle::AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
DelayedResponseMetadata metadata;
metadata.mSendTime = TimerMilli::GetNow() + aDelay;
@@ -2586,7 +2590,7 @@
void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Header header;
uint32_t keySequence;
const Key * mleKey;
@@ -2605,10 +2609,10 @@
otLogDebgMle("Receive UDP message");
VerifyOrExit(aMessageInfo.GetLinkInfo() != nullptr);
- VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = kErrorParse);
length = aMessage.ReadBytes(aMessage.GetOffset(), &header, sizeof(header));
- VerifyOrExit(header.IsValid() && header.GetLength() <= length, error = OT_ERROR_PARSE);
+ VerifyOrExit(header.IsValid() && header.GetLength() <= length, error = kErrorParse);
if (header.GetSecuritySuite() == Header::kNoSecurity)
{
@@ -2633,8 +2637,8 @@
ExitNow();
}
- VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(header.GetSecuritySuite() == Header::k154Security, error = OT_ERROR_PARSE);
+ VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
+ VerifyOrExit(header.GetSecuritySuite() == Header::k154Security, error = kErrorParse);
keySequence = header.GetKeyId();
@@ -2648,7 +2652,7 @@
}
VerifyOrExit(aMessage.GetOffset() + header.GetLength() + sizeof(messageTag) <= aMessage.GetLength(),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
aMessage.MoveOffset(header.GetLength() - 1);
IgnoreError(aMessage.Read(aMessage.GetLength() - sizeof(messageTag), messageTag));
@@ -2681,7 +2685,7 @@
aesCcm.Finalize(tag);
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- VerifyOrExit(memcmp(messageTag, tag, sizeof(tag)) == 0, error = OT_ERROR_SECURITY);
+ VerifyOrExit(memcmp(messageTag, tag, sizeof(tag)) == 0, error = kErrorSecurity);
#endif
if (keySequence > Get<KeyManager>().GetCurrentKeySequence())
@@ -2723,11 +2727,11 @@
ExitNow();
}
#endif
- VerifyOrExit(frameCounter >= neighbor->GetMleFrameCounter(), error = OT_ERROR_DUPLICATED);
+ VerifyOrExit(frameCounter >= neighbor->GetMleFrameCounter(), error = kErrorDuplicated);
}
else
{
- VerifyOrExit(keySequence > neighbor->GetKeySequence(), error = OT_ERROR_DUPLICATED);
+ VerifyOrExit(keySequence > neighbor->GetKeySequence(), error = kErrorDuplicated);
neighbor->SetKeySequence(keySequence);
neighbor->GetLinkFrameCounters().Reset();
neighbor->SetLinkAckFrameCounter(0);
@@ -2841,7 +2845,7 @@
#endif
default:
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
#if OPENTHREAD_CONFIG_MULTI_RADIO
@@ -2871,7 +2875,7 @@
void Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t sourceAddress;
LeaderData leaderData;
uint8_t tlvs[] = {Tlv::kNetworkData};
@@ -2922,7 +2926,7 @@
{
RouteTlv route;
- if ((Tlv::FindTlv(aMessage, route) == OT_ERROR_NONE) && route.IsValid())
+ if ((Tlv::FindTlv(aMessage, route) == kErrorNone) && route.IsValid())
{
// Overwrite Route Data
IgnoreError(Get<MleRouter>().ProcessRouteTlv(route));
@@ -2954,7 +2958,7 @@
void Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor)
{
- otError error;
+ Error error;
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
uint16_t metricsReportValueOffset;
uint16_t length;
@@ -2962,10 +2966,10 @@
Log(kMessageReceive, kTypeDataResponse, aMessageInfo.GetPeerAddr());
- VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = OT_ERROR_SECURITY);
+ VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
- if (Tlv::FindTlvValueOffset(aMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) == OT_ERROR_NONE)
+ if (Tlv::FindTlvValueOffset(aMessage, Tlv::kLinkMetricsReport, metricsReportValueOffset, length) == kErrorNone)
{
Get<LinkMetrics>().HandleLinkMetricsReport(aMessage, metricsReportValueOffset, length,
aMessageInfo.GetPeerAddr());
@@ -3004,9 +3008,9 @@
return (diff > 0);
}
-otError Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+Error Mle::HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
LeaderData leaderData;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
@@ -3029,7 +3033,7 @@
}
else
{
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
}
else if (!mRetrieveNewNetworkData)
@@ -3038,17 +3042,17 @@
}
// Active Timestamp
- if (Tlv::FindTlv(aMessage, activeTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone)
{
const MeshCoP::Timestamp *timestamp;
- VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
timestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
if (!IsLeader() && ((timestamp == nullptr) || (timestamp->Compare(activeTimestamp) != 0)) &&
- (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, activeDatasetOffset) != OT_ERROR_NONE))
+ (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, activeDatasetOffset) != kErrorNone))
{
ExitNow(dataRequest = true);
}
@@ -3059,17 +3063,17 @@
}
// Pending Timestamp
- if (Tlv::FindTlv(aMessage, pendingTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone)
{
const MeshCoP::Timestamp *timestamp;
- VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
timestamp = Get<MeshCoP::PendingDataset>().GetTimestamp();
// if received timestamp does not match the local value and message does not contain the dataset,
// send MLE Data Request
if (!IsLeader() && ((timestamp == nullptr) || (timestamp->Compare(pendingTimestamp) != 0)) &&
- (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, pendingDatasetOffset) != OT_ERROR_NONE))
+ (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, pendingDatasetOffset) != kErrorNone))
{
ExitNow(dataRequest = true);
}
@@ -3079,7 +3083,7 @@
pendingTimestamp.SetLength(0);
}
- if (Tlv::FindTlvOffset(aMessage, Tlv::kNetworkData, networkDataOffset) == OT_ERROR_NONE)
+ if (Tlv::FindTlvOffset(aMessage, Tlv::kNetworkData, networkDataOffset) == kErrorNone)
{
error =
Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
@@ -3145,7 +3149,7 @@
IgnoreError(SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay));
}
- else if (error == OT_ERROR_NONE)
+ else if (error == kErrorNone)
{
mDataRequestAttempts = 0;
mDataRequestState = kDataRequestNone;
@@ -3231,7 +3235,7 @@
void Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const ThreadLinkInfo *linkInfo = aMessageInfo.GetThreadLinkInfo();
Challenge response;
uint16_t version;
@@ -3255,11 +3259,11 @@
// Version
SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
- VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
+ VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
// Response
SuccessOrExit(error = ReadResponse(aMessage, response));
- VerifyOrExit(response == mParentRequestChallenge, error = OT_ERROR_PARSE);
+ VerifyOrExit(response == mParentRequestChallenge, error = kErrorParse);
aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddress);
@@ -3285,7 +3289,7 @@
// Connectivity
SuccessOrExit(error = Tlv::FindTlv(aMessage, connectivity));
- VerifyOrExit(connectivity.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(connectivity.IsValid(), error = kErrorParse);
// Share data with application, if requested.
if (mParentResponseCb)
@@ -3367,7 +3371,7 @@
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
// Time Parameter
- if (Tlv::FindTlv(aMessage, timeParameter) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, timeParameter) == kErrorNone)
{
VerifyOrExit(timeParameter.IsValid());
@@ -3424,7 +3428,7 @@
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
LeaderData leaderData;
uint16_t sourceAddress;
uint16_t shortAddress;
@@ -3439,7 +3443,7 @@
Log(kMessageReceive, kTypeChildIdResponse, aMessageInfo.GetPeerAddr(), sourceAddress);
- VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = OT_ERROR_SECURITY);
+ VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
VerifyOrExit(mAttachState == kAttachStateChildIdRequest);
@@ -3454,12 +3458,12 @@
SuccessOrExit(error);
// Active Timestamp
- if (Tlv::FindTlv(aMessage, activeTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone)
{
- VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
// Active Dataset
- if (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, offset) == OT_ERROR_NONE)
+ if (Tlv::FindTlvOffset(aMessage, Tlv::kActiveDataset, offset) == kErrorNone)
{
IgnoreError(aMessage.Read(offset, tlv));
IgnoreError(
@@ -3474,12 +3478,12 @@
}
// Pending Timestamp
- if (Tlv::FindTlv(aMessage, pendingTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone)
{
- VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
// Pending Dataset
- if (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, offset) == OT_ERROR_NONE)
+ if (Tlv::FindTlvOffset(aMessage, Tlv::kPendingDataset, offset) == kErrorNone)
{
IgnoreError(aMessage.Read(offset, tlv));
IgnoreError(
@@ -3520,7 +3524,7 @@
{
RouteTlv route;
- if (Tlv::FindTlv(aMessage, route) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, route) == kErrorNone)
{
SuccessOrExit(error = Get<MleRouter>().ProcessRouteTlv(route));
}
@@ -3546,7 +3550,7 @@
{
static const uint8_t kMaxResponseTlvs = 6;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t sourceAddress;
Challenge challenge;
RequestedTlvs requestedTlvs;
@@ -3561,15 +3565,15 @@
// Challenge
switch (ReadChallenge(aMessage, challenge))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
tlvs[numTlvs++] = Tlv::kResponse;
tlvs[numTlvs++] = Tlv::kMleFrameCounter;
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
if (aNeighbor == &mParent)
@@ -3578,13 +3582,13 @@
switch (Tlv::Find<StatusTlv>(aMessage, status))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
VerifyOrExit(status != StatusTlv::kError, IgnoreError(BecomeDetached()));
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
if (mParent.GetRloc16() != sourceAddress)
@@ -3605,7 +3609,7 @@
// TLV Request
switch (FindTlvRequest(aMessage, requestedTlvs))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
{
if (numTlvs >= sizeof(tlvs))
@@ -3617,10 +3621,10 @@
tlvs[numTlvs++] = requestedTlvs.mTlvs[i];
}
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
#if OPENTHREAD_CONFIG_MULTI_RADIO
@@ -3640,7 +3644,7 @@
const Ip6::MessageInfo &aMessageInfo,
const Neighbor * aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t status;
uint8_t mode;
Challenge response;
@@ -3655,11 +3659,11 @@
{
case kRoleDetached:
SuccessOrExit(error = ReadResponse(aMessage, response));
- VerifyOrExit(response == mParentRequestChallenge, error = OT_ERROR_SECURITY);
+ VerifyOrExit(response == mParentRequestChallenge, error = kErrorSecurity);
break;
case kRoleChild:
- VerifyOrExit((aNeighbor == &mParent) && mParent.IsStateValid(), error = OT_ERROR_SECURITY);
+ VerifyOrExit((aNeighbor == &mParent) && mParent.IsStateValid(), error = kErrorSecurity);
break;
default:
@@ -3668,7 +3672,7 @@
}
// Status
- if (Tlv::Find<StatusTlv>(aMessage, status) == OT_ERROR_NONE)
+ if (Tlv::Find<StatusTlv>(aMessage, status) == kErrorNone)
{
IgnoreError(BecomeDetached());
ExitNow();
@@ -3676,7 +3680,7 @@
// Mode
SuccessOrExit(error = Tlv::Find<ModeTlv>(aMessage, mode));
- VerifyOrExit(DeviceMode(mode) == mDeviceMode, error = OT_ERROR_DROP);
+ VerifyOrExit(DeviceMode(mode) == mDeviceMode, error = kErrorDrop);
switch (mRole)
{
@@ -3692,7 +3696,7 @@
mRetrieveNewNetworkData = true;
- // fall through
+ OT_FALL_THROUGH;
case kRoleChild:
// Source Address
@@ -3710,13 +3714,13 @@
// Timeout optional
switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
mTimeout = timeout;
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
if (!IsRxOnWhenIdle())
@@ -3738,7 +3742,7 @@
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
if (mChildUpdateRequestState == kChildUpdateRequestActive)
{
@@ -3755,7 +3759,7 @@
{
OT_UNUSED_VARIABLE(aMessageInfo);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ChannelTlv channelTlv;
ActiveTimestampTlv timestamp;
const MeshCoP::Timestamp *localTimestamp;
@@ -3765,12 +3769,12 @@
Log(kMessageReceive, kTypeAnnounce, aMessageInfo.GetPeerAddr());
SuccessOrExit(error = Tlv::FindTlv(aMessage, channelTlv));
- VerifyOrExit(channelTlv.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(channelTlv.IsValid(), error = kErrorParse);
channel = static_cast<uint8_t>(channelTlv.GetChannel());
SuccessOrExit(error = Tlv::FindTlv(aMessage, timestamp));
- VerifyOrExit(timestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(timestamp.IsValid(), error = kErrorParse);
SuccessOrExit(error = Tlv::Find<PanIdTlv>(aMessage, panId));
@@ -3795,6 +3799,7 @@
mAlternatePanId = panId;
SetAttachState(kAttachStateProcessAnnounce);
mAttachTimer.Start(kAnnounceProcessTimeout);
+ mAttachCounter = 0;
otLogNoteMle("Delay processing Announce - channel %d, panid 0x%02x", channel, panId);
}
@@ -3823,12 +3828,12 @@
const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
LinkMetrics::LinkMetricsStatus status;
Log(kMessageReceive, kTypeLinkMetricsManagementRequest, aMessageInfo.GetPeerAddr());
- VerifyOrExit(aNeighbor != nullptr, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
SuccessOrExit(error = Get<LinkMetrics>().HandleLinkMetricsManagementRequest(aMessage, *aNeighbor, status));
error = SendLinkMetricsManagementResponse(aMessageInfo.GetPeerAddr(), status);
@@ -3841,11 +3846,11 @@
const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Log(kMessageReceive, kTypeLinkMetricsManagementResponse, aMessageInfo.GetPeerAddr());
- VerifyOrExit(aNeighbor != nullptr, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aNeighbor != nullptr, error = kErrorInvalidState);
error = Get<LinkMetrics>().HandleLinkMetricsManagementResponse(aMessage, aMessageInfo.GetPeerAddr());
@@ -3855,7 +3860,7 @@
void Mle::HandleLinkProbe(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t seriesId;
Log(kMessageReceive, kTypeLinkProbe, aMessageInfo.GetPeerAddr());
@@ -3912,17 +3917,17 @@
return (aAddress.GetPrefix() == GetMeshLocalPrefix());
}
-otError Mle::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
+Error Mle::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
{
- otError error;
+ Error error;
if ((aMeshDest != GetRloc16()) || Get<ThreadNetif>().HasUnicastAddress(aIp6Header.GetDestination()))
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
else
{
- error = OT_ERROR_NO_ROUTE;
+ error = kErrorNoRoute;
}
return error;
@@ -3931,7 +3936,7 @@
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
void Mle::InformPreviousParent(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message = nullptr;
Ip6::MessageInfo messageInfo;
@@ -3939,7 +3944,7 @@
mCounters.mParentChanges++;
- VerifyOrExit((message = Get<Ip6::Ip6>().NewMessage(0)) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Ip6::Ip6>().NewMessage(0)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetLength(0));
messageInfo.SetSockAddr(GetMeshLocal64());
@@ -3952,9 +3957,9 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnMle("Failed to inform previous parent: %s", otThreadErrorToString(error));
+ otLogWarnMle("Failed to inform previous parent: %s", ErrorToString(error));
FreeMessage(message);
}
@@ -3964,7 +3969,7 @@
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
void Mle::HandleParentSearchTimer(Timer &aTimer)
{
- aTimer.GetOwner<Mle>().HandleParentSearchTimer();
+ aTimer.Get<Mle>().HandleParentSearchTimer();
}
void Mle::HandleParentSearchTimer(void)
@@ -4095,153 +4100,137 @@
#endif
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
-void Mle::LogProcessError(MessageType aType, otError aError)
+void Mle::LogProcessError(MessageType aType, Error aError)
{
LogError(kMessageReceive, aType, aError);
}
-void Mle::LogSendError(MessageType aType, otError aError)
+void Mle::LogSendError(MessageType aType, Error aError)
{
LogError(kMessageSend, aType, aError);
}
-void Mle::LogError(MessageAction aAction, MessageType aType, otError aError)
+void Mle::LogError(MessageAction aAction, MessageType aType, Error aError)
{
- if (aError != OT_ERROR_NONE)
+ if (aError != kErrorNone)
{
otLogWarnMle("Failed to %s %s%s: %s", aAction == kMessageSend ? "send" : "process", MessageTypeToString(aType),
- MessageTypeActionToSuffixString(aType, aAction), otThreadErrorToString(aError));
+ MessageTypeActionToSuffixString(aType, aAction), ErrorToString(aError));
}
}
const char *Mle::MessageActionToString(MessageAction aAction)
{
- const char *str = "Unknown";
+ static const char *const kMessageActionStrings[] = {
+ "Send", // (0) kMessageSend
+ "Receive", // (1) kMessageReceive
+ "Delay", // (2) kMessageDelay
+ "Remove Delayed", // (3) kMessageRemoveDelayed
+ };
- switch (aAction)
- {
- case kMessageSend:
- str = "Send";
- break;
- case kMessageReceive:
- str = "Receive";
- break;
- case kMessageDelay:
- str = "Delay";
- break;
- case kMessageRemoveDelayed:
- str = "Remove Delayed";
- break;
- }
+ static_assert(kMessageSend == 0, "kMessageSend value is incorrect");
+ static_assert(kMessageReceive == 1, "kMessageReceive value is incorrect");
+ static_assert(kMessageDelay == 2, "kMessageDelay value is incorrect");
+ static_assert(kMessageRemoveDelayed == 3, "kMessageRemoveDelayed value is incorrect");
- return str;
+ return kMessageActionStrings[aAction];
}
const char *Mle::MessageTypeToString(MessageType aType)
{
- const char *str = "Unknown";
-
- switch (aType)
- {
- case kTypeAdvertisement:
- str = "Advertisement";
- break;
- case kTypeAnnounce:
- str = "Announce";
- break;
- case kTypeChildIdRequest:
- str = "Child ID Request";
- break;
- case kTypeChildIdRequestShort:
- case kTypeChildIdResponse:
- str = "Child ID Response";
- break;
- case kTypeChildUpdateRequestOfParent:
+ static const char *const kMessageTypeStrings[] = {
+ "Advertisement", // (0) kTypeAdvertisement
+ "Announce", // (1) kTypeAnnounce
+ "Child ID Request", // (2) kTypeChildIdRequest
+ "Child ID Request", // (3) kTypeChildIdRequestShort
+ "Child ID Response", // (4) kTypeChildIdResponse
+ "Child Update Request", // (5) kTypeChildUpdateRequestOfParent
+ "Child Update Response", // (6) kTypeChildUpdateResponseOfParent
+ "Data Request", // (7) kTypeDataRequest
+ "Data Response", // (8) kTypeDataResponse
+ "Discovery Request", // (9) kTypeDiscoveryRequest
+ "Discovery Response", // (10) kTypeDiscoveryResponse
+ "delayed message", // (11) kTypeGenericDelayed
+ "UDP", // (12) kTypeGenericUdp
+ "Parent Request", // (13) kTypeParentRequestToRouters
+ "Parent Request", // (14) kTypeParentRequestToRoutersReeds
+ "Parent Response", // (15) kTypeParentResponse
#if OPENTHREAD_FTD
- case kTypeChildUpdateRequestOfChild:
-#endif
- str = "Child Update Request";
- break;
- case kTypeChildUpdateResponseOfParent:
-#if OPENTHREAD_FTD
- case kTypeChildUpdateResponseOfChild:
- case kTypeChildUpdateResponseOfUnknownChild:
-#endif
- str = "Child Update Response";
- break;
- case kTypeDataRequest:
- str = "Data Request";
- break;
- case kTypeDataResponse:
- str = "Data Response";
- break;
- case kTypeDiscoveryRequest:
- str = "Discovery Request";
- break;
- case kTypeDiscoveryResponse:
- str = "Discovery Response";
- break;
- case kTypeGenericDelayed:
- str = "delayed message";
- break;
- case kTypeGenericUdp:
- str = "UDP";
- break;
- case kTypeParentRequestToRouters:
- case kTypeParentRequestToRoutersReeds:
- str = "Parent Request";
- break;
- case kTypeParentResponse:
- str = "Parent Response";
- break;
-#if OPENTHREAD_FTD
- case kTypeAddressRelease:
- str = "Address Release";
- break;
- case kTypeAddressReleaseReply:
- str = "Address Release Reply";
- break;
- case kTypeAddressReply:
- str = "Address Reply";
- break;
- case kTypeAddressSolicit:
- str = "Address Solicit";
- break;
- case kTypeLinkAccept:
- str = "Link Accept";
- break;
- case kTypeLinkAcceptAndRequest:
- str = "Link Accept and Request";
- break;
- case kTypeLinkReject:
- str = "Link Reject";
- break;
- case kTypeLinkRequest:
- str = "Link Request";
- break;
- case kTypeParentRequest:
- str = "Parent Request";
- break;
+ "Address Release", // (16) kTypeAddressRelease
+ "Address Release Reply", // (17) kTypeAddressReleaseReply
+ "Address Reply", // (18) kTypeAddressReply
+ "Address Solicit", // (19) kTypeAddressSolicit
+ "Child Update Request", // (20) kTypeChildUpdateRequestOfChild
+ "Child Update Response", // (21) kTypeChildUpdateResponseOfChild
+ "Child Update Response", // (22) kTypeChildUpdateResponseOfUnknownChild
+ "Link Accept", // (23) kTypeLinkAccept
+ "Link Accept and Request", // (24) kTypeLinkAcceptAndRequest
+ "Link Reject", // (25) kTypeLinkReject
+ "Link Request", // (26) kTypeLinkRequest
+ "Parent Request", // (27) kTypeParentRequest
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
- case kTypeTimeSync:
- str = "Time Sync";
- break;
+ "Time Sync", // (28) kTypeTimeSync
+#endif
+#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ "Link Metrics Management Request", // (29) kTypeLinkMetricsManagementRequest
+ "Link Metrics Management Response", // (30) kTypeLinkMetricsManagementResponse
+ "Link Probe", // (31) kTypeLinkProbe
+#endif
+ };
+
+ static_assert(kTypeAdvertisement == 0, "kTypeAdvertisement value is incorrect");
+ static_assert(kTypeAnnounce == 1, "kTypeAnnounce value is incorrect");
+ static_assert(kTypeChildIdRequest == 2, "kTypeChildIdRequest value is incorrect");
+ static_assert(kTypeChildIdRequestShort == 3, "kTypeChildIdRequestShort value is incorrect");
+ static_assert(kTypeChildIdResponse == 4, "kTypeChildIdResponse value is incorrect");
+ static_assert(kTypeChildUpdateRequestOfParent == 5, "kTypeChildUpdateRequestOfParent value is incorrect");
+ static_assert(kTypeChildUpdateResponseOfParent == 6, "kTypeChildUpdateResponseOfParent value is incorrect");
+ static_assert(kTypeDataRequest == 7, "kTypeDataRequest value is incorrect");
+ static_assert(kTypeDataResponse == 8, "kTypeDataResponse value is incorrect");
+ static_assert(kTypeDiscoveryRequest == 9, "kTypeDiscoveryRequest value is incorrect");
+ static_assert(kTypeDiscoveryResponse == 10, "kTypeDiscoveryResponse value is incorrect");
+ static_assert(kTypeGenericDelayed == 11, "kTypeGenericDelayed value is incorrect");
+ static_assert(kTypeGenericUdp == 12, "kTypeGenericUdp value is incorrect");
+ static_assert(kTypeParentRequestToRouters == 13, "kTypeParentRequestToRouters value is incorrect");
+ static_assert(kTypeParentRequestToRoutersReeds == 14, "kTypeParentRequestToRoutersReeds value is incorrect");
+ static_assert(kTypeParentResponse == 15, "kTypeParentResponse value is incorrect");
+#if OPENTHREAD_FTD
+ static_assert(kTypeAddressRelease == 16, "kTypeAddressRelease value is incorrect");
+ static_assert(kTypeAddressReleaseReply == 17, "kTypeAddressReleaseReply value is incorrect");
+ static_assert(kTypeAddressReply == 18, "kTypeAddressReply value is incorrect");
+ static_assert(kTypeAddressSolicit == 19, "kTypeAddressSolicit value is incorrect");
+ static_assert(kTypeChildUpdateRequestOfChild == 20, "kTypeChildUpdateRequestOfChild value is incorrect");
+ static_assert(kTypeChildUpdateResponseOfChild == 21, "kTypeChildUpdateResponseOfChild value is incorrect");
+ static_assert(kTypeChildUpdateResponseOfUnknownChild == 22, "kTypeChildUpdateResponseOfUnknownChild is incorrect");
+ static_assert(kTypeLinkAccept == 23, "kTypeLinkAccept value is incorrect");
+ static_assert(kTypeLinkAcceptAndRequest == 24, "kTypeLinkAcceptAndRequest value is incorrect");
+ static_assert(kTypeLinkReject == 25, "kTypeLinkReject value is incorrect");
+ static_assert(kTypeLinkRequest == 26, "kTypeLinkRequest value is incorrect");
+ static_assert(kTypeParentRequest == 27, "kTypeParentRequest value is incorrect");
+#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+ static_assert(kTypeTimeSync == 28, "kTypeTimeSync value is incorrect");
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ static_assert(kTypeLinkMetricsManagementRequest == 29, "kTypeLinkMetricsManagementRequest value is incorrect)");
+ static_assert(kTypeLinkMetricsManagementResponse == 30, "kTypeLinkMetricsManagementResponse value is incorrect)");
+ static_assert(kTypeLinkProbe == 31, "kTypeLinkProbe value is incorrect)");
+#endif
+#else // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ static_assert(kTypeLinkMetricsManagementRequest == 28, "kTypeLinkMetricsManagementRequest value is incorrect)");
+ static_assert(kTypeLinkMetricsManagementResponse == 29, "kTypeLinkMetricsManagementResponse value is incorrect)");
+ static_assert(kTypeLinkProbe == 30, "kTypeLinkProbe value is incorrect)");
+#endif
+#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
+#else // OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+ static_assert(kTypeLinkMetricsManagementRequest == 16, "kTypeLinkMetricsManagementRequest value is incorrect)");
+ static_assert(kTypeLinkMetricsManagementResponse == 17, "kTypeLinkMetricsManagementResponse value is incorrect)");
+ static_assert(kTypeLinkProbe == 18, "kTypeLinkProbe value is incorrect)");
#endif
#endif // OPENTHREAD_FTD
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
- case kTypeLinkMetricsManagementRequest:
- str = "Link Metrics Management Request";
- break;
- case kTypeLinkMetricsManagementResponse:
- str = "Link Metrics Management Response";
- break;
- case kTypeLinkProbe:
- str = "Link Probe";
- break;
-#endif
- }
- return str;
+ return kMessageTypeStrings[aType];
}
const char *Mle::MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction)
@@ -4257,7 +4246,6 @@
case kTypeChildUpdateResponseOfParent:
str = (aAction == kMessageReceive) ? " from parent" : " to parent";
break;
-
case kTypeParentRequestToRouters:
str = " to routers";
break;
@@ -4284,32 +4272,21 @@
const char *Mle::RoleToString(DeviceRole aRole)
{
- const char *roleString = "Unknown";
+ static const char *const kRoleStrings[] = {
+ "Disabled", // (0) kRoleDisabled
+ "Detached", // (1) kRoleDetached
+ "Child", // (2) kRoleChild
+ "Router", // (3) kRoleRouter
+ "Leader", // (4) kRoleLeader
+ };
- switch (aRole)
- {
- case kRoleDisabled:
- roleString = "Disabled";
- break;
+ static_assert(kRoleDisabled == 0, "kRoleDisabled value is incorrect");
+ static_assert(kRoleDetached == 1, "kRoleDetached value is incorrect");
+ static_assert(kRoleChild == 2, "kRoleChild value is incorrect");
+ static_assert(kRoleRouter == 3, "kRoleRouter value is incorrect");
+ static_assert(kRoleLeader == 4, "kRoleLeader value is incorrect");
- case kRoleDetached:
- roleString = "Detached";
- break;
-
- case kRoleChild:
- roleString = "Child";
- break;
-
- case kRoleRouter:
- roleString = "Router";
- break;
-
- case kRoleLeader:
- roleString = "Leader";
- break;
- }
-
- return roleString;
+ return kRoleStrings[aRole];
}
// LCOV_EXCL_START
@@ -4318,96 +4295,61 @@
const char *Mle::AttachModeToString(AttachMode aMode)
{
- const char *str = "unknown";
+ static const char *const kAttachModeStrings[] = {
+ "any-partition", // (0) kAttachAny
+ "same-partition-try-1", // (1) kAttachSame1
+ "same-partition-try-2", // (2) kAttachSame2
+ "better-partition", // (3) kAttachBetter
+ "same-partition-downgrade", // (4) kAttachSameDowngrade
+ };
- switch (aMode)
- {
- case kAttachAny:
- str = "any-partition";
- break;
+ static_assert(kAttachAny == 0, "kAttachAny value is incorrect");
+ static_assert(kAttachSame1 == 1, "kAttachSame1 value is incorrect");
+ static_assert(kAttachSame2 == 2, "kAttachSame2 value is incorrect");
+ static_assert(kAttachBetter == 3, "kAttachBetter value is incorrect");
+ static_assert(kAttachSameDowngrade == 4, "kAttachSameDowngrade value is incorrect");
- case kAttachSame1:
- str = "same-partition-try-1";
- break;
-
- case kAttachSame2:
- str = "same-partition-try-2";
- break;
-
- case kAttachBetter:
- str = "better-partition";
- break;
-
- case kAttachSameDowngrade:
- str = "same-partition-downgrade";
- break;
- }
-
- return str;
+ return kAttachModeStrings[aMode];
}
const char *Mle::AttachStateToString(AttachState aState)
{
- const char *str = "Unknown";
-
- switch (aState)
- {
- case kAttachStateIdle:
- str = "Idle";
- break;
-
- case kAttachStateProcessAnnounce:
- str = "ProcessAnnounce";
- break;
-
- case kAttachStateStart:
- str = "Start";
- break;
-
- case kAttachStateParentRequestRouter:
- str = "ParentReqRouters";
- break;
-
- case kAttachStateParentRequestReed:
- str = "ParentReqReeds";
- break;
-
- case kAttachStateAnnounce:
- str = "Announce";
- break;
-
- case kAttachStateChildIdRequest:
- str = "ChildIdReq";
- break;
+ static const char *const kAttachStateStrings[] = {
+ "Idle", // (0) kAttachStateIdle
+ "ProcessAnnounce", // (1) kAttachStateProcessAnnounce
+ "Start", // (2) kAttachStateStart
+ "ParentReqRouters", // (3) kAttachStateParentRequestRouter
+ "ParentReqReeds", // (4) kAttachStateParentRequestReed
+ "Announce", // (5) kAttachStateAnnounce
+ "ChildIdReq", // (6) kAttachStateChildIdRequest
};
- return str;
+ static_assert(kAttachStateIdle == 0, "kAttachStateIdle value is incorrect");
+ static_assert(kAttachStateProcessAnnounce == 1, "kAttachStateProcessAnnounce value is incorrect");
+ static_assert(kAttachStateStart == 2, "kAttachStateStart value is incorrect");
+ static_assert(kAttachStateParentRequestRouter == 3, "kAttachStateParentRequestRouter value is incorrect");
+ static_assert(kAttachStateParentRequestReed == 4, "kAttachStateParentRequestReed value is incorrect");
+ static_assert(kAttachStateAnnounce == 5, "kAttachStateAnnounce value is incorrect");
+ static_assert(kAttachStateChildIdRequest == 6, "kAttachStateChildIdRequest value is incorrect");
+
+ return kAttachStateStrings[aState];
}
const char *Mle::ReattachStateToString(ReattachState aState)
{
- const char *str = "unknown";
+ static const char *const kReattachStateStrings[] = {
+ "", // (0) kReattachStop
+ "reattaching", // (1) kReattachStart
+ "reattaching with Active Dataset", // (2) kReattachActive
+ "reattaching with Pending Dataset", // (3) kReattachPending
+ };
- switch (aState)
- {
- case kReattachStop:
- str = "";
- break;
+ static_assert(kReattachStop == 0, "kReattachStop value is incorrect");
+ static_assert(kReattachStart == 1, "kReattachStart value is incorrect");
+ static_assert(kReattachActive == 2, "kReattachActive value is incorrect");
+ static_assert(kReattachPending == 3, "kReattachPending value is incorrect");
- case kReattachStart:
- str = "reattaching";
- break;
-
- case kReattachActive:
- str = "reattaching with Active Dataset";
- break;
-
- case kReattachPending:
- str = "reattaching with Pending Dataset";
- break;
- }
-
- return str;
+ return kReattachStateStrings[aState];
}
#endif // (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
@@ -4415,15 +4357,13 @@
// LCOV_EXCL_STOP
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
-otError Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination,
- const uint8_t * aSubTlvs,
- uint8_t aLength)
+Error Mle::SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
Tlv tlv;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandLinkMetricsManagementRequest));
// Link Metrics Management TLV
@@ -4467,8 +4407,8 @@
void Mle::DelayedResponseMetadata::RemoveFrom(Message &aMessage) const
{
- otError error = aMessage.SetLength(aMessage.GetLength() - sizeof(*this));
- OT_ASSERT(error == OT_ERROR_NONE);
+ Error error = aMessage.SetLength(aMessage.GetLength() - sizeof(*this));
+ OT_ASSERT(error == kErrorNone);
OT_UNUSED_VARIABLE(error);
}
diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp
index 95b5474..62a599d 100644
--- a/src/core/thread/mle.hpp
+++ b/src/core/thread/mle.hpp
@@ -111,19 +111,19 @@
/**
* This method enables MLE.
*
- * @retval OT_ERROR_NONE Successfully enabled MLE.
- * @retval OT_ERROR_ALREADY MLE was already enabled.
+ * @retval kErrorNone Successfully enabled MLE.
+ * @retval kErrorAlready MLE was already enabled.
*
*/
- otError Enable(void);
+ Error Enable(void);
/**
* This method disables MLE.
*
- * @retval OT_ERROR_NONE Successfully disabled MLE.
+ * @retval kErrorNone Successfully disabled MLE.
*
*/
- otError Disable(void);
+ Error Disable(void);
/**
* This method starts the MLE protocol operation.
@@ -131,11 +131,11 @@
* @param[in] aAnnounceAttach True if attach on the announced thread network with newer active timestamp,
* or False if not.
*
- * @retval OT_ERROR_NONE Successfully started the protocol operation.
- * @retval OT_ERROR_ALREADY The protocol operation was already started.
+ * @retval kErrorNone Successfully started the protocol operation.
+ * @retval kErrorAlready The protocol operation was already started.
*
*/
- otError Start(bool aAnnounceAttach);
+ Error Start(bool aAnnounceAttach);
/**
* This method stops the MLE protocol operation.
@@ -148,20 +148,20 @@
/**
* This method restores network information from non-volatile memory.
*
- * @retval OT_ERROR_NONE Successfully restore the network information.
- * @retval OT_ERROR_NOT_FOUND There is no valid network information stored in non-volatile memory.
+ * @retval kErrorNone Successfully restore the network information.
+ * @retval kErrorNotFound There is no valid network information stored in non-volatile memory.
*
*/
- otError Restore(void);
+ Error Restore(void);
/**
* This method stores network information into non-volatile memory.
*
- * @retval OT_ERROR_NONE Successfully store the network information.
- * @retval OT_ERROR_NO_BUFS Could not store the network information due to insufficient memory space.
+ * @retval kErrorNone Successfully store the network information.
+ * @retval kErrorNoBufs Could not store the network information due to insufficient memory space.
*
*/
- otError Store(void);
+ Error Store(void);
/**
* This method generates an MLE Announce message.
@@ -175,23 +175,23 @@
/**
* This method causes the Thread interface to detach from the Thread network.
*
- * @retval OT_ERROR_NONE Successfully detached from the Thread network.
- * @retval OT_ERROR_INVALID_STATE MLE is Disabled.
+ * @retval kErrorNone Successfully detached from the Thread network.
+ * @retval kErrorInvalidState MLE is Disabled.
*
*/
- otError BecomeDetached(void);
+ Error BecomeDetached(void);
/**
* This method causes the Thread interface to attempt an MLE attach.
*
* @param[in] aMode Indicates what partitions to attach to.
*
- * @retval OT_ERROR_NONE Successfully began the attach process.
- * @retval OT_ERROR_INVALID_STATE MLE is Disabled.
- * @retval OT_ERROR_BUSY An attach process is in progress.
+ * @retval kErrorNone Successfully began the attach process.
+ * @retval kErrorInvalidState MLE is Disabled.
+ * @retval kErrorBusy An attach process is in progress.
*
*/
- otError BecomeChild(AttachMode aMode);
+ Error BecomeChild(AttachMode aMode);
/**
* This method indicates whether or not the Thread device is attached to a Thread network.
@@ -290,11 +290,11 @@
*
* @param[in] aDeviceMode The device mode to set.
*
- * @retval OT_ERROR_NONE Successfully set the Mode TLV.
- * @retval OT_ERROR_INVALID_ARGS The mode combination specified in @p aMode is invalid.
+ * @retval kErrorNone Successfully set the Mode TLV.
+ * @retval kErrorInvalidArgs The mode combination specified in @p aMode is invalid.
*
*/
- otError SetDeviceMode(DeviceMode aDeviceMode);
+ Error SetDeviceMode(DeviceMode aDeviceMode);
/**
* This method indicates whether or not the device is rx-on-when-idle.
@@ -486,22 +486,22 @@
*
* @param[out] aAddress A reference to the Leader's RLOC.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Leader's RLOC.
- * @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
+ * @retval kErrorNone Successfully retrieved the Leader's RLOC.
+ * @retval kErrorDetached The Thread interface is not currently attached to a Thread Partition.
*
*/
- otError GetLeaderAddress(Ip6::Address &aAddress) const;
+ Error GetLeaderAddress(Ip6::Address &aAddress) const;
/**
* This method retrieves the Leader's ALOC.
*
* @param[out] aAddress A reference to the Leader's ALOC.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Leader's ALOC.
- * @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
+ * @retval kErrorNone Successfully retrieved the Leader's ALOC.
+ * @retval kErrorDetached The Thread interface is not currently attached to a Thread Partition.
*
*/
- otError GetLeaderAloc(Ip6::Address &aAddress) const { return GetLocatorAddress(aAddress, kAloc16Leader); }
+ Error GetLeaderAloc(Ip6::Address &aAddress) const { return GetLocatorAddress(aAddress, kAloc16Leader); }
/**
* This method computes the Commissioner's ALOC.
@@ -509,11 +509,11 @@
* @param[out] aAddress A reference to the Commissioner's ALOC.
* @param[in] aSessionId Commissioner session id.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Commissioner's ALOC.
- * @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
+ * @retval kErrorNone Successfully retrieved the Commissioner's ALOC.
+ * @retval kErrorDetached The Thread interface is not currently attached to a Thread Partition.
*
*/
- otError GetCommissionerAloc(Ip6::Address &aAddress, uint16_t aSessionId) const
+ Error GetCommissionerAloc(Ip6::Address &aAddress, uint16_t aSessionId) const
{
return GetLocatorAddress(aAddress, CommissionerAloc16FromId(aSessionId));
}
@@ -524,11 +524,11 @@
* @param[in] aServiceId Service ID to get ALOC for.
* @param[out] aAddress A reference to the Service ALOC.
*
- * @retval OT_ERROR_NONE Successfully retrieved the Service ALOC.
- * @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
+ * @retval kErrorNone Successfully retrieved the Service ALOC.
+ * @retval kErrorDetached The Thread interface is not currently attached to a Thread Partition.
*
*/
- otError GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const;
+ Error GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const;
/**
* This method returns the most recently received Leader Data.
@@ -691,11 +691,11 @@
* @param[out] aAddress A reference to the RLOC or ALOC.
* @param[in] aLocator RLOC16 or ALOC16.
*
- * @retval OT_ERROR_NONE If got the RLOC or ALOC successfully.
- * @retval OT_ERROR_DETACHED If device is detached.
+ * @retval kErrorNone If got the RLOC or ALOC successfully.
+ * @retval kErrorDetached If device is detached.
*
*/
- otError GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const;
+ Error GetLocatorAddress(Ip6::Address &aAddress, uint16_t aLocator) const;
/**
* This method schedules a Child Update Request.
@@ -707,7 +707,7 @@
* This method indicates whether or not the device has restored the network information from
* non-volatile settings after boot.
*
- * @retval true Sucessfully restored the network information.
+ * @retval true Successfully restored the network information.
* @retval false No valid network information was found.
*
*/
@@ -929,22 +929,22 @@
* @param[in] aMessage A reference to the message.
* @param[in] aCommand The MLE Command Type.
*
- * @retval OT_ERROR_NONE Successfully appended the header.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the header.
+ * @retval kErrorNone Successfully appended the header.
+ * @retval kErrorNoBufs Insufficient buffers available to append the header.
*
*/
- otError AppendHeader(Message &aMessage, Command aCommand);
+ Error AppendHeader(Message &aMessage, Command aCommand);
/**
* This method appends a Source Address TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Source Address TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Source Address TLV.
+ * @retval kErrorNone Successfully appended the Source Address TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Source Address TLV.
*
*/
- otError AppendSourceAddress(Message &aMessage) const;
+ Error AppendSourceAddress(Message &aMessage) const;
/**
* This method appends a Mode TLV to a message.
@@ -952,11 +952,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aMode The Device Mode.
*
- * @retval OT_ERROR_NONE Successfully appended the Mode TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Mode TLV.
+ * @retval kErrorNone Successfully appended the Mode TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Mode TLV.
*
*/
- otError AppendMode(Message &aMessage, DeviceMode aMode);
+ Error AppendMode(Message &aMessage, DeviceMode aMode);
/**
* This method appends a Timeout TLV to a message.
@@ -964,11 +964,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aTimeout The Timeout value.
*
- * @retval OT_ERROR_NONE Successfully appended the Timeout TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Timeout TLV.
+ * @retval kErrorNone Successfully appended the Timeout TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Timeout TLV.
*
*/
- otError AppendTimeout(Message &aMessage, uint32_t aTimeout);
+ Error AppendTimeout(Message &aMessage, uint32_t aTimeout);
/**
* This method appends a Challenge TLV to a message.
@@ -977,11 +977,11 @@
* @param[in] aChallenge A pointer to the Challenge value.
* @param[in] aChallengeLength The length of the Challenge value in bytes.
*
- * @retval OT_ERROR_NONE Successfully appended the Challenge TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Challenge TLV.
+ * @retval kErrorNone Successfully appended the Challenge TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Challenge TLV.
*
*/
- otError AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength);
+ Error AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength);
/**
* This method appends a Challenge TLV to a message.
@@ -989,11 +989,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aChallenge A reference to the Challenge data.
*
- * @retval OT_ERROR_NONE Successfully appended the Challenge TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Challenge TLV.
+ * @retval kErrorNone Successfully appended the Challenge TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Challenge TLV.
*
*/
- otError AppendChallenge(Message &aMessage, const Challenge &aChallenge);
+ Error AppendChallenge(Message &aMessage, const Challenge &aChallenge);
/**
* This method reads Challenge TLV from a message.
@@ -1001,12 +1001,12 @@
* @param[in] aMessage A reference to the message.
* @param[out] aChallenge A reference to the Challenge data where to output the read value.
*
- * @retval OT_ERROR_NONE Successfully read the Challenge TLV.
- * @retval OT_ERROR_NOT_FOUND Challenge TLV was not found in the message.
- * @retval OT_ERROR_PARSE Challenge TLV was found but could not be parsed.
+ * @retval kErrorNone Successfully read the Challenge TLV.
+ * @retval kErrorNotFound Challenge TLV was not found in the message.
+ * @retval kErrorParse Challenge TLV was found but could not be parsed.
*
*/
- otError ReadChallenge(const Message &aMessage, Challenge &aChallenge);
+ Error ReadChallenge(const Message &aMessage, Challenge &aChallenge);
/**
* This method appends a Response TLV to a message.
@@ -1014,11 +1014,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aResponse A reference to the Response data.
*
- * @retval OT_ERROR_NONE Successfully appended the Response TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Response TLV.
+ * @retval kErrorNone Successfully appended the Response TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Response TLV.
*
*/
- otError AppendResponse(Message &aMessage, const Challenge &aResponse);
+ Error AppendResponse(Message &aMessage, const Challenge &aResponse);
/**
* This method reads Response TLV from a message.
@@ -1026,23 +1026,23 @@
* @param[in] aMessage A reference to the message.
* @param[out] aResponse A reference to the Response data where to output the read value.
*
- * @retval OT_ERROR_NONE Successfully read the Response TLV.
- * @retval OT_ERROR_NOT_FOUND Response TLV was not found in the message.
- * @retval OT_ERROR_PARSE Response TLV was found but could not be parsed.
+ * @retval kErrorNone Successfully read the Response TLV.
+ * @retval kErrorNotFound Response TLV was not found in the message.
+ * @retval kErrorParse Response TLV was found but could not be parsed.
*
*/
- otError ReadResponse(const Message &aMessage, Challenge &aResponse);
+ Error ReadResponse(const Message &aMessage, Challenge &aResponse);
/**
* This method appends a Link Frame Counter TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Link Frame Counter TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Link Frame Counter TLV.
+ * @retval kErrorNone Successfully appended the Link Frame Counter TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Link Frame Counter TLV.
*
*/
- otError AppendLinkFrameCounter(Message &aMessage);
+ Error AppendLinkFrameCounter(Message &aMessage);
/**
* This method reads Link and MLE Frame Counters from a message.
@@ -1055,23 +1055,23 @@
* @param[out] aLinkFrameCounter A reference to an `uint32_t` to output the Link Frame Counter.
* @param[out] aMleFrameCounter A reference to an `uint32_t` to output the MLE Frame Counter.
*
- * @retval OT_ERROR_NONE Successfully read the counters.
- * @retval OT_ERROR_NOT_FOUND Link Frame Counter TLV was not found in the message.
- * @retval OT_ERROR_PARSE TLVs are not well-formed.
+ * @retval kErrorNone Successfully read the counters.
+ * @retval kErrorNotFound Link Frame Counter TLV was not found in the message.
+ * @retval kErrorParse TLVs are not well-formed.
*
*/
- otError ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
+ Error ReadFrameCounters(const Message &aMessage, uint32_t &aLinkFrameCounter, uint32_t &aMleFrameCounter) const;
/**
* This method appends an MLE Frame Counter TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Frame Counter TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the MLE Frame Counter TLV.
+ * @retval kErrorNone Successfully appended the Frame Counter TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the MLE Frame Counter TLV.
*
*/
- otError AppendMleFrameCounter(Message &aMessage);
+ Error AppendMleFrameCounter(Message &aMessage);
/**
* This method appends an Address16 TLV to a message.
@@ -1079,11 +1079,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aRloc16 The RLOC16 value.
*
- * @retval OT_ERROR_NONE Successfully appended the Address16 TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Address16 TLV.
+ * @retval kErrorNone Successfully appended the Address16 TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Address16 TLV.
*
*/
- otError AppendAddress16(Message &aMessage, uint16_t aRloc16);
+ Error AppendAddress16(Message &aMessage, uint16_t aRloc16);
/**
* This method appends a Network Data TLV to the message.
@@ -1091,11 +1091,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aStableOnly TRUE to append stable data, FALSE otherwise.
*
- * @retval OT_ERROR_NONE Successfully appended the Network Data TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Network Data TLV.
+ * @retval kErrorNone Successfully appended the Network Data TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Network Data TLV.
*
*/
- otError AppendNetworkData(Message &aMessage, bool aStableOnly);
+ Error AppendNetworkData(Message &aMessage, bool aStableOnly);
/**
* This method appends a TLV Request TLV to a message.
@@ -1104,11 +1104,11 @@
* @param[in] aTlvs A pointer to the list of TLV types.
* @param[in] aTlvsLength The number of TLV types in @p aTlvs
*
- * @retval OT_ERROR_NONE Successfully appended the TLV Request TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the TLV Request TLV.
+ * @retval kErrorNone Successfully appended the TLV Request TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the TLV Request TLV.
*
*/
- otError AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength);
+ Error AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength);
/**
* This method reads TLV Request TLV from a message.
@@ -1116,23 +1116,23 @@
* @param[in] aMessage A reference to the message.
* @param[out] aRequestedTlvs A reference to output the read list of requested TLVs.
*
- * @retval OT_ERROR_NONE Successfully read the TLV.
- * @retval OT_ERROR_NOT_FOUND TLV was not found in the message.
- * @retval OT_ERROR_PARSE TLV was found but could not be parsed.
+ * @retval kErrorNone Successfully read the TLV.
+ * @retval kErrorNotFound TLV was not found in the message.
+ * @retval kErrorParse TLV was found but could not be parsed.
*
*/
- otError FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs);
+ Error FindTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs);
/**
* This method appends a Leader Data TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Leader Data TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Leader Data TLV.
+ * @retval kErrorNone Successfully appended the Leader Data TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Leader Data TLV.
*
*/
- otError AppendLeaderData(Message &aMessage);
+ Error AppendLeaderData(Message &aMessage);
/**
* This method reads Leader Data TLV from a message.
@@ -1140,12 +1140,12 @@
* @param[in] aMessage A reference to the message.
* @param[out] aLeaderData A reference to output the Leader Data.
*
- * @retval OT_ERROR_NONE Successfully read the TLV.
- * @retval OT_ERROR_NOT_FOUND TLV was not found in the message.
- * @retval OT_ERROR_PARSE TLV was found but could not be parsed.
+ * @retval kErrorNone Successfully read the TLV.
+ * @retval kErrorNotFound TLV was not found in the message.
+ * @retval kErrorParse TLV was found but could not be parsed.
*
*/
- otError ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData);
+ Error ReadLeaderData(const Message &aMessage, LeaderData &aLeaderData);
/**
* This method appends a Scan Mask TLV to a message.
@@ -1153,11 +1153,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aScanMask The Scan Mask value.
*
- * @retval OT_ERROR_NONE Successfully appended the Scan Mask TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Scan Mask TLV.
+ * @retval kErrorNone Successfully appended the Scan Mask TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Scan Mask TLV.
*
*/
- otError AppendScanMask(Message &aMessage, uint8_t aScanMask);
+ Error AppendScanMask(Message &aMessage, uint8_t aScanMask);
/**
* This method appends a Status TLV to a message.
@@ -1165,11 +1165,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aStatus The Status value.
*
- * @retval OT_ERROR_NONE Successfully appended the Status TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Status TLV.
+ * @retval kErrorNone Successfully appended the Status TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Status TLV.
*
*/
- otError AppendStatus(Message &aMessage, StatusTlv::Status aStatus);
+ Error AppendStatus(Message &aMessage, StatusTlv::Status aStatus);
/**
* This method appends a Link Margin TLV to a message.
@@ -1177,22 +1177,22 @@
* @param[in] aMessage A reference to the message.
* @param[in] aLinkMargin The Link Margin value.
*
- * @retval OT_ERROR_NONE Successfully appended the Link Margin TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Link Margin TLV.
+ * @retval kErrorNone Successfully appended the Link Margin TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Link Margin TLV.
*
*/
- otError AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin);
+ Error AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin);
/**
* This method appends a Version TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Version TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Version TLV.
+ * @retval kErrorNone Successfully appended the Version TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Version TLV.
*
*/
- otError AppendVersion(Message &aMessage);
+ Error AppendVersion(Message &aMessage);
/**
* This method appends an Address Registration TLV to a message.
@@ -1200,11 +1200,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aMode Determines which addresses to include in the TLV (see `AddressRegistrationMode`).
*
- * @retval OT_ERROR_NONE Successfully appended the Address Registration TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Address Registration TLV.
+ * @retval kErrorNone Successfully appended the Address Registration TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Address Registration TLV.
*
*/
- otError AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode = kAppendAllAddresses);
+ Error AppendAddressRegistration(Message &aMessage, AddressRegistrationMode aMode = kAppendAllAddresses);
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
@@ -1212,80 +1212,80 @@
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Time Request TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Time Request TLV.
+ * @retval kErrorNone Successfully appended the Time Request TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Time Request TLV.
*
*/
- otError AppendTimeRequest(Message &aMessage);
+ Error AppendTimeRequest(Message &aMessage);
/**
* This method appends a Time Parameter TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Time Parameter TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Time Parameter TLV.
+ * @retval kErrorNone Successfully appended the Time Parameter TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Time Parameter TLV.
*
*/
- otError AppendTimeParameter(Message &aMessage);
+ Error AppendTimeParameter(Message &aMessage);
/**
* This method appends a XTAL Accuracy TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the XTAL Accuracy TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the XTAl Accuracy TLV.
+ * @retval kErrorNone Successfully appended the XTAL Accuracy TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the XTAl Accuracy TLV.
*
*/
- otError AppendXtalAccuracy(Message &aMessage);
+ Error AppendXtalAccuracy(Message &aMessage);
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-#if (!OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method appends a CSL Channel TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the CSL Channel TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the CSL Channel TLV.
+ * @retval kErrorNone Successfully appended the CSL Channel TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the CSL Channel TLV.
*
*/
- otError AppendCslChannel(Message &aMessage);
+ Error AppendCslChannel(Message &aMessage);
/**
* This method appends a CSL Sync Timeout TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the CSL Timeout TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the CSL Timeout TLV.
+ * @retval kErrorNone Successfully appended the CSL Timeout TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the CSL Timeout TLV.
*
*/
- otError AppendCslTimeout(Message &aMessage);
-#endif // (!OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ Error AppendCslTimeout(Message &aMessage);
+#endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE) || OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* This method appends a Active Timestamp TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Active Timestamp TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Active Timestamp TLV.
+ * @retval kErrorNone Successfully appended the Active Timestamp TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Active Timestamp TLV.
*
*/
- otError AppendActiveTimestamp(Message &aMessage);
+ Error AppendActiveTimestamp(Message &aMessage);
/**
* This method appends a Pending Timestamp TLV to a message.
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully appended the Pending Timestamp TLV.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Pending Timestamp TLV.
+ * @retval kErrorNone Successfully appended the Pending Timestamp TLV.
+ * @retval kErrorNoBufs Insufficient buffers available to append the Pending Timestamp TLV.
*
*/
- otError AppendPendingTimestamp(Message &aMessage);
+ Error AppendPendingTimestamp(Message &aMessage);
/**
* This method checks if the destination is reachable.
@@ -1293,11 +1293,11 @@
* @param[in] aMeshDest The RLOC16 of the destination.
* @param[in] aIp6Header The IPv6 header of the message.
*
- * @retval OT_ERROR_NONE The destination is reachable.
- * @retval OT_ERROR_NO_ROUTE The destination is not reachable and the message should be dropped.
+ * @retval kErrorNone The destination is reachable.
+ * @retval kErrorNoRoute The destination is not reachable and the message should be dropped.
*
*/
- otError CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
+ Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
/**
* This method returns the next hop towards an RLOC16 destination.
@@ -1319,25 +1319,25 @@
* @param[in] aExtraTlvs A pointer to extra TLVs.
* @param[in] aExtraTlvsLength Length of extra TLVs.
*
- * @retval OT_ERROR_NONE Successfully generated an MLE Data Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Data Request message.
+ * @retval kErrorNone Successfully generated an MLE Data Request message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Data Request message.
*
*/
- otError SendDataRequest(const Ip6::Address &aDestination,
- const uint8_t * aTlvs,
- uint8_t aTlvsLength,
- uint16_t aDelay,
- const uint8_t * aExtraTlvs = nullptr,
- uint8_t aExtraTlvsLength = 0);
+ Error SendDataRequest(const Ip6::Address &aDestination,
+ const uint8_t * aTlvs,
+ uint8_t aTlvsLength,
+ uint16_t aDelay,
+ const uint8_t * aExtraTlvs = nullptr,
+ uint8_t aExtraTlvsLength = 0);
/**
* This method generates an MLE Child Update Request message.
*
- * @retval OT_ERROR_NONE Successfully generated an MLE Child Update Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Child Update Request message.
+ * @retval kErrorNone Successfully generated an MLE Child Update Request message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Request message.
*
*/
- otError SendChildUpdateRequest(void);
+ Error SendChildUpdateRequest(void);
/**
* This method generates an MLE Child Update Response message.
@@ -1346,11 +1346,11 @@
* @param[in] aNumTlvs The number of TLV types in @p aTlvs.
* @param[in] aChallenge The Challenge for the response.
*
- * @retval OT_ERROR_NONE Successfully generated an MLE Child Update Response message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Child Update Response message.
+ * @retval kErrorNone Successfully generated an MLE Child Update Response message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Response message.
*
*/
- otError SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge);
+ Error SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge);
/**
* This method submits an MLE message to the UDP socket.
@@ -1358,11 +1358,11 @@
* @param[in] aMessage A reference to the message.
* @param[in] aDestination A reference to the IPv6 address of the destination.
*
- * @retval OT_ERROR_NONE Successfully submitted the MLE message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to form the rest of the MLE message.
+ * @retval kErrorNone Successfully submitted the MLE message.
+ * @retval kErrorNoBufs Insufficient buffers to form the rest of the MLE message.
*
*/
- otError SendMessage(Message &aMessage, const Ip6::Address &aDestination);
+ Error SendMessage(Message &aMessage, const Ip6::Address &aDestination);
/**
* This method sets the RLOC16 assigned to the Thread interface.
@@ -1401,11 +1401,11 @@
* @param[in] aDestination The IPv6 address of the recipient of the message.
* @param[in] aDelay The delay in milliseconds before transmission of the message.
*
- * @retval OT_ERROR_NONE Successfully queued the message to transmit after the delay.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to queue the message.
+ * @retval kErrorNone Successfully queued the message to transmit after the delay.
+ * @retval kErrorNoBufs Insufficient buffers to queue the message.
*
*/
- otError AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay);
+ Error AddDelayedResponse(Message &aMessage, const Ip6::Address &aDestination, uint16_t aDelay);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
/**
@@ -1437,29 +1437,29 @@
/**
* This static method emits a log message indicating an error in processing of a message.
*
- * Note that log message is emitted only if there is an error, i.e., @p aError is not `OT_ERROR_NONE`. The log
+ * Note that log message is emitted only if there is an error, i.e., @p aError is not `kErrorNone`. The log
* message will have the format "Failed to process {aMessageString} : {ErrorString}".
*
* @param[in] aType The message type.
* @param[in] aError The error in processing of the message.
*
*/
- static void LogProcessError(MessageType aType, otError aError);
+ static void LogProcessError(MessageType aType, Error aError);
/**
* This static method emits a log message indicating an error when sending a message.
*
- * Note that log message is emitted only if there is an error, i.e. @p aError is not `OT_ERROR_NONE`. The log
+ * Note that log message is emitted only if there is an error, i.e. @p aError is not `kErrorNone`. The log
* message will have the format "Failed to send {Message Type} : {ErrorString}".
*
* @param[in] aType The message type.
* @param[in] aError The error in sending the message.
*
*/
- static void LogSendError(MessageType aType, otError aError);
+ static void LogSendError(MessageType aType, Error aError);
#else
- static void LogProcessError(MessageType, otError) {}
- static void LogSendError(MessageType, otError) {}
+ static void LogProcessError(MessageType, Error) {}
+ static void LogSendError(MessageType, Error) {}
#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
/**
@@ -1520,13 +1520,11 @@
* @param[in] aSubTlvs A pointer to the buffer of the sub-TLVs in the message.
* @param[in] aLength The overall length of @p aSubTlvs.
*
- * @retval OT_ERROR_NONE Successfully sent a Link Metrics Management Request.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Link Metrics Management Request message.
+ * @retval kErrorNone Successfully sent a Link Metrics Management Request.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
*
*/
- otError SendLinkMetricsManagementRequest(const Ip6::Address &aDestination,
- const uint8_t * aSubTlvs,
- uint8_t aLength);
+ Error SendLinkMetricsManagementRequest(const Ip6::Address &aDestination, const uint8_t *aSubTlvs, uint8_t aLength);
/**
* This method sends an MLE Link Probe message.
@@ -1536,12 +1534,12 @@
* @param[in] aBuf A pointer to the data payload.
* @param[in] aLength The length of the data payload in Link Probe TLV, [0, 64].
*
- * @retval OT_ERROR_NONE Successfully sent a Link Metrics Management Request.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Link Metrics Management Request message.
- * @retval OT_ERROR_INVALID_ARGS Series ID is not a valid value, not within range [1, 254].
+ * @retval kErrorNone Successfully sent a Link Metrics Management Request.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Link Metrics Management Request message.
+ * @retval kErrorInvalidArgs Series ID is not a valid value, not within range [1, 254].
*
*/
- otError SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength);
+ Error SendLinkProbe(const Ip6::Address &aDestination, uint8_t aSeriesId, uint8_t *aBuf, uint8_t aLength);
#endif
@@ -1575,11 +1573,15 @@
kParentSearchBackoffInterval = (OPENTHREAD_CONFIG_PARENT_SEARCH_BACKOFF_INTERVAL * 1000u),
kParentSearchJitterInterval = (15 * 1000u),
kParentSearchRssThreadhold = OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD,
+ };
- // Parameters for "attach backoff" feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds.
- kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL,
- kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL,
- kAttachBackoffJitter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL,
+ // Parameters for "attach backoff" feature (CONFIG_ENABLE_ATTACH_BACKOFF) - Intervals are in milliseconds.
+ enum : uint32_t
+ {
+ kAttachBackoffMinInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MINIMUM_INTERVAL,
+ kAttachBackoffMaxInterval = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL,
+ kAttachBackoffJitter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_JITTER_INTERVAL,
+ kAttachBackoffDelayToResetCounter = OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_DELAY_TO_RESET_BACKOFF_INTERVAL,
};
enum ParentRequestType
@@ -1603,9 +1605,9 @@
struct DelayedResponseMetadata
{
- otError AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
- void ReadFrom(const Message &aMessage);
- void RemoveFrom(Message &aMessage) const;
+ Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
+ void ReadFrom(const Message &aMessage);
+ void RemoveFrom(Message &aMessage) const;
Ip6::Address mDestination; // IPv6 address of the message destination.
TimeMilli mSendTime; // Time when the message shall be sent.
@@ -1713,7 +1715,7 @@
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ScheduleMessageTransmissionTimer(void);
- otError ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer);
+ Error ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer);
void HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
void HandleChildIdResponse(const Message & aMessage,
@@ -1735,18 +1737,18 @@
Neighbor * aNeighbor);
void HandleLinkProbe(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
#endif
- otError HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- void ProcessAnnounce(void);
- bool HasUnregisteredAddress(void);
+ Error HandleLeaderData(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ void ProcessAnnounce(void);
+ bool HasUnregisteredAddress(void);
uint32_t GetAttachStartDelay(void) const;
- otError SendParentRequest(ParentRequestType aType);
- otError SendChildIdRequest(void);
- otError SendOrphanAnnounce(void);
+ Error SendParentRequest(ParentRequestType aType);
+ Error SendChildIdRequest(void);
+ Error SendOrphanAnnounce(void);
bool PrepareAnnounceState(void);
void SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Address &aDestination);
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
- otError SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus);
+ Error SendLinkMetricsManagementResponse(const Ip6::Address &aDestination, LinkMetrics::LinkMetricsStatus aStatus);
#endif
uint32_t Reattach(void);
@@ -1777,7 +1779,7 @@
#endif
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
- static void LogError(MessageAction aAction, MessageType aType, otError aError);
+ static void LogError(MessageAction aAction, MessageType aType, Error aError);
static const char *MessageActionToString(MessageAction aAction);
static const char *MessageTypeToString(MessageType aType);
static const char *MessageTypeActionToSuffixString(MessageType aType, MessageAction aAction);
diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp
index ae1b03a..06853d4 100644
--- a/src/core/thread/mle_router.cpp
+++ b/src/core/thread/mle_router.cpp
@@ -56,7 +56,7 @@
MleRouter::MleRouter(Instance &aInstance)
: Mle(aInstance)
- , mAdvertiseTimer(aInstance, MleRouter::HandleAdvertiseTimer, nullptr, this)
+ , mAdvertiseTrickleTimer(aInstance, MleRouter::HandleAdvertiseTrickleTimer)
, mAddressSolicit(UriPath::kAddressSolicit, &MleRouter::HandleAddressSolicit, this)
, mAddressRelease(UriPath::kAddressRelease, &MleRouter::HandleAddressRelease, this)
, mChildTable(aInstance)
@@ -114,11 +114,11 @@
return mRouterEligible && IsFullThreadDevice();
}
-otError MleRouter::SetRouterEligible(bool aEligible)
+Error MleRouter::SetRouterEligible(bool aEligible)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsFullThreadDevice() || !aEligible, error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(IsFullThreadDevice() || !aEligible, error = kErrorNotCapable);
mRouterEligible = aEligible;
@@ -146,13 +146,13 @@
return error;
}
-otError MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
+Error MleRouter::BecomeRouter(ThreadStatusTlv::Status aStatus)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsRouter(), error = OT_ERROR_NONE);
- VerifyOrExit(IsRouterEligible(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
+ VerifyOrExit(!IsRouter(), error = kErrorNone);
+ VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
otLogInfoMle("Attempt to become router");
@@ -179,17 +179,17 @@
return error;
}
-otError MleRouter::BecomeLeader(void)
+Error MleRouter::BecomeLeader(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Router * router;
uint32_t partitionId;
uint8_t leaderId;
- VerifyOrExit(!Get<MeshCoP::ActiveDataset>().IsPartiallyComplete(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsDisabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(!IsLeader(), error = OT_ERROR_NONE);
- VerifyOrExit(IsRouterEligible(), error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(!Get<MeshCoP::ActiveDataset>().IsPartiallyComplete(), error = kErrorInvalidState);
+ VerifyOrExit(!IsDisabled(), error = kErrorInvalidState);
+ VerifyOrExit(!IsLeader(), error = kErrorNone);
+ VerifyOrExit(IsRouterEligible(), error = kErrorNotCapable);
mRouterTable.Clear();
@@ -225,7 +225,7 @@
Get<Tmf::TmfAgent>().RemoveResource(mAddressRelease);
Get<MeshCoP::ActiveDataset>().StopLeader();
Get<MeshCoP::PendingDataset>().StopLeader();
- StopAdvertiseTimer();
+ StopAdvertiseTrickleTimer();
Get<NetworkData::Leader>().Stop();
Get<ThreadNetif>().UnsubscribeAllRoutersMulticast();
}
@@ -295,7 +295,8 @@
RemoveChildren();
}
- // fall through
+ OT_FALL_THROUGH;
+
case kAttachBetter:
if (HasChildren() && mPreviousPartitionIdRouter != mLeaderData.GetPartitionId())
{
@@ -323,7 +324,7 @@
mAttachCounter = 0;
mAttachTimer.Stop();
mMessageTransmissionTimer.Stop();
- StopAdvertiseTimer();
+ StopAdvertiseTrickleTimer();
ResetAdvertiseInterval();
Get<ThreadNetif>().SubscribeAllRoutersMulticast();
@@ -354,7 +355,7 @@
mAttachCounter = 0;
mAttachTimer.Stop();
mMessageTransmissionTimer.Stop();
- StopAdvertiseTimer();
+ StopAdvertiseTrickleTimer();
ResetAdvertiseInterval();
IgnoreError(GetLeaderAloc(mLeaderAloc.GetAddress()));
Get<ThreadNetif>().AddUnicastAddress(mLeaderAloc);
@@ -385,39 +386,37 @@
otLogNoteMle("Leader partition id 0x%x", mLeaderData.GetPartitionId());
}
-bool MleRouter::HandleAdvertiseTimer(TrickleTimer &aTimer)
+void MleRouter::HandleAdvertiseTrickleTimer(TrickleTimer &aTimer)
{
- return aTimer.GetOwner<MleRouter>().HandleAdvertiseTimer();
+ aTimer.Get<MleRouter>().HandleAdvertiseTrickleTimer();
}
-bool MleRouter::HandleAdvertiseTimer(void)
+void MleRouter::HandleAdvertiseTrickleTimer(void)
{
- bool continueTrickle = true;
-
- VerifyOrExit(IsRouterEligible(), continueTrickle = false);
+ VerifyOrExit(IsRouterEligible(), mAdvertiseTrickleTimer.Stop());
SendAdvertisement();
exit:
- return continueTrickle;
+ return;
}
-void MleRouter::StopAdvertiseTimer(void)
+void MleRouter::StopAdvertiseTrickleTimer(void)
{
- mAdvertiseTimer.Stop();
+ mAdvertiseTrickleTimer.Stop();
}
void MleRouter::ResetAdvertiseInterval(void)
{
VerifyOrExit(IsRouterOrLeader());
- if (!mAdvertiseTimer.IsRunning())
+ if (!mAdvertiseTrickleTimer.IsRunning())
{
- mAdvertiseTimer.Start(Time::SecToMsec(kAdvertiseIntervalMin), Time::SecToMsec(kAdvertiseIntervalMax),
- TrickleTimer::kModeNormal);
+ mAdvertiseTrickleTimer.Start(TrickleTimer::kModeTrickle, Time::SecToMsec(kAdvertiseIntervalMin),
+ Time::SecToMsec(kAdvertiseIntervalMax));
}
- mAdvertiseTimer.IndicateInconsistent();
+ mAdvertiseTrickleTimer.IndicateInconsistent();
exit:
return;
@@ -425,7 +424,7 @@
void MleRouter::SendAdvertisement(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message = nullptr;
@@ -442,7 +441,7 @@
// children to detach.
VerifyOrExit(!mAddressSolicitPending);
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandAdvertisement));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
@@ -473,18 +472,18 @@
LogSendError(kTypeAdvertisement, error);
}
-otError MleRouter::SendLinkRequest(Neighbor *aNeighbor)
+Error MleRouter::SendLinkRequest(Neighbor *aNeighbor)
{
static const uint8_t detachedTlvs[] = {Tlv::kAddress16, Tlv::kRoute};
static const uint8_t routerTlvs[] = {Tlv::kLinkMargin};
static const uint8_t validNeighborTlvs[] = {Tlv::kLinkMargin, Tlv::kRoute};
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message;
Ip6::Address destination;
destination.Clear();
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandLinkRequest));
SuccessOrExit(error = AppendVersion(*message));
@@ -560,7 +559,7 @@
void MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Neighbor * neighbor = nullptr;
Challenge challenge;
uint16_t version;
@@ -570,33 +569,33 @@
Log(kMessageReceive, kTypeLinkRequest, aMessageInfo.GetPeerAddr());
- VerifyOrExit(IsRouterOrLeader(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsRouterOrLeader(), error = kErrorInvalidState);
- VerifyOrExit(!IsAttaching(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!IsAttaching(), error = kErrorInvalidState);
// Challenge
SuccessOrExit(error = ReadChallenge(aMessage, challenge));
// Version
SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
- VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
+ VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
// Leader Data
switch (ReadLeaderData(aMessage, leaderData))
{
- case OT_ERROR_NONE:
- VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId(), error = OT_ERROR_INVALID_STATE);
+ case kErrorNone:
+ VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId(), error = kErrorInvalidState);
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Source Address
switch (Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
if (IsActiveRouter(sourceAddress))
{
Mac::ExtAddress extAddr;
@@ -604,8 +603,8 @@
aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
neighbor = mRouterTable.GetRouter(RouterIdFromRloc16(sourceAddress));
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_PARSE);
- VerifyOrExit(!neighbor->IsStateLinkRequest(), error = OT_ERROR_ALREADY);
+ VerifyOrExit(neighbor != nullptr, error = kErrorParse);
+ VerifyOrExit(!neighbor->IsStateLinkRequest(), error = kErrorAlready);
if (!neighbor->IsStateValid())
{
@@ -624,33 +623,33 @@
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
// lack of source address indicates router coming out of reset
VerifyOrExit(aNeighbor && aNeighbor->IsStateValid() && IsActiveRouter(aNeighbor->GetRloc16()),
- error = OT_ERROR_DROP);
+ error = kErrorDrop);
neighbor = aNeighbor;
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// TLV Request
switch (FindTlvRequest(aMessage, requestedTlvs))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
requestedTlvs.mNumTlvs = 0;
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
if (neighbor != nullptr)
{
- neighbor->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == OT_ERROR_NONE);
+ neighbor->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == kErrorNone);
}
#endif
@@ -667,12 +666,12 @@
LogProcessError(kTypeLinkRequest, error);
}
-otError MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
- Neighbor * aNeighbor,
- const RequestedTlvs & aRequestedTlvs,
- const Challenge & aChallenge)
+Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
+ Neighbor * aNeighbor,
+ const RequestedTlvs & aRequestedTlvs,
+ const Challenge & aChallenge)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
static const uint8_t routerTlvs[] = {Tlv::kLinkMargin};
Message * message;
Command command;
@@ -680,7 +679,7 @@
command = (aNeighbor == nullptr || aNeighbor->IsStateValid()) ? kCommandLinkAccept : kCommandLinkAcceptAndRequest;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, command));
SuccessOrExit(error = AppendVersion(*message));
SuccessOrExit(error = AppendSourceAddress(*message));
@@ -708,7 +707,7 @@
break;
case Tlv::kAddress16:
- VerifyOrExit(aNeighbor != nullptr, error = OT_ERROR_DROP);
+ VerifyOrExit(aNeighbor != nullptr, error = kErrorDrop);
SuccessOrExit(error = AppendAddress16(*message, aNeighbor->GetRloc16()));
break;
@@ -716,7 +715,7 @@
break;
default:
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
}
@@ -761,7 +760,7 @@
uint32_t aKeySequence,
Neighbor * aNeighbor)
{
- otError error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, false);
+ Error error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, false);
LogProcessError(kTypeLinkAccept, error);
}
@@ -771,20 +770,20 @@
uint32_t aKeySequence,
Neighbor * aNeighbor)
{
- otError error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, true);
+ Error error = HandleLinkAccept(aMessage, aMessageInfo, aKeySequence, aNeighbor, true);
LogProcessError(kTypeLinkAcceptAndRequest, error);
}
-otError MleRouter::HandleLinkAccept(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- uint32_t aKeySequence,
- Neighbor * aNeighbor,
- bool aRequest)
+Error MleRouter::HandleLinkAccept(const Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ uint32_t aKeySequence,
+ Neighbor * aNeighbor,
+ bool aRequest)
{
static const uint8_t dataRequestTlvs[] = {Tlv::kNetworkData};
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Router * router;
Neighbor::State neighborState;
Mac::ExtAddress extAddr;
@@ -805,7 +804,7 @@
Log(kMessageReceive, aRequest ? kTypeLinkAcceptAndRequest : kTypeLinkAccept, aMessageInfo.GetPeerAddr(),
sourceAddress);
- VerifyOrExit(IsActiveRouter(sourceAddress), error = OT_ERROR_PARSE);
+ VerifyOrExit(IsActiveRouter(sourceAddress), error = kErrorParse);
routerId = RouterIdFromRloc16(sourceAddress);
router = mRouterTable.GetRouter(routerId);
@@ -818,17 +817,19 @@
switch (neighborState)
{
case Neighbor::kStateLinkRequest:
- VerifyOrExit(response.Matches(router->GetChallenge(), router->GetChallengeSize()), error = OT_ERROR_SECURITY);
+ VerifyOrExit(response.Matches(router->GetChallenge(), router->GetChallengeSize()), error = kErrorSecurity);
break;
case Neighbor::kStateInvalid:
- VerifyOrExit((mChallengeTimeout > 0) && (response == mChallenge), error = OT_ERROR_SECURITY);
+ VerifyOrExit((mChallengeTimeout > 0) && (response == mChallenge), error = kErrorSecurity);
+
+ OT_FALL_THROUGH;
case Neighbor::kStateValid:
break;
default:
- ExitNow(error = OT_ERROR_SECURITY);
+ ExitNow(error = kErrorSecurity);
}
// Remove stale neighbors
@@ -839,7 +840,7 @@
// Version
SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
- VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
+ VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
// Link and MLE Frame Counters
SuccessOrExit(error = ReadFrameCounters(aMessage, linkFrameCounter, mleFrameCounter));
@@ -847,16 +848,16 @@
// Link Margin
switch (Tlv::Find<LinkMarginTlv>(aMessage, linkMargin))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
// Link Margin TLV may be skipped in Router Synchronization process after Reset
- VerifyOrExit(IsDetached(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(IsDetached(), error = kErrorNotFound);
// Wait for an MLE Advertisement to establish a routing cost to the neighbor
linkMargin = 0;
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
switch (mRole)
@@ -868,7 +869,7 @@
case kRoleDetached:
// Address16
SuccessOrExit(error = Tlv::Find<Address16Tlv>(aMessage, address16));
- VerifyOrExit(GetRloc16() == address16, error = OT_ERROR_DROP);
+ VerifyOrExit(GetRloc16() == address16, error = kErrorDrop);
// Leader Data
SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
@@ -876,7 +877,7 @@
// Route
SuccessOrExit(error = Tlv::FindTlv(aMessage, Tlv::kRoute, sizeof(route), route));
- VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(route.IsValid(), error = kErrorParse);
mRouterTable.Clear();
SuccessOrExit(error = ProcessRouteTlv(route));
router = mRouterTable.GetRouter(routerId);
@@ -918,9 +919,9 @@
}
// Route (optional)
- if (Tlv::FindTlv(aMessage, route) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, route) == kErrorNone)
{
- VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(route.IsValid(), error = kErrorParse);
SuccessOrExit(error = ProcessRouteTlv(route));
UpdateRoutes(route, routerId);
// need to update router after ProcessRouteTlv
@@ -945,6 +946,7 @@
router->SetLinkAckFrameCounter(linkFrameCounter);
router->SetMleFrameCounter(mleFrameCounter);
router->SetLastHeard(TimerMilli::GetNow());
+ router->SetVersion(static_cast<uint8_t>(version));
router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
DeviceMode::kModeFullNetworkData));
router->GetLinkInfo().Clear();
@@ -967,13 +969,13 @@
// TLV Request
switch (FindTlvRequest(aMessage, requestedTlvs))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
requestedTlvs.mNumTlvs = 0;
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
SuccessOrExit(error = SendLinkAccept(aMessageInfo, router, requestedTlvs, challenge));
@@ -1025,11 +1027,11 @@
return rval;
}
-otError MleRouter::SetRouterSelectionJitter(uint8_t aRouterJitter)
+Error MleRouter::SetRouterSelectionJitter(uint8_t aRouterJitter)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aRouterJitter > 0, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aRouterJitter > 0, error = kErrorInvalidArgs);
mRouterSelectionJitter = aRouterJitter;
@@ -1037,16 +1039,16 @@
return error;
}
-otError MleRouter::ProcessRouteTlv(const RouteTlv &aRoute)
+Error MleRouter::ProcessRouteTlv(const RouteTlv &aRoute)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
mRouterTable.UpdateRouterIdSet(aRoute.GetRouterIdSequence(), aRoute.GetRouterIdMask());
if (IsRouter() && !mRouterTable.IsAllocated(mRouterId))
{
IgnoreError(BecomeDetached());
- error = OT_ERROR_NO_ROUTE;
+ error = kErrorNoRoute;
}
return error;
@@ -1119,11 +1121,9 @@
return rval;
}
-otError MleRouter::HandleAdvertisement(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- Neighbor * aNeighbor)
+Error MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const ThreadLinkInfo *linkInfo = aMessageInfo.GetThreadLinkInfo();
uint8_t linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->GetRss());
Mac::ExtAddress extAddr;
@@ -1144,9 +1144,9 @@
SuccessOrExit(error = ReadLeaderData(aMessage, leaderData));
// Route Data (optional)
- if (Tlv::FindTlv(aMessage, route) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, route) == kErrorNone)
{
- VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(route.IsValid(), error = kErrorParse);
}
else
{
@@ -1160,13 +1160,13 @@
{
otLogNoteMle("Different partition (peer:%u, local:%u)", partitionId, mLeaderData.GetPartitionId());
- VerifyOrExit(linkMargin >= OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN, error = OT_ERROR_LINK_MARGIN_LOW);
+ VerifyOrExit(linkMargin >= OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN, error = kErrorLinkMarginLow);
if (route.IsValid() && IsFullThreadDevice() && (mPreviousPartitionIdTimeout > 0) &&
(partitionId == mPreviousPartitionId))
{
VerifyOrExit((static_cast<int8_t>(route.GetRouterIdSequence() - mPreviousPartitionRouterIdSequence) > 0),
- error = OT_ERROR_DROP);
+ error = kErrorDrop);
}
if (IsChild() && (aNeighbor == &mParent || !IsFullThreadDevice()))
@@ -1184,7 +1184,7 @@
IgnoreError(BecomeChild(kAttachBetter));
}
- ExitNow(error = OT_ERROR_DROP);
+ ExitNow(error = kErrorDrop);
}
else if (leaderData.GetLeaderRouterId() != GetLeaderId())
{
@@ -1194,7 +1194,7 @@
{
otLogInfoMle("Leader ID mismatch");
IgnoreError(BecomeDetached());
- error = OT_ERROR_DROP;
+ error = kErrorDrop;
}
ExitNow();
@@ -1267,7 +1267,7 @@
if (mParent.GetRloc16() != sourceAddress)
{
IgnoreError(BecomeDetached());
- ExitNow(error = OT_ERROR_NO_ROUTE);
+ ExitNow(error = kErrorNoRoute);
}
if (IsFullThreadDevice())
@@ -1330,7 +1330,7 @@
router->SetLastHeard(TimerMilli::GetNow());
router->SetState(Neighbor::kStateLinkRequest);
IgnoreError(SendLinkRequest(router));
- ExitNow(error = OT_ERROR_NO_ROUTE);
+ ExitNow(error = kErrorNoRoute);
}
}
@@ -1360,7 +1360,7 @@
mRouterSelectionJitterTimeout = 1 + Random::NonCrypto::GetUint8InRange(0, mRouterSelectionJitter);
}
- // fall through
+ OT_FALL_THROUGH;
case kRoleLeader:
router = mRouterTable.GetRouter(routerId);
@@ -1377,7 +1377,7 @@
router->SetLastHeard(TimerMilli::GetNow());
router->SetState(Neighbor::kStateLinkRequest);
IgnoreError(SendLinkRequest(router));
- ExitNow(error = OT_ERROR_NO_ROUTE);
+ ExitNow(error = kErrorNoRoute);
}
router->SetLastHeard(TimerMilli::GetNow());
@@ -1549,7 +1549,7 @@
void MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mac::ExtAddress extAddr;
uint16_t version;
uint8_t scanMask;
@@ -1559,12 +1559,12 @@
Log(kMessageReceive, kTypeParentRequest, aMessageInfo.GetPeerAddr());
- VerifyOrExit(IsRouterEligible(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
// A Router/REED MUST NOT send an MLE Parent Response if:
// 0. It is detached or attempting to another partition
- VerifyOrExit(!IsDetached() && !IsAttaching(), error = OT_ERROR_DROP);
+ VerifyOrExit(!IsDetached() && !IsAttaching(), error = kErrorDrop);
// 1. It has no available Child capacity (if Max Child Count minus
// Child Count would be equal to zero)
@@ -1573,7 +1573,7 @@
// 2. It is disconnected from its Partition (that is, it has not
// received an updated ID sequence number within LEADER_TIMEOUT
// seconds)
- VerifyOrExit(mRouterTable.GetLeaderAge() < mNetworkIdTimeout, error = OT_ERROR_DROP);
+ VerifyOrExit(mRouterTable.GetLeaderAge() < mNetworkIdTimeout, error = kErrorDrop);
// 3. Its current routing path cost to the Leader is infinite.
leader = mRouterTable.GetLeader();
@@ -1582,7 +1582,7 @@
VerifyOrExit(IsLeader() || GetLinkCost(GetLeaderId()) < kMaxRouteCost ||
(IsChild() && leader->GetCost() + 1 < kMaxRouteCost) ||
(leader->GetCost() + GetLinkCost(leader->GetNextHop()) < kMaxRouteCost),
- error = OT_ERROR_DROP);
+ error = kErrorDrop);
// 4. It is a REED and there are already `kMaxRouters` active routers in
// the network (because Leader would reject any further address solicit).
@@ -1592,7 +1592,7 @@
// Version
SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
- VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
+ VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
// Scan Mask
SuccessOrExit(error = Tlv::Find<ScanMaskTlv>(aMessage, scanMask));
@@ -1605,7 +1605,7 @@
case kRoleChild:
VerifyOrExit(ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
- VerifyOrExit(mRouterTable.GetActiveRouterCount() < kMaxRouters, error = OT_ERROR_DROP);
+ VerifyOrExit(mRouterTable.GetActiveRouterCount() < kMaxRouters, error = kErrorDrop);
break;
case kRoleRouter:
@@ -1621,7 +1621,7 @@
if (child == nullptr)
{
- VerifyOrExit((child = mChildTable.GetNewChild()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((child = mChildTable.GetNewChild()) != nullptr, error = kErrorNoBufs);
// MAC Address
child->SetExtAddress(extAddr);
@@ -1630,12 +1630,12 @@
child->ResetLinkFailures();
child->SetState(Neighbor::kStateParentRequest);
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
- child->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == OT_ERROR_NONE);
+ child->SetTimeSyncEnabled(Tlv::Find<TimeRequestTlv>(aMessage, nullptr, 0) == kErrorNone);
#endif
}
else if (TimerMilli::GetNow() - child->GetLastHeard() < kParentRequestRouterTimeout - kParentRequestDuplicateMargin)
{
- ExitNow(error = OT_ERROR_DUPLICATED);
+ ExitNow(error = kErrorDuplicated);
}
if (!child->IsStateValidOrRestoring())
@@ -1687,7 +1687,7 @@
// If no Backbone Router service after jitter, try to register its own Backbone Router Service.
if (!Get<BackboneRouter::Leader>().HasPrimary())
{
- if (Get<BackboneRouter::Local>().AddService() == OT_ERROR_NONE)
+ if (Get<BackboneRouter::Local>().AddService() == kErrorNone)
{
Get<NetworkData::Notifier>().HandleServerDataUpdated();
}
@@ -1725,19 +1725,18 @@
InformPreviousChannel();
}
- if (!mAdvertiseTimer.IsRunning())
+ if (!mAdvertiseTrickleTimer.IsRunning())
{
SendAdvertisement();
- mAdvertiseTimer.Start(Time::SecToMsec(kReedAdvertiseInterval),
- Time::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter),
- TrickleTimer::kModePlainTimer);
+ mAdvertiseTrickleTimer.Start(TrickleTimer::kModePlainTimer, Time::SecToMsec(kReedAdvertiseInterval),
+ Time::SecToMsec(kReedAdvertiseInterval + kReedAdvertiseJitter));
}
ExitNow();
}
- // fall through
+ OT_FALL_THROUGH;
case kRoleRouter:
// verify path to leader
@@ -1786,7 +1785,7 @@
OT_UNREACHABLE_CODE(break);
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
if (child.IsCslSynchronized() &&
TimerMilli::GetNow() - child.GetCslLastHeard() >= Time::SecToMsec(child.GetCslTimeout()))
{
@@ -1887,12 +1886,12 @@
void MleRouter::SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message;
uint16_t delay;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetDirectTransmission();
SuccessOrExit(error = AppendHeader(*message, kCommandParentResponse));
@@ -1952,11 +1951,11 @@
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
-otError MleRouter::SetMaxChildIpAddresses(uint8_t aMaxIpAddresses)
+Error MleRouter::SetMaxChildIpAddresses(uint8_t aMaxIpAddresses)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aMaxIpAddresses <= OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aMaxIpAddresses <= OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD, error = kErrorInvalidArgs);
mMaxChildIpAddresses = aMaxIpAddresses;
@@ -1965,9 +1964,9 @@
}
#endif
-otError MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild)
+Error MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
AddressRegistrationEntry entry;
Ip6::Address address;
Lowpan::Context context;
@@ -1988,7 +1987,7 @@
#endif
SuccessOrExit(error = aMessage.Read(aOffset, tlv));
- VerifyOrExit(tlv.GetLength() <= (aMessage.GetLength() - aOffset - sizeof(tlv)), error = OT_ERROR_PARSE);
+ VerifyOrExit(tlv.GetLength() <= (aMessage.GetLength() - aOffset - sizeof(tlv)), error = kErrorParse);
offset = aOffset + sizeof(tlv);
end = offset + tlv.GetLength();
@@ -2035,7 +2034,7 @@
if (entry.IsCompressed())
{
- if (Get<NetworkData::Leader>().GetContext(entry.GetContextId(), context) != OT_ERROR_NONE)
+ if (Get<NetworkData::Leader>().GetContext(entry.GetContextId(), context) != kErrorNone)
{
otLogWarnMle("Failed to get context %d for compressed address from child 0x%04x", entry.GetContextId(),
aChild.GetRloc16());
@@ -2074,7 +2073,7 @@
if (mMaxChildIpAddresses > 0 && storedCount >= mMaxChildIpAddresses)
{
// Skip remaining address registration entries but keep logging skipped addresses.
- error = OT_ERROR_NO_BUFS;
+ error = kErrorNoBufs;
}
else
#endif
@@ -2085,7 +2084,7 @@
error = aChild.AddIp6Address(address);
}
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
storedCount++;
otLogInfoMle("Child 0x%04x IPv6 address[%d]=%s", aChild.GetRloc16(), storedCount,
@@ -2093,7 +2092,7 @@
}
else
{
- otLogWarnMle("Error %s adding IPv6 address %s to child 0x%04x", otThreadErrorToString(error),
+ otLogWarnMle("Error %s adding IPv6 address %s to child 0x%04x", ErrorToString(error),
address.ToString().AsCString(), aChild.GetRloc16());
}
@@ -2147,7 +2146,7 @@
registeredCount, (registeredCount == 1) ? "" : "es", storedCount, (storedCount == 1) ? "" : "es");
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
@@ -2157,7 +2156,7 @@
const Ip6::MessageInfo &aMessageInfo,
uint32_t aKeySequence)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mac::ExtAddress extAddr;
uint16_t version;
Challenge response;
@@ -2176,24 +2175,24 @@
Log(kMessageReceive, kTypeChildIdRequest, aMessageInfo.GetPeerAddr());
- VerifyOrExit(IsRouterEligible(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
// only process message when operating as a child, router, or leader
- VerifyOrExit(IsAttached(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsAttached(), error = kErrorInvalidState);
// Find Child
aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
- VerifyOrExit(child != nullptr, error = OT_ERROR_ALREADY);
+ VerifyOrExit(child != nullptr, error = kErrorAlready);
// Version
SuccessOrExit(error = Tlv::Find<VersionTlv>(aMessage, version));
- VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
+ VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = kErrorParse);
// Response
SuccessOrExit(error = ReadResponse(aMessage, response));
- VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = OT_ERROR_SECURITY);
+ VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity);
// Remove existing MLE messages
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleGeneral);
@@ -2213,22 +2212,22 @@
// TLV Request
SuccessOrExit(error = FindTlvRequest(aMessage, requestedTlvs));
- VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = OT_ERROR_PARSE);
+ VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = kErrorParse);
// Active Timestamp
activeTimestamp.SetLength(0);
- if (Tlv::FindTlv(aMessage, activeTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone)
{
- VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
}
// Pending Timestamp
pendingTimestamp.SetLength(0);
- if (Tlv::FindTlv(aMessage, pendingTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone)
{
- VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
}
if (!mode.IsFullThreadDevice())
@@ -2321,7 +2320,7 @@
{
static const uint8_t kMaxResponseTlvs = 10;
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mac::ExtAddress extAddr;
uint8_t modeBitmask;
DeviceMode mode;
@@ -2345,14 +2344,14 @@
// Challenge
switch (ReadChallenge(aMessage, challenge))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
tlvs[tlvslength++] = Tlv::kResponse;
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
challenge.mLength = 0;
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Find Child
@@ -2390,7 +2389,7 @@
}
// Ip6 Address TLV
- if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == OT_ERROR_NONE)
+ if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
{
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
tlvs[tlvslength++] = Tlv::kAddressRegistration;
@@ -2399,17 +2398,17 @@
// Leader Data
switch (ReadLeaderData(aMessage, leaderData))
{
- case OT_ERROR_NONE:
- case OT_ERROR_NOT_FOUND:
+ case kErrorNone:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Timeout
switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
if (child->GetTimeout() != timeout)
{
child->SetTimeout(timeout);
@@ -2419,18 +2418,18 @@
tlvs[tlvslength++] = Tlv::kTimeout;
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// TLV Request
switch (FindTlvRequest(aMessage, requestedTlvs))
{
- case OT_ERROR_NONE:
- VerifyOrExit(requestedTlvs.mNumTlvs <= (kMaxResponseTlvs - tlvslength), error = OT_ERROR_PARSE);
+ case kErrorNone:
+ VerifyOrExit(requestedTlvs.mNumTlvs <= (kMaxResponseTlvs - tlvslength), error = kErrorParse);
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
{
// Skip LeaderDataTlv since it is already included by default.
@@ -2440,24 +2439,24 @@
}
}
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
if (child->IsCslSynchronized())
{
CslChannelTlv cslChannel;
uint32_t cslTimeout;
- if (Tlv::Find<CslTimeoutTlv>(aMessage, cslTimeout) == OT_ERROR_NONE)
+ if (Tlv::Find<CslTimeoutTlv>(aMessage, cslTimeout) == kErrorNone)
{
child->SetCslTimeout(cslTimeout);
}
- if (Tlv::FindTlv(aMessage, cslChannel) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, cslChannel) == kErrorNone)
{
child->SetCslChannel(static_cast<uint8_t>(cslChannel.GetChannel()));
}
@@ -2467,7 +2466,7 @@
child->SetCslChannel(0);
}
}
-#endif // !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
child->SetLastHeard(TimerMilli::GetNow());
@@ -2478,7 +2477,7 @@
childDidChange = true;
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
if (child->IsRxOnWhenIdle())
{
// Clear CSL synchronization state
@@ -2522,7 +2521,7 @@
uint32_t aKeySequence,
Neighbor * aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t sourceAddress;
uint32_t timeout;
Challenge response;
@@ -2536,7 +2535,7 @@
if ((aNeighbor == nullptr) || IsActiveRouter(aNeighbor->GetRloc16()))
{
Log(kMessageReceive, kTypeChildUpdateResponseOfUnknownChild, aMessageInfo.GetPeerAddr());
- ExitNow(error = OT_ERROR_NOT_FOUND);
+ ExitNow(error = kErrorNotFound);
}
child = static_cast<Child *>(aNeighbor);
@@ -2544,14 +2543,14 @@
// Response
switch (ReadResponse(aMessage, response))
{
- case OT_ERROR_NONE:
- VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = OT_ERROR_SECURITY);
+ case kErrorNone:
+ VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity);
break;
- case OT_ERROR_NOT_FOUND:
- VerifyOrExit(child->IsStateValid(), error = OT_ERROR_SECURITY);
+ case kErrorNotFound:
+ VerifyOrExit(child->IsStateValid(), error = kErrorSecurity);
break;
default:
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
Log(kMessageReceive, kTypeChildUpdateResponseOfChild, aMessageInfo.GetPeerAddr(), child->GetRloc16());
@@ -2559,7 +2558,7 @@
// Source Address
switch (Tlv::Find<SourceAddressTlv>(aMessage, sourceAddress))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
if (child->GetRloc16() != sourceAddress)
{
RemoveNeighbor(*child);
@@ -2568,65 +2567,65 @@
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Status
switch (Tlv::Find<ThreadStatusTlv>(aMessage, status))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
VerifyOrExit(status != StatusTlv::kError, RemoveNeighbor(*child));
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Link-Layer Frame Counter
switch (Tlv::Find<LinkFrameCounterTlv>(aMessage, linkFrameCounter))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
child->GetLinkFrameCounters().SetAll(linkFrameCounter);
child->SetLinkAckFrameCounter(linkFrameCounter);
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// MLE Frame Counter
switch (Tlv::Find<MleFrameCounterTlv>(aMessage, mleFrameCounter))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
child->SetMleFrameCounter(mleFrameCounter);
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
// Timeout
switch (Tlv::Find<TimeoutTlv>(aMessage, timeout))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
child->SetTimeout(timeout);
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// Ip6 Address
- if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == OT_ERROR_NONE)
+ if (Tlv::FindTlvOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset) == kErrorNone)
{
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
}
@@ -2634,7 +2633,7 @@
// Leader Data
switch (ReadLeaderData(aMessage, leaderData))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
if (child->IsFullNetworkData())
{
child->SetNetworkDataVersion(leaderData.GetDataVersion());
@@ -2644,10 +2643,10 @@
child->SetNetworkDataVersion(leaderData.GetStableDataVersion());
}
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
SetChildStateToValid(*child);
@@ -2663,7 +2662,7 @@
const Ip6::MessageInfo &aMessageInfo,
const Neighbor * aNeighbor)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
RequestedTlvs requestedTlvs;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
@@ -2672,26 +2671,26 @@
Log(kMessageReceive, kTypeDataRequest, aMessageInfo.GetPeerAddr());
- VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = OT_ERROR_SECURITY);
+ VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = kErrorSecurity);
// TLV Request
SuccessOrExit(error = FindTlvRequest(aMessage, requestedTlvs));
- VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = OT_ERROR_PARSE);
+ VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = kErrorParse);
// Active Timestamp
activeTimestamp.SetLength(0);
- if (Tlv::FindTlv(aMessage, activeTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, activeTimestamp) == kErrorNone)
{
- VerifyOrExit(activeTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(activeTimestamp.IsValid(), error = kErrorParse);
}
// Pending Timestamp
pendingTimestamp.SetLength(0);
- if (Tlv::FindTlv(aMessage, pendingTimestamp) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, pendingTimestamp) == kErrorNone)
{
- VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(pendingTimestamp.IsValid(), error = kErrorParse);
}
memset(tlvs, Tlv::kInvalid, sizeof(tlvs));
@@ -2797,7 +2796,7 @@
void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Tlv tlv;
MeshCoP::Tlv meshcopTlv;
MeshCoP::DiscoveryRequestTlv discoveryRequest;
@@ -2810,10 +2809,10 @@
discoveryRequest.SetLength(0);
// only Routers and REEDs respond
- VerifyOrExit(IsRouterEligible(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
// find MLE Discovery TLV
- VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == OT_ERROR_NONE, error = OT_ERROR_PARSE);
+ VerifyOrExit(Tlv::FindTlvOffset(aMessage, Tlv::kDiscovery, offset) == kErrorNone, error = kErrorParse);
IgnoreError(aMessage.Read(offset, tlv));
offset += sizeof(tlv);
@@ -2827,13 +2826,13 @@
{
case MeshCoP::Tlv::kDiscoveryRequest:
IgnoreError(aMessage.Read(offset, discoveryRequest));
- VerifyOrExit(discoveryRequest.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(discoveryRequest.IsValid(), error = kErrorParse);
break;
case MeshCoP::Tlv::kExtendedPanId:
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aMessage, offset, extPanId));
- VerifyOrExit(Get<Mac::Mac>().GetExtendedPanId() != extPanId, error = OT_ERROR_DROP);
+ VerifyOrExit(Get<Mac::Mac>().GetExtendedPanId() != extPanId, error = kErrorDrop);
break;
@@ -2866,7 +2865,7 @@
else // if steering data is not set out of band, fall back to network data
#endif
{
- VerifyOrExit(Get<NetworkData::Leader>().IsJoiningEnabled(), error = OT_ERROR_SECURITY);
+ VerifyOrExit(Get<NetworkData::Leader>().IsJoiningEnabled(), error = kErrorSecurity);
}
}
}
@@ -2877,9 +2876,9 @@
LogProcessError(kTypeDiscoveryRequest, error);
}
-otError MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage)
+Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message;
uint16_t startOffset;
Tlv tlv;
@@ -2887,7 +2886,7 @@
MeshCoP::NetworkNameTlv networkName;
uint16_t delay;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleDiscoverResponse);
message->SetPanId(aDiscoverRequestMessage.GetPanId());
#if OPENTHREAD_CONFIG_MULTI_RADIO
@@ -2968,13 +2967,13 @@
return error;
}
-otError MleRouter::SendChildIdResponse(Child &aChild)
+Error MleRouter::SendChildIdResponse(Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandChildIdResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendLeaderData(*message));
@@ -3059,10 +3058,10 @@
return error;
}
-otError MleRouter::SendChildUpdateRequest(Child &aChild)
+Error MleRouter::SendChildUpdateRequest(Child &aChild)
{
static const uint8_t tlvs[] = {Tlv::kTimeout, Tlv::kAddressRegistration};
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message;
@@ -3088,7 +3087,7 @@
}
}
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleChildUpdateRequest);
SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateRequest));
SuccessOrExit(error = AppendSourceAddress(*message));
@@ -3126,10 +3125,10 @@
uint8_t aTlvsLength,
const Challenge & aChallenge)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message *message;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandChildUpdateResponse));
for (int i = 0; i < aTlvsLength; i++)
@@ -3203,7 +3202,7 @@
{
OT_UNUSED_VARIABLE(aRequestMessage);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Message * message = nullptr;
Neighbor *neighbor;
bool stableOnly;
@@ -3214,7 +3213,7 @@
ExitNow();
}
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeMleDataResponse);
SuccessOrExit(error = AppendHeader(*message, kCommandDataResponse));
SuccessOrExit(error = AppendSourceAddress(*message));
@@ -3244,7 +3243,7 @@
case Tlv::kLinkMetricsReport:
OT_ASSERT(aRequestMessage != nullptr);
neighbor = mNeighborTable.FindNeighbor(aDestination);
- VerifyOrExit(neighbor != nullptr, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(neighbor != nullptr, error = kErrorInvalidState);
SuccessOrExit(error = Get<LinkMetrics>().AppendLinkMetricsReport(*message, *aRequestMessage, *neighbor));
break;
#endif
@@ -3440,11 +3439,11 @@
return rval;
}
-otError MleRouter::SetPreferredRouterId(uint8_t aRouterId)
+Error MleRouter::SetPreferredRouterId(uint8_t aRouterId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsDetached() || IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsDetached() || IsDisabled(), error = kErrorInvalidState);
mPreviousRouterId = aRouterId;
@@ -3479,9 +3478,9 @@
return;
}
-otError MleRouter::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
+Error MleRouter::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (IsChild())
{
@@ -3517,21 +3516,21 @@
ExitNow();
}
- error = OT_ERROR_NO_ROUTE;
+ error = kErrorNoRoute;
exit:
return error;
}
-otError MleRouter::SendAddressSolicit(ThreadStatusTlv::Status aStatus)
+Error MleRouter::SendAddressSolicit(ThreadStatusTlv::Status aStatus)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::MessageInfo messageInfo;
Coap::Message * message = nullptr;
VerifyOrExit(!mAddressSolicitPending);
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kAddressSolicit));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -3566,11 +3565,11 @@
void MleRouter::SendAddressRelease(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::MessageInfo messageInfo;
Coap::Message * message;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kAddressRelease));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -3594,7 +3593,7 @@
void MleRouter::HandleAddressSolicitResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<MleRouter *>(aContext)->HandleAddressSolicitResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -3602,7 +3601,7 @@
void MleRouter::HandleAddressSolicitResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
@@ -3615,7 +3614,7 @@
mAddressSolicitPending = false;
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage != nullptr && aMessage != nullptr);
+ VerifyOrExit(aResult == kErrorNone && aMessage != nullptr && aMessage != nullptr);
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged);
@@ -3707,7 +3706,7 @@
void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mac::ExtAddress extAddress;
uint16_t rloc16;
uint8_t status;
@@ -3716,7 +3715,7 @@
uint16_t xtalAccuracy;
#endif
- VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = OT_ERROR_PARSE);
+ VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorParse);
Log(kMessageReceive, kTypeAddressSolicit, aMessageInfo.GetPeerAddr());
@@ -3749,19 +3748,19 @@
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
OT_UNREACHABLE_CODE(break);
}
switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
router = mRouterTable.Allocate(RouterIdFromRloc16(rloc16));
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
- ExitNow(error = OT_ERROR_PARSE);
+ ExitNow(error = kErrorParse);
}
// allocate new router id
@@ -3785,7 +3784,7 @@
exit:
- if (error == OT_ERROR_NONE)
+ if (error == kErrorNone)
{
SendAddressSolicitResponse(aMessage, router, aMessageInfo);
}
@@ -3795,11 +3794,11 @@
const Router * aRouter,
const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ThreadRouterMaskTlv routerMaskTlv;
Coap::Message * message;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -3987,7 +3986,7 @@
aTlv.SetSedDatagramCount(OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT);
}
-otError MleRouter::AppendConnectivity(Message &aMessage)
+Error MleRouter::AppendConnectivity(Message &aMessage)
{
ConnectivityTlv tlv;
@@ -3997,9 +3996,9 @@
return tlv.AppendTo(aMessage);
}
-otError MleRouter::AppendChildAddresses(Message &aMessage, Child &aChild)
+Error MleRouter::AppendChildAddresses(Message &aMessage, Child &aChild)
{
- otError error;
+ Error error;
Tlv tlv;
AddressRegistrationEntry entry;
Lowpan::Context context;
@@ -4011,7 +4010,7 @@
for (const Ip6::Address &address : aChild.IterateIp6Addresses())
{
- if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != OT_ERROR_NONE)
+ if (address.IsMulticast() || Get<NetworkData::Leader>().GetContext(address, context) != kErrorNone)
{
// uncompressed entry
entry.SetUncompressed();
@@ -4140,7 +4139,7 @@
aTlv.SetRouteDataLength(routerCount);
}
-otError MleRouter::AppendRoute(Message &aMessage, Neighbor *aNeighbor)
+Error MleRouter::AppendRoute(Message &aMessage, Neighbor *aNeighbor)
{
RouteTlv tlv;
@@ -4150,12 +4149,12 @@
return tlv.AppendTo(aMessage);
}
-otError MleRouter::AppendActiveDataset(Message &aMessage)
+Error MleRouter::AppendActiveDataset(Message &aMessage)
{
return Get<MeshCoP::ActiveDataset>().AppendMleDatasetTlv(aMessage);
}
-otError MleRouter::AppendPendingDataset(Message &aMessage)
+Error MleRouter::AppendPendingDataset(Message &aMessage)
{
return Get<MeshCoP::PendingDataset>().AppendMleDatasetTlv(aMessage);
}
@@ -4301,12 +4300,12 @@
return false;
}
-otError MleRouter::SetAssignParentPriority(int8_t aParentPriority)
+Error MleRouter::SetAssignParentPriority(int8_t aParentPriority)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
VerifyOrExit(aParentPriority <= kParentPriorityHigh && aParentPriority >= kParentPriorityUnspecified,
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
mParentPriority = aParentPriority;
@@ -4314,11 +4313,11 @@
return error;
}
-otError MleRouter::GetMaxChildTimeout(uint32_t &aTimeout) const
+Error MleRouter::GetMaxChildTimeout(uint32_t &aTimeout) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
- VerifyOrExit(IsRouterOrLeader(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(IsRouterOrLeader(), error = kErrorInvalidState);
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
{
@@ -4332,7 +4331,7 @@
aTimeout = child.GetTimeout();
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
exit:
@@ -4352,13 +4351,13 @@
return;
}
-otError MleRouter::SendTimeSync(void)
+Error MleRouter::SendTimeSync(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6::Address destination;
Message * message = nullptr;
- VerifyOrExit((message = NewMleMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = NewMleMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = AppendHeader(*message, kCommandTimeSync));
message->SetTimeSync(true);
diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp
index 01470c6..ffb9ea6 100644
--- a/src/core/thread/mle_router.hpp
+++ b/src/core/thread/mle_router.hpp
@@ -104,11 +104,11 @@
*
* @param[in] aEligible TRUE to configure device router-eligible, FALSE otherwise.
*
- * @retval OT_ERROR_NONE Successfully set the router-eligible configuration.
- * @retval OT_ERROR_NOT_CAPABLE The device is not capable of becoming a router.
+ * @retval kErrorNone Successfully set the router-eligible configuration.
+ * @retval kErrorNotCapable The device is not capable of becoming a router.
*
*/
- otError SetRouterEligible(bool aEligible);
+ Error SetRouterEligible(bool aEligible);
/**
* This method indicates whether a node is the only router on the network.
@@ -124,22 +124,22 @@
*
* @param[in] aStatus The reason for requesting a Router ID.
*
- * @retval OT_ERROR_NONE Successfully generated an Address Solicit message.
- * @retval OT_ERROR_NOT_CAPABLE Device is not capable of becoming a router
- * @retval OT_ERROR_INVALID_STATE Thread is not enabled
+ * @retval kErrorNone Successfully generated an Address Solicit message.
+ * @retval kErrorNotCapable Device is not capable of becoming a router
+ * @retval kErrorInvalidState Thread is not enabled
*
*/
- otError BecomeRouter(ThreadStatusTlv::Status aStatus);
+ Error BecomeRouter(ThreadStatusTlv::Status aStatus);
/**
* This method causes the Thread interface to become a Leader and start a new partition.
*
- * @retval OT_ERROR_NONE Successfully become a Leader and started a new partition.
- * @retval OT_ERROR_NOT_CAPABLE Device is not capable of becoming a leader
- * @retval OT_ERROR_INVALID_STATE Thread is not enabled
+ * @retval kErrorNone Successfully become a Leader and started a new partition.
+ * @retval kErrorNotCapable Device is not capable of becoming a leader
+ * @retval kErrorInvalidState Thread is not enabled
*
*/
- otError BecomeLeader(void);
+ Error BecomeLeader(void);
/**
* This method returns the Leader Weighting value for this Thread interface.
@@ -184,11 +184,11 @@
*
* @param[in] aRouterId The preferred Router Id.
*
- * @retval OT_ERROR_NONE Successfully set the preferred Router Id.
- * @retval OT_ERROR_INVALID_STATE Could not set (role is other than detached and disabled)
+ * @retval kErrorNone Successfully set the preferred Router Id.
+ * @retval kErrorInvalidState Could not set (role is other than detached and disabled)
*
*/
- otError SetPreferredRouterId(uint8_t aRouterId);
+ Error SetPreferredRouterId(uint8_t aRouterId);
/**
* This method gets the Partition Id which the device joined successfully once.
@@ -282,7 +282,7 @@
* @returns The ROUTER_SELECTION_JITTER value.
*
*/
- otError SetRouterSelectionJitter(uint8_t aRouterJitter);
+ Error SetRouterSelectionJitter(uint8_t aRouterJitter);
/**
* This method returns the current router selection jitter timeout value.
@@ -384,11 +384,11 @@
* @param[in] aMeshDest The RLOC16 of the destination.
* @param[in] aIp6Header A reference to the IPv6 header of the message.
*
- * @retval OT_ERROR_NONE The destination is reachable.
- * @retval OT_ERROR_NO_ROUTE The destination is not reachable and the message should be dropped.
+ * @retval kErrorNone The destination is reachable.
+ * @retval kErrorNoRoute The destination is not reachable and the message should be dropped.
*
*/
- otError CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
+ Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header);
/**
* This method resolves 2-hop routing loops.
@@ -429,13 +429,13 @@
/**
* This method generates an MLE Child Update Request message to be sent to the parent.
*
- * @retval OT_ERROR_NONE Successfully generated an MLE Child Update Request message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Child Update Request message.
+ * @retval kErrorNone Successfully generated an MLE Child Update Request message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Request message.
*
*/
- otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
+ Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
- otError SendLinkRequest(Neighbor *aNeighbor);
+ Error SendLinkRequest(Neighbor *aNeighbor);
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
/**
@@ -463,23 +463,23 @@
*
* @param[in] aParentPriority The parent priority value.
*
- * @retval OT_ERROR_NONE Successfully set the parent priority.
- * @retval OT_ERROR_INVALID_ARGS If the parent priority value is not among 1, 0, -1 and -2.
+ * @retval kErrorNone Successfully set the parent priority.
+ * @retval kErrorInvalidArgs If the parent priority value is not among 1, 0, -1 and -2.
*
*/
- otError SetAssignParentPriority(int8_t aParentPriority);
+ Error SetAssignParentPriority(int8_t aParentPriority);
/**
* This method gets the longest MLE Timeout TLV for all active MTD children.
*
* @param[out] aTimeout A reference to where the information is placed.
*
- * @retval OT_ERROR_NONE Successfully get the max child timeout
- * @retval OT_ERROR_INVALID_STATE Not an active router
- * @retval OT_ERROR_NOT_FOUND NO MTD child
+ * @retval kErrorNone Successfully get the max child timeout
+ * @retval kErrorInvalidState Not an active router
+ * @retval kErrorNotFound NO MTD child
*
*/
- otError GetMaxChildTimeout(uint32_t &aTimeout) const;
+ Error GetMaxChildTimeout(uint32_t &aTimeout) const;
/**
* This function sets the callback that is called when processing an MLE Discovery Request message.
@@ -514,11 +514,11 @@
/**
* This method generates an MLE Time Synchronization message.
*
- * @retval OT_ERROR_NONE Successfully sent an MLE Time Synchronization message.
- * @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Time Synchronization message.
+ * @retval kErrorNone Successfully sent an MLE Time Synchronization message.
+ * @retval kErrorNoBufs Insufficient buffers to generate the MLE Time Synchronization message.
*
*/
- otError SendTimeSync(void);
+ Error SendTimeSync(void);
#endif
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
@@ -547,11 +547,11 @@
* @param[in] aMaxIpAddresses The maximum number of IP addresses that each MTD child may register with this
* device as parent. 0 to clear the setting and restore the default.
*
- * @retval OT_ERROR_NONE Successfully set/cleared the number.
- * @retval OT_ERROR_INVALID_ARGS If exceeds the allowed maximum number.
+ * @retval kErrorNone Successfully set/cleared the number.
+ * @retval kErrorInvalidArgs If exceeds the allowed maximum number.
*
*/
- otError SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
+ Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses);
#endif
private:
@@ -562,30 +562,30 @@
kUnsolicitedDataResponseJitter = 500u, ///< Maximum delay before unsolicited Data Response in milliseconds.
};
- otError AppendConnectivity(Message &aMessage);
- otError AppendChildAddresses(Message &aMessage, Child &aChild);
- otError AppendRoute(Message &aMessage, Neighbor *aNeighbor = nullptr);
- otError AppendActiveDataset(Message &aMessage);
- otError AppendPendingDataset(Message &aMessage);
- void HandleDetachStart(void);
- void HandleChildStart(AttachMode aMode);
- void HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
- void HandleLinkAccept(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- uint32_t aKeySequence,
- Neighbor * aNeighbor);
- otError HandleLinkAccept(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- uint32_t aKeySequence,
- Neighbor * aNeighbor,
- bool aRequest);
- void HandleLinkAcceptAndRequest(const Message & aMessage,
- const Ip6::MessageInfo &aMessageInfo,
- uint32_t aKeySequence,
- Neighbor * aNeighbor);
- otError HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *);
- void HandleParentRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
- void HandleChildIdRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
+ Error AppendConnectivity(Message &aMessage);
+ Error AppendChildAddresses(Message &aMessage, Child &aChild);
+ Error AppendRoute(Message &aMessage, Neighbor *aNeighbor = nullptr);
+ Error AppendActiveDataset(Message &aMessage);
+ Error AppendPendingDataset(Message &aMessage);
+ void HandleDetachStart(void);
+ void HandleChildStart(AttachMode aMode);
+ void HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
+ void HandleLinkAccept(const Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ uint32_t aKeySequence,
+ Neighbor * aNeighbor);
+ Error HandleLinkAccept(const Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ uint32_t aKeySequence,
+ Neighbor * aNeighbor,
+ bool aRequest);
+ void HandleLinkAcceptAndRequest(const Message & aMessage,
+ const Ip6::MessageInfo &aMessageInfo,
+ uint32_t aKeySequence,
+ Neighbor * aNeighbor);
+ Error HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *);
+ void HandleParentRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ void HandleChildIdRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
void HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint32_t aKeySequence);
void HandleChildUpdateResponse(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
@@ -598,45 +598,45 @@
void HandleTimeSync(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const Neighbor *aNeighbor);
#endif
- otError ProcessRouteTlv(const RouteTlv &aRoute);
- void StopAdvertiseTimer(void);
- otError SendAddressSolicit(ThreadStatusTlv::Status aStatus);
- void SendAddressRelease(void);
- void SendAddressSolicitResponse(const Coap::Message & aRequest,
- const Router * aRouter,
- const Ip6::MessageInfo &aMessageInfo);
- void SendAdvertisement(void);
- otError SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
- Neighbor * aNeighbor,
- const RequestedTlvs & aRequestedTlvs,
- const Challenge & aChallenge);
- void SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest);
- otError SendChildIdResponse(Child &aChild);
- otError SendChildUpdateRequest(Child &aChild);
- void SendChildUpdateResponse(Child * aChild,
- const Ip6::MessageInfo &aMessageInfo,
- const uint8_t * aTlvs,
- uint8_t aTlvsLength,
- const Challenge & aChallenge);
- void SendDataResponse(const Ip6::Address &aDestination,
- const uint8_t * aTlvs,
- uint8_t aTlvsLength,
- uint16_t aDelay,
- const Message * aRequestMessage = nullptr);
- otError SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
- void SetStateRouter(uint16_t aRloc16);
- void SetStateLeader(uint16_t aRloc16);
- void StopLeader(void);
- void SynchronizeChildNetworkData(void);
- otError UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild);
- void UpdateRoutes(const RouteTlv &aRoute, uint8_t aRouterId);
- bool UpdateLinkQualityOut(const RouteTlv &aRoute, Router &aNeighbor, bool &aResetAdvInterval);
+ Error ProcessRouteTlv(const RouteTlv &aRoute);
+ void StopAdvertiseTrickleTimer(void);
+ Error SendAddressSolicit(ThreadStatusTlv::Status aStatus);
+ void SendAddressRelease(void);
+ void SendAddressSolicitResponse(const Coap::Message & aRequest,
+ const Router * aRouter,
+ const Ip6::MessageInfo &aMessageInfo);
+ void SendAdvertisement(void);
+ Error SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
+ Neighbor * aNeighbor,
+ const RequestedTlvs & aRequestedTlvs,
+ const Challenge & aChallenge);
+ void SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest);
+ Error SendChildIdResponse(Child &aChild);
+ Error SendChildUpdateRequest(Child &aChild);
+ void SendChildUpdateResponse(Child * aChild,
+ const Ip6::MessageInfo &aMessageInfo,
+ const uint8_t * aTlvs,
+ uint8_t aTlvsLength,
+ const Challenge & aChallenge);
+ void SendDataResponse(const Ip6::Address &aDestination,
+ const uint8_t * aTlvs,
+ uint8_t aTlvsLength,
+ uint16_t aDelay,
+ const Message * aRequestMessage = nullptr);
+ Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
+ void SetStateRouter(uint16_t aRloc16);
+ void SetStateLeader(uint16_t aRloc16);
+ void StopLeader(void);
+ void SynchronizeChildNetworkData(void);
+ Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, Child &aChild);
+ void UpdateRoutes(const RouteTlv &aRoute, uint8_t aRouterId);
+ bool UpdateLinkQualityOut(const RouteTlv &aRoute, Router &aNeighbor, bool &aResetAdvInterval);
static void HandleAddressSolicitResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleAddressSolicitResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleAddressRelease(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleAddressRelease(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleAddressSolicit(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
@@ -653,11 +653,11 @@
bool HasOneNeighborWithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId);
bool HasSmallNumberOfChildren(void);
- static bool HandleAdvertiseTimer(TrickleTimer &aTimer);
- bool HandleAdvertiseTimer(void);
+ static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
+ void HandleAdvertiseTrickleTimer(void);
void HandleTimeTick(void);
- TrickleTimer mAdvertiseTimer;
+ TrickleTimer mAdvertiseTrickleTimer;
Coap::Resource mAddressSolicit;
Coap::Resource mAddressRelease;
@@ -728,14 +728,14 @@
uint8_t GetCost(uint16_t) { return 0; }
- otError RemoveNeighbor(Neighbor &) { return BecomeDetached(); }
- void RemoveRouterLink(Router &) { IgnoreError(BecomeDetached()); }
+ Error RemoveNeighbor(Neighbor &) { return BecomeDetached(); }
+ void RemoveRouterLink(Router &) { IgnoreError(BecomeDetached()); }
static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
- otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
+ Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
- otError CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
+ Error CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header)
{
return Mle::CheckReachability(aMeshDest, aIp6Header);
}
diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp
index a70c3a1..4da6c30 100644
--- a/src/core/thread/mle_tlvs.hpp
+++ b/src/core/thread/mle_tlvs.hpp
@@ -1265,7 +1265,7 @@
bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
} OT_TOOL_PACKED_END;
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (!OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
/**
* This class implements CSL Channel TLV generation and parsing.
*
@@ -1330,7 +1330,7 @@
uint16_t mChannel;
} OT_TOOL_PACKED_END;
-#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (!OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
/**
* @}
diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp
index f409b3d..b210fa6 100644
--- a/src/core/thread/mle_types.hpp
+++ b/src/core/thread/mle_types.hpp
@@ -345,10 +345,7 @@
* @param[in] aMode A mode TLV bitmask to initialize the `DeviceMode` object.
*
*/
- explicit DeviceMode(uint8_t aMode)
- : mMode(aMode)
- {
- }
+ explicit DeviceMode(uint8_t aMode) { Set(aMode); }
/**
* This constructor initializes a `DeviceMode` object from a given mode configuration structure.
diff --git a/src/core/thread/mlr_manager.cpp b/src/core/thread/mlr_manager.cpp
index 287ec60..e66766a 100644
--- a/src/core/thread/mlr_manager.cpp
+++ b/src/core/thread/mlr_manager.cpp
@@ -225,22 +225,22 @@
void MlrManager::SendMulticastListenerRegistration(void)
{
- otError error;
+ Error error;
Mle::MleRouter &mle = Get<Mle::MleRouter>();
- Ip6::Address addresses[kIPv6AddressesNumMax];
+ Ip6::Address addresses[kIp6AddressesNumMax];
uint8_t addressesNum = 0;
- VerifyOrExit(!mMlrPending, error = OT_ERROR_BUSY);
- VerifyOrExit(mle.IsAttached(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(mle.IsFullThreadDevice() || mle.GetParent().IsThreadVersion1p1(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!mMlrPending, error = kErrorBusy);
+ VerifyOrExit(mle.IsAttached(), error = kErrorInvalidState);
+ VerifyOrExit(mle.IsFullThreadDevice() || mle.GetParent().IsThreadVersion1p1(), error = kErrorInvalidState);
+ VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorInvalidState);
#if OPENTHREAD_CONFIG_MLR_ENABLE
// Append Netif multicast addresses
for (Ip6::ExternalNetifMulticastAddress &addr :
Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
{
- if (addressesNum >= kIPv6AddressesNumMax)
+ if (addressesNum >= kIp6AddressesNumMax)
{
break;
}
@@ -257,7 +257,7 @@
// Append Child multicast addresses
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
{
- if (addressesNum >= kIPv6AddressesNumMax)
+ if (addressesNum >= kIp6AddressesNumMax)
{
break;
}
@@ -269,7 +269,7 @@
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
{
- if (addressesNum >= kIPv6AddressesNumMax)
+ if (addressesNum >= kIp6AddressesNumMax)
{
break;
}
@@ -283,25 +283,27 @@
}
#endif
- VerifyOrExit(addressesNum > 0, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(addressesNum > 0, error = kErrorNotFound);
SuccessOrExit(
error = SendMulticastListenerRegistrationMessage(
addresses, addressesNum, nullptr, &MlrManager::HandleMulticastListenerRegistrationResponse, this));
mMlrPending = true;
- // TODO: not enable fast polls for SSED
+ // Generally Thread 1.2 Router would send MLR.req on bebelf for MA (scope >=4) subscribed by its MTD child.
+ // When Thread 1.2 MTD attaches to Thread 1.1 parent, 1.2 MTD should send MLR.req to PBBR itself.
+ // In this case, Thread 1.2 sleepy end device relies on fast data poll to fetch the response timely.
if (!Get<Mle::Mle>().IsRxOnWhenIdle())
{
- Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
+ Get<DataPollSender>().SendFastPolls();
}
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
SetMulticastAddressMlrState(kMlrStateRegistering, kMlrStateToRegister);
- if (error == OT_ERROR_NO_BUFS)
+ if (error == kErrorNoBufs)
{
ScheduleSend(1);
}
@@ -312,21 +314,21 @@
}
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-otError MlrManager::RegisterMulticastListeners(const otIp6Address * aAddresses,
- uint8_t aAddressNum,
- const uint32_t * aTimeout,
- otIp6RegisterMulticastListenersCallback aCallback,
- void * aContext)
+Error MlrManager::RegisterMulticastListeners(const otIp6Address * aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t * aTimeout,
+ otIp6RegisterMulticastListenersCallback aCallback,
+ void * aContext)
{
- otError error;
+ Error error;
- VerifyOrExit(aAddresses != nullptr, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aAddressNum > 0 && aAddressNum <= kIPv6AddressesNumMax, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aContext == nullptr || aCallback != nullptr, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(aAddresses != nullptr, error = kErrorInvalidArgs);
+ VerifyOrExit(aAddressNum > 0 && aAddressNum <= kIp6AddressesNumMax, error = kErrorInvalidArgs);
+ VerifyOrExit(aContext == nullptr || aCallback != nullptr, error = kErrorInvalidArgs);
+ VerifyOrExit(Get<MeshCoP::Commissioner>().IsActive(), error = kErrorInvalidState);
// Only allow one outstanding registration if callback is specified.
- VerifyOrExit(!mRegisterMulticastListenersPending, error = OT_ERROR_BUSY);
+ VerifyOrExit(!mRegisterMulticastListenersPending, error = kErrorBusy);
SuccessOrExit(error = SendMulticastListenerRegistrationMessage(
aAddresses, aAddressNum, aTimeout, &MlrManager::HandleRegisterMulticastListenersResponse, this));
@@ -342,7 +344,7 @@
void MlrManager::HandleRegisterMulticastListenersResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<MlrManager *>(aContext)->HandleRegisterMulticastListenersResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -350,13 +352,13 @@
void MlrManager::HandleRegisterMulticastListenersResponse(otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
uint8_t status;
- otError error;
- Ip6::Address failedAddresses[kIPv6AddressesNumMax];
+ Error error;
+ Ip6::Address failedAddresses[kIp6AddressesNumMax];
uint8_t failedAddressNum = 0;
otIp6RegisterMulticastListenersCallback callback = mRegisterMulticastListenersCallback;
void * context = mRegisterMulticastListenersContext;
@@ -376,23 +378,23 @@
#endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-otError MlrManager::SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses,
- uint8_t aAddressNum,
- const uint32_t * aTimeout,
- Coap::ResponseHandler aResponseHandler,
- void * aResponseContext)
+Error MlrManager::SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t * aTimeout,
+ Coap::ResponseHandler aResponseHandler,
+ void * aResponseContext)
{
OT_UNUSED_VARIABLE(aTimeout);
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mle::MleRouter & mle = Get<Mle::MleRouter>();
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- IPv6AddressesTlv addressesTlv;
+ Ip6AddressesTlv addressesTlv;
- VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(Get<BackboneRouter::Leader>().HasPrimary(), error = kErrorInvalidState);
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
message->InitAsConfirmablePost();
SuccessOrExit(message->GenerateRandomToken(Coap::Message::kDefaultTokenLength));
@@ -438,7 +440,7 @@
error = Get<Tmf::TmfAgent>().SendMessage(*message, messageInfo, aResponseHandler, aResponseContext);
exit:
- otLogInfoMlr("Send MLR.req: %s, addressNum=%d", otThreadErrorToString(error), aAddressNum);
+ otLogInfoMlr("Send MLR.req: %s, addressNum=%d", ErrorToString(error), aAddressNum);
FreeMessageOnError(message, error);
return error;
}
@@ -446,7 +448,7 @@
void MlrManager::HandleMulticastListenerRegistrationResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<MlrManager *>(aContext)->HandleMulticastListenerRegistrationResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -454,21 +456,21 @@
void MlrManager::HandleMulticastListenerRegistrationResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
uint8_t status;
- otError error;
- Ip6::Address failedAddresses[kIPv6AddressesNumMax];
+ Error error;
+ Ip6::Address failedAddresses[kIp6AddressesNumMax];
uint8_t failedAddressNum = 0;
error = ParseMulticastListenerRegistrationResponse(aResult, aMessage, status, failedAddresses, failedAddressNum);
- FinishMulticastListenerRegistration(error == OT_ERROR_NONE && status == ThreadStatusTlv::MlrStatus::kMlrSuccess,
+ FinishMulticastListenerRegistration(error == kErrorNone && status == ThreadStatusTlv::MlrStatus::kMlrSuccess,
failedAddresses, failedAddressNum);
- if (error == OT_ERROR_NONE && status == ThreadStatusTlv::MlrStatus::kMlrSuccess)
+ if (error == kErrorNone && status == ThreadStatusTlv::MlrStatus::kMlrSuccess)
{
// keep sending until all multicast addresses are registered.
ScheduleSend(0);
@@ -481,7 +483,7 @@
// The Device has just attempted a Multicast Listener Registration which failed, and it retries the same
// registration with a random time delay chosen in the interval [0, Reregistration Delay].
// This is required by Thread 1.2 Specification 5.24.2.3
- if (Get<BackboneRouter::Leader>().GetConfig(config) == OT_ERROR_NONE)
+ if (Get<BackboneRouter::Leader>().GetConfig(config) == kErrorNone)
{
reregDelay = config.mReregistrationDelay > 1
? Random::NonCrypto::GetUint16InRange(1, config.mReregistrationDelay)
@@ -491,27 +493,27 @@
}
}
-otError MlrManager::ParseMulticastListenerRegistrationResponse(otError aResult,
- Coap::Message *aMessage,
- uint8_t & aStatus,
- Ip6::Address * aFailedAddresses,
- uint8_t & aFailedAddressNum)
+Error MlrManager::ParseMulticastListenerRegistrationResponse(Error aResult,
+ Coap::Message *aMessage,
+ uint8_t & aStatus,
+ Ip6::Address * aFailedAddresses,
+ uint8_t & aFailedAddressNum)
{
- otError error;
+ Error error;
uint16_t addressesOffset, addressesLength;
aStatus = ThreadStatusTlv::MlrStatus::kMlrGeneralFailure;
- VerifyOrExit(aResult == OT_ERROR_NONE && aMessage != nullptr, error = OT_ERROR_PARSE);
- VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, error = OT_ERROR_PARSE);
+ VerifyOrExit(aResult == kErrorNone && aMessage != nullptr, error = kErrorParse);
+ VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, error = kErrorParse);
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(*aMessage, aStatus));
- if (ThreadTlv::FindTlvValueOffset(*aMessage, IPv6AddressesTlv::kIPv6Addresses, addressesOffset, addressesLength) ==
- OT_ERROR_NONE)
+ if (ThreadTlv::FindTlvValueOffset(*aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
+ kErrorNone)
{
- VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, error = OT_ERROR_PARSE);
- VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIPv6AddressesNumMax, error = OT_ERROR_PARSE);
+ VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, error = kErrorParse);
+ VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= kIp6AddressesNumMax, error = kErrorParse);
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
{
@@ -520,11 +522,11 @@
}
}
- VerifyOrExit(aFailedAddressNum == 0 || aStatus != ThreadStatusTlv::MlrStatus::kMlrSuccess, error = OT_ERROR_PARSE);
+ VerifyOrExit(aFailedAddressNum == 0 || aStatus != ThreadStatusTlv::MlrStatus::kMlrSuccess, error = kErrorParse);
exit:
LogMlrResponse(aResult, error, aStatus, aFailedAddresses, aFailedAddressNum);
- return aResult != OT_ERROR_NONE ? aResult : error;
+ return aResult != kErrorNone ? aResult : error;
}
void MlrManager::SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState)
@@ -692,7 +694,7 @@
#endif // OPENTHREAD_CONFIG_LOG_MLR && OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
}
-void MlrManager::AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIPv6AddressesNumMax],
+void MlrManager::AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIp6AddressesNumMax],
uint8_t & aAddressNum,
const Ip6::Address &aAddress)
{
@@ -735,8 +737,8 @@
return contains;
}
-void MlrManager::LogMlrResponse(otError aResult,
- otError aError,
+void MlrManager::LogMlrResponse(Error aResult,
+ Error aError,
uint8_t aStatus,
const Ip6::Address *aFailedAddresses,
uint8_t aFailedAddressNum)
@@ -748,14 +750,14 @@
OT_UNUSED_VARIABLE(aFailedAddressNum);
#if OPENTHREAD_CONFIG_LOG_BBR
- if (aResult == OT_ERROR_NONE && aError == OT_ERROR_NONE && aStatus == ThreadStatusTlv::MlrStatus::kMlrSuccess)
+ if (aResult == kErrorNone && aError == kErrorNone && aStatus == ThreadStatusTlv::MlrStatus::kMlrSuccess)
{
- otLogInfoBbr("Receive MLR.rsp OK", otThreadErrorToString(aResult));
+ otLogInfoBbr("Receive MLR.rsp OK", ErrorToString(aResult));
}
else
{
- otLogWarnBbr("Receive MLR.rsp: result=%s, error=%s, status=%d, failedAddressNum=%d",
- otThreadErrorToString(aResult), otThreadErrorToString(aError), aStatus, aFailedAddressNum);
+ otLogWarnBbr("Receive MLR.rsp: result=%s, error=%s, status=%d, failedAddressNum=%d", ErrorToString(aResult),
+ ErrorToString(aError), aStatus, aFailedAddressNum);
for (uint8_t i = 0; i < aFailedAddressNum; i++)
{
diff --git a/src/core/thread/mlr_manager.hpp b/src/core/thread/mlr_manager.hpp
index fa2a9f1..65abcea 100644
--- a/src/core/thread/mlr_manager.hpp
+++ b/src/core/thread/mlr_manager.hpp
@@ -38,6 +38,10 @@
#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
+#if OPENTHREAD_CONFIG_MLR_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
+#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLR_ENABLE"
+#endif
+
#include "backbone_router/bbr_leader.hpp"
#include "coap/coap_message.hpp"
#include "common/locator.hpp"
@@ -122,53 +126,53 @@
* @param aCallback A callback function.
* @param aContext A user context pointer.
*
- * @retval OT_ERROR_NONE Successfully sent MLR.req. The @p aCallback will be called iff this method
- * returns OT_ERROR_NONE.
- * @retval OT_ERROR_BUSY If a previous registration was ongoing.
- * @retval OT_ERROR_INVALID_ARGS If one or more arguments are invalid.
- * @retval OT_ERROR_INVALID_STATE If the device was not in a valid state to send MLR.req (e.g. Commissioner not
- * started, Primary Backbone Router not found).
- * @retval OT_ERROR_NO_BUFS If insufficient message buffers available.
+ * @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method
+ * returns kErrorNone.
+ * @retval kErrorBusy If a previous registration was ongoing.
+ * @retval kErrorInvalidArgs If one or more arguments are invalid.
+ * @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not
+ * started, Primary Backbone Router not found).
+ * @retval kErrorNoBufs If insufficient message buffers available.
*
*/
- otError RegisterMulticastListeners(const otIp6Address * aAddresses,
- uint8_t aAddressNum,
- const uint32_t * aTimeout,
- otIp6RegisterMulticastListenersCallback aCallback,
- void * aContext);
+ Error RegisterMulticastListeners(const otIp6Address * aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t * aTimeout,
+ otIp6RegisterMulticastListenersCallback aCallback,
+ void * aContext);
#endif
private:
void HandleNotifierEvents(Events aEvents);
- void SendMulticastListenerRegistration(void);
- otError SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses,
- uint8_t aAddressNum,
- const uint32_t * aTimeout,
- Coap::ResponseHandler aResponseHandler,
- void * aResponseContext);
+ void SendMulticastListenerRegistration(void);
+ Error SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t * aTimeout,
+ Coap::ResponseHandler aResponseHandler,
+ void * aResponseContext);
- static void HandleMulticastListenerRegistrationResponse(void * aContext,
- otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleMulticastListenerRegistrationResponse(Coap::Message * aMessage,
- const Ip6::MessageInfo *aMessageInfo,
- otError aResult);
- static otError ParseMulticastListenerRegistrationResponse(otError aResult,
- Coap::Message *aMessage,
- uint8_t & aStatus,
- Ip6::Address * aFailedAddresses,
- uint8_t & aFailedAddressNum);
+ static void HandleMulticastListenerRegistrationResponse(void * aContext,
+ otMessage * aMessage,
+ const otMessageInfo *aMessageInfo,
+ Error aResult);
+ void HandleMulticastListenerRegistrationResponse(Coap::Message * aMessage,
+ const Ip6::MessageInfo *aMessageInfo,
+ Error aResult);
+ static Error ParseMulticastListenerRegistrationResponse(Error aResult,
+ Coap::Message *aMessage,
+ uint8_t & aStatus,
+ Ip6::Address * aFailedAddresses,
+ uint8_t & aFailedAddressNum);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
static void HandleRegisterMulticastListenersResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
void HandleRegisterMulticastListenersResponse(otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
+ Error aResult);
#endif
#if OPENTHREAD_CONFIG_MLR_ENABLE
@@ -189,7 +193,7 @@
const Ip6::Address *aFailedAddresses,
uint8_t aFailedAddressNum);
- void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIPv6AddressesNumMax],
+ void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIp6AddressesNumMax],
uint8_t & aAddressNum,
const Ip6::Address &aAddress);
static bool AddressListContains(const Ip6::Address *aAddressList,
@@ -204,8 +208,8 @@
void LogMulticastAddresses(void);
void CheckInvariants(void) const;
- static void LogMlrResponse(otError aResult,
- otError aError,
+ static void LogMlrResponse(Error aResult,
+ Error aError,
uint8_t aStatus,
const Ip6::Address *aFailedAddresses,
uint8_t aFailedAddressNum);
diff --git a/src/core/thread/neighbor_table.cpp b/src/core/thread/neighbor_table.cpp
index 1a25a01..6d86a1b 100644
--- a/src/core/thread/neighbor_table.cpp
+++ b/src/core/thread/neighbor_table.cpp
@@ -137,21 +137,21 @@
Neighbor *NeighborTable::FindNeighbor(const Ip6::Address &aIp6Address, Neighbor::StateFilter aFilter)
{
Neighbor * neighbor = nullptr;
- Mac::Address macAddresss;
+ Mac::Address macAddress;
if (aIp6Address.IsLinkLocal())
{
- aIp6Address.GetIid().ConvertToMacAddress(macAddresss);
+ aIp6Address.GetIid().ConvertToMacAddress(macAddress);
}
if (Get<Mle::Mle>().IsRoutingLocator(aIp6Address))
{
- macAddresss.SetShort(aIp6Address.GetIid().GetLocator());
+ macAddress.SetShort(aIp6Address.GetIid().GetLocator());
}
- if (!macAddresss.IsNone())
+ if (!macAddress.IsNone())
{
- neighbor = FindChildOrRouter(Neighbor::AddressMatcher(macAddresss, aFilter));
+ neighbor = FindChildOrRouter(Neighbor::AddressMatcher(macAddress, aFilter));
ExitNow();
}
@@ -178,9 +178,9 @@
return neighbor;
}
-otError NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
+Error NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
int16_t index;
// Non-negative iterator value gives the Child index into child table
@@ -226,7 +226,7 @@
}
aIterator = -index;
- error = OT_ERROR_NOT_FOUND;
+ error = kErrorNotFound;
exit:
return error;
@@ -236,9 +236,9 @@
#if OPENTHREAD_MTD
-otError NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
+Error NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
VerifyOrExit(aIterator == OT_NEIGHBOR_INFO_ITERATOR_INIT);
@@ -247,7 +247,7 @@
aNeighInfo.SetFrom(Get<Mle::Mle>().GetParent());
aNeighInfo.mIsChild = false;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
exit:
return error;
diff --git a/src/core/thread/neighbor_table.hpp b/src/core/thread/neighbor_table.hpp
index b10f66f..af6ed85 100644
--- a/src/core/thread/neighbor_table.hpp
+++ b/src/core/thread/neighbor_table.hpp
@@ -191,11 +191,11 @@
it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT.
* @param[out] aNeighInfo The neighbor information.
*
- * @retval OT_ERROR_NONE Successfully found the next neighbor entry in table.
- * @retval OT_ERROR_NOT_FOUND No subsequent neighbor entry exists in the table.
+ * @retval kErrorNone Successfully found the next neighbor entry in table.
+ * @retval kErrorNotFound No subsequent neighbor entry exists in the table.
*
*/
- otError GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo);
+ Error GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo);
/**
* This method registers the "neighbor table changed" callback function.
diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp
index 7dc6cd0..6f6358a 100644
--- a/src/core/thread/network_data.cpp
+++ b/src/core/thread/network_data.cpp
@@ -170,12 +170,12 @@
return tlv;
}
-otError NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const
+Error NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
OT_ASSERT(aData != nullptr);
- VerifyOrExit(aDataLength >= mLength, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aDataLength >= mLength, error = kErrorNoBufs);
memcpy(aData, mTlvs, mLength);
aDataLength = mLength;
@@ -189,12 +189,12 @@
return error;
}
-otError NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const
+Error NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const
{
return GetNextOnMeshPrefix(aIterator, Mac::kShortAddrBroadcast, aConfig);
}
-otError NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const
+Error NetworkData::GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const
{
Config config;
@@ -205,12 +205,12 @@
return Iterate(aIterator, aRloc16, config);
}
-otError NetworkData::GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const
+Error NetworkData::GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const
{
return GetNextExternalRoute(aIterator, Mac::kShortAddrBroadcast, aConfig);
}
-otError NetworkData::GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const
+Error NetworkData::GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const
{
Config config;
@@ -221,12 +221,12 @@
return Iterate(aIterator, aRloc16, config);
}
-otError NetworkData::GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const
+Error NetworkData::GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const
{
return GetNextService(aIterator, Mac::kShortAddrBroadcast, aConfig);
}
-otError NetworkData::GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const
+Error NetworkData::GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const
{
Config config;
@@ -237,7 +237,7 @@
return Iterate(aIterator, aRloc16, config);
}
-otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const
+Error NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const
{
// Iterate to the next entry in Network Data matching `aRloc16`
// (can be set to `Mac::kShortAddrBroadcast` to allow any RLOC).
@@ -249,7 +249,7 @@
// indicating the type of entry and the non-nullptr config is updated
// with the entry info.
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
NetworkDataIterator iterator(aIterator);
for (const NetworkDataTlv *cur; (cur = iterator.GetTlv(mTlvs)) < GetTlvsEnd(); iterator.AdvanceTlv(mTlvs))
@@ -307,7 +307,7 @@
aConfig.mService = nullptr;
aConfig.mOnMeshPrefix->SetFrom(*prefixTlv, *borderRouter, *borderRouterEntry);
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -333,7 +333,7 @@
aConfig.mService = nullptr;
aConfig.mExternalRoute->SetFrom(GetInstance(), *prefixTlv, *hasRoute, *hasRouteEntry);
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -370,7 +370,7 @@
iterator.MarkEntryAsNotNew();
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
}
@@ -381,9 +381,9 @@
return error;
}
-otError NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const
+Error NetworkData::GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const
{
- otError error;
+ Error error;
ServiceConfig config;
SuccessOrExit(error = GetNextService(aIterator, aRloc16, config));
@@ -399,13 +399,13 @@
OnMeshPrefixConfig outerConfig;
bool rval = true;
- while (aCompare.GetNextOnMeshPrefix(outerIterator, aRloc16, outerConfig) == OT_ERROR_NONE)
+ while (aCompare.GetNextOnMeshPrefix(outerIterator, aRloc16, outerConfig) == kErrorNone)
{
Iterator innerIterator = kIteratorInit;
OnMeshPrefixConfig innerConfig;
- otError error;
+ Error error;
- while ((error = GetNextOnMeshPrefix(innerIterator, aRloc16, innerConfig)) == OT_ERROR_NONE)
+ while ((error = GetNextOnMeshPrefix(innerIterator, aRloc16, innerConfig)) == kErrorNone)
{
if (outerConfig == innerConfig)
{
@@ -413,7 +413,7 @@
}
}
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
ExitNow(rval = false);
}
@@ -429,13 +429,13 @@
ExternalRouteConfig outerConfig;
bool rval = true;
- while (aCompare.GetNextExternalRoute(outerIterator, aRloc16, outerConfig) == OT_ERROR_NONE)
+ while (aCompare.GetNextExternalRoute(outerIterator, aRloc16, outerConfig) == kErrorNone)
{
Iterator innerIterator = kIteratorInit;
ExternalRouteConfig innerConfig;
- otError error;
+ Error error;
- while ((error = GetNextExternalRoute(innerIterator, aRloc16, innerConfig)) == OT_ERROR_NONE)
+ while ((error = GetNextExternalRoute(innerIterator, aRloc16, innerConfig)) == kErrorNone)
{
if (outerConfig == innerConfig)
{
@@ -443,7 +443,7 @@
}
}
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
ExitNow(rval = false);
}
@@ -459,13 +459,13 @@
ServiceConfig outerConfig;
bool rval = true;
- while (aCompare.GetNextService(outerIterator, aRloc16, outerConfig) == OT_ERROR_NONE)
+ while (aCompare.GetNextService(outerIterator, aRloc16, outerConfig) == kErrorNone)
{
Iterator innerIterator = kIteratorInit;
ServiceConfig innerConfig;
- otError error;
+ Error error;
- while ((error = GetNextService(innerIterator, aRloc16, innerConfig)) == OT_ERROR_NONE)
+ while ((error = GetNextService(innerIterator, aRloc16, innerConfig)) == kErrorNone)
{
if (outerConfig == innerConfig)
{
@@ -473,7 +473,7 @@
}
}
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
ExitNow(rval = false);
}
@@ -489,7 +489,7 @@
uint8_t serviceId;
bool rval = false;
- while (GetNextServiceId(iterator, aRloc16, serviceId) == OT_ERROR_NONE)
+ while (GetNextServiceId(iterator, aRloc16, serviceId) == kErrorNone)
{
if (serviceId == aServiceId)
{
@@ -800,13 +800,13 @@
NetworkData::RemoveTlv(mTlvs, mLength, aTlv);
}
-otError NetworkData::SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext)
+Error NetworkData::SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kServerData));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -837,9 +837,9 @@
return error;
}
-otError NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const
+Error NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const
{
- otError error;
+ Error error;
OnMeshPrefixConfig prefixConfig;
ExternalRouteConfig routeConfig;
ServiceConfig serviceConfig;
diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp
index 38ad173..7311666 100644
--- a/src/core/thread/network_data.hpp
+++ b/src/core/thread/network_data.hpp
@@ -76,6 +76,10 @@
*/
namespace NetworkData {
+namespace Service {
+class Manager;
+}
+
/**
* @addtogroup core-netdata-core
*
@@ -157,6 +161,14 @@
*/
Ip6::Prefix &GetPrefix(void) { return static_cast<Ip6::Prefix &>(mPrefix); }
+ /**
+ * This method sets the prefix.
+ *
+ * @param[in] aPrefix The prefix to set to.
+ *
+ */
+ void SetPrefix(const Ip6::Prefix &aPrefix) { mPrefix = aPrefix; }
+
private:
void SetFrom(Instance & aInstance,
const PrefixTlv & aPrefixTlv,
@@ -168,7 +180,7 @@
* This type represents a Service configuration.
*
*/
-class ServiceConfig : public otServiceConfig, public Clearable<ServiceConfig>
+class ServiceConfig : public otServiceConfig, public Clearable<ServiceConfig>, public Unequatable<ServiceConfig>
{
friend class NetworkData;
@@ -177,7 +189,7 @@
* This class represents a Server configuration.
*
*/
- class ServerConfig : public otServerConfig
+ class ServerConfig : public otServerConfig, public Unequatable<ServerConfig>
{
friend class ServiceConfig;
@@ -193,17 +205,6 @@
*/
bool operator==(const ServerConfig &aOther) const;
- /**
- * This method overloads operator `!=` to evaluate whether or not two `ServerConfig` instances are unequal.
- *
- * @param[in] aOther The other `ServerConfig` instance to compare with.
- *
- * @retval TRUE If the two `ServerConfig` instances are unequal.
- * @retval FALSE If the two `ServerConfig` instances are not unequal.
- *
- */
- bool operator!=(const ServerConfig &aOther) const { return !(*this == aOther); }
-
private:
void SetFrom(const ServerTlv &aServerTlv);
};
@@ -235,17 +236,6 @@
*/
bool operator==(const ServiceConfig &aOther) const;
- /**
- * This method overloads operator `!=` to evaluate whether or not two `ServiceConfig` instances are unequal.
- *
- * @param[in] aOther The other `ServiceConfig` instance to compare with.
- *
- * @retval TRUE If the two `ServiceConfig` instances are unequal.
- * @retval FALSE If the two `ServiceConfig` instances are not unequal.
- *
- */
- bool operator!=(const ServiceConfig &aOther) const { return !(*this == aOther); }
-
private:
void SetFrom(const ServiceTlv &aServiceTlv, const ServerTlv &aServerTlv);
};
@@ -256,6 +246,8 @@
*/
class NetworkData : public InstanceLocator
{
+ friend class Service::Manager;
+
public:
enum
{
@@ -295,11 +287,11 @@
* @param[inout] aDataLength On entry, size of the data buffer pointed to by @p aData.
* On exit, number of copied bytes.
*
- * @retval OT_ERROR_NONE Successfully copied full Thread Network Data.
- * @retval OT_ERROR_NO_BUFS Not enough space to fully copy Thread Network Data.
+ * @retval kErrorNone Successfully copied full Thread Network Data.
+ * @retval kErrorNoBufs Not enough space to fully copy Thread Network Data.
*
*/
- otError GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const;
+ Error GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const;
/**
* This method provides the next On Mesh prefix in the Thread Network Data.
@@ -307,11 +299,11 @@
* @param[inout] aIterator A reference to the Network Data iterator.
* @param[out] aConfig A reference to a config variable where the On Mesh Prefix information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next On Mesh prefix.
- * @retval OT_ERROR_NOT_FOUND No subsequent On Mesh prefix exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next On Mesh prefix.
+ * @retval kErrorNotFound No subsequent On Mesh prefix exists in the Thread Network Data.
*
*/
- otError GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const;
+ Error GetNextOnMeshPrefix(Iterator &aIterator, OnMeshPrefixConfig &aConfig) const;
/**
* This method provides the next On Mesh prefix in the Thread Network Data for a given RLOC16.
@@ -320,11 +312,11 @@
* @param[in] aRloc16 The RLOC16 value.
* @param[out] aConfig A reference to a config variable where the On Mesh Prefix information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next On Mesh prefix.
- * @retval OT_ERROR_NOT_FOUND No subsequent On Mesh prefix exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next On Mesh prefix.
+ * @retval kErrorNotFound No subsequent On Mesh prefix exists in the Thread Network Data.
*
*/
- otError GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const;
+ Error GetNextOnMeshPrefix(Iterator &aIterator, uint16_t aRloc16, OnMeshPrefixConfig &aConfig) const;
/**
* This method provides the next external route in the Thread Network Data.
@@ -332,11 +324,11 @@
* @param[inout] aIterator A reference to the Network Data iterator.
* @param[out] aConfig A reference to a config variable where the external route information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next external route.
- * @retval OT_ERROR_NOT_FOUND No subsequent external route exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next external route.
+ * @retval kErrorNotFound No subsequent external route exists in the Thread Network Data.
*
*/
- otError GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const;
+ Error GetNextExternalRoute(Iterator &aIterator, ExternalRouteConfig &aConfig) const;
/**
* This method provides the next external route in the Thread Network Data for a given RLOC16.
@@ -345,11 +337,11 @@
* @param[in] aRloc16 The RLOC16 value.
* @param[out] aConfig A reference to a config variable where the external route information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next external route.
- * @retval OT_ERROR_NOT_FOUND No subsequent external route exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next external route.
+ * @retval kErrorNotFound No subsequent external route exists in the Thread Network Data.
*
*/
- otError GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const;
+ Error GetNextExternalRoute(Iterator &aIterator, uint16_t aRloc16, ExternalRouteConfig &aConfig) const;
/**
* This method provides the next service in the Thread Network Data.
@@ -357,11 +349,11 @@
* @param[inout] aIterator A reference to the Network Data iterator.
* @param[out] aConfig A reference to a config variable where the service information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next service.
- * @retval OT_ERROR_NOT_FOUND No subsequent service exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next service.
+ * @retval kErrorNotFound No subsequent service exists in the Thread Network Data.
*
*/
- otError GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const;
+ Error GetNextService(Iterator &aIterator, ServiceConfig &aConfig) const;
/**
* This method provides the next service in the Thread Network Data for a given RLOC16.
@@ -370,11 +362,11 @@
* @param[in] aRloc16 The RLOC16 value.
* @param[out] aConfig A reference to a config variable where the service information will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next service.
- * @retval OT_ERROR_NOT_FOUND No subsequent service exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next service.
+ * @retval kErrorNotFound No subsequent service exists in the Thread Network Data.
*
*/
- otError GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const;
+ Error GetNextService(Iterator &aIterator, uint16_t aRloc16, ServiceConfig &aConfig) const;
/**
* This method provides the next Service ID in the Thread Network Data for a given RLOC16.
@@ -383,11 +375,11 @@
* @param[in] aRloc16 The RLOC16 value.
* @param[out] aServiceId A reference to variable where the Service ID will be placed.
*
- * @retval OT_ERROR_NONE Successfully found the next service.
- * @retval OT_ERROR_NOT_FOUND No subsequent service exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next service.
+ * @retval kErrorNotFound No subsequent service exists in the Thread Network Data.
*
*/
- otError GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const;
+ Error GetNextServiceId(Iterator &aIterator, uint16_t aRloc16, uint8_t &aServiceId) const;
/**
* This method indicates whether or not the Thread Network Data contains all of the on mesh prefix information
@@ -447,11 +439,11 @@
* @param[inout] aIterator A reference to the Network Data iterator.
* @param[out] aRloc16 The RLOC16 value.
*
- * @retval OT_ERROR_NONE Successfully found the next server.
- * @retval OT_ERROR_NOT_FOUND No subsequent server exists in the Thread Network Data.
+ * @retval kErrorNone Successfully found the next server.
+ * @retval kErrorNotFound No subsequent server exists in the Thread Network Data.
*
*/
- otError GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const;
+ Error GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const;
protected:
/**
@@ -825,11 +817,11 @@
* @param[in] aHandler A function pointer that is called when the transaction ends.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully enqueued the notification message.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message.
+ * @retval kErrorNone Successfully enqueued the notification message.
+ * @retval kErrorNoBufs Insufficient message buffers to generate the notification message.
*
*/
- otError SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext);
+ Error SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext);
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type.
@@ -968,13 +960,6 @@
uint8_t mLength; ///< The number of valid bytes in @var mTlvs.
private:
- enum
- {
- kDataResubmitDelay = 300000, ///< DATA_RESUBMIT_DELAY (milliseconds) if the device itself is the server.
- kProxyResubmitDelay = 5000, ///< Resubmit delay (milliseconds) if deregister as the child server proxy.
-
- };
-
class NetworkDataIterator
{
public:
@@ -1048,7 +1033,7 @@
ServiceConfig * mService;
};
- otError Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const;
+ Error Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aConfig) const;
static void RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, PrefixTlv &aPrefix);
static void RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, ServiceTlv &aService);
diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp
index 250343b..d4ad9bc 100644
--- a/src/core/thread/network_data_leader.cpp
+++ b/src/core/thread/network_data_leader.cpp
@@ -67,17 +67,17 @@
Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
}
-otError LeaderBase::GetServiceId(uint32_t aEnterpriseNumber,
- const uint8_t *aServiceData,
- uint8_t aServiceDataLength,
- bool aServerStable,
- uint8_t & aServiceId) const
+Error LeaderBase::GetServiceId(uint32_t aEnterpriseNumber,
+ const uint8_t *aServiceData,
+ uint8_t aServiceDataLength,
+ bool aServerStable,
+ uint8_t & aServiceId) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Iterator iterator = kIteratorInit;
ServiceConfig serviceConfig;
- while (GetNextService(iterator, serviceConfig) == OT_ERROR_NONE)
+ while (GetNextService(iterator, serviceConfig) == kErrorNone)
{
if (aEnterpriseNumber == serviceConfig.mEnterpriseNumber &&
aServiceDataLength == serviceConfig.mServiceDataLength &&
@@ -85,7 +85,7 @@
aServerStable == serviceConfig.mServerConfig.mStable)
{
aServiceId = serviceConfig.mServiceId;
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -93,51 +93,6 @@
return error;
}
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-otError LeaderBase::GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfig &aConfig) const
-{
- otError error = OT_ERROR_NOT_FOUND;
- uint8_t serviceData = ServiceTlv::kServiceDataBackboneRouter;
- const ServerTlv * rvalServerTlv = nullptr;
- const BackboneRouterServerData *rvalServerData = nullptr;
- const ServiceTlv * serviceTlv;
- const ServerTlv * serverTlv;
-
- serviceTlv = Get<Leader>().FindService(ServiceTlv::kThreadEnterpriseNumber, &serviceData, sizeof(serviceData));
-
- VerifyOrExit(serviceTlv != nullptr, aConfig.mServer16 = Mac::kShortAddrInvalid);
-
- for (const NetworkDataTlv *start = serviceTlv->GetSubTlvs();
- (serverTlv = FindTlv<ServerTlv>(start, serviceTlv->GetNext())) != nullptr; start = serverTlv->GetNext())
- {
- const BackboneRouterServerData *serverData =
- reinterpret_cast<const BackboneRouterServerData *>(serverTlv->GetServerData());
-
- if (rvalServerTlv == nullptr ||
- (serverTlv->GetServer16() == Mle::Mle::Rloc16FromRouterId(Get<Mle::MleRouter>().GetLeaderId())) ||
- serverData->GetSequenceNumber() > rvalServerData->GetSequenceNumber() ||
- (serverData->GetSequenceNumber() == rvalServerData->GetSequenceNumber() &&
- serverTlv->GetServer16() > rvalServerTlv->GetServer16()))
- {
- rvalServerTlv = serverTlv;
- rvalServerData = serverData;
- }
- }
-
- VerifyOrExit(rvalServerTlv != nullptr);
-
- aConfig.mServer16 = rvalServerTlv->GetServer16();
- aConfig.mSequenceNumber = rvalServerData->GetSequenceNumber();
- aConfig.mReregistrationDelay = rvalServerData->GetReregistrationDelay();
- aConfig.mMlrTimeout = rvalServerData->GetMlrTimeout();
-
- error = OT_ERROR_NONE;
-
-exit:
- return error;
-}
-#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-
const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
{
const PrefixTlv *prefixTlv;
@@ -155,7 +110,7 @@
return prefixTlv;
}
-otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
+Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
{
const PrefixTlv * prefix = nullptr;
const ContextTlv *contextTlv;
@@ -186,12 +141,12 @@
}
}
- return (aContext.mPrefix.GetLength() > 0) ? OT_ERROR_NONE : OT_ERROR_NOT_FOUND;
+ return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
}
-otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
+Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
const PrefixTlv *prefix;
if (aContextId == Mle::kMeshLocalPrefixContextId)
@@ -199,7 +154,7 @@
aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
aContext.mCompressFlag = true;
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
for (const NetworkDataTlv *start = GetTlvsStart(); (prefix = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr;
@@ -215,29 +170,29 @@
aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength());
aContext.mContextId = contextTlv->GetContextId();
aContext.mCompressFlag = contextTlv->IsCompress();
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
exit:
return error;
}
-otError LeaderBase::GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16) const
+Error LeaderBase::GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Lowpan::Context lowpanContext;
- if ((GetContext(aContextId, lowpanContext)) == OT_ERROR_NONE)
+ if ((GetContext(aContextId, lowpanContext)) == kErrorNone)
{
Iterator iterator = kIteratorInit;
OnMeshPrefixConfig config;
- while (GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
if (lowpanContext.mPrefix.ContainsPrefix(config.GetPrefix()))
{
aRloc16 = config.mRloc16;
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
}
@@ -280,29 +235,29 @@
return rval;
}
-otError LeaderBase::RouteLookup(const Ip6::Address &aSource,
- const Ip6::Address &aDestination,
- uint8_t * aPrefixMatchLength,
- uint16_t * aRloc16) const
+Error LeaderBase::RouteLookup(const Ip6::Address &aSource,
+ const Ip6::Address &aDestination,
+ uint8_t * aPrefixMatchLength,
+ uint16_t * aRloc16) const
{
- otError error = OT_ERROR_NO_ROUTE;
+ Error error = kErrorNoRoute;
const PrefixTlv *prefix = nullptr;
while ((prefix = FindNextMatchingPrefix(aSource, prefix)) != nullptr)
{
- if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatchLength, aRloc16) == OT_ERROR_NONE)
+ if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatchLength, aRloc16) == kErrorNone)
{
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
- if (DefaultRouteLookup(*prefix, aRloc16) == OT_ERROR_NONE)
+ if (DefaultRouteLookup(*prefix, aRloc16) == kErrorNone)
{
if (aPrefixMatchLength)
{
*aPrefixMatchLength = 0;
}
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
}
@@ -310,12 +265,12 @@
return error;
}
-otError LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
- const Ip6::Address &aDestination,
- uint8_t * aPrefixMatchLength,
- uint16_t * aRloc16) const
+Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
+ const Ip6::Address &aDestination,
+ uint8_t * aPrefixMatchLength,
+ uint16_t * aRloc16) const
{
- otError error = OT_ERROR_NO_ROUTE;
+ Error error = kErrorNoRoute;
const PrefixTlv * prefixTlv;
const HasRouteEntry *bestRouteEntry = nullptr;
uint8_t bestMatchLength = 0;
@@ -374,15 +329,15 @@
*aPrefixMatchLength = bestMatchLength;
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
return error;
}
-otError LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const
+Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const
{
- otError error = OT_ERROR_NO_ROUTE;
+ Error error = kErrorNoRoute;
const BorderRouterTlv * borderRouter;
const BorderRouterEntry *route = nullptr;
@@ -416,26 +371,26 @@
*aRloc16 = route->GetRloc();
}
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
return error;
}
-otError LeaderBase::SetNetworkData(uint8_t aVersion,
- uint8_t aStableVersion,
- bool aStableOnly,
- const Message &aMessage,
- uint16_t aMessageOffset)
+Error LeaderBase::SetNetworkData(uint8_t aVersion,
+ uint8_t aStableVersion,
+ bool aStableOnly,
+ const Message &aMessage,
+ uint16_t aMessageOffset)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mle::Tlv tlv;
uint16_t length;
SuccessOrExit(error = aMessage.Read(aMessageOffset, tlv));
length = aMessage.ReadBytes(aMessageOffset + sizeof(tlv), mTlvs, tlv.GetLength());
- VerifyOrExit(length == tlv.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(length == tlv.GetLength(), error = kErrorParse);
mLength = tlv.GetLength();
mVersion = aVersion;
@@ -462,19 +417,19 @@
return error;
}
-otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
+Error LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
CommissioningDataTlv *commissioningDataTlv;
RemoveCommissioningData();
if (aValueLength > 0)
{
- VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = kErrorNoBufs);
commissioningDataTlv =
static_cast<CommissioningDataTlv *>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
- VerifyOrExit(commissioningDataTlv != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(commissioningDataTlv != nullptr, error = kErrorNoBufs);
commissioningDataTlv->Init();
commissioningDataTlv->SetLength(aValueLength);
@@ -540,24 +495,24 @@
return;
}
-otError LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
+Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const MeshCoP::Tlv * steeringDataTlv;
MeshCoP::SteeringData steeringData;
steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
- VerifyOrExit(steeringDataTlv != nullptr, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
static_cast<const MeshCoP::SteeringDataTlv *>(steeringDataTlv)->CopyTo(steeringData);
- VerifyOrExit(steeringData.Contains(aFilterIndexes), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
exit:
return error;
}
-otError LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
+Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
{
FilterIndexes filterIndexes;
Mac::ExtAddress joinerId;
@@ -568,7 +523,7 @@
return SteeringDataCheck(filterIndexes);
}
-otError LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
+Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
{
FilterIndexes filterIndexes;
diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp
index f869125..baf93d6 100644
--- a/src/core/thread/network_data_leader.hpp
+++ b/src/core/thread/network_data_leader.hpp
@@ -38,10 +38,6 @@
#include <stdint.h>
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-#include "backbone_router/bbr_leader.hpp"
-#endif
-
#include "coap/coap.hpp"
#include "common/timer.hpp"
#include "net/ip6_address.hpp"
@@ -105,11 +101,11 @@
* @param[in] aAddress A reference to an IPv6 address.
* @param[out] aContext A reference to 6LoWPAN Context information.
*
- * @retval OT_ERROR_NONE Successfully retrieved 6LoWPAN Context information.
- * @retval OT_ERROR_NOT_FOUND Could not find the 6LoWPAN Context information.
+ * @retval kErrorNone Successfully retrieved 6LoWPAN Context information.
+ * @retval kErrorNotFound Could not find the 6LoWPAN Context information.
*
*/
- otError GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const;
+ Error GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const;
/**
* This method retrieves the 6LoWPAN Context information based on a given Context ID.
@@ -117,11 +113,11 @@
* @param[in] aContextId The Context ID value.
* @param[out] aContext A reference to the 6LoWPAN Context information.
*
- * @retval OT_ERROR_NONE Successfully retrieved 6LoWPAN Context information.
- * @retval OT_ERROR_NOT_FOUND Could not find the 6LoWPAN Context information.
+ * @retval kErrorNone Successfully retrieved 6LoWPAN Context information.
+ * @retval kErrorNotFound Could not find the 6LoWPAN Context information.
*
*/
- otError GetContext(uint8_t aContextId, Lowpan::Context &aContext) const;
+ Error GetContext(uint8_t aContextId, Lowpan::Context &aContext) const;
/**
* This method indicates whether or not the given IPv6 address is on-mesh.
@@ -142,14 +138,14 @@
* @param[out] aPrefixMatchLength A pointer to output the longest prefix match length in bits.
* @param[out] aRloc16 A pointer to the RLOC16 for the selected route.
*
- * @retval OT_ERROR_NONE Successfully found a route.
- * @retval OT_ERROR_NO_ROUTE No valid route was found.
+ * @retval kErrorNone Successfully found a route.
+ * @retval kErrorNoRoute No valid route was found.
*
*/
- otError RouteLookup(const Ip6::Address &aSource,
- const Ip6::Address &aDestination,
- uint8_t * aPrefixMatchLength,
- uint16_t * aRloc16) const;
+ Error RouteLookup(const Ip6::Address &aSource,
+ const Ip6::Address &aDestination,
+ uint8_t * aPrefixMatchLength,
+ uint16_t * aRloc16) const;
/**
* This method is used by non-Leader devices to set newly received Network Data from the Leader.
@@ -160,15 +156,15 @@
* @param[in] aMessage A reference to the MLE message.
* @param[in] aMessageOffset The offset in @p aMessage for the Network Data TLV.
*
- * @retval OT_ERROR_NONE Successfully set the network data.
- * @retval OT_ERROR_PARSE Network Data TLV in @p aMessage is not valid.
+ * @retval kErrorNone Successfully set the network data.
+ * @retval kErrorParse Network Data TLV in @p aMessage is not valid.
*
*/
- otError SetNetworkData(uint8_t aVersion,
- uint8_t aStableVersion,
- bool aStableOnly,
- const Message &aMessage,
- uint16_t aMessageOffset);
+ Error SetNetworkData(uint8_t aVersion,
+ uint8_t aStableVersion,
+ bool aStableOnly,
+ const Message &aMessage,
+ uint16_t aMessageOffset);
/**
* This method returns a pointer to the Commissioning Data.
@@ -228,35 +224,35 @@
* @param[in] aValue A pointer to the Commissioning Data value.
* @param[in] aValueLength The length of @p aValue.
*
- * @retval OT_ERROR_NONE Successfully added the Commissioning Data.
- * @retval OT_ERROR_NO_BUFS Insufficient space to add the Commissioning Data.
+ * @retval kErrorNone Successfully added the Commissioning Data.
+ * @retval kErrorNoBufs Insufficient space to add the Commissioning Data.
*
*/
- otError SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength);
+ Error SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength);
/**
* This method checks if the steering data includes a Joiner.
*
* @param[in] aEui64 A reference to the Joiner's IEEE EUI-64.
*
- * @retval OT_ERROR_NONE @p aEui64 is in the bloom filter.
- * @retval OT_ERROR_INVALID_STATE No steering data present.
- * @retval OT_ERROR_NOT_FOUND @p aEui64 is not in the bloom filter.
+ * @retval kErrorNone @p aEui64 is in the bloom filter.
+ * @retval kErrorInvalidState No steering data present.
+ * @retval kErrorNotFound @p aEui64 is not in the bloom filter.
*
*/
- otError SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const;
+ Error SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const;
/**
* This method checks if the steering data includes a Joiner with a given discerner value.
*
* @param[in] aDiscerner A reference to the Joiner Discerner.
*
- * @retval OT_ERROR_NONE @p aDiscerner is in the bloom filter.
- * @retval OT_ERROR_INVALID_STATE No steering data present.
- * @retval OT_ERROR_NOT_FOUND @p aDiscerner is not in the bloom filter.
+ * @retval kErrorNone @p aDiscerner is in the bloom filter.
+ * @retval kErrorInvalidState No steering data present.
+ * @retval kErrorNotFound @p aDiscerner is not in the bloom filter.
*
*/
- otError SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const;
+ Error SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const;
/**
* This method gets the Rloc of Dhcp Agent of specified contextId.
@@ -264,11 +260,11 @@
* @param[in] aContextId A pointer to the Commissioning Data value.
* @param[out] aRloc16 The reference of which for output the Rloc16.
*
- * @retval OT_ERROR_NONE Successfully get the Rloc of Dhcp Agent.
- * @retval OT_ERROR_NOT_FOUND The specified @p aContextId could not be found.
+ * @retval kErrorNone Successfully get the Rloc of Dhcp Agent.
+ * @retval kErrorNotFound The specified @p aContextId could not be found.
*
*/
- otError GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16) const;
+ Error GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16) const;
/**
* This method gets the Service ID for the specified service.
@@ -279,28 +275,15 @@
* @param[in] aServerStable The Stable flag value for Server TLV
* @param[out] aServiceId A reference where to put the Service ID.
*
- * @retval OT_ERROR_NONE Successfully got the Service ID.
- * @retval OT_ERROR_NOT_FOUND The specified service was not found.
+ * @retval kErrorNone Successfully got the Service ID.
+ * @retval kErrorNotFound The specified service was not found.
*
*/
- otError GetServiceId(uint32_t aEnterpriseNumber,
- const uint8_t *aServiceData,
- uint8_t aServiceDataLength,
- bool aServerStable,
- uint8_t & aServiceId) const;
-
-#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
- /**
- * This method gets the Primary Backbone Router (PBBR) in the Thread Network.
- *
- * @param[out] aConfig The Primary Backbone Router configuration.
- *
- * @retval OT_ERROR_NONE Successfully got the Primary Backbone Router configuration.
- * @retval OT_ERROR_NOT_FOUND No Backbone Router Service in the Thread Network.
- *
- */
- otError GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfig &aConfig) const;
-#endif
+ Error GetServiceId(uint32_t aEnterpriseNumber,
+ const uint8_t *aServiceData,
+ uint8_t aServiceDataLength,
+ bool aServerStable,
+ uint8_t & aServiceId) const;
protected:
uint8_t mStableVersion;
@@ -313,12 +296,12 @@
void RemoveCommissioningData(void);
- otError ExternalRouteLookup(uint8_t aDomainId,
- const Ip6::Address &aDestination,
- uint8_t * aPrefixMatchLength,
- uint16_t * aRloc16) const;
- otError DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const;
- otError SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
+ Error ExternalRouteLookup(uint8_t aDomainId,
+ const Ip6::Address &aDestination,
+ uint8_t * aPrefixMatchLength,
+ uint16_t * aRloc16) const;
+ Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const;
+ Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
};
/**
diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp
index c07db93..f3fc965 100644
--- a/src/core/thread/network_data_leader_ftd.cpp
+++ b/src/core/thread/network_data_leader_ftd.cpp
@@ -57,7 +57,7 @@
Leader::Leader(Instance &aInstance)
: LeaderBase(aInstance)
- , mTimer(aInstance, Leader::HandleTimer, this)
+ , mTimer(aInstance, Leader::HandleTimer)
, mServerData(UriPath::kServerData, &Leader::HandleServerData, this)
, mCommissioningDataGet(UriPath::kCommissionerGet, &Leader::HandleCommissioningGet, this)
, mCommissioningDataSet(UriPath::kCommissionerSet, &Leader::HandleCommissioningSet, this)
@@ -148,16 +148,16 @@
switch (Tlv::Find<ThreadRloc16Tlv>(aMessage, rloc16))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
RemoveBorderRouter(rloc16, kMatchModeRloc16);
break;
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
ExitNow();
}
- if (Tlv::FindTlv(aMessage, networkData) == OT_ERROR_NONE)
+ if (Tlv::FindTlv(aMessage, networkData) == kErrorNone)
{
VerifyOrExit(networkData.IsValid());
RegisterNetworkData(aMessageInfo.GetPeerAddr().GetIid().GetLocator(), networkData.GetTlvs(),
@@ -298,13 +298,13 @@
uint16_t aLength,
const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message;
CommissioningDataTlv *commDataTlv;
uint8_t * data = nullptr;
uint8_t length = 0;
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -317,7 +317,7 @@
length = commDataTlv->GetLength();
}
- VerifyOrExit(data && length, error = OT_ERROR_DROP);
+ VerifyOrExit(data && length, error = kErrorDrop);
if (aLength == 0)
{
@@ -361,10 +361,10 @@
const Ip6::MessageInfo & aMessageInfo,
MeshCoP::StateTlv::State aState)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message *message;
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -397,20 +397,20 @@
return matched;
}
-otError Leader::Validate(const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aRloc16)
+Error Leader::Validate(const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aRloc16)
{
// Validate that the `aTlvs` contains well-formed TLVs, sub-TLVs,
// and entries all matching `aRloc16` (no other entry for other
// RLOCs and no duplicates TLVs).
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const NetworkDataTlv *end = reinterpret_cast<const NetworkDataTlv *>(aTlvs + aTlvsLength);
for (const NetworkDataTlv *cur = reinterpret_cast<const NetworkDataTlv *>(aTlvs); cur < end; cur = cur->GetNext())
{
uint8_t offset;
- VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = OT_ERROR_PARSE);
+ VerifyOrExit((cur + 1) <= end && cur->GetNext() <= end, error = kErrorParse);
offset = static_cast<uint8_t>(reinterpret_cast<const uint8_t *>(cur) - aTlvs);
@@ -420,11 +420,11 @@
{
const PrefixTlv *prefix = static_cast<const PrefixTlv *>(cur);
- VerifyOrExit(prefix->IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(prefix->IsValid(), error = kErrorParse);
// Ensure there is no duplicate Prefix TLVs with same prefix.
VerifyOrExit(FindPrefix(prefix->GetPrefix(), prefix->GetPrefixLength(), aTlvs, offset) == nullptr,
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
SuccessOrExit(error = ValidatePrefix(*prefix, aRloc16));
break;
@@ -434,13 +434,13 @@
{
const ServiceTlv *service = static_cast<const ServiceTlv *>(cur);
- VerifyOrExit(service->IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(service->IsValid(), error = kErrorParse);
// Ensure there is no duplicate Service TLV with same
// Enterprise Number and Service Data.
VerifyOrExit(FindService(service->GetEnterpriseNumber(), service->GetServiceData(),
service->GetServiceDataLength(), aTlvs, offset) == nullptr,
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
SuccessOrExit(error = ValidateService(*service, aRloc16));
break;
@@ -455,13 +455,13 @@
return error;
}
-otError Leader::ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16)
+Error Leader::ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16)
{
// Validate that `aPrefix` TLV contains well-formed sub-TLVs and
// and entries all matching `aRloc16` (no other entry for other
// RLOCs).
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
const NetworkDataTlv *subEnd = aPrefix.GetNext();
bool foundTempHasRoute = false;
bool foundStableHasRoute = false;
@@ -529,19 +529,19 @@
if (foundStableBorderRouter || foundTempBorderRouter || foundStableHasRoute || foundTempHasRoute)
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
exit:
return error;
}
-otError Leader::ValidateService(const ServiceTlv &aService, uint16_t aRloc16)
+Error Leader::ValidateService(const ServiceTlv &aService, uint16_t aRloc16)
{
// Validate that `aService` TLV contains a single well-formed
// Server sub-TLV associated with `aRloc16`.
- otError error = OT_ERROR_PARSE;
+ Error error = kErrorParse;
const NetworkDataTlv *subEnd = aService.GetNext();
bool foundServer = false;
@@ -569,7 +569,7 @@
if (foundServer)
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
exit:
@@ -699,11 +699,11 @@
void Leader::RegisterNetworkData(uint16_t aRloc16, const uint8_t *aTlvs, uint8_t aTlvsLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
const NetworkDataTlv *end = reinterpret_cast<const NetworkDataTlv *>(aTlvs + aTlvsLength);
ChangedFlags flags;
- VerifyOrExit(Get<RouterTable>().IsAllocated(Mle::Mle::RouterIdFromRloc16(aRloc16)), error = OT_ERROR_NO_ROUTE);
+ VerifyOrExit(Get<RouterTable>().IsAllocated(Mle::Mle::RouterIdFromRloc16(aRloc16)), error = kErrorNoRoute);
// Validate that the `aTlvs` contains well-formed TLVs, sub-TLVs,
// and entries all matching `aRloc16` (no other RLOCs).
@@ -737,21 +737,21 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogNoteNetData("Failed to register network data: %s", otThreadErrorToString(error));
+ otLogNoteNetData("Failed to register network data: %s", ErrorToString(error));
}
}
-otError Leader::AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags)
+Error Leader::AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
PrefixTlv *dstPrefix = FindPrefix(aPrefix.GetPrefix(), aPrefix.GetPrefixLength());
if (dstPrefix == nullptr)
{
dstPrefix = static_cast<PrefixTlv *>(AppendTlv(PrefixTlv::CalculateSize(aPrefix.GetPrefixLength())));
- VerifyOrExit(dstPrefix != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(dstPrefix != nullptr, error = kErrorNoBufs);
dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
}
@@ -789,9 +789,9 @@
return error;
}
-otError Leader::AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags)
+Error Leader::AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServiceTlv *dstService =
FindService(aService.GetEnterpriseNumber(), aService.GetServiceData(), aService.GetServiceDataLength());
const ServerTlv *server;
@@ -804,7 +804,7 @@
dstService = static_cast<ServiceTlv *>(
AppendTlv(ServiceTlv::CalculateSize(aService.GetEnterpriseNumber(), aService.GetServiceDataLength())));
- VerifyOrExit(dstService != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(dstService != nullptr, error = kErrorNoBufs);
dstService->Init(serviceId, aService.GetEnterpriseNumber(), aService.GetServiceData(),
aService.GetServiceDataLength());
@@ -830,16 +830,16 @@
return error;
}
-otError Leader::AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags)
+Error Leader::AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
HasRouteTlv * dstHasRoute = FindHasRoute(aDstPrefix, aHasRoute.IsStable());
const HasRouteEntry *entry = aHasRoute.GetFirstEntry();
if (dstHasRoute == nullptr)
{
// Ensure there is space for `HasRouteTlv` and a single entry.
- VerifyOrExit(CanInsert(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanInsert(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)), error = kErrorNoBufs);
dstHasRoute = static_cast<HasRouteTlv *>(aDstPrefix.GetNext());
Insert(dstHasRoute, sizeof(HasRouteTlv));
@@ -854,7 +854,7 @@
VerifyOrExit(!ContainsMatchingEntry(dstHasRoute, *entry));
- VerifyOrExit(CanInsert(sizeof(HasRouteEntry)), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanInsert(sizeof(HasRouteEntry)), error = kErrorNoBufs);
Insert(dstHasRoute->GetNext(), sizeof(HasRouteEntry));
dstHasRoute->IncreaseLength(sizeof(HasRouteEntry));
@@ -867,11 +867,9 @@
return error;
}
-otError Leader::AddBorderRouter(const BorderRouterTlv &aBorderRouter,
- PrefixTlv & aDstPrefix,
- ChangedFlags & aChangedFlags)
+Error Leader::AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
BorderRouterTlv * dstBorderRouter = FindBorderRouter(aDstPrefix, aBorderRouter.IsStable());
ContextTlv * dstContext = FindContext(aDstPrefix);
uint8_t contextId = 0;
@@ -891,7 +889,7 @@
// and a `ContextTlv` (if not already present).
VerifyOrExit(CanInsert(sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry) +
((dstContext == nullptr) ? sizeof(ContextTlv) : 0)),
- error = OT_ERROR_NO_BUFS);
+ error = kErrorNoBufs);
dstBorderRouter = static_cast<BorderRouterTlv *>(aDstPrefix.GetNext());
Insert(dstBorderRouter, sizeof(BorderRouterTlv));
@@ -907,7 +905,7 @@
if (dstContext == nullptr)
{
// Ensure there is space for a `ContextTlv` and a single entry.
- VerifyOrExit(CanInsert(sizeof(BorderRouterEntry) + sizeof(ContextTlv)), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanInsert(sizeof(BorderRouterEntry) + sizeof(ContextTlv)), error = kErrorNoBufs);
dstContext = static_cast<ContextTlv *>(aDstPrefix.GetNext());
Insert(dstContext, sizeof(ContextTlv));
@@ -925,7 +923,7 @@
VerifyOrExit(!ContainsMatchingEntry(dstBorderRouter, *entry));
- VerifyOrExit(CanInsert(sizeof(BorderRouterEntry)), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanInsert(sizeof(BorderRouterEntry)), error = kErrorNoBufs);
Insert(dstBorderRouter->GetNext(), sizeof(BorderRouterEntry));
dstBorderRouter->IncreaseLength(sizeof(BorderRouterEntry));
@@ -937,15 +935,15 @@
return error;
}
-otError Leader::AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags)
+Error Leader::AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServerTlv *dstServer;
uint8_t tlvSize = aServer.GetSize();
VerifyOrExit(!ContainsMatchingServer(&aDstService, aServer));
- VerifyOrExit(CanInsert(tlvSize), error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(CanInsert(tlvSize), error = kErrorNoBufs);
dstServer = static_cast<ServerTlv *>(aDstService.GetNext());
Insert(dstServer, tlvSize);
@@ -963,9 +961,9 @@
return error;
}
-otError Leader::AllocateServiceId(uint8_t &aServiceId) const
+Error Leader::AllocateServiceId(uint8_t &aServiceId) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
uint8_t serviceId;
for (serviceId = Mle::kServiceMinId; serviceId <= Mle::kServiceMaxId; serviceId++)
@@ -973,7 +971,7 @@
if (FindServiceById(serviceId) == nullptr)
{
aServiceId = serviceId;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
otLogInfoNetData("Allocated Service ID = %d", serviceId);
break;
}
@@ -1001,9 +999,9 @@
return service;
}
-otError Leader::AllocateContextId(uint8_t &aContextId)
+Error Leader::AllocateContextId(uint8_t &aContextId)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
for (uint8_t contextId = kMinContextId; contextId < kMinContextId + kNumContextIds; contextId++)
{
@@ -1011,7 +1009,7 @@
{
mContextUsed |= (1 << contextId);
aContextId = contextId;
- error = OT_ERROR_NONE;
+ error = kErrorNone;
otLogInfoNetData("Allocated Context ID = %d", contextId);
break;
}
@@ -1331,7 +1329,7 @@
void Leader::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Leader>().HandleTimer();
+ aTimer.Get<Leader>().HandleTimer();
}
void Leader::HandleTimer(void)
@@ -1361,15 +1359,15 @@
}
}
-otError Leader::RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext)
+Error Leader::RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
Iterator iterator = kIteratorInit;
uint16_t rloc16;
VerifyOrExit(Get<Mle::MleRouter>().IsRouterOrLeader());
- while (GetNextServer(iterator, rloc16) == OT_ERROR_NONE)
+ while (GetNextServer(iterator, rloc16) == kErrorNone)
{
if (!Mle::Mle::IsActiveRouter(rloc16) && Mle::Mle::RouterIdMatch(Get<Mle::MleRouter>().GetRloc16(), rloc16) &&
Get<ChildTable>().FindChild(rloc16, Child::kInStateValid) == nullptr)
diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp
index fe5657f..0643947 100644
--- a/src/core/thread/network_data_leader_ftd.hpp
+++ b/src/core/thread/network_data_leader_ftd.hpp
@@ -164,12 +164,12 @@
* @param[in] aHandler A function pointer that is called when the transaction ends.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE A stale child entry was found and successfully enqueued a SVR_DATA.ntf message.
- * @retval OT_ERROR_NO_BUFS A stale child entry was found, but insufficient message buffers were available.
- * @retval OT_ERROR_NOT_FOUND No stale child entries were found.
+ * @retval kErrorNone A stale child entry was found and successfully enqueued a SVR_DATA.ntf message.
+ * @retval kErrorNoBufs A stale child entry was found, but insufficient message buffers were available.
+ * @retval kErrorNotFound No stale child entries were found.
*
*/
- otError RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext);
+ Error RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext);
private:
class ChangedFlags
@@ -209,18 +209,18 @@
void RegisterNetworkData(uint16_t aRloc16, const uint8_t *aTlvs, uint8_t aTlvsLength);
- otError AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags);
- otError AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
- otError AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
- otError AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags);
- otError AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags);
+ Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags);
+ Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
+ Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
+ Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags);
+ Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags);
- otError AllocateServiceId(uint8_t &aServiceId) const;
+ Error AllocateServiceId(uint8_t &aServiceId) const;
- otError AllocateContextId(uint8_t &aContextId);
- void FreeContextId(uint8_t aContextId);
- void StartContextReuseTimer(uint8_t aContextId);
- void StopContextReuseTimer(uint8_t aContextId);
+ Error AllocateContextId(uint8_t &aContextId);
+ void FreeContextId(uint8_t aContextId);
+ void StartContextReuseTimer(uint8_t aContextId);
+ void StopContextReuseTimer(uint8_t aContextId);
void RemoveContext(uint8_t aContextId);
void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
@@ -258,9 +258,9 @@
static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode);
- static otError Validate(const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aRloc16);
- static otError ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16);
- static otError ValidateService(const ServiceTlv &aService, uint16_t aRloc16);
+ static Error Validate(const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aRloc16);
+ static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16);
+ static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16);
static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry);
static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry);
diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp
index 04e20dd..bef1b26 100644
--- a/src/core/thread/network_data_local.cpp
+++ b/src/core/thread/network_data_local.cpp
@@ -54,20 +54,20 @@
}
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-otError Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
+Error Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig)
{
- otError error;
+ Error error;
uint16_t flags = 0;
// Add Prefix validation check:
// Thread 1.1 Specification 5.13.2 says
// "A valid prefix MUST NOT allow both DHCPv6 and SLAAC for address configuration"
- VerifyOrExit(!aConfig.mDhcp || !aConfig.mSlaac, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aConfig.mDhcp || !aConfig.mSlaac, error = kErrorInvalidArgs);
// RFC 4944 Section 6 says:
// An IPv6 address prefix used for stateless autoconfiguration [RFC4862]
// of an IEEE 802.15.4 interface MUST have a length of 64 bits.
- VerifyOrExit(!aConfig.mSlaac || aConfig.mPrefix.mLength == OT_IP6_PREFIX_BITSIZE, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aConfig.mSlaac || aConfig.mPrefix.mLength == OT_IP6_PREFIX_BITSIZE, error = kErrorInvalidArgs);
if (aConfig.mPreferred)
{
@@ -118,33 +118,33 @@
return error;
}
-otError Local::RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix)
+Error Local::RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix)
{
return RemovePrefix(aPrefix, NetworkDataTlv::kTypeBorderRouter);
}
-otError Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
+Error Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig)
{
return AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeHasRoute, aConfig.mPreference, /* aFlags */ 0,
aConfig.mStable);
}
-otError Local::RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix)
+Error Local::RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix)
{
return RemovePrefix(aPrefix, NetworkDataTlv::kTypeHasRoute);
}
-otError Local::AddPrefix(const Ip6::Prefix & aPrefix,
- NetworkDataTlv::Type aSubTlvType,
- int8_t aPrf,
- uint16_t aFlags,
- bool aStable)
+Error Local::AddPrefix(const Ip6::Prefix & aPrefix,
+ NetworkDataTlv::Type aSubTlvType,
+ int8_t aPrf,
+ uint16_t aFlags,
+ bool aStable)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t subTlvLength;
PrefixTlv *prefixTlv;
- VerifyOrExit((aPrefix.GetLength() > 0) && aPrefix.IsValid(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((aPrefix.GetLength() > 0) && aPrefix.IsValid(), error = kErrorInvalidArgs);
switch (aPrf)
{
@@ -153,10 +153,10 @@
case OT_ROUTE_PREFERENCE_HIGH:
break;
default:
- ExitNow(error = OT_ERROR_INVALID_ARGS);
+ ExitNow(error = kErrorInvalidArgs);
}
- VerifyOrExit(!aPrefix.ContainsPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix()), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aPrefix.ContainsPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix()), error = kErrorInvalidArgs);
IgnoreError(RemovePrefix(aPrefix, aSubTlvType));
@@ -165,7 +165,7 @@
: sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
prefixTlv = static_cast<PrefixTlv *>(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength));
- VerifyOrExit(prefixTlv != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(prefixTlv != nullptr, error = kErrorNoBufs);
prefixTlv->Init(0, aPrefix);
prefixTlv->SetSubTlvsLength(subTlvLength);
@@ -200,13 +200,13 @@
return error;
}
-otError Local::RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType)
+Error Local::RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
PrefixTlv *tlv;
- VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = OT_ERROR_NOT_FOUND);
- VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = kErrorNotFound);
+ VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != nullptr, error = kErrorNotFound);
RemoveTlv(tlv);
exit:
@@ -252,14 +252,14 @@
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-otError Local::AddService(uint32_t aEnterpriseNumber,
- const uint8_t *aServiceData,
- uint8_t aServiceDataLength,
- bool aServerStable,
- const uint8_t *aServerData,
- uint8_t aServerDataLength)
+Error Local::AddService(uint32_t aEnterpriseNumber,
+ const uint8_t *aServiceData,
+ uint8_t aServiceDataLength,
+ bool aServerStable,
+ const uint8_t *aServerData,
+ uint8_t aServerDataLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServiceTlv *serviceTlv;
ServerTlv * serverTlv;
uint16_t serviceTlvSize =
@@ -267,10 +267,10 @@
IgnoreError(RemoveService(aEnterpriseNumber, aServiceData, aServiceDataLength));
- VerifyOrExit(serviceTlvSize <= kMaxSize, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(serviceTlvSize <= kMaxSize, error = kErrorNoBufs);
serviceTlv = static_cast<ServiceTlv *>(AppendTlv(serviceTlvSize));
- VerifyOrExit(serviceTlv != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit(serviceTlv != nullptr, error = kErrorNoBufs);
serviceTlv->Init(/* aServiceId */ 0, aEnterpriseNumber, aServiceData, aServiceDataLength);
serviceTlv->SetSubTlvsLength(sizeof(ServerTlv) + aServerDataLength);
@@ -294,13 +294,13 @@
return error;
}
-otError Local::RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength)
+Error Local::RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
ServiceTlv *tlv;
VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, aServiceDataLength)) != nullptr,
- error = OT_ERROR_NOT_FOUND);
+ error = kErrorNotFound);
RemoveTlv(tlv);
exit:
@@ -361,9 +361,9 @@
}
}
-otError Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext)
+Error Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t rloc = Get<Mle::MleRouter>().GetRloc16();
bool isConsistent = true;
@@ -372,7 +372,7 @@
// Don't send this Server Data Notification if the device is going to upgrade to Router
if (Get<Mle::MleRouter>().IsExpectedToBecomeRouter())
{
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
}
#endif
@@ -386,7 +386,7 @@
isConsistent = isConsistent && IsServiceConsistent();
#endif
- VerifyOrExit(!isConsistent, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!isConsistent, error = kErrorNotFound);
if (mOldRloc == rloc)
{
diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp
index 8eae4c9..71facfb 100644
--- a/src/core/thread/network_data_local.hpp
+++ b/src/core/thread/network_data_local.hpp
@@ -76,45 +76,45 @@
*
* @param[in] aConfig A reference to the on mesh perfix configuration.
*
- * @retval OT_ERROR_NONE Successfully added the Border Router entry.
- * @retval OT_ERROR_NO_BUFS Insufficient space to add the Border Router entry.
- * @retval OT_ERROR_INVALID_ARGS The prefix is mesh local prefix.
+ * @retval kErrorNone Successfully added the Border Router entry.
+ * @retval kErrorNoBufs Insufficient space to add the Border Router entry.
+ * @retval kErrorInvalidArgs The prefix is mesh local prefix.
*
*/
- otError AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig);
+ Error AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig);
/**
* This method removes a Border Router entry from the Thread Network Data.
*
* @param[in] aPrefix The Prefix to remove.
*
- * @retval OT_ERROR_NONE Successfully removed the Border Router entry.
- * @retval OT_ERROR_NOT_FOUND Could not find the Border Router entry.
+ * @retval kErrorNone Successfully removed the Border Router entry.
+ * @retval kErrorNotFound Could not find the Border Router entry.
*
*/
- otError RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix);
+ Error RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix);
/**
* This method adds a Has Route entry to the Thread Network data.
*
* @param[in] aConfig A reference to the external route configuration.
*
- * @retval OT_ERROR_NONE Successfully added the Has Route entry.
- * @retval OT_ERROR_NO_BUFS Insufficient space to add the Has Route entry.
+ * @retval kErrorNone Successfully added the Has Route entry.
+ * @retval kErrorNoBufs Insufficient space to add the Has Route entry.
*
*/
- otError AddHasRoutePrefix(const ExternalRouteConfig &aConfig);
+ Error AddHasRoutePrefix(const ExternalRouteConfig &aConfig);
/**
* This method removes a Border Router entry from the Thread Network Data.
*
* @param[in] aPrefix The Prefix to remove.
*
- * @retval OT_ERROR_NONE Successfully removed the Border Router entry.
- * @retval OT_ERROR_NOT_FOUND Could not find the Border Router entry.
+ * @retval kErrorNone Successfully removed the Border Router entry.
+ * @retval kErrorNotFound Could not find the Border Router entry.
*
*/
- otError RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix);
+ Error RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix);
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
@@ -128,16 +128,16 @@
* @param[in] aServerData A pointer to the Server Data
* @param[in] aServerDataLength The length of @p aServerData in bytes.
*
- * @retval OT_ERROR_NONE Successfully added the Service entry.
- * @retval OT_ERROR_NO_BUFS Insufficient space to add the Service entry.
+ * @retval kErrorNone Successfully added the Service entry.
+ * @retval kErrorNoBufs Insufficient space to add the Service entry.
*
*/
- otError AddService(uint32_t aEnterpriseNumber,
- const uint8_t *aServiceData,
- uint8_t aServiceDataLength,
- bool aServerStable,
- const uint8_t *aServerData,
- uint8_t aServerDataLength);
+ Error AddService(uint32_t aEnterpriseNumber,
+ const uint8_t *aServiceData,
+ uint8_t aServiceDataLength,
+ bool aServerStable,
+ const uint8_t *aServerData,
+ uint8_t aServerDataLength);
/**
* This method removes a Service entry from the Thread Network local data.
@@ -146,12 +146,12 @@
* @param[in] aServiceData A pointer to the service data.
* @param[in] aServiceDataLength The length of @p aServiceData in bytes.
*
- * @retval OT_ERROR_NONE Successfully removed the Border Router entry.
- * @retval OT_ERROR_NOT_FOUND Could not find the Border Router entry.
+ * @retval kErrorNone Successfully removed the Service entry.
+ * @retval kErrorNotFound Could not find the Service entry.
*
*/
- otError RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength);
-#endif
+ Error RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength);
+#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
/**
* This method sends a Server Data Notification message to the Leader.
@@ -159,26 +159,26 @@
* @param[in] aHandler A function pointer that is called when the transaction ends.
* @param[in] aContext A pointer to arbitrary context information.
*
- * @retval OT_ERROR_NONE Successfully enqueued the notification message.
- * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message.
- * @retval OT_ERROR_INVALID_STATE Device is a REED and is in the process of becoming a Router.
- * @retval OT_ERROR_NOT_FOUND Server Data is already consistent with network data.
+ * @retval kErrorNone Successfully enqueued the notification message.
+ * @retval kErrorNoBufs Insufficient message buffers to generate the notification message.
+ * @retval kErrorInvalidState Device is a REED and is in the process of becoming a Router.
+ * @retval kErrorNotFound Server Data is already consistent with network data.
*
*/
- otError UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext);
+ Error UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext);
private:
void UpdateRloc(void);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
- otError AddPrefix(const Ip6::Prefix & aPrefix,
- NetworkDataTlv::Type aSubTlvType,
- int8_t aPrf,
- uint16_t aFlags,
- bool aStable);
- otError RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType);
- void UpdateRloc(PrefixTlv &aPrefixTlv);
- bool IsOnMeshPrefixConsistent(void) const;
- bool IsExternalRouteConsistent(void) const;
+ Error AddPrefix(const Ip6::Prefix & aPrefix,
+ NetworkDataTlv::Type aSubTlvType,
+ int8_t aPrf,
+ uint16_t aFlags,
+ bool aStable);
+ Error RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType);
+ void UpdateRloc(PrefixTlv &aPrefixTlv);
+ bool IsOnMeshPrefixConsistent(void) const;
+ bool IsExternalRouteConsistent(void) const;
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp
index eed8087..7ea123a 100644
--- a/src/core/thread/network_data_notifier.cpp
+++ b/src/core/thread/network_data_notifier.cpp
@@ -46,7 +46,7 @@
Notifier::Notifier(Instance &aInstance)
: InstanceLocator(aInstance)
- , mTimer(aInstance, Notifier::HandleTimer, this)
+ , mTimer(aInstance, Notifier::HandleTimer)
, mNextDelay(0)
, mWaitingForResponse(false)
{
@@ -60,7 +60,7 @@
void Notifier::SynchronizeServerData(void)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
VerifyOrExit(Get<Mle::MleRouter>().IsAttached() && !mWaitingForResponse);
@@ -69,30 +69,30 @@
#if OPENTHREAD_FTD
mNextDelay = kDelayRemoveStaleChildren;
error = Get<Leader>().RemoveStaleChildEntries(&Notifier::HandleCoapResponse, this);
- VerifyOrExit(error == OT_ERROR_NOT_FOUND);
+ VerifyOrExit(error == kErrorNotFound);
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
mNextDelay = kDelaySynchronizeServerData;
error = Get<Local>().UpdateInconsistentServerData(&Notifier::HandleCoapResponse, this);
- VerifyOrExit(error == OT_ERROR_NOT_FOUND);
+ VerifyOrExit(error == kErrorNotFound);
#endif
exit:
switch (error)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
mWaitingForResponse = true;
break;
- case OT_ERROR_NO_BUFS:
+ case kErrorNoBufs:
mTimer.Start(kDelayNoBufs);
break;
#if OPENTHREAD_FTD
- case OT_ERROR_INVALID_STATE:
+ case kErrorInvalidState:
mTimer.Start(Time::SecToMsec(Get<Mle::MleRouter>().GetRouterSelectionJitterTimeout() + 1));
break;
#endif
- case OT_ERROR_NOT_FOUND:
+ case kErrorNotFound:
break;
default:
OT_ASSERT(false);
@@ -115,7 +115,7 @@
void Notifier::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<Notifier>().HandleTimer();
+ aTimer.Get<Notifier>().HandleTimer();
}
void Notifier::HandleTimer(void)
@@ -123,10 +123,7 @@
SynchronizeServerData();
}
-void Notifier::HandleCoapResponse(void * aContext,
- otMessage * aMessage,
- const otMessageInfo *aMessageInfo,
- otError aResult)
+void Notifier::HandleCoapResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessage);
OT_UNUSED_VARIABLE(aMessageInfo);
@@ -134,18 +131,18 @@
static_cast<Notifier *>(aContext)->HandleCoapResponse(aResult);
}
-void Notifier::HandleCoapResponse(otError aResult)
+void Notifier::HandleCoapResponse(Error aResult)
{
mWaitingForResponse = false;
switch (aResult)
{
- case OT_ERROR_NONE:
+ case kErrorNone:
mTimer.Start(mNextDelay + 1);
break;
- case OT_ERROR_RESPONSE_TIMEOUT:
- case OT_ERROR_ABORT:
+ case kErrorResponseTimeout:
+ case kErrorAbort:
SynchronizeServerData();
break;
diff --git a/src/core/thread/network_data_notifier.hpp b/src/core/thread/network_data_notifier.hpp
index dcc3195..433072c 100644
--- a/src/core/thread/network_data_notifier.hpp
+++ b/src/core/thread/network_data_notifier.hpp
@@ -85,8 +85,8 @@
static void HandleCoapResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleCoapResponse(otError aResult);
+ Error aResult);
+ void HandleCoapResponse(Error aResult);
void SynchronizeServerData(void);
diff --git a/src/core/thread/network_data_service.cpp b/src/core/thread/network_data_service.cpp
new file mode 100644
index 0000000..ed18e3f
--- /dev/null
+++ b/src/core/thread/network_data_service.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2021, 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 function for managing Thread Network Data service/server entries.
+ *
+ */
+
+#include "network_data_service.hpp"
+
+#include "common/code_utils.hpp"
+#include "common/instance.hpp"
+#include "common/locator-getters.hpp"
+#include "thread/network_data_local.hpp"
+
+namespace ot {
+namespace NetworkData {
+namespace Service {
+
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+
+Error Manager::AddService(uint8_t aServiceNumber,
+ bool aServerStable,
+ const void *aServerData,
+ uint8_t aServerDataLength)
+{
+ Error error;
+
+ SuccessOrExit(error = Get<Local>().AddService(kThreadEnterpriseNumber, &aServiceNumber, sizeof(aServiceNumber),
+ aServerStable, reinterpret_cast<const uint8_t *>(aServerData),
+ aServerDataLength));
+
+ Get<Notifier>().HandleServerDataUpdated();
+
+exit:
+ return error;
+}
+
+Error Manager::RemoveService(uint8_t aServiceNumber)
+{
+ Error error;
+
+ SuccessOrExit(error = Get<Local>().RemoveService(kThreadEnterpriseNumber, &aServiceNumber, sizeof(aServiceNumber)));
+ Get<Notifier>().HandleServerDataUpdated();
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+
+Error Manager::GetServiceId(uint8_t aServiceNumber, bool aServerStable, uint8_t &aServiceId) const
+{
+ return Get<Leader>().GetServiceId(kThreadEnterpriseNumber, &aServiceNumber, sizeof(aServiceNumber), aServerStable,
+ aServiceId);
+}
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+void Manager::GetBackboneRouterPrimary(ot::BackboneRouter::BackboneRouterConfig &aConfig) const
+{
+ const uint8_t serviceData = BackboneRouter::kServiceNumber;
+ const ServerTlv * rvalServerTlv = nullptr;
+ const BackboneRouter::ServerData *rvalServerData = nullptr;
+ Iterator iterator;
+
+ aConfig.mServer16 = Mac::kShortAddrInvalid;
+
+ iterator.mServiceTlv = Get<Leader>().FindService(kThreadEnterpriseNumber, &serviceData, sizeof(serviceData));
+
+ VerifyOrExit(iterator.mServiceTlv != nullptr);
+
+ while (IterateToNextServer(iterator) == kErrorNone)
+ {
+ const BackboneRouter::ServerData *serverData;
+
+ if (iterator.mServerSubTlv->GetServerDataLength() < sizeof(BackboneRouter::ServerData))
+ {
+ continue;
+ }
+
+ serverData = reinterpret_cast<const BackboneRouter::ServerData *>(iterator.mServerSubTlv->GetServerData());
+
+ if (rvalServerTlv == nullptr ||
+ (iterator.mServerSubTlv->GetServer16() ==
+ Mle::Mle::Rloc16FromRouterId(Get<Mle::MleRouter>().GetLeaderId())) ||
+ serverData->GetSequenceNumber() > rvalServerData->GetSequenceNumber() ||
+ (serverData->GetSequenceNumber() == rvalServerData->GetSequenceNumber() &&
+ iterator.mServerSubTlv->GetServer16() > rvalServerTlv->GetServer16()))
+ {
+ rvalServerTlv = iterator.mServerSubTlv;
+ rvalServerData = serverData;
+ }
+ }
+
+ VerifyOrExit(rvalServerTlv != nullptr);
+
+ aConfig.mServer16 = rvalServerTlv->GetServer16();
+ aConfig.mSequenceNumber = rvalServerData->GetSequenceNumber();
+ aConfig.mReregistrationDelay = rvalServerData->GetReregistrationDelay();
+ aConfig.mMlrTimeout = rvalServerData->GetMlrTimeout();
+
+exit:
+ return;
+}
+
+#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+Error Manager::GetNextSrpServerInfo(Iterator &aIterator, SrpServer::Info &aInfo) const
+{
+ Error error = kErrorNotFound;
+
+ if (aIterator.mServiceTlv == nullptr)
+ {
+ const uint8_t serviceData = SrpServer::kServiceNumber;
+
+ aIterator.mServiceTlv = Get<Leader>().FindService(kThreadEnterpriseNumber, &serviceData, sizeof(serviceData));
+ VerifyOrExit(aIterator.mServiceTlv != nullptr);
+ }
+ else
+ {
+ VerifyOrExit(aIterator.mServerSubTlv != nullptr);
+ }
+
+ while ((error = IterateToNextServer(aIterator)) == kErrorNone)
+ {
+ const SrpServer::ServerData *serverData;
+
+ if (aIterator.mServerSubTlv->GetServerDataLength() < sizeof(SrpServer::ServerData))
+ {
+ continue;
+ }
+
+ serverData = reinterpret_cast<const SrpServer::ServerData *>(aIterator.mServerSubTlv->GetServerData());
+
+ aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16();
+ aInfo.mSockAddr.GetAddress().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(), aInfo.mRloc16);
+ aInfo.mSockAddr.SetPort(serverData->GetPort());
+
+ break;
+ }
+
+exit:
+ return error;
+}
+
+Error Manager::IterateToNextServer(Iterator &aIterator) const
+{
+ const NetworkDataTlv *start;
+
+ start =
+ (aIterator.mServerSubTlv != nullptr) ? aIterator.mServerSubTlv->GetNext() : aIterator.mServiceTlv->GetSubTlvs();
+ aIterator.mServerSubTlv = NetworkData::FindTlv<ServerTlv>(start, aIterator.mServiceTlv->GetNext());
+
+ return (aIterator.mServerSubTlv != nullptr) ? kErrorNone : kErrorNotFound;
+}
+
+} // namespace Service
+} // namespace NetworkData
+} // namespace ot
diff --git a/src/core/thread/network_data_service.hpp b/src/core/thread/network_data_service.hpp
new file mode 100644
index 0000000..313b2a8
--- /dev/null
+++ b/src/core/thread/network_data_service.hpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2021, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions related to Thread Network Data service/server entries.
+ */
+
+#ifndef NETWORK_DATA_SERVICE_HPP_
+#define NETWORK_DATA_SERVICE_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/netdata.h>
+
+#include "backbone_router/bbr_leader.hpp"
+#include "common/encoding.hpp"
+#include "common/locator.hpp"
+#include "common/non_copyable.hpp"
+#include "net/socket.hpp"
+#include "thread/network_data_tlvs.hpp"
+
+namespace ot {
+namespace NetworkData {
+namespace Service {
+
+using ot::Encoding::BigEndian::HostSwap16;
+using ot::Encoding::BigEndian::HostSwap32;
+
+enum : uint32_t
+{
+ kThreadEnterpriseNumber = ServiceTlv::kThreadEnterpriseNumber, ///< Thread enterprise number.
+};
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+/**
+ * This type implements Thread Network Data "Backbone Router Service" server data generation and parsing.
+ *
+ */
+class BackboneRouter
+{
+public:
+ enum : uint8_t
+ {
+ kServiceNumber = 0x01, ///< Backbone Router service data number (THREAD_SERVICE_DATA_BBR).
+ };
+
+ /**
+ * This class implements the generation and parsing of "Backbone Router Service" server data.
+ *
+ */
+ OT_TOOL_PACKED_BEGIN
+ class ServerData
+ {
+ public:
+ /**
+ * This method returns the length (in bytes) of server data.
+ *
+ * @returns The server data length in bytes.
+ *
+ */
+ uint8_t GetLength(void) const { return sizeof(ServerData); }
+
+ /**
+ * This method returns the sequence number of Backbone Router.
+ *
+ * @returns The sequence number of the Backbone Router.
+ *
+ */
+ uint8_t GetSequenceNumber(void) const { return mSequenceNumber; }
+
+ /**
+ * This method sets the sequence number of Backbone Router.
+ *
+ * @param[in] aSequenceNumber The sequence number of Backbone Router.
+ *
+ */
+ void SetSequenceNumber(uint8_t aSequenceNumber) { mSequenceNumber = aSequenceNumber; }
+
+ /**
+ * This method returns the Registration Delay (in seconds) of Backbone Router.
+ *
+ * @returns The BBR Registration Delay (in seconds) of Backbone Router.
+ *
+ */
+ uint16_t GetReregistrationDelay(void) const { return HostSwap16(mReregistrationDelay); }
+
+ /**
+ * This method sets the Registration Delay (in seconds) of Backbone Router.
+ *
+ * @param[in] aReregistrationDelay The Registration Delay (in seconds) of Backbone Router.
+ *
+ */
+ void SetReregistrationDelay(uint16_t aReregistrationDelay)
+ {
+ mReregistrationDelay = HostSwap16(aReregistrationDelay);
+ }
+
+ /**
+ * This method returns the multicast listener report timeout (in seconds) of Backbone Router.
+ *
+ * @returns The multicast listener report timeout (in seconds) of Backbone Router.
+ *
+ */
+ uint32_t GetMlrTimeout(void) const { return HostSwap32(mMlrTimeout); }
+
+ /**
+ * This method sets multicast listener report timeout (in seconds) of Backbone Router.
+ *
+ * @param[in] aMlrTimeout The multicast listener report timeout (in seconds) of Backbone Router.
+ *
+ */
+ void SetMlrTimeout(uint32_t aMlrTimeout) { mMlrTimeout = HostSwap32(aMlrTimeout); }
+
+ private:
+ uint8_t mSequenceNumber;
+ uint16_t mReregistrationDelay;
+ uint32_t mMlrTimeout;
+ } OT_TOOL_PACKED_END;
+
+ BackboneRouter(void) = delete;
+};
+
+#endif // #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+
+/**
+ * This type implements Thread Network Data "SRP Server Service" server data generation and parsing.
+ *
+ */
+class SrpServer
+{
+public:
+ enum : uint8_t
+ {
+ kServiceNumber = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_NUMBER, ///< SRP Sever Service number
+ };
+
+ /**
+ * This structure represents information about an SRP server (from "SRP Server Service" Server entries).
+ *
+ */
+ struct Info
+ {
+ Ip6::SockAddr mSockAddr; ///< The SRP server address (IPv6 address and port number).
+ uint16_t mRloc16; ///< The RLOC16 of SRP server.
+ };
+
+ /**
+ * This class implements generation and parsing of "SRP Server Service" server data.
+ *
+ */
+ OT_TOOL_PACKED_BEGIN
+ class ServerData
+ {
+ public:
+ /** This method returns the length (in bytes) of server data.
+ *
+ * @returns The server data length in bytes.
+ *
+ */
+ uint8_t GetLength(void) const { return sizeof(ServerData); }
+
+ /**
+ * This method returns the port number being used by the SRP server.
+ *
+ * @return The port number of SPR server.
+ *
+ */
+ uint16_t GetPort(void) const { return HostSwap16(mPort); }
+
+ /**
+ * This method sets the SRP port number in `ServerData`.
+ *
+ * @param[in] aPort The port number of SRP server.
+ *
+ */
+ void SetPort(uint16_t aPort) { mPort = HostSwap16(aPort); }
+
+ private:
+ uint16_t mPort;
+ } OT_TOOL_PACKED_END;
+
+ SrpServer(void) = delete;
+};
+
+/**
+ * This class manages the Thread Service entries in Thread Network Data.
+ *
+ */
+class Manager : public InstanceLocator, private NonCopyable
+{
+public:
+ /**
+ * This class represents an iterator used to iterate through Network Data Service entries.
+ *
+ */
+ class Iterator : public Clearable<Iterator>
+ {
+ friend class Manager;
+
+ public:
+ /**
+ * This constructor initializes the iterator (as empty/clear).
+ *
+ */
+ Iterator(void)
+ : mServiceTlv(nullptr)
+ , mServerSubTlv(nullptr)
+ {
+ }
+
+ private:
+ const ServiceTlv *mServiceTlv;
+ const ServerTlv * mServerSubTlv;
+ };
+
+ /**
+ * This constructor initializes the `Manager` object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ */
+ explicit Manager(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ {
+ }
+
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+ /**
+ * This method adds a Thread Service entry to the local Thread Network Data.
+ *
+ * When successfully added, this method also invokes `Notifier::HandleServerDataUpdated()` to register the changes
+ * in local Network Data with leader.
+ *
+ * The template type `ServiceType` has the following requirements:
+ * - It MUST have a constant `ServiceType::kServiceNumber` specifying the service number.
+ * - It MUST define nested type `ServiceType::ServerData` representing the server data (and its format).
+ * - The `ServiceType::ServerData` MUST provide `GetLength()` method returning the length of server data.
+ *
+ * @tparam ServiceType The service type to be added.
+ *
+ * @param[in] aServerData The server data.
+ * @param[in] aServerStable The Stable flag value for Server TLV.
+ *
+ * @retval kErrorNone Successfully added the Service entry.
+ * @retval kErrorNoBufs Insufficient space to add the Service entry.
+ *
+ */
+ template <typename ServiceType>
+ Error Add(const typename ServiceType::ServerData &aServerData, bool aServerStable = true)
+ {
+ return AddService(ServiceType::kServiceNumber, aServerStable, &aServerData, aServerData.GetLength());
+ }
+
+ /**
+ * This method removed a Thread Service entry to the local Thread Network Data.
+ *
+ * When successfully removed, this method also invokes `Notifier::HandleServerDataUpdated()` to register the
+ * changes in local Network Data with leader.
+ *
+ * The template type `ServiceType` has the following requirements:
+ * - It MUST have a constant `ServiceType::kServiceNumber` specifying the service number.
+ *
+ * @tparam ServiceType The service type to be removed.
+ *
+ * @retval kErrorNone Successfully removed the Service entry.
+ * @retval kErrorNotFound Could not find the Service entry.
+ *
+ */
+ template <typename ServiceType> Error Remove(void) { return RemoveService(ServiceType::kServiceNumber); }
+
+#endif
+
+ /**
+ * This method gets the Service ID for the specified service from Thread Network Data.
+ *
+ * The template type `ServiceType` has the following requirements:
+ * - It MUST have a constant `ServiceType::kServiceNumber` specifying the service number.
+ *
+ * @tparam ServiceType The service type to be added.
+ *
+ * @param[in] aServerStable The Stable flag value for Server TLV
+ * @param[out] aServiceId A reference where to put the Service ID.
+ *
+ * @retval kErrorNone Successfully got the Service ID.
+ * @retval kErrorNotFound The specified service was not found.
+ *
+ */
+ template <typename ServiceType> Error GetServiceId(bool aServerStable, uint8_t &aServiceId) const
+ {
+ return GetServiceId(ServiceType::kServiceNumber, aServerStable, aServiceId);
+ }
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ /**
+ * This method gets the Primary Backbone Router (PBBR) in the Thread Network Data.
+ *
+ * @param[out] aConfig The Primary Backbone Router configuration.
+ *
+ */
+ void GetBackboneRouterPrimary(ot::BackboneRouter::BackboneRouterConfig &aConfig) const;
+#endif
+
+ /**
+ * This method gets the next SRP server info from the Thread Network Data "SRP Server Service" entries.
+ *
+ * This method allows caller to iterate through all server entries for Network Data "SRP Server Service". To get
+ * the first entry @p aIterator should be cleared (e.g., a new instance of `Iterator` or calling `Clear()` method).
+ *
+ * @param[inout] aIterator A reference to an iterator.
+ * @param[out] aInfo A reference to `SrpServer::Info` to return the next SRP server info.
+ *
+ * @retval kErrorNone Successfully got the next SRP server info. @p aInfo and @p aIterator are updated.
+ * @retval kErrorNotFound No more SRP server entries in Network Data.
+ *
+ */
+ Error GetNextSrpServerInfo(Iterator &aIterator, SrpServer::Info &aInfo) const;
+
+private:
+#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+ Error AddService(uint8_t aServiceNumber, bool aServerStable, const void *aServerData, uint8_t aServerDataLength);
+ Error RemoveService(uint8_t aServiceNumber);
+#endif
+
+ Error GetServiceId(uint8_t aServiceNumber, bool aServerStable, uint8_t &aServiceId) const;
+ Error IterateToNextServer(Iterator &aIterator) const;
+};
+
+} // namespace Service
+} // namespace NetworkData
+} // namespace ot
+
+#endif // NETWORK_DATA_SERVICE_HPP_
diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp
index ed01d00..ceac708 100644
--- a/src/core/thread/network_data_tlvs.hpp
+++ b/src/core/thread/network_data_tlvs.hpp
@@ -990,9 +990,12 @@
public:
enum
{
- kType = kTypeService, ///< The TLV Type.
- kThreadEnterpriseNumber = 44970, ///< Thread enterprise number.
- kServiceDataBackboneRouter = 0x01, ///< const THREAD_SERVICE_DATA_BBR
+ kType = kTypeService, ///< The TLV Type.
+ };
+
+ enum : uint32_t
+ {
+ kThreadEnterpriseNumber = 44970, ///< Thread enterprise number.
};
/**
@@ -1287,67 +1290,6 @@
uint16_t mServer16;
} OT_TOOL_PACKED_END;
-OT_TOOL_PACKED_BEGIN
-class BackboneRouterServerData
-{
-public:
- /**
- * This method returns the sequence number of Backbone Router.
- *
- * @returns The sequence number of the Backbone Router.
- *
- */
- uint8_t GetSequenceNumber(void) const { return mSequenceNumber; }
-
- /**
- * This method sets the sequence number of Backbone Router.
- *
- * @param[in] aSequenceNumber The sequence number of Backbone Router.
- *
- */
- void SetSequenceNumber(uint8_t aSequenceNumber) { mSequenceNumber = aSequenceNumber; }
-
- /**
- * This method returns the Registration Delay (in seconds) of Backbone Router.
- *
- * @returns The BBR Registration Delay (in seconds) of Backbone Router.
- *
- */
- uint16_t GetReregistrationDelay(void) const { return HostSwap16(mReregistrationDelay); }
-
- /**
- * This method sets the Registration Delay (in seconds) of Backbone Router.
- *
- * @param[in] aReregistrationDelay The Registration Delay (in seconds) of Backbone Router.
- *
- */
- void SetReregistrationDelay(uint16_t aReregistrationDelay)
- {
- mReregistrationDelay = HostSwap16(aReregistrationDelay);
- }
-
- /**
- * This method returns the multicast listener report timeout (in seconds) of Backbone Router.
- *
- * @returns The multicast listener report timeout (in seconds) of Backbone Router.
- *
- */
- uint32_t GetMlrTimeout(void) const { return HostSwap32(mMlrTimeout); }
-
- /**
- * This method sets multicast listener report timeout (in seconds) of Backbone Router.
- *
- * @param[in] aMlrTimeout The multicast listener report timeout (in seconds) of Backbone Router.
- *
- */
- void SetMlrTimeout(uint32_t aMlrTimeout) { mMlrTimeout = HostSwap32(aMlrTimeout); }
-
-private:
- uint8_t mSequenceNumber;
- uint16_t mReregistrationDelay;
- uint32_t mMlrTimeout;
-} OT_TOOL_PACKED_END;
-
/**
* @}
*
diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp
index a26525b..4941840 100644
--- a/src/core/thread/network_diagnostic.cpp
+++ b/src/core/thread/network_diagnostic.cpp
@@ -69,23 +69,18 @@
Get<Tmf::TmfAgent>().AddResource(mDiagnosticReset);
}
-void NetworkDiagnostic::SetReceiveDiagnosticGetCallback(otReceiveDiagnosticGetCallback aCallback,
- void * aCallbackContext)
+Error NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address & aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount,
+ otReceiveDiagnosticGetCallback aCallback,
+ void * aCallbackContext)
{
- mReceiveDiagnosticGetCallback = aCallback;
- mReceiveDiagnosticGetCallbackContext = aCallbackContext;
-}
-
-otError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestination,
- const uint8_t aTlvTypes[],
- uint8_t aCount)
-{
- otError error;
+ Error error;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
otCoapResponseHandler handler = nullptr;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
if (aDestination.IsMulticast())
{
@@ -122,6 +117,9 @@
SuccessOrExit(error = Get<Tmf::TmfAgent>().SendMessage(*message, messageInfo, handler, this));
+ mReceiveDiagnosticGetCallback = aCallback;
+ mReceiveDiagnosticGetCallbackContext = aCallbackContext;
+
otLogInfoNetDiag("Sent diagnostic get");
exit:
@@ -132,7 +130,7 @@
void NetworkDiagnostic::HandleDiagnosticGetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
static_cast<NetworkDiagnostic *>(aContext)->HandleDiagnosticGetResponse(
static_cast<Coap::Message *>(aMessage), static_cast<const Ip6::MessageInfo *>(aMessageInfo), aResult);
@@ -140,10 +138,10 @@
void NetworkDiagnostic::HandleDiagnosticGetResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
- otError aResult)
+ Error aResult)
{
SuccessOrExit(aResult);
- VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, aResult = OT_ERROR_FAILED);
+ VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, aResult = kErrorFailed);
exit:
if (mReceiveDiagnosticGetCallback)
@@ -152,7 +150,7 @@
}
else
{
- otLogDebgNetDiag("Received diagnostic get response, error = %s", otThreadErrorToString(aResult));
+ otLogDebgNetDiag("Received diagnostic get response, error = %s", ErrorToString(aResult));
}
return;
}
@@ -173,7 +171,7 @@
if (mReceiveDiagnosticGetCallback)
{
- mReceiveDiagnosticGetCallback(OT_ERROR_NONE, &aMessage, &aMessageInfo, mReceiveDiagnosticGetCallbackContext);
+ mReceiveDiagnosticGetCallback(kErrorNone, &aMessage, &aMessageInfo, mReceiveDiagnosticGetCallbackContext);
}
SuccessOrExit(Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo));
@@ -184,9 +182,9 @@
return;
}
-otError NetworkDiagnostic::AppendIp6AddressList(Message &aMessage)
+Error NetworkDiagnostic::AppendIp6AddressList(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Ip6AddressListTlv tlv;
uint8_t count = 0;
@@ -211,9 +209,9 @@
}
#if OPENTHREAD_FTD
-otError NetworkDiagnostic::AppendChildTable(Message &aMessage)
+Error NetworkDiagnostic::AppendChildTable(Message &aMessage)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t count = 0;
uint8_t timeout = 0;
ChildTableTlv tlv;
@@ -280,11 +278,11 @@
aMacCountersTlv.SetIfOutDiscards(macCounters.mTxErrBusyChannel);
}
-otError NetworkDiagnostic::FillRequestedTlvs(const Message & aRequest,
- Message & aResponse,
- NetworkDiagnosticTlv &aNetworkDiagnosticTlv)
+Error NetworkDiagnostic::FillRequestedTlvs(const Message & aRequest,
+ Message & aResponse,
+ NetworkDiagnosticTlv &aNetworkDiagnosticTlv)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t offset = 0;
uint8_t type;
@@ -434,7 +432,7 @@
{
uint32_t maxTimeout;
- if (Get<Mle::MleRouter>().GetMaxChildTimeout(maxTimeout) == OT_ERROR_NONE)
+ if (Get<Mle::MleRouter>().GetMaxChildTimeout(maxTimeout) == kErrorNone)
{
SuccessOrExit(error = Tlv::Append<MaxChildTimeoutTlv>(aResponse, maxTimeout));
}
@@ -463,29 +461,29 @@
void NetworkDiagnostic::HandleDiagnosticGetQuery(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
NetworkDiagnosticTlv networkDiagnosticTlv;
Ip6::MessageInfo messageInfo;
- VerifyOrExit(aMessage.IsPostRequest(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessage.IsPostRequest(), error = kErrorDrop);
otLogInfoNetDiag("Received diagnostic get query");
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), networkDiagnosticTlv));
- VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_PARSE);
+ VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = kErrorParse);
// DIAG_GET.qry may be sent as a confirmable message.
if (aMessage.IsConfirmable())
{
- if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == OT_ERROR_NONE)
+ if (Get<Tmf::TmfAgent>().SendEmptyAck(aMessage, aMessageInfo) == kErrorNone)
{
otLogInfoNetDiag("Sent diagnostic get query acknowledgment");
}
}
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDiagnosticGetAnswer));
@@ -532,20 +530,20 @@
void NetworkDiagnostic::HandleDiagnosticGetRequest(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Coap::Message * message = nullptr;
NetworkDiagnosticTlv networkDiagnosticTlv;
Ip6::MessageInfo messageInfo(aMessageInfo);
- VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = OT_ERROR_DROP);
+ VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = kErrorDrop);
otLogInfoNetDiag("Received diagnostic get request");
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), networkDiagnosticTlv));
- VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = OT_ERROR_PARSE);
+ VerifyOrExit(networkDiagnosticTlv.GetType() == NetworkDiagnosticTlv::kTypeList, error = kErrorParse);
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->SetDefaultResponseHeader(aMessage));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -566,15 +564,15 @@
FreeMessageOnError(message, error);
}
-otError NetworkDiagnostic::SendDiagnosticReset(const Ip6::Address &aDestination,
- const uint8_t aTlvTypes[],
- uint8_t aCount)
+Error NetworkDiagnostic::SendDiagnosticReset(const Ip6::Address &aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount)
{
- otError error;
+ Error error;
Coap::Message * message = nullptr;
Ip6::MessageInfo messageInfo;
- VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = Get<Tmf::TmfAgent>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kDiagnosticReset));
@@ -726,11 +724,11 @@
ParseMode(aChildTableTlvEntry.GetMode(), aChildEntry.mMode);
}
-otError NetworkDiagnostic::GetNextDiagTlv(const Coap::Message &aMessage,
- Iterator & aIterator,
- otNetworkDiagTlv & aNetworkDiagTlv)
+Error NetworkDiagnostic::GetNextDiagTlv(const Coap::Message &aMessage,
+ Iterator & aIterator,
+ otNetworkDiagTlv & aNetworkDiagTlv)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t offset = aMessage.GetOffset() + aIterator;
NetworkDiagnosticTlv tlv;
@@ -738,7 +736,7 @@
{
uint16_t tlvTotalLength;
- VerifyOrExit(aMessage.Read(offset, tlv) == OT_ERROR_NONE, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(aMessage.Read(offset, tlv) == kErrorNone, error = kErrorNotFound);
switch (tlv.GetType())
{
@@ -769,7 +767,7 @@
ConnectivityTlv connectivity;
SuccessOrExit(error = aMessage.Read(offset, connectivity));
- VerifyOrExit(connectivity.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(connectivity.IsValid(), error = kErrorParse);
ParseConnectivity(connectivity, aNetworkDiagTlv.mData.mConnectivity);
break;
@@ -780,9 +778,9 @@
RouteTlv route;
tlvTotalLength = sizeof(tlv) + tlv.GetLength();
- VerifyOrExit(tlvTotalLength <= sizeof(route), error = OT_ERROR_PARSE);
+ VerifyOrExit(tlvTotalLength <= sizeof(route), error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offset, &route, tlvTotalLength));
- VerifyOrExit(route.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(route.IsValid(), error = kErrorParse);
ParseRoute(route, aNetworkDiagTlv.mData.mRoute);
break;
@@ -793,7 +791,7 @@
LeaderDataTlv leaderData;
SuccessOrExit(error = aMessage.Read(offset, leaderData));
- VerifyOrExit(leaderData.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(leaderData.IsValid(), error = kErrorParse);
ParseLeaderData(leaderData, aNetworkDiagTlv.mData.mLeaderData);
break;
@@ -804,11 +802,10 @@
NetworkDataTlv networkData;
tlvTotalLength = sizeof(tlv) + tlv.GetLength();
- VerifyOrExit(tlvTotalLength <= sizeof(networkData), error = OT_ERROR_PARSE);
+ VerifyOrExit(tlvTotalLength <= sizeof(networkData), error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offset, &networkData, tlvTotalLength));
- VerifyOrExit(networkData.IsValid(), error = OT_ERROR_PARSE);
- VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mNetworkData.m8) >= networkData.GetLength(),
- error = OT_ERROR_PARSE);
+ VerifyOrExit(networkData.IsValid(), error = kErrorParse);
+ VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mNetworkData.m8) >= networkData.GetLength(), error = kErrorParse);
memcpy(aNetworkDiagTlv.mData.mNetworkData.m8, networkData.GetNetworkData(), networkData.GetLength());
aNetworkDiagTlv.mData.mNetworkData.mCount = networkData.GetLength();
@@ -819,9 +816,9 @@
{
Ip6AddressListTlv &ip6AddrList = static_cast<Ip6AddressListTlv &>(tlv);
- VerifyOrExit(ip6AddrList.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(ip6AddrList.IsValid(), error = kErrorParse);
VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mIp6AddrList.mList) >= ip6AddrList.GetLength(),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offset + sizeof(ip6AddrList), aNetworkDiagTlv.mData.mIp6AddrList.mList,
ip6AddrList.GetLength()));
aNetworkDiagTlv.mData.mIp6AddrList.mCount = ip6AddrList.GetLength() / OT_IP6_ADDRESS_SIZE;
@@ -833,7 +830,7 @@
MacCountersTlv macCounters;
SuccessOrExit(error = aMessage.Read(offset, macCounters));
- VerifyOrExit(macCounters.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(macCounters.IsValid(), error = kErrorParse);
ParseMacCounters(macCounters, aNetworkDiagTlv.mData.mMacCounters);
break;
@@ -851,15 +848,14 @@
{
ChildTableTlv &childTable = static_cast<ChildTableTlv &>(tlv);
- VerifyOrExit(childTable.IsValid(), error = OT_ERROR_PARSE);
+ VerifyOrExit(childTable.IsValid(), error = kErrorParse);
VerifyOrExit(childTable.GetNumEntries() <= OT_ARRAY_LENGTH(aNetworkDiagTlv.mData.mChildTable.mTable),
- error = OT_ERROR_PARSE);
+ error = kErrorParse);
for (uint8_t i = 0; i < childTable.GetNumEntries(); ++i)
{
ChildTableEntry childEntry;
- VerifyOrExit(childTable.ReadEntry(childEntry, aMessage, offset, i) == OT_ERROR_NONE,
- error = OT_ERROR_PARSE);
+ VerifyOrExit(childTable.ReadEntry(childEntry, aMessage, offset, i) == kErrorNone, error = kErrorParse);
ParseChildEntry(childEntry, aNetworkDiagTlv.mData.mChildTable.mTable[i]);
}
aNetworkDiagTlv.mData.mChildTable.mCount = childTable.GetNumEntries();
@@ -868,7 +864,7 @@
case NetworkDiagnosticTlv::kChannelPages:
{
- VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mChannelPages.m8) >= tlv.GetLength(), error = OT_ERROR_PARSE);
+ VerifyOrExit(sizeof(aNetworkDiagTlv.mData.mChannelPages.m8) >= tlv.GetLength(), error = kErrorParse);
SuccessOrExit(
error = aMessage.Read(offset + sizeof(tlv), aNetworkDiagTlv.mData.mChannelPages.m8, tlv.GetLength()));
aNetworkDiagTlv.mData.mChannelPages.mCount = tlv.GetLength();
diff --git a/src/core/thread/network_diagnostic.hpp b/src/core/thread/network_diagnostic.hpp
index 510a9ea..e5a2b68 100644
--- a/src/core/thread/network_diagnostic.hpp
+++ b/src/core/thread/network_diagnostic.hpp
@@ -82,25 +82,22 @@
explicit NetworkDiagnostic(Instance &aInstance);
/**
- * This method registers a callback to provide received raw DIAG_GET.rsp or an DIAG_GET.ans payload.
- *
- * @param[in] aCallback A pointer to a function that is called when an DIAG_GET.rsp or an DIAG_GET.ans
- * is received or nullptr to disable the callback.
- * @param[in] aCallbackContext A pointer to application-specific context.
- *
- */
- void SetReceiveDiagnosticGetCallback(otReceiveDiagnosticGetCallback aCallback, void *aCallbackContext);
-
- /**
* This method sends Diagnostic Get request. If the @p aDestination is of multicast type, the DIAG_GET.qry
* message is sent or the DIAG_GET.req otherwise.
*
- * @param[in] aDestination A reference to the destination address.
- * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
- * @param[in] aCount Number of types in aTlvTypes
+ * @param[in] aDestination A reference to the destination address.
+ * @param[in] aTlvTypes An array of Network Diagnostic TLV types.
+ * @param[in] aCount Number of types in aTlvTypes.
+ * @param[in] aCallback A pointer to a function that is called when Network Diagnostic Get response
+ * is received or NULL to disable the callback.
+ * @param[in] aCallbackContext A pointer to application-specific context.
*
*/
- otError SendDiagnosticGet(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount);
+ Error SendDiagnosticGet(const Ip6::Address & aDestination,
+ const uint8_t aTlvTypes[],
+ uint8_t aCount,
+ otReceiveDiagnosticGetCallback aCallback,
+ void * aCallbackContext);
/**
* This method sends Diagnostic Reset request.
@@ -110,7 +107,7 @@
* @param[in] aCount Number of types in aTlvTypes
*
*/
- otError SendDiagnosticReset(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount);
+ Error SendDiagnosticReset(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount);
/**
* This static method gets the next Network Diagnostic TLV in a given message.
@@ -119,20 +116,18 @@
* @param[inout] aIterator The Network Diagnostic iterator. To get the first TLV set it to `kIteratorInit`.
* @param[out] aNetworkDiagTlv A reference to a Network Diagnostic TLV to output the next TLV.
*
- * @retval OT_ERROR_NONE Successfully found the next Network Diagnostic TLV.
- * @retval OT_ERROR_NOT_FOUND No subsequent Network Diagnostic TLV exists in the message.
- * @retval OT_ERROR_PARSE Parsing the next Network Diagnostic failed.
+ * @retval kErrorNone Successfully found the next Network Diagnostic TLV.
+ * @retval kErrorNotFound No subsequent Network Diagnostic TLV exists in the message.
+ * @retval kErrorParse Parsing the next Network Diagnostic failed.
*
*/
- static otError GetNextDiagTlv(const Coap::Message &aMessage,
- Iterator & aIterator,
- otNetworkDiagTlv & aNetworkDiagTlv);
+ static Error GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, otNetworkDiagTlv &aNetworkDiagTlv);
private:
- otError AppendIp6AddressList(Message &aMessage);
- otError AppendChildTable(Message &aMessage);
- void FillMacCountersTlv(MacCountersTlv &aMacCountersTlv);
- otError FillRequestedTlvs(const Message &aRequest, Message &aResponse, NetworkDiagnosticTlv &aNetworkDiagnosticTlv);
+ Error AppendIp6AddressList(Message &aMessage);
+ Error AppendChildTable(Message &aMessage);
+ void FillMacCountersTlv(MacCountersTlv &aMacCountersTlv);
+ Error FillRequestedTlvs(const Message &aRequest, Message &aResponse, NetworkDiagnosticTlv &aNetworkDiagnosticTlv);
static void HandleDiagnosticGetRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleDiagnosticGetRequest(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
@@ -143,8 +138,8 @@
static void HandleDiagnosticGetResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
- otError aResult);
- void HandleDiagnosticGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, otError aResult);
+ Error aResult);
+ void HandleDiagnosticGetResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleDiagnosticGetAnswer(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleDiagnosticGetAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp
index 1bb44c3..cd56d08 100644
--- a/src/core/thread/network_diagnostic_tlvs.hpp
+++ b/src/core/thread/network_diagnostic_tlvs.hpp
@@ -1098,6 +1098,7 @@
* @param[in] aIndex The index into the Child Table list.
*
* @returns A reference to the Child Table entry.
+ *
*/
ChildTableEntry &GetEntry(uint16_t aIndex)
{
@@ -1112,16 +1113,17 @@
* @param[in] aOffset The offset of the ChildTableTLV in aMessage.
* @param[in] aIndex The index into the Child Table list.
*
- * @retval OT_ERROR_NOT_FOUND No such entry is found.
- * @retval OT_ERROR_NONE Successfully read the entry.
+ * @retval kErrorNotFound No such entry is found.
+ * @retval kErrorNone Successfully read the entry.
+ *
*/
- otError ReadEntry(ChildTableEntry &aEntry, const Message &aMessage, uint16_t aOffset, uint8_t aIndex) const
+ Error ReadEntry(ChildTableEntry &aEntry, const Message &aMessage, uint16_t aOffset, uint8_t aIndex) const
{
return ((aIndex < GetNumEntries()) &&
(aMessage.Read(aOffset + sizeof(ChildTableTlv) + (aIndex * sizeof(ChildTableEntry)), aEntry) ==
- OT_ERROR_NONE))
- ? OT_ERROR_NONE
- : OT_ERROR_INVALID_ARGS;
+ kErrorNone))
+ ? kErrorNone
+ : kErrorInvalidArgs;
}
} OT_TOOL_PACKED_END;
diff --git a/src/core/thread/panid_query_server.cpp b/src/core/thread/panid_query_server.cpp
index 8d4b082..77a5e1f 100644
--- a/src/core/thread/panid_query_server.cpp
+++ b/src/core/thread/panid_query_server.cpp
@@ -50,7 +50,7 @@
: InstanceLocator(aInstance)
, mChannelMask(0)
, mPanId(Mac::kPanIdBroadcast)
- , mTimer(aInstance, PanIdQueryServer::HandleTimer, this)
+ , mTimer(aInstance, PanIdQueryServer::HandleTimer)
, mPanIdQuery(UriPath::kPanIdQuery, &PanIdQueryServer::HandleQuery, this)
{
Get<Tmf::TmfAgent>().AddResource(mPanIdQuery);
@@ -110,12 +110,12 @@
void PanIdQueryServer::SendConflict(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
MeshCoP::ChannelMaskTlv channelMask;
Ip6::MessageInfo messageInfo;
Coap::Message * message;
- VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Tmf::TmfAgent>())) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->InitAsConfirmablePost(UriPath::kPanIdConflict));
SuccessOrExit(error = message->SetPayloadMarker());
@@ -140,7 +140,7 @@
void PanIdQueryServer::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<PanIdQueryServer>().HandleTimer();
+ aTimer.Get<PanIdQueryServer>().HandleTimer();
}
void PanIdQueryServer::HandleTimer(void)
diff --git a/src/core/thread/radio_selector.cpp b/src/core/thread/radio_selector.cpp
index f630d89..e7d7c0a 100644
--- a/src/core/thread/radio_selector.cpp
+++ b/src/core/thread/radio_selector.cpp
@@ -127,7 +127,7 @@
}
}
-void RadioSelector::UpdateOnSendDone(Mac::TxFrame &aFrame, otError aTxError)
+void RadioSelector::UpdateOnSendDone(Mac::TxFrame &aFrame, Error aTxError)
{
otLogLevel logLevel = OT_LOG_LEVEL_INFO;
Mac::RadioType radioType = aFrame.GetRadioType();
@@ -140,7 +140,7 @@
// TREL radio link uses deferred ack model. We ignore
// `SendDone` event from `Mac` layer with success status and
// wait for deferred ack callback.
- VerifyOrExit(aTxError != OT_ERROR_NONE);
+ VerifyOrExit(aTxError != kErrorNone);
}
#endif
@@ -152,15 +152,14 @@
if (neighbor->GetSupportedRadioTypes().Contains(radioType))
{
- logLevel =
- UpdatePreference(*neighbor, radioType,
- (aTxError == OT_ERROR_NONE) ? kPreferenceChangeOnTxSuccess : kPreferenceChangeOnTxError);
+ logLevel = UpdatePreference(
+ *neighbor, radioType, (aTxError == kErrorNone) ? kPreferenceChangeOnTxSuccess : kPreferenceChangeOnTxError);
- Log(logLevel, (aTxError == OT_ERROR_NONE) ? "UpdateOnTxSucc" : "UpdateOnTxErr", radioType, *neighbor);
+ Log(logLevel, (aTxError == kErrorNone) ? "UpdateOnTxSucc" : "UpdateOnTxErr", radioType, *neighbor);
}
else
{
- VerifyOrExit(aTxError == OT_ERROR_NONE);
+ VerifyOrExit(aTxError == kErrorNone);
neighbor->AddSupportedRadioType(radioType);
neighbor->SetRadioPreference(radioType, kInitPreference);
@@ -172,7 +171,7 @@
}
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
-void RadioSelector::UpdateOnDeferredAck(Neighbor &aNeighbor, otError aTxError, bool &aAllowNeighborRemove)
+void RadioSelector::UpdateOnDeferredAck(Neighbor &aNeighbor, Error aTxError, bool &aAllowNeighborRemove)
{
otLogLevel logLevel = OT_LOG_LEVEL_INFO;
@@ -181,10 +180,10 @@
if (aNeighbor.GetSupportedRadioTypes().Contains(Mac::kRadioTypeTrel))
{
logLevel = UpdatePreference(aNeighbor, Mac::kRadioTypeTrel,
- (aTxError == OT_ERROR_NONE) ? kPreferenceChangeOnDeferredAckSuccess
- : kPreferenceChangeOnDeferredAckTimeout);
+ (aTxError == kErrorNone) ? kPreferenceChangeOnDeferredAckSuccess
+ : kPreferenceChangeOnDeferredAckTimeout);
- Log(logLevel, (aTxError == OT_ERROR_NONE) ? "UpdateOnDefAckSucc" : "UpdateOnDefAckFail", Mac::kRadioTypeTrel,
+ Log(logLevel, (aTxError == kErrorNone) ? "UpdateOnDefAckSucc" : "UpdateOnDefAckFail", Mac::kRadioTypeTrel,
aNeighbor);
// In case of deferred ack timeout, we check if the neighbor
@@ -192,7 +191,7 @@
// tx. If it it does, we set `aAllowNeighborRemove` to `false`
// to ensure neighbor is not removed yet.
- VerifyOrExit(aTxError != OT_ERROR_NONE);
+ VerifyOrExit(aTxError != kErrorNone);
for (Mac::RadioType radio : sRadioSelectionOrder)
{
@@ -206,7 +205,7 @@
}
else
{
- VerifyOrExit(aTxError == OT_ERROR_NONE);
+ VerifyOrExit(aTxError == kErrorNone);
aNeighbor.AddSupportedRadioType(Mac::kRadioTypeTrel);
aNeighbor.SetRadioPreference(Mac::kRadioTypeTrel, kInitPreference);
diff --git a/src/core/thread/radio_selector.hpp b/src/core/thread/radio_selector.hpp
index 369f15b..30471ab 100644
--- a/src/core/thread/radio_selector.hpp
+++ b/src/core/thread/radio_selector.hpp
@@ -140,7 +140,7 @@
* @param[in] aTxError The transmission error.
*
*/
- void UpdateOnSendDone(Mac::TxFrame &aFrame, otError aTxError);
+ void UpdateOnSendDone(Mac::TxFrame &aFrame, Error aTxError);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
@@ -149,11 +149,11 @@
* The deferred ack model is used by TREL radio link.
*
* @param[in] aNeighbor The neighbor from which ack was expected
- * @param[in] aError The deferred ack status (`OT_ERROR_NONE` indicates ack was received).
+ * @param[in] aError The deferred ack status (`kErrorNone` indicates ack was received).
* @param[out] aAllowNeighborRemove Boolean variable to output whether the neighbor is allowed to be removed.
*
*/
- void UpdateOnDeferredAck(Neighbor &aNeighbor, otError aTxError, bool &aAllowNeighborRemove);
+ void UpdateOnDeferredAck(Neighbor &aNeighbor, Error aTxError, bool &aAllowNeighborRemove);
#endif
/**
diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp
index ea2efec..e727189 100644
--- a/src/core/thread/router_table.cpp
+++ b/src/core/thread/router_table.cpp
@@ -44,13 +44,13 @@
RouterTable::Iterator::Iterator(Instance &aInstance)
: InstanceLocator(aInstance)
- , mRouter(Get<RouterTable>().GetFirstEntry())
+ , ItemPtrIterator(Get<RouterTable>().GetFirstEntry())
{
}
void RouterTable::Iterator::Advance(void)
{
- mRouter = Get<RouterTable>().GetNextEntry(mRouter);
+ mItem = Get<RouterTable>().GetNextEntry(mItem);
}
RouterTable::RouterTable(Instance &aInstance)
@@ -261,15 +261,15 @@
return rval;
}
-otError RouterTable::Release(uint8_t aRouterId)
+Error RouterTable::Release(uint8_t aRouterId)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint16_t rloc16 = Mle::Mle::Rloc16FromRouterId(aRouterId);
OT_ASSERT(aRouterId <= Mle::kMaxRouterId);
- VerifyOrExit(Get<Mle::MleRouter>().IsLeader(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(IsAllocated(aRouterId), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(Get<Mle::MleRouter>().IsLeader(), error = kErrorInvalidState);
+ VerifyOrExit(IsAllocated(aRouterId), error = kErrorNotFound);
mAllocatedRouterIds.Remove(aRouterId);
UpdateAllocation();
@@ -397,9 +397,9 @@
return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateAny));
}
-otError RouterTable::GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo)
+Error RouterTable::GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Router *router;
uint8_t routerId;
@@ -409,13 +409,13 @@
}
else
{
- VerifyOrExit(Mle::Mle::IsActiveRouter(aRouterId), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(Mle::Mle::IsActiveRouter(aRouterId), error = kErrorInvalidArgs);
routerId = Mle::Mle::RouterIdFromRloc16(aRouterId);
- VerifyOrExit(routerId <= Mle::kMaxRouterId, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(routerId <= Mle::kMaxRouterId, error = kErrorInvalidArgs);
}
router = GetRouter(routerId);
- VerifyOrExit(router != nullptr, error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(router != nullptr, error = kErrorNotFound);
aRouterInfo.SetFrom(*router);
diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp
index c798a4f..4942063 100644
--- a/src/core/thread/router_table.hpp
+++ b/src/core/thread/router_table.hpp
@@ -34,6 +34,7 @@
#if OPENTHREAD_FTD
#include "common/encoding.hpp"
+#include "common/iterator_utils.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "mac/mac_types.hpp"
@@ -53,8 +54,9 @@
* This class represents an iterator for iterating through entries in the router table.
*
*/
- class Iterator : public InstanceLocator
+ class Iterator : public InstanceLocator, public ItemPtrIterator<Router, Iterator>
{
+ friend class ItemPtrIterator<Router, Iterator>;
friend class IteratorBuilder;
public:
@@ -66,78 +68,6 @@
*/
explicit Iterator(Instance &aInstance);
- /**
- * This method indicates if the iterator has reached the end of the list, i.e., iterator is empty.
- *
- * @retval TRUE The iterator has reached the end of the list.
- * @retval FALSE The iterator currently points to a valid entry.
- *
- */
- bool IsDone(void) const { return (mRouter == nullptr); }
-
- /**
- * This method overloads `++` operator (pre-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next entry. If there are no more entries matching the iterator
- * becomes empty (i.e., `IsDone()` returns `true`).
- *
- */
- void operator++(void) { Advance(); }
-
- /**
- * This method overloads `++` operator (post-increment) to advance the iterator.
- *
- * The iterator is moved to point to the next entry. If there are no more entries matching the iterator
- * becomes empty (i.e., `IsDone()` returns `true`).
- *
- */
- void operator++(int) { Advance(); }
-
- /**
- * This method overloads the `*` dereference operator and gets a reference to `Router` entry to which the
- * iterator is currently pointing.
- *
- * This method MUST be used when the iterator is not empty/finished (i.e., `IsDone()` returns `false`).
- *
- * @returns A reference to the `Router` entry currently pointed by the iterator.
- *
- */
- Router &operator*(void) { return *mRouter; }
-
- /**
- * This method overloads the `->` dereference operator and gets a pointer to `Router` entry to which the
- * iterator is currently pointing.
- *
- * @returns A pointer to the `Router` entry associated with the iterator, or `nullptr` if iterator is
- * empty/done.
- *
- */
- Router *operator->(void) { return mRouter; }
-
- /**
- * This method overloads operator `==` to evaluate whether or not two `Iterator` instances point to the same
- * router entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `Iterator` objects point to the same router entry or both are done.
- * @retval FALSE If the two `Iterator` objects do not point to the same router entry.
- *
- */
- bool operator==(const Iterator &aOther) { return mRouter == aOther.mRouter; }
-
- /**
- * This method overloads operator `!=` to evaluate whether or not two `Iterator` instances point to the same
- * router entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `Iterator` objects do not point to the same router entry.
- * @retval FALSE If the two `Iterator` objects point to the same router entry or both are done.
- *
- */
- bool operator!=(const Iterator &aOther) { return mRouter != aOther.mRouter; }
-
private:
enum IteratorType
{
@@ -146,13 +76,10 @@
Iterator(Instance &aInstance, IteratorType)
: InstanceLocator(aInstance)
- , mRouter(nullptr)
{
}
void Advance(void);
-
- Router *mRouter;
};
/**
@@ -196,12 +123,12 @@
*
* @param[in] aRouterId The router id.
*
- * @retval OT_ERROR_NONE Successfully released the router id.
- * @retval OT_ERROR_INVALID_STATE The device is not currently operating as a leader.
- * @retval OT_ERROR_NOT_FOUND The router id is not currently allocated.
+ * @retval kErrorNone Successfully released the router id.
+ * @retval kErrorInvalidState The device is not currently operating as a leader.
+ * @retval kErrorNotFound The router id is not currently allocated.
*
*/
- otError Release(uint8_t aRouterId);
+ Error Release(uint8_t aRouterId);
/**
* This method removes a router link.
@@ -338,12 +265,12 @@
* @param[in] aRouterId The router ID or RLOC16 for a given router.
* @param[out] aRouterInfo The router information.
*
- * @retval OT_ERROR_NONE Successfully retrieved the router info for given id.
- * @retval OT_ERROR_INVALID_ARGS @p aRouterId is not a valid value for a router.
- * @retval OT_ERROR_NOT_FOUND No router entry with the given id.
+ * @retval kErrorNone Successfully retrieved the router info for given id.
+ * @retval kErrorInvalidArgs @p aRouterId is not a valid value for a router.
+ * @retval kErrorNotFound No router entry with the given id.
*
*/
- otError GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo);
+ Error GetRouterInfo(uint16_t aRouterId, Router::Info &aRouterInfo);
/**
* This method returns the Router ID Sequence.
diff --git a/src/core/thread/src_match_controller.cpp b/src/core/thread/src_match_controller.cpp
index aeb501e..d16df33 100644
--- a/src/core/thread/src_match_controller.cpp
+++ b/src/core/thread/src_match_controller.cpp
@@ -134,7 +134,7 @@
}
else
{
- VerifyOrExit(AddAddress(aChild) == OT_ERROR_NONE, Enable(false));
+ VerifyOrExit(AddAddress(aChild) == kErrorNone, Enable(false));
aChild.SetIndirectSourceMatchPending(false);
}
@@ -142,16 +142,16 @@
return;
}
-otError SourceMatchController::AddAddress(const Child &aChild)
+Error SourceMatchController::AddAddress(const Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aChild.IsIndirectSourceMatchShort())
{
error = Get<Radio>().AddSrcMatchShortEntry(aChild.GetRloc16());
- otLogDebgMac("SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(),
- otThreadErrorToString(error), error);
+ otLogDebgMac("SrcAddrMatch - Adding short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
+ error);
}
else
{
@@ -161,7 +161,7 @@
error = Get<Radio>().AddSrcMatchExtEntry(address);
otLogDebgMac("SrcAddrMatch - Adding addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
- otThreadErrorToString(error), error);
+ ErrorToString(error), error);
}
return error;
@@ -169,7 +169,7 @@
void SourceMatchController::ClearEntry(Child &aChild)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (aChild.IsIndirectSourceMatchPending())
{
@@ -182,8 +182,8 @@
{
error = Get<Radio>().ClearSrcMatchShortEntry(aChild.GetRloc16());
- otLogDebgMac("SrcAddrMatch - Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(),
- otThreadErrorToString(error), error);
+ otLogDebgMac("SrcAddrMatch - Clearing short addr: 0x%04x -- %s (%d)", aChild.GetRloc16(), ErrorToString(error),
+ error);
}
else
{
@@ -193,7 +193,7 @@
error = Get<Radio>().ClearSrcMatchExtEntry(address);
otLogDebgMac("SrcAddrMatch - Clearing addr: %s -- %s (%d)", aChild.GetExtAddress().ToString().AsCString(),
- otThreadErrorToString(error), error);
+ ErrorToString(error), error);
}
SuccessOrExit(error);
@@ -208,9 +208,9 @@
return;
}
-otError SourceMatchController::AddPendingEntries(void)
+Error SourceMatchController::AddPendingEntries(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
diff --git a/src/core/thread/src_match_controller.hpp b/src/core/thread/src_match_controller.hpp
index 83abe9d..f41d1e8 100644
--- a/src/core/thread/src_match_controller.hpp
+++ b/src/core/thread/src_match_controller.hpp
@@ -36,7 +36,7 @@
#include "openthread-core-config.h"
-#include <openthread/error.h>
+#include "common/error.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
@@ -169,20 +169,20 @@
*
* @param[in] aChild A reference to the child
*
- * @retval OT_ERROR_NONE Child's address was added successfully to the source match table.
- * @retval OT_ERROR_NO_BUFS No available space in the source match table.
+ * @retval kErrorNone Child's address was added successfully to the source match table.
+ * @retval kErrorNoBufs No available space in the source match table.
*
*/
- otError AddAddress(const Child &aChild);
+ Error AddAddress(const Child &aChild);
/**
* This method adds all pending entries to the source match table.
*
- * @retval OT_ERROR_NONE All pending entries were successfully added.
- * @retval OT_ERROR_NO_BUFS No available space in the source match table.
+ * @retval kErrorNone All pending entries were successfully added.
+ * @retval kErrorNoBufs No available space in the source match table.
*
*/
- otError AddPendingEntries(void);
+ Error AddPendingEntries(void);
bool mEnabled;
};
diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp
index faf611b..3824c1d 100644
--- a/src/core/thread/thread_netif.cpp
+++ b/src/core/thread/thread_netif.cpp
@@ -62,6 +62,12 @@
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
, mDnsClient(aInstance)
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ , mSrpClient(aInstance)
+#endif
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+ , mDnssdServer(aInstance)
+#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
, mSntpClient(aInstance)
#endif
@@ -83,6 +89,7 @@
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
, mNetworkDataNotifier(aInstance)
#endif
+ , mNetworkDataServiceManager(aInstance)
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
, mNetworkDiagnostic(aInstance)
#endif
@@ -121,6 +128,10 @@
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
, mDuaManager(aInstance)
#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ , mSrpServer(aInstance)
+#endif
+
, mChildSupervisor(aInstance)
, mSupervisionListener(aInstance)
, mAnnounceBegin(aInstance)
@@ -151,6 +162,9 @@
SubscribeAllNodesMulticast();
IgnoreError(Get<Mle::MleRouter>().Enable());
IgnoreError(Get<Tmf::TmfAgent>().Start());
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+ IgnoreError(Get<Dns::ServiceDiscovery::Server>().Start());
+#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
IgnoreError(Get<Dns::Client>().Start());
#endif
@@ -168,11 +182,14 @@
VerifyOrExit(mIsUp);
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
- IgnoreError(Get<Dns::Client>().Stop());
+ Get<Dns::Client>().Stop();
#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
IgnoreError(Get<Sntp::Client>().Stop());
#endif
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+ Get<Dns::ServiceDiscovery::Server>().Stop();
+#endif
#if OPENTHREAD_CONFIG_DTLS_ENABLE
Get<Coap::CoapSecure>().Stop();
#endif
@@ -194,16 +211,16 @@
return;
}
-otError ThreadNetif::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint8_t *aPrefixMatch)
+Error ThreadNetif::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint8_t *aPrefixMatch)
{
- otError error;
+ Error error;
uint16_t rloc;
SuccessOrExit(error = Get<NetworkData::Leader>().RouteLookup(aSource, aDestination, aPrefixMatch, &rloc));
if (rloc == Get<Mle::MleRouter>().GetRloc16())
{
- error = OT_ERROR_NO_ROUTE;
+ error = kErrorNoRoute;
}
exit:
diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp
index 7a61830..3fd86cf 100644
--- a/src/core/thread/thread_netif.hpp
+++ b/src/core/thread/thread_netif.hpp
@@ -64,6 +64,10 @@
#include "thread/dua_manager.hpp"
#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+#include "net/srp_server.hpp"
+#endif
+
#include "meshcop/dataset_manager.hpp"
#if OPENTHREAD_CONFIG_JOINER_ENABLE
@@ -76,9 +80,11 @@
#include "net/dhcp6_client.hpp"
#include "net/dhcp6_server.hpp"
#include "net/dns_client.hpp"
+#include "net/dnssd_server.hpp"
#include "net/ip6_filter.hpp"
#include "net/netif.hpp"
#include "net/sntp_client.hpp"
+#include "net/srp_client.hpp"
#include "thread/address_resolver.hpp"
#include "thread/announce_begin_server.hpp"
#include "thread/discover_scanner.hpp"
@@ -90,6 +96,7 @@
#include "thread/mle_router.hpp"
#include "thread/network_data_local.hpp"
#include "thread/network_data_notifier.hpp"
+#include "thread/network_data_service.hpp"
#include "thread/network_diagnostic.hpp"
#include "thread/panid_query_server.hpp"
#include "thread/radio_selector.hpp"
@@ -154,10 +161,10 @@
*
* @param[in] aMessage A reference to the message.
*
- * @retval OT_ERROR_NONE Successfully submitted the message to the interface.
+ * @retval kErrorNone Successfully submitted the message to the interface.
*
*/
- otError SendMessage(Message &aMessage) { return mMeshForwarder.SendMessage(aMessage); }
+ Error SendMessage(Message &aMessage) { return mMeshForwarder.SendMessage(aMessage); }
/**
* This method performs a route lookup.
@@ -166,11 +173,11 @@
* @param[in] aDestination A reference to the IPv6 destination address.
* @param[out] aPrefixMatch A pointer where the number of prefix match bits for the chosen route is stored.
*
- * @retval OT_ERROR_NONE Successfully found a route.
- * @retval OT_ERROR_NO_ROUTE Could not find a valid route.
+ * @retval kErrorNone Successfully found a route.
+ * @retval kErrorNoRoute Could not find a valid route.
*
*/
- otError RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint8_t *aPrefixMatch);
+ Error RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint8_t *aPrefixMatch);
/**
* This method indicates whether @p aAddress matches an on-mesh prefix.
@@ -196,10 +203,16 @@
#endif
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
Dns::Client mDnsClient;
-#endif // OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
+#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ Srp::Client mSrpClient;
+#endif
+#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
+ Dns::ServiceDiscovery::Server mDnssdServer;
+#endif
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
Sntp::Client mSntpClient;
-#endif // OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
+#endif
MeshCoP::ActiveDataset mActiveDataset;
MeshCoP::PendingDataset mPendingDataset;
Ip6::Filter mIp6Filter;
@@ -219,6 +232,7 @@
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
NetworkData::Notifier mNetworkDataNotifier;
#endif
+ NetworkData::Service::Manager mNetworkDataServiceManager;
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
NetworkDiagnostic::NetworkDiagnostic mNetworkDiagnostic;
#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE
@@ -262,6 +276,10 @@
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
DuaManager mDuaManager;
#endif
+#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ Srp::Server mSrpServer;
+#endif
+
Utils::ChildSupervisor mChildSupervisor;
Utils::SupervisionListener mSupervisionListener;
AnnounceBeginServer mAnnounceBegin;
diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp
index fd112a0..f4c349b 100644
--- a/src/core/thread/thread_tlvs.hpp
+++ b/src/core/thread/thread_tlvs.hpp
@@ -51,8 +51,8 @@
enum
{
// Thread 1.2.0 5.19.13 limits the number of IPv6 addresses should be [1, 15].
- kIPv6AddressesNumMin = 1,
- kIPv6AddressesNumMax = 15,
+ kIp6AddressesNumMin = 1,
+ kIp6AddressesNumMax = 15,
};
/**
@@ -76,12 +76,12 @@
kStatus = 4, ///< Status TLV
kLastTransactionTime = 6, ///< Time Since Last Transaction TLV
kRouterMask = 7, ///< Router Mask TLV
- kNDOption = 8, ///< ND Option TLV
- kNDData = 9, ///< ND Data TLV
+ kNdOption = 8, ///< ND Option TLV
+ kNdData = 9, ///< ND Data TLV
kThreadNetworkData = 10, ///< Thread Network Data TLV
kTimeout = 11, ///< Timeout TLV
kNetworkName = 12, ///< Network Name TLV
- kIPv6Addresses = 14, ///< IPv6 Addresses TLV
+ kIp6Addresses = 14, ///< IPv6 Addresses TLV
kCommissionerSessionId = 15, ///< Commissioner Session ID TLV
};
@@ -316,14 +316,14 @@
*
*/
OT_TOOL_PACKED_BEGIN
-class IPv6AddressesTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kIPv6Addresses>
+class Ip6AddressesTlv : public ThreadTlv, public TlvInfo<ThreadTlv::kIp6Addresses>
{
public:
/**
* This method initializes the TLV.
*
*/
- void Init(void) { SetType(kIPv6Addresses); }
+ void Init(void) { SetType(kIp6Addresses); }
/**
* This method indicates whether or not the TLV appears to be well-formed.
@@ -334,8 +334,8 @@
*/
bool IsValid(void) const
{
- return GetLength() >= sizeof(Ip6::Address) * kIPv6AddressesNumMin &&
- GetLength() <= sizeof(Ip6::Address) * kIPv6AddressesNumMax && (GetLength() % sizeof(Ip6::Address)) == 0;
+ return GetLength() >= sizeof(Ip6::Address) * kIp6AddressesNumMin &&
+ GetLength() <= sizeof(Ip6::Address) * kIp6AddressesNumMax && (GetLength() % sizeof(Ip6::Address)) == 0;
}
/**
diff --git a/src/core/thread/time_sync_service.cpp b/src/core/thread/time_sync_service.cpp
index eeee380..31abebb 100644
--- a/src/core/thread/time_sync_service.cpp
+++ b/src/core/thread/time_sync_service.cpp
@@ -62,7 +62,7 @@
, mNetworkTimeOffset(0)
, mTimeSyncCallback(nullptr)
, mTimeSyncCallbackContext(nullptr)
- , mTimer(aInstance, HandleTimeout, this)
+ , mTimer(aInstance, HandleTimeout)
, mCurrentStatus(OT_NETWORK_TIME_UNSYNCHRONIZED)
{
CheckAndHandleChanges(false);
@@ -161,7 +161,7 @@
if (mTimeSyncRequired)
{
- VerifyOrExit(Get<Mle::MleRouter>().SendTimeSync() == OT_ERROR_NONE);
+ VerifyOrExit(Get<Mle::MleRouter>().SendTimeSync() == kErrorNone);
mLastTimeSyncSent = TimerMilli::GetNow();
mTimeSyncRequired = false;
@@ -210,7 +210,7 @@
void TimeSync::HandleTimeout(Timer &aTimer)
{
- aTimer.GetOwner<TimeSync>().HandleTimeout();
+ aTimer.Get<TimeSync>().HandleTimeout();
}
void TimeSync::CheckAndHandleChanges(bool aTimeUpdated)
diff --git a/src/core/thread/tmf.cpp b/src/core/thread/tmf.cpp
index 0d6977f..6ae4c68 100644
--- a/src/core/thread/tmf.cpp
+++ b/src/core/thread/tmf.cpp
@@ -38,16 +38,16 @@
namespace ot {
namespace Tmf {
-otError TmfAgent::Start(void)
+Error TmfAgent::Start(void)
{
return Coap::Start(kUdpPort, OT_NETIF_THREAD);
}
-otError TmfAgent::Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
+Error TmfAgent::Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext)
{
OT_UNUSED_VARIABLE(aMessage);
- return static_cast<TmfAgent *>(aContext)->IsTmfMessage(aMessageInfo) ? OT_ERROR_NONE : OT_ERROR_NOT_TMF;
+ return static_cast<TmfAgent *>(aContext)->IsTmfMessage(aMessageInfo) ? kErrorNone : kErrorNotTmf;
}
bool TmfAgent::IsTmfMessage(const Ip6::MessageInfo &aMessageInfo) const
diff --git a/src/core/thread/tmf.hpp b/src/core/thread/tmf.hpp
index c3a0787..6de0173 100644
--- a/src/core/thread/tmf.hpp
+++ b/src/core/thread/tmf.hpp
@@ -66,11 +66,11 @@
/**
* This method starts the TMF agent.
*
- * @retval OT_ERROR_NONE Successfully started the CoAP service.
- * @retval OT_ERROR_FAILED Failed to start the TMF agent.
+ * @retval kErrorNone Successfully started the CoAP service.
+ * @retval kErrorFailed Failed to start the TMF agent.
*
*/
- otError Start(void);
+ Error Start(void);
/**
* This method returns whether Thread Management Framework Addressing Rules are met.
@@ -82,7 +82,7 @@
bool IsTmfMessage(const Ip6::MessageInfo &aMessageInfo) const;
private:
- static otError Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
+ static Error Filter(const ot::Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
};
} // namespace Tmf
diff --git a/src/core/thread/topology.cpp b/src/core/thread/topology.cpp
index 3c94c34..f169ee4 100644
--- a/src/core/thread/topology.cpp
+++ b/src/core/thread/topology.cpp
@@ -234,7 +234,7 @@
mFullThreadDevice = aChild.IsFullThreadDevice();
mFullNetworkData = aChild.IsFullNetworkData();
mIsStateRestoring = aChild.IsStateRestoring();
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mIsCslSynced = aChild.IsCslSynchronized();
#else
mIsCslSynced = false;
@@ -255,13 +255,13 @@
{
const Ip6::Address *address;
+ if ((mIndex == 0) && (mChild.GetMeshLocalIp6Address(mMeshLocalAddress) != kErrorNone))
+ {
+ mIndex++;
+ }
+
while (true)
{
- if ((mIndex == 0) && (mChild.GetMeshLocalIp6Address(mMeshLocalAddress) != OT_ERROR_NONE))
- {
- mIndex++;
- }
-
address = GetAddress();
VerifyOrExit((address != nullptr) && !address->IsUnspecified(), mIndex = kMaxIndex);
@@ -292,11 +292,11 @@
#endif
}
-otError Child::GetMeshLocalIp6Address(Ip6::Address &aAddress) const
+Error Child::GetMeshLocalIp6Address(Ip6::Address &aAddress) const
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!mMeshLocalIid.IsUnspecified(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!mMeshLocalIid.IsUnspecified(), error = kErrorNotFound);
aAddress.SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
aAddress.SetIid(mMeshLocalIid);
@@ -305,15 +305,15 @@
return error;
}
-otError Child::AddIp6Address(const Ip6::Address &aAddress)
+Error Child::AddIp6Address(const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!aAddress.IsUnspecified(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs);
if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
{
- VerifyOrExit(mMeshLocalIid.IsUnspecified(), error = OT_ERROR_ALREADY);
+ VerifyOrExit(mMeshLocalIid.IsUnspecified(), error = kErrorAlready);
mMeshLocalIid = aAddress.GetIid();
ExitNow();
}
@@ -326,28 +326,28 @@
ExitNow();
}
- VerifyOrExit(ip6Address != aAddress, error = OT_ERROR_ALREADY);
+ VerifyOrExit(ip6Address != aAddress, error = kErrorAlready);
}
- error = OT_ERROR_NO_BUFS;
+ error = kErrorNoBufs;
exit:
return error;
}
-otError Child::RemoveIp6Address(const Ip6::Address &aAddress)
+Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
uint16_t index;
- VerifyOrExit(!aAddress.IsUnspecified(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs);
if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
{
if (aAddress.GetIid() == mMeshLocalIid)
{
mMeshLocalIid.Clear();
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
ExitNow();
@@ -359,7 +359,7 @@
if (mIp6Address[index] == aAddress)
{
- error = OT_ERROR_NONE;
+ error = kErrorNone;
break;
}
}
diff --git a/src/core/thread/topology.hpp b/src/core/thread/topology.hpp
index dd066e5..657df3a 100644
--- a/src/core/thread/topology.hpp
+++ b/src/core/thread/topology.hpp
@@ -39,6 +39,7 @@
#include <openthread/thread_ftd.h>
#include "common/clearable.hpp"
+#include "common/equatable.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
@@ -821,7 +822,7 @@
class Child : public Neighbor,
public IndirectSender::ChildInfo,
public DataPollHandler::ChildInfo
-#if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
,
public CslTxScheduler::ChildInfo
#endif
@@ -854,7 +855,7 @@
* This class defines an iterator used to go through IPv6 address entries of a child.
*
*/
- class AddressIterator
+ class AddressIterator : public Unequatable<AddressIterator>
{
friend class AddressIteratorBuilder;
@@ -969,19 +970,6 @@
*/
bool operator==(const AddressIterator &aOther) const { return (mIndex == aOther.mIndex); }
- /**
- * This method overloads operator `!=` to evaluate whether or not two `Iterator` instances are unequal.
- *
- * This method MUST be used when the two iterators are associated with the same `Child` entry.
- *
- * @param[in] aOther The other `Iterator` to compare with.
- *
- * @retval TRUE If the two `Iterator` objects are unequal.
- * @retval FALSE If the two `Iterator` objects are not unequal.
- *
- */
- bool operator!=(const AddressIterator &aOther) const { return !(*this == aOther); }
-
private:
enum IteratorType : uint8_t
{
@@ -1032,11 +1020,11 @@
*
* @param[out] aAddress A reference to an IPv6 address to provide address (if any).
*
- * @retval OT_ERROR_NONE Successfully found the mesh-local address and updated @p aAddress.
- * @retval OT_ERROR_NOT_FOUND No mesh-local IPv6 address in the IPv6 address list.
+ * @retval kErrorNone Successfully found the mesh-local address and updated @p aAddress.
+ * @retval kErrorNotFound No mesh-local IPv6 address in the IPv6 address list.
*
*/
- otError GetMeshLocalIp6Address(Ip6::Address &aAddress) const;
+ Error GetMeshLocalIp6Address(Ip6::Address &aAddress) const;
/**
* This method returns the Mesh Local Interface Identifier.
@@ -1073,25 +1061,25 @@
*
* @param[in] aAddress A reference to IPv6 address to be added.
*
- * @retval OT_ERROR_NONE Successfully added the new address.
- * @retval OT_ERROR_ALREADY Address is already in the list.
- * @retval OT_ERROR_NO_BUFS Already at maximum number of addresses. No entry available to add the new address.
- * @retval OT_ERROR_INVALID_ARGS Address is invalid (it is the Unspecified Address).
+ * @retval kErrorNone Successfully added the new address.
+ * @retval kErrorAlready Address is already in the list.
+ * @retval kErrorNoBufs Already at maximum number of addresses. No entry available to add the new address.
+ * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address).
*
*/
- otError AddIp6Address(const Ip6::Address &aAddress);
+ Error AddIp6Address(const Ip6::Address &aAddress);
/**
* This method removes an IPv6 address from the list.
*
* @param[in] aAddress A reference to IPv6 address to be removed.
*
- * @retval OT_ERROR_NONE Successfully removed the address.
- * @retval OT_ERROR_NOT_FOUND Address was not found in the list.
- * @retval OT_ERROR_INVALID_ARGS Address is invalid (it is the Unspecified Address).
+ * @retval kErrorNone Successfully removed the address.
+ * @retval kErrorNotFound Address was not found in the list.
+ * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address).
*
*/
- otError RemoveIp6Address(const Ip6::Address &aAddress);
+ Error RemoveIp6Address(const Ip6::Address &aAddress);
/**
* This method indicates whether an IPv6 address is in the list of IPv6 addresses of the child.
diff --git a/src/core/utils/channel_manager.cpp b/src/core/utils/channel_manager.cpp
index 8886682..70b05cb 100644
--- a/src/core/utils/channel_manager.cpp
+++ b/src/core/utils/channel_manager.cpp
@@ -39,8 +39,8 @@
#include "common/locator-getters.hpp"
#include "common/logging.hpp"
#include "common/random.hpp"
+#include "meshcop/dataset_updater.hpp"
#include "radio/radio.hpp"
-#include "utils/dataset_updater.hpp"
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
@@ -54,7 +54,7 @@
, mDelay(kMinimumDelay)
, mChannel(0)
, mState(kStateIdle)
- , mTimer(aInstance, ChannelManager::HandleTimer, this)
+ , mTimer(aInstance, ChannelManager::HandleTimer)
, mAutoSelectInterval(kDefaultAutoSelectInterval)
, mAutoSelectEnabled(false)
{
@@ -73,7 +73,6 @@
if (mState == kStateChangeInProgress)
{
VerifyOrExit(mChannel != aChannel);
- Get<DatasetUpdater>().CancelUpdate();
}
mState = kStateChangeRequested;
@@ -87,11 +86,11 @@
return;
}
-otError ChannelManager::SetDelay(uint16_t aDelay)
+Error ChannelManager::SetDelay(uint16_t aDelay)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aDelay >= kMinimumDelay, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aDelay >= kMinimumDelay, error = kErrorInvalidArgs);
mDelay = aDelay;
exit:
@@ -106,22 +105,22 @@
dataset.SetChannel(mChannel);
dataset.SetDelay(Time::SecToMsec(mDelay));
- switch (Get<DatasetUpdater>().RequestUpdate(dataset, HandleDatasetUpdateDone, this, kChangeCheckWaitInterval))
+ switch (Get<MeshCoP::DatasetUpdater>().RequestUpdate(dataset, HandleDatasetUpdateDone, this))
{
- case OT_ERROR_NONE:
+ case kErrorNone:
mState = kStateChangeInProgress;
// Wait for the `HandleDatasetUpdateDone()` callback.
break;
- case OT_ERROR_BUSY:
- case OT_ERROR_NO_BUFS:
+ case kErrorBusy:
+ case kErrorNoBufs:
mTimer.Start(kPendingDatasetTxRetryInterval);
break;
- case OT_ERROR_INVALID_STATE:
+ case kErrorInvalidState:
otLogInfoUtil("ChannelManager: Request to change to channel %d failed. Device is disabled", mChannel);
- // Fall through
+ OT_FALL_THROUGH;
default:
mState = kStateIdle;
@@ -130,21 +129,21 @@
}
}
-void ChannelManager::HandleDatasetUpdateDone(otError aError, void *aContext)
+void ChannelManager::HandleDatasetUpdateDone(Error aError, void *aContext)
{
static_cast<ChannelManager *>(aContext)->HandleDatasetUpdateDone(aError);
}
-void ChannelManager::HandleDatasetUpdateDone(otError aError)
+void ChannelManager::HandleDatasetUpdateDone(Error aError)
{
- if (aError == OT_ERROR_NONE)
+ if (aError == kErrorNone)
{
otLogInfoUtil("ChannelManager: Channel changed to %d", mChannel);
}
else
{
otLogInfoUtil("ChannelManager: Canceling channel change to %d%s", mChannel,
- (aError == OT_ERROR_ALREADY) ? " since current ActiveDataset is more recent" : "");
+ (aError == kErrorAlready) ? " since current ActiveDataset is more recent" : "");
}
mState = kStateIdle;
@@ -153,7 +152,7 @@
void ChannelManager::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<ChannelManager>().HandleTimer();
+ aTimer.Get<ChannelManager>().HandleTimer();
}
void ChannelManager::HandleTimer(void)
@@ -177,9 +176,9 @@
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
-otError ChannelManager::FindBetterChannel(uint8_t &aNewChannel, uint16_t &aOccupancy)
+Error ChannelManager::FindBetterChannel(uint8_t &aNewChannel, uint16_t &aOccupancy)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
Mac::ChannelMask favoredAndSupported;
Mac::ChannelMask favoredBest;
Mac::ChannelMask supportedBest;
@@ -190,7 +189,7 @@
{
otLogInfoUtil("ChannelManager: Too few samples (%d <= %d) to select channel",
Get<ChannelMonitor>().GetSampleCount(), kMinChannelMonitorSampleCount);
- ExitNow(error = OT_ERROR_INVALID_STATE);
+ ExitNow(error = kErrorInvalidState);
}
favoredAndSupported = mFavoredChannelMask;
@@ -220,7 +219,7 @@
favoredOccupancy = supportedOccupancy;
}
- VerifyOrExit(!favoredBest.IsEmpty(), error = OT_ERROR_NOT_FOUND);
+ VerifyOrExit(!favoredBest.IsEmpty(), error = kErrorNotFound);
aNewChannel = favoredBest.ChooseRandomChannel();
aOccupancy = favoredOccupancy;
@@ -240,16 +239,16 @@
return shouldAttempt;
}
-otError ChannelManager::RequestChannelSelect(bool aSkipQualityCheck)
+Error ChannelManager::RequestChannelSelect(bool aSkipQualityCheck)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t curChannel, newChannel;
uint16_t curOccupancy, newOccupancy;
otLogInfoUtil("ChannelManager: Request to select channel (skip quality check: %s)",
aSkipQualityCheck ? "yes" : "no");
- VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = kErrorInvalidState);
VerifyOrExit(aSkipQualityCheck || ShouldAttemptChannelChange());
@@ -281,10 +280,9 @@
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogInfoUtil("ChannelManager: Request to select better channel failed, error: %s",
- otThreadErrorToString(error));
+ otLogInfoUtil("ChannelManager: Request to select better channel failed, error: %s", ErrorToString(error));
}
return error;
@@ -318,12 +316,12 @@
}
}
-otError ChannelManager::SetAutoChannelSelectionInterval(uint32_t aInterval)
+Error ChannelManager::SetAutoChannelSelectionInterval(uint32_t aInterval)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint32_t prevInterval = mAutoSelectInterval;
- VerifyOrExit((aInterval != 0) && (aInterval <= Time::MsecToSec(Timer::kMaxDelay)), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((aInterval != 0) && (aInterval <= Time::MsecToSec(Timer::kMaxDelay)), error = kErrorInvalidArgs);
mAutoSelectInterval = aInterval;
diff --git a/src/core/utils/channel_manager.hpp b/src/core/utils/channel_manager.hpp
index a74b0eb..8027647 100644
--- a/src/core/utils/channel_manager.hpp
+++ b/src/core/utils/channel_manager.hpp
@@ -120,11 +120,11 @@
*
* @param[in] aDelay Delay in seconds.
*
- * @retval OT_ERROR_NONE Delay was updated successfully.
- * @retval OT_ERROR_INVALID_ARGS The given delay @p aDelay is shorter than `kMinimumDelay`.
+ * @retval kErrorNone Delay was updated successfully.
+ * @retval kErrorInvalidArgs The given delay @p aDelay is shorter than `kMinimumDelay`.
*
*/
- otError SetDelay(uint16_t aDelay);
+ Error SetDelay(uint16_t aDelay);
/**
* This method requests that `ChannelManager` checks and selects a new channel and starts a channel change.
@@ -150,12 +150,12 @@
*
* @param[in] aSkipQualityCheck Indicates whether the quality check (step 1) should be skipped.
*
- * @retval OT_ERROR_NONE Channel selection finished successfully.
- * @retval OT_ERROR_NOT_FOUND Supported channels is empty, therefore could not select a channel.
- * @retval OT_ERROR_INVALID_STATE Thread is not enabled or not enough data to select new channel.
+ * @retval kErrorNone Channel selection finished successfully.
+ * @retval kErrorNotFound Supported channels is empty, therefore could not select a channel.
+ * @retval kErrorInvalidState Thread is not enabled or not enough data to select new channel.
*
*/
- otError RequestChannelSelect(bool aSkipQualityCheck);
+ Error RequestChannelSelect(bool aSkipQualityCheck);
/**
* This method enables/disables the auto-channel-selection functionality.
@@ -181,11 +181,11 @@
*
* @param[in] aInterval The interval (in seconds).
*
- * @retval OT_ERROR_NONE The interval was set successfully.
- * @retval OT_ERROR_INVALID_ARGS The @p aInterval is not valid (zero).
+ * @retval kErrorNone The interval was set successfully.
+ * @retval kErrorInvalidArgs The @p aInterval is not valid (zero).
*
*/
- otError SetAutoChannelSelectionInterval(uint32_t aInterval);
+ Error SetAutoChannelSelectionInterval(uint32_t aInterval);
/**
* This method gets the period interval (in seconds) used by auto-channel-selection functionality.
@@ -233,9 +233,6 @@
// Retry interval to resend Pending Dataset in case of tx failure (in ms).
kPendingDatasetTxRetryInterval = 20000,
- // Wait time after sending Pending Dataset to check whether the channel was changed (in ms).
- kChangeCheckWaitInterval = 30000,
-
// Maximum jitter/wait time to start a requested channel change (in ms).
kRequestStartJitterInterval = 10000,
@@ -265,15 +262,15 @@
};
void StartDatasetUpdate(void);
- static void HandleDatasetUpdateDone(otError aError, void *aContext);
- void HandleDatasetUpdateDone(otError aError);
+ static void HandleDatasetUpdateDone(Error aError, void *aContext);
+ void HandleDatasetUpdateDone(Error aError);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
void StartAutoSelectTimer(void);
#if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
- otError FindBetterChannel(uint8_t &aNewChannel, uint16_t &aOccupancy);
- bool ShouldAttemptChannelChange(void);
+ Error FindBetterChannel(uint8_t &aNewChannel, uint16_t &aOccupancy);
+ bool ShouldAttemptChannelChange(void);
#endif
Mac::ChannelMask mSupportedChannelMask;
diff --git a/src/core/utils/channel_monitor.cpp b/src/core/utils/channel_monitor.cpp
index 5c5ba27..9fef24f 100644
--- a/src/core/utils/channel_monitor.cpp
+++ b/src/core/utils/channel_monitor.cpp
@@ -62,16 +62,16 @@
: InstanceLocator(aInstance)
, mChannelMaskIndex(0)
, mSampleCount(0)
- , mTimer(aInstance, ChannelMonitor::HandleTimer, this)
+ , mTimer(aInstance, ChannelMonitor::HandleTimer)
{
memset(mChannelOccupancy, 0, sizeof(mChannelOccupancy));
}
-otError ChannelMonitor::Start(void)
+Error ChannelMonitor::Start(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!IsRunning(), error = OT_ERROR_ALREADY);
+ VerifyOrExit(!IsRunning(), error = kErrorAlready);
Clear();
mTimer.Start(kTimerInterval);
otLogDebgUtil("ChannelMonitor: Starting");
@@ -80,11 +80,11 @@
return error;
}
-otError ChannelMonitor::Stop(void)
+Error ChannelMonitor::Stop(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(IsRunning(), error = OT_ERROR_ALREADY);
+ VerifyOrExit(IsRunning(), error = kErrorAlready);
mTimer.Stop();
otLogDebgUtil("ChannelMonitor: Stopping");
@@ -114,7 +114,7 @@
void ChannelMonitor::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<ChannelMonitor>().HandleTimer();
+ aTimer.Get<ChannelMonitor>().HandleTimer();
}
void ChannelMonitor::HandleTimer(void)
@@ -212,7 +212,7 @@
channel = Mac::ChannelMask::kChannelIteratorFirst;
- while (aMask.GetNextChannel(channel) == OT_ERROR_NONE)
+ while (aMask.GetNextChannel(channel) == kErrorNone)
{
uint16_t occupancy = GetChannelOccupancy(channel);
diff --git a/src/core/utils/channel_monitor.hpp b/src/core/utils/channel_monitor.hpp
index 076ae55..3f8c900 100644
--- a/src/core/utils/channel_monitor.hpp
+++ b/src/core/utils/channel_monitor.hpp
@@ -110,22 +110,22 @@
*
* Once started, any previously collected data is cleared.
*
- * @retval OT_ERROR_NONE Channel Monitoring started successfully.
- * @retval OT_ERROR_ALREADY Channel Monitoring has already been started.
+ * @retval kErrorNone Channel Monitoring started successfully.
+ * @retval kErrorAlready Channel Monitoring has already been started.
*
*/
- otError Start(void);
+ Error Start(void);
/**
* This method stops the Channel Monitoring operation.
*
* @note After `Stop()`, the previous data is still valid and can be read.
*
- * @retval OT_ERROR_NONE Channel Monitoring stopped successfully.
- * @retval OT_ERROR_ALREADY Channel Monitoring has already been stopped.
+ * @retval kErrorNone Channel Monitoring stopped successfully.
+ * @retval kErrorAlready Channel Monitoring has already been stopped.
*
*/
- otError Stop(void);
+ Error Stop(void);
/**
* This method indicates whether the Channel Monitoring operation is started and running.
diff --git a/src/core/utils/child_supervision.cpp b/src/core/utils/child_supervision.cpp
index 1ca45ef..e6be59f 100644
--- a/src/core/utils/child_supervision.cpp
+++ b/src/core/utils/child_supervision.cpp
@@ -155,7 +155,7 @@
SupervisionListener::SupervisionListener(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimeout(0)
- , mTimer(aInstance, SupervisionListener::HandleTimer, this)
+ , mTimer(aInstance, SupervisionListener::HandleTimer)
{
SetTimeout(kDefaultTimeout);
}
@@ -206,7 +206,7 @@
void SupervisionListener::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<SupervisionListener>().HandleTimer();
+ aTimer.Get<SupervisionListener>().HandleTimer();
}
void SupervisionListener::HandleTimer(void)
diff --git a/src/core/utils/dataset_updater.cpp b/src/core/utils/dataset_updater.cpp
deleted file mode 100644
index 10aea32..0000000
--- a/src/core/utils/dataset_updater.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2020, The OpenThread Authors.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holder nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- * This file implements Dataset Updater.
- *
- */
-
-#include "dataset_updater.hpp"
-
-#include "common/code_utils.hpp"
-#include "common/instance.hpp"
-#include "common/locator-getters.hpp"
-#include "common/logging.hpp"
-#include "common/random.hpp"
-
-#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
-
-namespace ot {
-namespace Utils {
-
-DatasetUpdater::DatasetUpdater(Instance &aInstance)
- : InstanceLocator(aInstance)
- , mState(kStateIdle)
- , mWaitInterval(kWaitInterval)
- , mCallback(nullptr)
- , mCallbackContext(nullptr)
- , mTimer(aInstance, DatasetUpdater::HandleTimer, this)
- , mDataset(nullptr)
-{
-}
-
-otError DatasetUpdater::RequestUpdate(const MeshCoP::Dataset::Info &aDataset,
- Callback aCallback,
- void * aContext,
- uint32_t aReryWaitInterval)
-{
- otError error = OT_ERROR_NONE;
- Message *message = nullptr;
-
- VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), error = OT_ERROR_INVALID_STATE);
- VerifyOrExit(mState == kStateIdle, error = OT_ERROR_BUSY);
-
- VerifyOrExit(!aDataset.IsActiveTimestampPresent() && !aDataset.IsPendingTimestampPresent(),
- error = OT_ERROR_INVALID_ARGS);
-
- message = Get<MessagePool>().New(Message::kTypeOther, 0);
- VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
-
- SuccessOrExit(error = message->Append(aDataset));
-
- mCallback = aCallback;
- mCallbackContext = aContext;
- mWaitInterval = aReryWaitInterval;
- mDataset = message;
- mState = kStateUpdateRequested;
-
- PreparePendingDataset();
-
-exit:
- FreeMessageOnError(message, error);
- return error;
-}
-
-void DatasetUpdater::CancelUpdate(void)
-{
- if (mState != kStateIdle)
- {
- FreeMessage(mDataset);
- mState = kStateIdle;
- mTimer.Stop();
- }
-}
-
-void DatasetUpdater::HandleTimer(Timer &aTimer)
-{
- aTimer.GetOwner<DatasetUpdater>().HandleTimer();
-}
-
-void DatasetUpdater::HandleTimer(void)
-{
- switch (mState)
- {
- case kStateIdle:
- break;
- case kStateUpdateRequested:
- case kStateSentMgmtPendingDataset:
- PreparePendingDataset();
- break;
- }
-}
-
-void DatasetUpdater::PreparePendingDataset(void)
-{
- otError error;
- MeshCoP::Dataset::Info newDataset;
- MeshCoP::Dataset::Info curDataset;
-
- VerifyOrExit(mState != kStateIdle);
-
- VerifyOrExit(!Get<Mle::Mle>().IsDisabled(), Finish(OT_ERROR_INVALID_STATE));
-
- error = Get<MeshCoP::ActiveDataset>().Read(curDataset);
-
- if (error != OT_ERROR_NONE)
- {
- // If there is no valid Active Dataset but MLE is not disabled,
- // set the timer to try again after the retry interval. This
- // handles the situation where a dataset update request comes
- // right after the network is formed but before the active
- // dataset is created.
-
- mState = kStateUpdateRequested;
- mTimer.Start(kRetryInterval);
- ExitNow();
- }
-
- IgnoreError(mDataset->Read(0, newDataset));
-
- if (newDataset.IsSubsetOf(curDataset))
- {
- // If new requested Dataset is already contained in the current
- // Active Dataset, no change is required, and we can report the
- // update to be successful.
-
- Finish(OT_ERROR_NONE);
- ExitNow();
- }
-
- if (newDataset.IsActiveTimestampPresent())
- {
- // Presence of the active timestamp in the new Dataset
- // indicates that it is a retry. In this case, we ensure
- // that the timestamp is ahead of current active dataset.
- // This covers the case where another device in network
- // requested a Dataset update after this device.
-
- VerifyOrExit(newDataset.GetActiveTimestamp() > curDataset.GetActiveTimestamp(), Finish(OT_ERROR_ALREADY));
- }
- else
- {
- newDataset.SetActiveTimestamp(curDataset.GetActiveTimestamp() +
- Random::NonCrypto::GetUint32InRange(1, kMaxTimestampIncrease));
- }
-
- if (!newDataset.IsDelayPresent())
- {
- newDataset.SetDelay(kDefaultDelay);
- }
-
- if (!newDataset.IsPendingTimestampPresent())
- {
- uint32_t timestampIncrease = Random::NonCrypto::GetUint32InRange(1, kMaxTimestampIncrease);
-
- if (Get<MeshCoP::PendingDataset>().Read(curDataset) == OT_ERROR_NONE)
- {
- newDataset.SetPendingTimestamp(curDataset.GetPendingTimestamp() + timestampIncrease);
- }
- else
- {
- newDataset.SetPendingTimestamp(timestampIncrease);
- }
-
- mDataset->Write(0, newDataset);
- }
-
- error = Get<MeshCoP::PendingDataset>().SendSetRequest(newDataset, nullptr, 0);
-
- if (error == OT_ERROR_NONE)
- {
- mState = kStateSentMgmtPendingDataset;
- mTimer.Start(newDataset.GetDelay() + mWaitInterval);
- }
- else
- {
- mTimer.Start(kRetryInterval);
- }
-
-exit:
- return;
-}
-
-void DatasetUpdater::Finish(otError aError)
-{
- FreeMessage(mDataset);
- mState = kStateIdle;
-
- if (mCallback != nullptr)
- {
- mCallback(aError, mCallbackContext);
- }
-}
-
-void DatasetUpdater::HandleNotifierEvents(Events aEvents)
-{
- VerifyOrExit(mState == kStateSentMgmtPendingDataset);
-
- if (aEvents.Contains(kEventActiveDatasetChanged))
- {
- MeshCoP::Dataset::Info requestedDataset;
- MeshCoP::Dataset::Info activeDataset;
-
- SuccessOrExit(Get<MeshCoP::ActiveDataset>().Read(activeDataset));
- IgnoreError(mDataset->Read(0, requestedDataset));
-
- if (requestedDataset.IsSubsetOf(activeDataset))
- {
- Finish(OT_ERROR_NONE);
- }
- else if (requestedDataset.GetActiveTimestamp() <= activeDataset.GetActiveTimestamp())
- {
- Finish(OT_ERROR_ALREADY);
- }
- }
-
-exit:
- return;
-}
-
-} // namespace Utils
-} // namespace ot
-
-#endif // #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
diff --git a/src/core/utils/flash.cpp b/src/core/utils/flash.cpp
index 8f47176..f7ba540 100644
--- a/src/core/utils/flash.cpp
+++ b/src/core/utils/flash.cpp
@@ -114,9 +114,9 @@
}
}
-otError Flash::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
+Error Flash::Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
uint16_t valueLength = 0;
int index = 0; // This must be initalized to 0. See [Note] in Delete().
uint32_t offset;
@@ -151,7 +151,7 @@
}
valueLength = record.GetLength();
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
index++;
@@ -165,22 +165,22 @@
return error;
}
-otError Flash::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+Error Flash::Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
return Add(aKey, true, aValue, aValueLength);
}
-otError Flash::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
+Error Flash::Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
- bool first = (Get(aKey, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND);
+ bool first = (Get(aKey, 0, nullptr, nullptr) == kErrorNotFound);
return Add(aKey, first, aValue, aValueLength);
}
-otError Flash::Add(uint16_t aKey, bool aFirst, const uint8_t *aValue, uint16_t aValueLength)
+Error Flash::Add(uint16_t aKey, bool aFirst, const uint8_t *aValue, uint16_t aValueLength)
{
- otError error = OT_ERROR_NONE;
- Record record;
+ Error error = kErrorNone;
+ Record record;
record.Init(aKey, aFirst);
record.SetData(aValue, aValueLength);
@@ -190,7 +190,7 @@
if ((mSwapSize - record.GetSize()) < mSwapUsed)
{
Swap();
- VerifyOrExit((mSwapSize - record.GetSize()) >= mSwapUsed, error = OT_ERROR_NO_BUFS);
+ VerifyOrExit((mSwapSize - record.GetSize()) >= mSwapUsed, error = kErrorNoBufs);
}
otPlatFlashWrite(&GetInstance(), mSwapIndex, mSwapUsed, &record, record.GetSize());
@@ -255,9 +255,9 @@
mSwapUsed = dstOffset;
}
-otError Flash::Delete(uint16_t aKey, int aIndex)
+Error Flash::Delete(uint16_t aKey, int aIndex)
{
- otError error = OT_ERROR_NOT_FOUND;
+ Error error = kErrorNotFound;
int index = 0; // This must be initalized to 0. See [Note] below.
RecordHeader record;
@@ -279,7 +279,7 @@
{
record.SetDeleted();
otPlatFlashWrite(&GetInstance(), mSwapIndex, offset, &record, sizeof(record));
- error = OT_ERROR_NONE;
+ error = kErrorNone;
}
/* [Note] If the operation gets interrupted here and aIndex is 0, the next record (index == 1) will never get
diff --git a/src/core/utils/flash.hpp b/src/core/utils/flash.hpp
index ecac26c..5bb7ed3 100644
--- a/src/core/utils/flash.hpp
+++ b/src/core/utils/flash.hpp
@@ -34,10 +34,10 @@
#include <stdint.h>
#include <string.h>
-#include <openthread/error.h>
#include <openthread/platform/toolchain.h>
#include "common/debug.hpp"
+#include "common/error.hpp"
#include "common/locator.hpp"
namespace ot {
@@ -77,11 +77,11 @@
* At return, the actual length of the setting is written.
* May be nullptr if performing a presence check.
*
- * @retval OT_ERROR_NONE The value was fetched successfully.
- * @retval OT_ERROR_NOT_FOUND The key was not found.
+ * @retval kErrorNone The value was fetched successfully.
+ * @retval kErrorNotFound The key was not found.
*
*/
- otError Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const;
+ Error Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const;
/**
* This method sets or replaces the value identified by @p aKey.
@@ -94,11 +94,11 @@
* MUST NOT be nullptr if @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by @p aValue. May be zero.
*
- * @retval OT_ERROR_NONE The value was changed.
- * @retval OT_ERROR_NO_BUFS Not enough space to store the value.
+ * @retval kErrorNone The value was changed.
+ * @retval kErrorNoBufs Not enough space to store the value.
*
*/
- otError Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+ Error Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/**
* This method adds a value to @p aKey.
@@ -108,11 +108,11 @@
* MUST NOT be nullptr if @p aValueLength is non-zero.
* @param[in] aValueLength The length of the data pointed to by @p aValue. May be zero.
*
- * @retval OT_ERROR_NONE The value was added.
- * @retval OT_ERROR_NO_BUFS Not enough space to store the value.
+ * @retval kErrorNone The value was added.
+ * @retval kErrorNoBufs Not enough space to store the value.
*
*/
- otError Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+ Error Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
/**
* This method removes a value from @p aKey.
@@ -122,11 +122,11 @@
* @param[in] aIndex The index of the value to be removed.
* If set to -1, all values for @p aKey will be removed.
*
- * @retval OT_ERROR_NONE The given key and index was found and removed successfully.
- * @retval OT_ERROR_NOT_FOUND The given key or index was not found.
+ * @retval kErrorNone The given key and index was found and removed successfully.
+ * @retval kErrorNotFound The given key or index was not found.
*
*/
- otError Delete(uint16_t aKey, int aIndex);
+ Error Delete(uint16_t aKey, int aIndex);
/**
* This method removes all values.
@@ -220,10 +220,10 @@
uint8_t mData[kMaxDataSize];
} OT_TOOL_PACKED_END;
- otError Add(uint16_t aKey, bool aFirst, const uint8_t *aValue, uint16_t aValueLength);
- bool DoesValidRecordExist(uint32_t aOffset, uint16_t aKey) const;
- void SanitizeFreeSpace(void);
- void Swap(void);
+ Error Add(uint16_t aKey, bool aFirst, const uint8_t *aValue, uint16_t aValueLength);
+ bool DoesValidRecordExist(uint32_t aOffset, uint16_t aKey) const;
+ void SanitizeFreeSpace(void);
+ void Swap(void);
uint32_t mSwapSize;
uint32_t mSwapUsed;
diff --git a/src/core/utils/heap.cpp b/src/core/utils/heap.cpp
index 6ecf45c..0f8432d 100644
--- a/src/core/utils/heap.cpp
+++ b/src/core/utils/heap.cpp
@@ -34,6 +34,8 @@
#include "heap.hpp"
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
#include <string.h>
#include "common/code_utils.hpp"
@@ -217,3 +219,5 @@
} // namespace Utils
} // namespace ot
+
+#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
diff --git a/src/core/utils/heap.hpp b/src/core/utils/heap.hpp
index 60f2244..e0d1e66 100644
--- a/src/core/utils/heap.hpp
+++ b/src/core/utils/heap.hpp
@@ -37,6 +37,8 @@
#include "openthread-core-config.h"
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
#include <stddef.h>
#include <stdint.h>
@@ -353,4 +355,6 @@
} // namespace Utils
} // namespace ot
+#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
#endif // OT_HEAP_HPP_
diff --git a/src/core/utils/jam_detector.cpp b/src/core/utils/jam_detector.cpp
index 7a09aee..75b1ab1 100644
--- a/src/core/utils/jam_detector.cpp
+++ b/src/core/utils/jam_detector.cpp
@@ -49,7 +49,7 @@
: InstanceLocator(aInstance)
, mHandler(nullptr)
, mContext(nullptr)
- , mTimer(aInstance, JamDetector::HandleTimer, this)
+ , mTimer(aInstance, JamDetector::HandleTimer)
, mHistoryBitmap(0)
, mCurSecondStartTime(0)
, mSampleInterval(0)
@@ -62,12 +62,12 @@
{
}
-otError JamDetector::Start(Handler aHandler, void *aContext)
+Error JamDetector::Start(Handler aHandler, void *aContext)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(!mEnabled, error = OT_ERROR_ALREADY);
- VerifyOrExit(aHandler != nullptr, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(!mEnabled, error = kErrorAlready);
+ VerifyOrExit(aHandler != nullptr, error = kErrorInvalidArgs);
mHandler = aHandler;
mContext = aContext;
@@ -81,11 +81,11 @@
return error;
}
-otError JamDetector::Stop(void)
+Error JamDetector::Stop(void)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(mEnabled, error = OT_ERROR_ALREADY);
+ VerifyOrExit(mEnabled, error = kErrorAlready);
mEnabled = false;
mJamState = false;
@@ -131,12 +131,12 @@
otLogInfoUtil("JamDetector - RSSI threshold set to %d", mRssiThreshold);
}
-otError JamDetector::SetWindow(uint8_t aWindow)
+Error JamDetector::SetWindow(uint8_t aWindow)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aWindow != 0, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aWindow <= kMaxWindow, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aWindow != 0, error = kErrorInvalidArgs);
+ VerifyOrExit(aWindow <= kMaxWindow, error = kErrorInvalidArgs);
mWindow = aWindow;
otLogInfoUtil("JamDetector - window set to %d", mWindow);
@@ -145,12 +145,12 @@
return error;
}
-otError JamDetector::SetBusyPeriod(uint8_t aBusyPeriod)
+Error JamDetector::SetBusyPeriod(uint8_t aBusyPeriod)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(aBusyPeriod != 0, error = OT_ERROR_INVALID_ARGS);
- VerifyOrExit(aBusyPeriod <= mWindow, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aBusyPeriod != 0, error = kErrorInvalidArgs);
+ VerifyOrExit(aBusyPeriod <= mWindow, error = kErrorInvalidArgs);
mBusyPeriod = aBusyPeriod;
otLogInfoUtil("JamDetector - busy period set to %d", mBusyPeriod);
@@ -161,7 +161,7 @@
void JamDetector::HandleTimer(Timer &aTimer)
{
- aTimer.GetOwner<JamDetector>().HandleTimer();
+ aTimer.Get<JamDetector>().HandleTimer();
}
void JamDetector::HandleTimer(void)
diff --git a/src/core/utils/jam_detector.hpp b/src/core/utils/jam_detector.hpp
index 787b945..e0ab57d 100644
--- a/src/core/utils/jam_detector.hpp
+++ b/src/core/utils/jam_detector.hpp
@@ -77,20 +77,20 @@
* @param[in] aHandler A pointer to a function called when jamming is detected.
* @param[in] aContext A pointer to application-specific context.
*
- * @retval OT_ERROR_NONE Successfully started the jamming detection.
- * @retval OT_ERROR_ALREADY Jam detection has been started before.
+ * @retval kErrorNone Successfully started the jamming detection.
+ * @retval kErrorAlready Jam detection has been started before.
*
*/
- otError Start(Handler aHandler, void *aContext);
+ Error Start(Handler aHandler, void *aContext);
/**
* Stop the jamming detection.
*
- * @retval OT_ERROR_NONE Successfully stopped the jamming detection.
- * @retval OT_ERROR_ALREADY Jam detection is already stopped.
+ * @retval kErrorNone Successfully stopped the jamming detection.
+ * @retval kErrorAlready Jam detection is already stopped.
*
*/
- otError Stop(void);
+ Error Stop(void);
/**
* Get the Jam Detection Status
@@ -126,11 +126,11 @@
*
* @param[in] aWindow The Jam Detection window (valid range is 1 to 63)
*
- * @retval OT_ERROR_NONE Successfully set the window.
- * @retval OT_ERROR_INVALID_ARGS The given input parameter not within valid range (1-63)
+ * @retval kErrorNone Successfully set the window.
+ * @retval kErrorInvalidArgs The given input parameter not within valid range (1-63)
*
*/
- otError SetWindow(uint8_t aWindow);
+ Error SetWindow(uint8_t aWindow);
/**
* Get the Jam Detection Detection Window (in seconds).
@@ -148,11 +148,11 @@
* @param[in] aBusyPeriod The Jam Detection busy period (should be non-zero and
less than or equal to Jam Detection Window)
*
- * @retval OT_ERROR_NONE Successfully set the window.
- * @retval OT_ERROR_INVALID_ARGS The given input is not within the valid range.
+ * @retval kErrorNone Successfully set the window.
+ * @retval kErrorInvalidArgs The given input is not within the valid range.
*
*/
- otError SetBusyPeriod(uint8_t aBusyPeriod);
+ Error SetBusyPeriod(uint8_t aBusyPeriod);
/**
* Get the Jam Detection Busy Period (in seconds)
diff --git a/src/core/utils/lookup_table.hpp b/src/core/utils/lookup_table.hpp
index 92e4e39..6779588 100644
--- a/src/core/utils/lookup_table.hpp
+++ b/src/core/utils/lookup_table.hpp
@@ -35,7 +35,8 @@
#define LOOKUP_TABLE_HPP_
#include <stdint.h>
-#include <openthread/error.h>
+
+#include "common/error.hpp"
namespace ot {
namespace Utils {
diff --git a/src/core/utils/otns.cpp b/src/core/utils/otns.cpp
index f75b342..65d44a6 100644
--- a/src/core/utils/otns.cpp
+++ b/src/core/utils/otns.cpp
@@ -38,6 +38,7 @@
#include "common/debug.hpp"
#include "common/locator-getters.hpp"
+#include "common/logging.hpp"
namespace ot {
namespace Utils {
@@ -157,50 +158,50 @@
void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
- otError error;
+ char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
+ Error error;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=send,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnCore("Otns::EmitCoapSend failed: %s", otThreadErrorToString(error));
+ otLogWarnCore("Otns::EmitCoapSend failed: %s", ErrorToString(error));
}
}
void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
- otError error = OT_ERROR_NONE;
+ char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
+ Error error = kErrorNone;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=recv,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnCore("Otns::EmitCoapReceive failed: %s", otThreadErrorToString(error));
+ otLogWarnCore("Otns::EmitCoapReceive failed: %s", ErrorToString(error));
}
}
-void Otns::EmitCoapSendFailure(otError aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
+void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
- otError error = OT_ERROR_NONE;
+ char uriPath[Coap::Message::kMaxReceivedUriPath + 1];
+ Error error = kErrorNone;
SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));
EmitStatus("coap=send_error,%d,%d,%d,%s,%s,%d,%s", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(),
uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort(),
- otThreadErrorToString(aError));
+ ErrorToString(aError));
exit:
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
- otLogWarnCore("Otns::EmitCoapSendFailure failed: %s", otThreadErrorToString(error));
+ otLogWarnCore("Otns::EmitCoapSendFailure failed: %s", ErrorToString(error));
}
}
diff --git a/src/core/utils/otns.hpp b/src/core/utils/otns.hpp
index 2d670d9..d877b36 100644
--- a/src/core/utils/otns.hpp
+++ b/src/core/utils/otns.hpp
@@ -160,7 +160,7 @@
* @param[in] aMessageInfo The message info.
*
*/
- static void EmitCoapSendFailure(otError aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+ static void EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This function emits the received COAP message info to OTNS.
diff --git a/src/core/utils/parse_cmdline.cpp b/src/core/utils/parse_cmdline.cpp
index c9008e3..993012d 100644
--- a/src/core/utils/parse_cmdline.cpp
+++ b/src/core/utils/parse_cmdline.cpp
@@ -53,20 +53,20 @@
return IsSeparator(aChar) || (aChar == '\\');
}
-static otError ParseDigit(char aDigitChar, uint8_t &aValue)
+static Error ParseDigit(char aDigitChar, uint8_t &aValue)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
- VerifyOrExit(('0' <= aDigitChar) && (aDigitChar <= '9'), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(('0' <= aDigitChar) && (aDigitChar <= '9'), error = kErrorInvalidArgs);
aValue = static_cast<uint8_t>(aDigitChar - '0');
exit:
return error;
}
-static otError ParseHexDigit(char aHexChar, uint8_t &aValue)
+static Error ParseHexDigit(char aHexChar, uint8_t &aValue)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
if (('A' <= aHexChar) && (aHexChar <= 'F'))
{
@@ -84,10 +84,10 @@
return error;
}
-otError ParseCmd(char *aCommandString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax)
+Error ParseCmd(char *aCommandString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax)
{
- otError error = OT_ERROR_NONE;
- char * cmd;
+ Error error = kErrorNone;
+ char *cmd;
aArgsLength = 0;
@@ -105,7 +105,7 @@
if ((*cmd != '\0') && ((aArgsLength == 0) || (*(cmd - 1) == '\0')))
{
- VerifyOrExit(aArgsLength < aArgsLengthMax, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(aArgsLength < aArgsLengthMax, error = kErrorInvalidArgs);
aArgs[aArgsLength++] = cmd;
}
}
@@ -114,38 +114,38 @@
return error;
}
-template <typename UintType> otError ParseUint(const char *aString, UintType &aUint)
+template <typename UintType> Error ParseUint(const char *aString, UintType &aUint)
{
- otError error;
+ Error error;
uint64_t value;
SuccessOrExit(error = ParseAsUint64(aString, value));
- VerifyOrExit(value <= NumericLimits<UintType>::Max(), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value <= NumericLimits<UintType>::Max(), error = kErrorInvalidArgs);
aUint = static_cast<UintType>(value);
exit:
return error;
}
-otError ParseAsUint8(const char *aString, uint8_t &aUint8)
+Error ParseAsUint8(const char *aString, uint8_t &aUint8)
{
return ParseUint<uint8_t>(aString, aUint8);
}
-otError ParseAsUint16(const char *aString, uint16_t &aUint16)
+Error ParseAsUint16(const char *aString, uint16_t &aUint16)
{
return ParseUint<uint16_t>(aString, aUint16);
}
-otError ParseAsUint32(const char *aString, uint32_t &aUint32)
+Error ParseAsUint32(const char *aString, uint32_t &aUint32)
{
return ParseUint<uint32_t>(aString, aUint32);
}
-otError ParseAsUint64(const char *aString, uint64_t &aUint64)
+Error ParseAsUint64(const char *aString, uint64_t &aUint64)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint64_t value = 0;
const char *cur = aString;
bool isHex = false;
@@ -168,10 +168,10 @@
uint64_t newValue;
SuccessOrExit(error = isHex ? ParseHexDigit(*cur, digit) : ParseDigit(*cur, digit));
- VerifyOrExit(value <= (isHex ? kMaxHexBeforeOveflow : kMaxDecBeforeOverlow), error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(value <= (isHex ? kMaxHexBeforeOveflow : kMaxDecBeforeOverlow), error = kErrorInvalidArgs);
value = isHex ? (value << 4) : (value * 10);
newValue = value + digit;
- VerifyOrExit(newValue >= value, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(newValue >= value, error = kErrorInvalidArgs);
value = newValue;
cur++;
} while (*cur != '\0');
@@ -182,34 +182,34 @@
return error;
}
-template <typename IntType> otError ParseInt(const char *aString, IntType &aInt)
+template <typename IntType> Error ParseInt(const char *aString, IntType &aInt)
{
- otError error;
+ Error error;
int32_t value;
SuccessOrExit(error = ParseAsInt32(aString, value));
VerifyOrExit((NumericLimits<IntType>::Min() <= value) && (value <= NumericLimits<IntType>::Max()),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
aInt = static_cast<IntType>(value);
exit:
return error;
}
-otError ParseAsInt8(const char *aString, int8_t &aInt8)
+Error ParseAsInt8(const char *aString, int8_t &aInt8)
{
return ParseInt<int8_t>(aString, aInt8);
}
-otError ParseAsInt16(const char *aString, int16_t &aInt16)
+Error ParseAsInt16(const char *aString, int16_t &aInt16)
{
return ParseInt<int16_t>(aString, aInt16);
}
-otError ParseAsInt32(const char *aString, int32_t &aInt32)
+Error ParseAsInt32(const char *aString, int32_t &aInt32)
{
- otError error;
+ Error error;
uint64_t value;
bool isNegavtive = false;
@@ -226,16 +226,16 @@
SuccessOrExit(error = ParseAsUint64(aString, value));
VerifyOrExit(value <= (isNegavtive ? static_cast<uint64_t>(-static_cast<int64_t>(NumericLimits<int32_t>::Min()))
: static_cast<uint64_t>(NumericLimits<int32_t>::Max())),
- error = OT_ERROR_INVALID_ARGS);
+ error = kErrorInvalidArgs);
aInt32 = static_cast<int32_t>(isNegavtive ? -static_cast<int64_t>(value) : static_cast<int64_t>(value));
exit:
return error;
}
-otError ParseAsBool(const char *aString, bool &aBool)
+Error ParseAsBool(const char *aString, bool &aBool)
{
- otError error;
+ Error error;
uint32_t value;
SuccessOrExit(error = ParseAsUint32(aString, value));
@@ -246,14 +246,14 @@
}
#if OPENTHREAD_FTD || OPENTHREAD_MTD
-otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix)
+Error ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix)
{
enum : uint8_t
{
kMaxIp6AddressStringSize = 45,
};
- otError error = OT_ERROR_INVALID_ARGS;
+ Error error = kErrorInvalidArgs;
char string[kMaxIp6AddressStringSize];
const char *prefixLengthStr;
@@ -273,21 +273,21 @@
}
#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
-otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)
+Error ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)
{
- otError error;
+ Error error;
uint16_t readSize = aSize;
SuccessOrExit(error = ParseAsHexString(aString, readSize, aBuffer, kDisallowTruncate));
- VerifyOrExit(readSize == aSize, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(readSize == aSize, error = kErrorInvalidArgs);
exit:
return error;
}
-otError ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode)
+Error ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode)
{
- otError error = OT_ERROR_NONE;
+ Error error = kErrorNone;
uint8_t byte = 0;
uint16_t readBytes = 0;
const char *hex = aString;
@@ -296,7 +296,7 @@
if (aMode == kDisallowTruncate)
{
- VerifyOrExit((hexLength + 1) / 2 <= aSize, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit((hexLength + 1) / 2 <= aSize, error = kErrorInvalidArgs);
}
// Handle the case where number of chars in hex string is odd.
diff --git a/src/core/utils/parse_cmdline.hpp b/src/core/utils/parse_cmdline.hpp
index 6c3facd..f680fff 100644
--- a/src/core/utils/parse_cmdline.hpp
+++ b/src/core/utils/parse_cmdline.hpp
@@ -85,8 +85,8 @@
* @param[in] aString The string to parse.
* @param[out] aUint8 A reference to an `uint8_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsUint8(const char *aString, uint8_t &aUint8);
@@ -99,8 +99,8 @@
* @param[in] aString The string to parse.
* @param[out] aUint16 A reference to an `uint16_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsUint16(const char *aString, uint16_t &aUint16);
@@ -113,8 +113,8 @@
* @param[in] aString The string to parse.
* @param[out] aUint32 A reference to an `uint32_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsUint32(const char *aString, uint32_t &aUint32);
@@ -127,8 +127,8 @@
* @param[in] aString The string to parse.
* @param[out] aUint64 A reference to an `uint64_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsUint64(const char *aString, uint64_t &aUint64);
@@ -142,8 +142,8 @@
* @param[in] aString The string to parse.
* @param[out] aInt8 A reference to an `int8_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsInt8(const char *aString, int8_t &aInt8);
@@ -157,8 +157,8 @@
* @param[in] aString The string to parse.
* @param[out] aInt16 A reference to an `int16_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsInt16(const char *aString, int16_t &aInt16);
@@ -172,8 +172,8 @@
* @param[in] aString The string to parse.
* @param[out] aInt32 A reference to an `int32_t` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number (e.g., value out of range).
*
*/
otError ParseAsInt32(const char *aString, int32_t &aInt32);
@@ -186,8 +186,8 @@
* @param[in] aString The string to parse.
* @param[out] aBool A reference to a `bool` variable to output the parsed value.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number.
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid number.
*
*/
otError ParseAsBool(const char *aString, bool &aBool);
@@ -200,8 +200,8 @@
* @param[in] aString The string to parse.
* @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 address.
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid IPv6 address.
*
*/
inline otError ParseAsIp6Address(const char *aString, otIp6Address &aAddress)
@@ -217,8 +217,8 @@
* @param[in] aString The string to parse.
* @param[out] aPrefix A reference to an `otIp6Prefix` to output the parsed IPv6 prefix.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 prefix
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid IPv6 prefix
*
*/
otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix);
@@ -227,16 +227,16 @@
/**
* This function parses a hex string into a byte array of fixed expected size.
*
- * This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p aSize bytes (after parsing). If
+ * This function returns `kErrorNone` only when the hex string contains exactly @p aSize bytes (after parsing). If
* there are fewer or more bytes in hex string that @p aSize, the parsed bytes (up to @p aSize) are copied into the
- * `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned.
+ * `aBuffer` and `kErrorInvalidArgs` is returned.
*
* @param[in] aString The string to parse.
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
* @param[in] aSize The expected size of byte sequence (number of bytes after parsing).
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes.
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid hex bytes and/or not @p aSize bytes.
*
*/
otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize);
@@ -244,17 +244,17 @@
/**
* This template function parses a hex string into a a given fixed size array.
*
- * This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p kBufferSize bytes (after parsing).
+ * This function returns `kErrorNone` only when the hex string contains exactly @p kBufferSize bytes (after parsing).
* If there are fewer or more bytes in hex string that @p kBufferSize, the parsed bytes (up to @p kBufferSize) are
- * copied into the `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned.
+ * copied into the `aBuffer` and `kErrorInvalidArgs` is returned.
*
* @tparam kBufferSize The byte array size (number of bytes).
*
* @param[in] aString The string to parse.
* @param[out] aBuffer A reference to a byte array to output the parsed byte sequence.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes.
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid hex bytes and/or not @p aSize bytes.
*
*/
template <uint16_t kBufferSize> static otError ParseAsHexString(const char *aString, uint8_t (&aBuffer)[kBufferSize])
@@ -275,8 +275,8 @@
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
* @param[in] aMode Indicates parsing mode whether to allow truncation or not.
*
- * @retval OT_ERROR_NONE The string was parsed successfully.
- * @retval OT_ERROR_INVALID_ARGS The string does not contain valid format or too many bytes (if truncation not allowed)
+ * @retval kErrorNone The string was parsed successfully.
+ * @retval kErrorInvalidArgs The string does not contain valid format or too many bytes (if truncation not allowed)
*
*/
otError ParseAsHexString(const char * aString,
diff --git a/src/core/utils/ping_sender.cpp b/src/core/utils/ping_sender.cpp
new file mode 100644
index 0000000..22d4045
--- /dev/null
+++ b/src/core/utils/ping_sender.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2021, 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 ping sender module.
+ */
+
+#include "ping_sender.hpp"
+
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+#include "common/encoding.hpp"
+#include "common/locator-getters.hpp"
+#include "common/random.hpp"
+
+namespace ot {
+namespace Utils {
+
+using Encoding::BigEndian::HostSwap32;
+
+void PingSender::Config::SetUnspecifiedToDefault(void)
+{
+ if (mSize == 0)
+ {
+ mSize = kDefaultSize;
+ }
+
+ if (mCount == 0)
+ {
+ mCount = kDefaultCount;
+ }
+
+ if (mInterval == 0)
+ {
+ mInterval = kDefaultInterval;
+ }
+}
+
+void PingSender::Config::InvokeCallback(const Reply &aReply) const
+{
+ VerifyOrExit(mCallback != nullptr);
+ mCallback(&aReply, mCallbackContext);
+
+exit:
+ return;
+}
+
+PingSender::PingSender(Instance &aInstance)
+ : InstanceLocator(aInstance)
+ , mIdentifier(0)
+ , mTimer(aInstance, PingSender::HandleTimer)
+ , mIcmpHandler(PingSender::HandleIcmpReceive, this)
+{
+ IgnoreError(Get<Ip6::Icmp>().RegisterHandler(mIcmpHandler));
+}
+
+Error PingSender::Ping(const Config &aConfig)
+{
+ Error error = kErrorNone;
+
+ VerifyOrExit(!mTimer.IsRunning(), error = kErrorBusy);
+
+ mConfig = aConfig;
+ mConfig.SetUnspecifiedToDefault();
+ VerifyOrExit(mConfig.mInterval <= Timer::kMaxDelay, error = kErrorInvalidArgs);
+
+ mIdentifier++;
+ SendPing();
+
+exit:
+ return error;
+}
+
+void PingSender::Stop(void)
+{
+ mTimer.Stop();
+ mIdentifier++;
+}
+
+void PingSender::SendPing(void)
+{
+ TimeMilli now = TimerMilli::GetNow();
+ Message * message = nullptr;
+ Ip6::MessageInfo messageInfo;
+
+ messageInfo.SetPeerAddr(mConfig.GetDestination());
+ messageInfo.mHopLimit = mConfig.mHopLimit;
+ messageInfo.mAllowZeroHopLimit = mConfig.mAllowZeroHopLimit;
+
+ message = Get<Ip6::Icmp>().NewMessage(0);
+ VerifyOrExit(message != nullptr);
+
+ SuccessOrExit(message->Append(HostSwap32(now.GetValue())));
+
+ if (mConfig.mSize > message->GetLength())
+ {
+ SuccessOrExit(message->SetLength(mConfig.mSize));
+ }
+
+ SuccessOrExit(Get<Ip6::Icmp>().SendEchoRequest(*message, messageInfo, mIdentifier));
+
+#if OPENTHREAD_CONFIG_OTNS_ENABLE
+ Get<Utils::Otns>().EmitPingRequest(mConfig.GetDestination(), mConfig.mSize, now.GetValue(), mConfig.mHopLimit);
+#endif
+
+ message = nullptr;
+
+exit:
+ FreeMessage(message);
+ mConfig.mCount--;
+
+ if (mConfig.mCount != 0)
+ {
+ mTimer.Start(mConfig.mInterval);
+ }
+}
+
+void PingSender::HandleTimer(Timer &aTimer)
+{
+ aTimer.Get<PingSender>().HandleTimer();
+}
+
+void PingSender::HandleTimer(void)
+{
+ SendPing();
+}
+
+void PingSender::HandleIcmpReceive(void * aContext,
+ otMessage * aMessage,
+ const otMessageInfo *aMessageInfo,
+ const otIcmp6Header *aIcmpHeader)
+{
+ reinterpret_cast<PingSender *>(aContext)->HandleIcmpReceive(*static_cast<Message *>(aMessage),
+ *static_cast<const Ip6::MessageInfo *>(aMessageInfo),
+ *static_cast<const Ip6::Icmp::Header *>(aIcmpHeader));
+}
+
+void PingSender::HandleIcmpReceive(const Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const Ip6::Icmp::Header &aIcmpHeader)
+{
+ Reply reply;
+ uint32_t timestamp;
+
+ VerifyOrExit(aIcmpHeader.GetType() == Ip6::Icmp::Header::kTypeEchoReply);
+ VerifyOrExit(aIcmpHeader.GetId() == mIdentifier);
+
+ SuccessOrExit(aMessage.Read(aMessage.GetOffset(), timestamp));
+ timestamp = HostSwap32(timestamp);
+
+ reply.mSenderAddress = aMessageInfo.GetPeerAddr();
+ reply.mRoundTripTime = TimerMilli::GetNow() - TimeMilli(timestamp);
+ reply.mSize = aMessage.GetLength() - aMessage.GetOffset();
+ reply.mSequenceNumber = aIcmpHeader.GetSequence();
+ reply.mHopLimit = aMessageInfo.GetHopLimit();
+
+#if OPENTHREAD_CONFIG_OTNS_ENABLE
+ Get<Utils::Otns>().EmitPingReply(aMessageInfo.GetPeerAddr(), reply.mSize, timestamp, reply.mHopLimit);
+#endif
+
+ mConfig.InvokeCallback(reply);
+
+exit:
+ return;
+}
+
+} // namespace Utils
+} // namespace ot
+
+#endif // #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
diff --git a/src/core/utils/ping_sender.hpp b/src/core/utils/ping_sender.hpp
new file mode 100644
index 0000000..9e283ed
--- /dev/null
+++ b/src/core/utils/ping_sender.hpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2021, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file includes definitions to support ping functionality.
+ */
+
+#ifndef PING_SENDER_HPP_
+#define PING_SENDER_HPP_
+
+#include "openthread-core-config.h"
+
+#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+#include <openthread/ping_sender.h>
+
+#include "common/code_utils.hpp"
+#include "common/locator.hpp"
+#include "common/message.hpp"
+#include "common/non_copyable.hpp"
+#include "common/time.hpp"
+#include "common/timer.hpp"
+#include "net/icmp6.hpp"
+#include "net/ip6_address.hpp"
+
+namespace ot {
+namespace Utils {
+
+/**
+ * This class implements sending ICMPv6 Echo Request messages and processing ICMPv6 Echo Reply messages.
+ *
+ */
+class PingSender : public InstanceLocator, private NonCopyable
+{
+public:
+ /**
+ * This class represents a ping reply.
+ *
+ */
+ typedef otPingSenderReply Reply;
+
+ /**
+ * This class represents a ping request configuration.
+ *
+ */
+ class Config : public otPingSenderConfig
+ {
+ friend class PingSender;
+
+ public:
+ /**
+ * This method gets the destination IPv6 address to ping.
+ *
+ * @returns The ping destination IPv6 address.
+ *
+ */
+ Ip6::Address &GetDestination(void) { return static_cast<Ip6::Address &>(mDestination); }
+
+ /**
+ * This method gets the destination IPv6 address to ping.
+ *
+ * @returns The ping destination IPv6 address.
+ *
+ */
+ const Ip6::Address &GetDestination(void) const { return static_cast<const Ip6::Address &>(mDestination); }
+
+ private:
+ enum : uint16_t
+ {
+ kDefaultSize = OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_SIZE,
+ kDefaultCount = OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_COUNT,
+ };
+
+ enum : uint32_t
+ {
+ kDefaultInterval = OPENTHREAD_CONFIG_PING_SENDER_DEFAULT_INTEVRAL,
+ };
+
+ void SetUnspecifiedToDefault(void);
+ void InvokeCallback(const Reply &aReply) const;
+ };
+
+ /**
+ * This constructor initializes the `PingSender` object.
+ *
+ * @param[in] aInstance A reference to the OpenThread instance.
+ *
+ */
+ explicit PingSender(Instance &aInstance);
+
+ /**
+ * This method starts a ping.
+ *
+ * @param[in] aConfig The ping config to use.
+ *
+ * @retval kErrorNone The ping started successfully.
+ * @retval kErrorBusy Could not start since busy with a previous ongoing ping request.
+ * @retval kErrorInvalidArgs The @p aConfig contains invalid parameters (e.g., ping interval is too long).
+ *
+ */
+ Error Ping(const Config &aConfig);
+
+ /**
+ * This method stops an ongoing ping.
+ *
+ */
+ void Stop(void);
+
+private:
+ void SendPing(void);
+ static void HandleTimer(Timer &aTimer);
+ void HandleTimer(void);
+ static void HandleIcmpReceive(void * aContext,
+ otMessage * aMessage,
+ const otMessageInfo *aMessageInfo,
+ const otIcmp6Header *aIcmpHeader);
+ void HandleIcmpReceive(const Message & aMessage,
+ const Ip6::MessageInfo & aMessageInfo,
+ const Ip6::Icmp::Header &aIcmpHeader);
+
+ Config mConfig;
+ uint16_t mIdentifier;
+ TimerMilli mTimer;
+ Ip6::Icmp::Handler mIcmpHandler;
+};
+
+} // namespace Utils
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_PING_SENDER_ENABLE
+
+#endif // PING_SENDER_HPP_
diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp
index 4222c38..168d3c0 100644
--- a/src/core/utils/slaac_address.cpp
+++ b/src/core/utils/slaac_address.cpp
@@ -164,7 +164,7 @@
{
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
if (config.mDp)
{
@@ -197,7 +197,7 @@
iterator = NetworkData::kIteratorInit;
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
{
Ip6::Prefix &prefix = config.GetPrefix();
@@ -252,10 +252,10 @@
}
}
-otError Slaac::GenerateIid(Ip6::NetifUnicastAddress &aAddress,
- uint8_t * aNetworkId,
- uint8_t aNetworkIdLength,
- uint8_t * aDadCounter) const
+Error Slaac::GenerateIid(Ip6::NetifUnicastAddress &aAddress,
+ uint8_t * aNetworkId,
+ uint8_t aNetworkIdLength,
+ uint8_t * aDadCounter) const
{
/*
* This method generates a semantically opaque IID per RFC 7217.
@@ -272,7 +272,7 @@
*
*/
- otError error = OT_ERROR_FAILED;
+ Error error = kErrorFailed;
const uint8_t netIface[] = {'w', 'p', 'a', 'n'};
uint8_t dadCounter = aDadCounter ? *aDadCounter : 0;
IidSecretKey secretKey;
@@ -294,9 +294,9 @@
sha256.Update(aNetworkId, aNetworkIdLength);
}
- sha256.Update(netIface, sizeof(netIface));
- sha256.Update(reinterpret_cast<uint8_t *>(&dadCounter), sizeof(dadCounter));
- sha256.Update(secretKey.m8, sizeof(IidSecretKey));
+ sha256.Update(netIface);
+ sha256.Update(dadCounter);
+ sha256.Update(secretKey);
sha256.Finish(hash);
aAddress.GetAddress().GetIid().SetBytes(hash.GetBytes());
@@ -313,7 +313,7 @@
}
// Exit and return the address if the IID is not reserved,
- ExitNow(error = OT_ERROR_NONE);
+ ExitNow(error = kErrorNone);
}
otLogWarnUtil("SLAAC: Failed to generate a non-reserved IID after %d attempts", kMaxIidCreationAttempts);
@@ -324,17 +324,17 @@
void Slaac::GetIidSecretKey(IidSecretKey &aKey) const
{
- otError error;
+ Error error;
error = Get<Settings>().ReadSlaacIidSecretKey(aKey);
- VerifyOrExit(error != OT_ERROR_NONE);
+ VerifyOrExit(error != kErrorNone);
// If there is no previously saved secret key, generate
// a random one and save it.
error = Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey));
- if (error != OT_ERROR_NONE)
+ if (error != kErrorNone)
{
IgnoreError(Random::Crypto::FillBuffer(aKey.m8, sizeof(IidSecretKey)));
}
diff --git a/src/core/utils/slaac_address.hpp b/src/core/utils/slaac_address.hpp
index f8a82e7..1b0d3cf 100644
--- a/src/core/utils/slaac_address.hpp
+++ b/src/core/utils/slaac_address.hpp
@@ -135,14 +135,14 @@
* @param[inout] aDadCounter A pointer to the DAD_Counter that is employed to resolve Duplicate
* Address Detection connflicts.
*
- * @retval OT_ERROR_NONE If successfully generated the IID.
- * @retval OT_ERROR_FAILED If no valid IID was generated.
+ * @retval kErrorNone If successfully generated the IID.
+ * @retval kErrorFailed If no valid IID was generated.
*
*/
- otError GenerateIid(Ip6::NetifUnicastAddress &aAddress,
- uint8_t * aNetworkId = nullptr,
- uint8_t aNetworkIdLength = 0,
- uint8_t * aDadCounter = nullptr) const;
+ Error GenerateIid(Ip6::NetifUnicastAddress &aAddress,
+ uint8_t * aNetworkId = nullptr,
+ uint8_t aNetworkIdLength = 0,
+ uint8_t * aDadCounter = nullptr) const;
private:
enum
diff --git a/tests/scripts/expect/cli-anycast.exp b/src/lib/platform/BUILD.gn
similarity index 74%
copy from tests/scripts/expect/cli-anycast.exp
copy to src/lib/platform/BUILD.gn
index 3081a6b..c46831e 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/src/lib/platform/BUILD.gn
@@ -1,6 +1,4 @@
-#!/usr/bin/expect -f
-#
-# Copyright (c) 2020, The OpenThread Authors.
+# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,30 +25,18 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+visibility = [ "../../../*" ]
+platform_sources = [
+ "exit_code.c",
+ "exit_code.h",
+]
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
+config("platform_config") {
+ include_dirs = [ ".." ]
}
-dispose
+static_library("libopenthread-platform") {
+ sources = platform_sources
+ public_configs = [ ":platform_config" ]
+}
diff --git a/src/lib/spinel/BUILD.gn b/src/lib/spinel/BUILD.gn
index 0747f91..e4e8f03 100644
--- a/src/lib/spinel/BUILD.gn
+++ b/src/lib/spinel/BUILD.gn
@@ -69,6 +69,7 @@
public_deps = [
":spinel-api",
"../../core:libopenthread_core_headers",
+ "../platform:libopenthread-platform",
]
public_configs = [ ":spinel_config_openthread_message_enable" ]
}
@@ -78,6 +79,7 @@
public_deps = [
":spinel-api",
"../../core:libopenthread_core_headers",
+ "../platform:libopenthread-platform",
]
public_configs = [ ":spinel_config_openthread_message_disable" ]
}
diff --git a/src/lib/spinel/CMakeLists.txt b/src/lib/spinel/CMakeLists.txt
index f7b24ba..1f2dd8d 100644
--- a/src/lib/spinel/CMakeLists.txt
+++ b/src/lib/spinel/CMakeLists.txt
@@ -38,13 +38,13 @@
target_compile_definitions(openthread-spinel-ncp PRIVATE
OPENTHREAD_FTD=1
- OPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+ OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
target_compile_definitions(openthread-spinel-rcp PRIVATE
OPENTHREAD_RADIO=1
- OPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+ OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=0
)
diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp
index df57b34..e21083a 100644
--- a/src/lib/spinel/radio_spinel.hpp
+++ b/src/lib/spinel/radio_spinel.hpp
@@ -113,13 +113,14 @@
/**
* Initialize this radio transceiver.
*
- * @param[in] aResetRadio TRUE to reset on init, FALSE to not reset on init.
- * @param[in] aRestoreDatasetFromNcp TRUE to restore dataset to host from non-volatile memory
- * (only used when attempts to upgrade from NCP to RCP mode),
- * FALSE otherwise.
+ * @param[in] aResetRadio TRUE to reset on init, FALSE to not reset on init.
+ * @param[in] aRestoreDatasetFromNcp TRUE to restore dataset to host from non-volatile memory
+ * (only used when attempts to upgrade from NCP to RCP mode),
+ * FALSE otherwise.
+ * @param[in] aSkipRcpCompatibilityCheck TRUE to skip RCP compatibility check, FALSE to perform the check.
*
*/
- void Init(bool aResetRadio, bool aRestoreDataSetFromNcp);
+ void Init(bool aResetRadio, bool aRestoreDataSetFromNcp, bool aSkipRcpCompatibilityCheck);
/**
* Deinitialize this radio transceiver.
@@ -651,6 +652,29 @@
otError SetMacFrameCounter(uint32_t aMacFrameCounter);
/**
+ * This method sets the radio region code.
+ *
+ * @param[in] aRegionCode The radio region code.
+ *
+ * @retval OT_ERROR_NONE Successfully set region code.
+ * @retval OT_ERROR_FAILED Other platform specific errors.
+ *
+ */
+ otError SetRadioRegion(uint16_t aRegionCode);
+
+ /**
+ * This method gets the radio region code.
+ *
+ * @param[out] aRegionCode The radio region code.
+ *
+ * @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr.
+ * @retval OT_ERROR_NONE Successfully got region code.
+ * @retval OT_ERROR_FAILED Other platform specific errors.
+ *
+ */
+ otError GetRadioRegion(uint16_t *aRegionCode);
+
+ /**
* This method checks whether the spinel interface is radio-only.
*
* @param[out] aSupportsRcpApiVersion A reference to a boolean variable to update whether the list of spinel
diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp
index be5c201..612443b 100644
--- a/src/lib/spinel/radio_spinel_impl.hpp
+++ b/src/lib/spinel/radio_spinel_impl.hpp
@@ -38,7 +38,6 @@
#include <openthread/dataset.h>
#include <openthread/platform/diag.h>
-#include <openthread/platform/settings.h>
#include <openthread/platform/time.h>
#include "common/code_utils.hpp"
@@ -80,7 +79,7 @@
namespace ot {
namespace Spinel {
-static otError SpinelStatusToOtError(spinel_status_t aError)
+static inline otError SpinelStatusToOtError(spinel_status_t aError)
{
otError ret;
@@ -154,7 +153,7 @@
return ret;
}
-static void LogIfFail(const char *aText, otError aError)
+static inline void LogIfFail(const char *aText, otError aError)
{
OT_UNUSED_VARIABLE(aText);
OT_UNUSED_VARIABLE(aError);
@@ -220,7 +219,9 @@
}
template <typename InterfaceType, typename ProcessContextType>
-void RadioSpinel<InterfaceType, ProcessContextType>::Init(bool aResetRadio, bool aRestoreDatasetFromNcp)
+void RadioSpinel<InterfaceType, ProcessContextType>::Init(bool aResetRadio,
+ bool aRestoreDatasetFromNcp,
+ bool aSkipRcpCompatibilityCheck)
{
otError error = OT_ERROR_NONE;
bool supportsRcpApiVersion;
@@ -247,14 +248,19 @@
if (aRestoreDatasetFromNcp)
{
+#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
exitCode = (RestoreDatasetFromNcp() == OT_ERROR_NONE) ? OT_EXIT_SUCCESS : OT_EXIT_FAILURE;
+#endif
}
DieNow(exitCode);
}
- SuccessOrDie(CheckRcpApiVersion(supportsRcpApiVersion));
- SuccessOrDie(CheckRadioCapabilities());
+ if (!aSkipRcpCompatibilityCheck)
+ {
+ SuccessOrDie(CheckRcpApiVersion(supportsRcpApiVersion));
+ SuccessOrDie(CheckRadioCapabilities());
+ }
mRxRadioFrame.mPsdu = mRxPsdu;
mTxRadioFrame.mPsdu = mTxPsdu;
@@ -408,12 +414,13 @@
return error;
}
+#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::RestoreDatasetFromNcp(void)
{
otError error = OT_ERROR_NONE;
- otPlatSettingsInit(mInstance);
+ Instance::Get().template Get<SettingsDriver>().Init();
otLogInfoPlat("Trying to get saved dataset from NCP");
SuccessOrExit(
@@ -422,9 +429,10 @@
error = Get(SPINEL_PROP_THREAD_PENDING_DATASET, SPINEL_DATATYPE_VOID_S, &RadioSpinel::ThreadDatasetHandler));
exit:
- otPlatSettingsDeinit(mInstance);
+ Instance::Get().template Get<SettingsDriver>().Deinit();
return error;
}
+#endif
template <typename InterfaceType, typename ProcessContextType>
void RadioSpinel<InterfaceType, ProcessContextType>::Deinit(void)
@@ -581,6 +589,7 @@
LogIfFail("Error processing response", error);
}
+#if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::ThreadDatasetHandler(const uint8_t *aBuffer, uint16_t aLength)
{
@@ -727,13 +736,14 @@
opDataset.mComponents.mIsActiveTimestampPresent = true;
SuccessOrExit(error = dataset.SetFrom(static_cast<MeshCoP::Dataset::Info &>(opDataset)));
- SuccessOrExit(error = otPlatSettingsSet(
- mInstance, isActive ? SettingsBase::kKeyActiveDataset : SettingsBase::kKeyPendingDataset,
- dataset.GetBytes(), dataset.GetSize()));
+ SuccessOrExit(error = Instance::Get().template Get<SettingsDriver>().Set(
+ isActive ? SettingsBase::kKeyActiveDataset : SettingsBase::kKeyPendingDataset, dataset.GetBytes(),
+ dataset.GetSize()));
exit:
return error;
}
+#endif // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
template <typename InterfaceType, typename ProcessContextType>
void RadioSpinel<InterfaceType, ProcessContextType>::HandleWaitingResponse(uint32_t aCommand,
@@ -2116,13 +2126,14 @@
localTxTimestamp = otPlatTimeGet();
// Dummy timestamp payload to make request length same as response
- error = GetWithParam(SPINEL_PROP_RCP_TIMESTAMP, buffer, packed, SPINEL_DATATYPE_UINT64_S, &remoteTimestamp);
+ error = GetWithParam(SPINEL_PROP_RCP_TIMESTAMP, buffer, static_cast<spinel_size_t>(packed),
+ SPINEL_DATATYPE_UINT64_S, &remoteTimestamp);
localRxTimestamp = otPlatTimeGet();
VerifyOrExit(error == OT_ERROR_NONE, mRadioTimeRecalcStart = localRxTimestamp);
- mRadioTimeOffset = remoteTimestamp - ((localRxTimestamp / 2) + (localTxTimestamp / 2));
+ mRadioTimeOffset = static_cast<int64_t>(remoteTimestamp - ((localRxTimestamp / 2) + (localTxTimestamp / 2)));
mIsTimeSynced = true;
mRadioTimeRecalcStart = localRxTimestamp + RCP_TIME_OFFSET_CHECK_INTERVAL;
@@ -2146,6 +2157,8 @@
template <typename InterfaceType, typename ProcessContextType>
void RadioSpinel<InterfaceType, ProcessContextType>::HandleRcpUnexpectedReset(spinel_status_t aStatus)
{
+ OT_UNUSED_VARIABLE(aStatus);
+
otLogCritPlat("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus));
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
@@ -2262,8 +2275,12 @@
sizeof(otMacKey)));
}
- SuccessOrDie(Instance::Get().template Get<Settings>().ReadNetworkInfo(networkInfo));
- SuccessOrDie(Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S, networkInfo.GetMacFrameCounter()));
+ if (mInstance != nullptr)
+ {
+ SuccessOrDie(static_cast<Instance *>(mInstance)->template Get<Settings>().ReadNetworkInfo(networkInfo));
+ SuccessOrDie(
+ Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S, networkInfo.GetMacFrameCounter()));
+ }
for (int i = 0; i < mSrcMatchShortEntryCount; ++i)
{
@@ -2329,5 +2346,23 @@
return error;
}
+template <typename InterfaceType, typename ProcessContextType>
+otError RadioSpinel<InterfaceType, ProcessContextType>::SetRadioRegion(uint16_t aRegionCode)
+{
+ return Set(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
+}
+
+template <typename InterfaceType, typename ProcessContextType>
+otError RadioSpinel<InterfaceType, ProcessContextType>::GetRadioRegion(uint16_t *aRegionCode)
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(aRegionCode != nullptr, error = OT_ERROR_INVALID_ARGS);
+ error = Get(SPINEL_PROP_PHY_REGION_CODE, SPINEL_DATATYPE_UINT16_S, aRegionCode);
+
+exit:
+ return error;
+}
+
} // namespace Spinel
} // namespace ot
diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c
index 7595a7f..9181e6e 100644
--- a/src/lib/spinel/spinel.c
+++ b/src/lib/spinel/spinel.c
@@ -1148,1619 +1148,489 @@
// LCOV_EXCL_START
+struct spinel_cstr
+{
+ uint32_t val;
+ const char *str;
+};
+#define __SPINEL_CSTR(PREFIX, VALUE) \
+ { \
+ (uint32_t) PREFIX##VALUE, #VALUE \
+ }
+
+static const char *spinel_to_cstr(const struct spinel_cstr *table, uint32_t val)
+{
+ int i;
+
+ for (i = 0; table[i].str; i++)
+ if (val == table[i].val)
+ return table[i].str;
+ return "UNKNOWN";
+}
+
+#define SPINEL_COMMAND_CSTR(VALUE) __SPINEL_CSTR(SPINEL_CMD_, VALUE)
const char *spinel_command_to_cstr(spinel_command_t command)
{
- const char *ret = "UNKNOWN";
+ static const struct spinel_cstr spinel_commands_cstr[] = {
+ SPINEL_COMMAND_CSTR(NOOP),
+ SPINEL_COMMAND_CSTR(RESET),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_GET),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_SET),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_INSERT),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_REMOVE),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_IS),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_INSERTED),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_REMOVED),
+ SPINEL_COMMAND_CSTR(NET_SAVE),
+ SPINEL_COMMAND_CSTR(NET_CLEAR),
+ SPINEL_COMMAND_CSTR(NET_RECALL),
+ SPINEL_COMMAND_CSTR(HBO_OFFLOAD),
+ SPINEL_COMMAND_CSTR(HBO_RECLAIM),
+ SPINEL_COMMAND_CSTR(HBO_DROP),
+ SPINEL_COMMAND_CSTR(HBO_OFFLOADED),
+ SPINEL_COMMAND_CSTR(HBO_RECLAIMED),
+ SPINEL_COMMAND_CSTR(HBO_DROPPED),
+ SPINEL_COMMAND_CSTR(PEEK),
+ SPINEL_COMMAND_CSTR(PEEK_RET),
+ SPINEL_COMMAND_CSTR(POKE),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_MULTI_GET),
+ SPINEL_COMMAND_CSTR(PROP_VALUE_MULTI_SET),
+ SPINEL_COMMAND_CSTR(PROP_VALUES_ARE),
+ {0},
+ };
- switch (command)
- {
- case SPINEL_CMD_NOOP:
- ret = "NOOP";
- break;
-
- case SPINEL_CMD_RESET:
- ret = "RESET";
- break;
-
- case SPINEL_CMD_PROP_VALUE_GET:
- ret = "PROP_VALUE_GET";
- break;
-
- case SPINEL_CMD_PROP_VALUE_SET:
- ret = "PROP_VALUE_SET";
- break;
-
- case SPINEL_CMD_PROP_VALUE_INSERT:
- ret = "PROP_VALUE_INSERT";
- break;
-
- case SPINEL_CMD_PROP_VALUE_REMOVE:
- ret = "PROP_VALUE_REMOVE";
- break;
-
- case SPINEL_CMD_PROP_VALUE_IS:
- ret = "PROP_VALUE_IS";
- break;
-
- case SPINEL_CMD_PROP_VALUE_INSERTED:
- ret = "PROP_VALUE_INSERTED";
- break;
-
- case SPINEL_CMD_PROP_VALUE_REMOVED:
- ret = "PROP_VALUE_REMOVED";
- break;
-
- case SPINEL_CMD_NET_SAVE:
- ret = "NET_SAVE";
- break;
-
- case SPINEL_CMD_NET_CLEAR:
- ret = "NET_CLEAR";
- break;
-
- case SPINEL_CMD_NET_RECALL:
- ret = "NET_RECALL";
- break;
-
- case SPINEL_CMD_HBO_OFFLOAD:
- ret = "HBO_OFFLOAD";
- break;
-
- case SPINEL_CMD_HBO_RECLAIM:
- ret = "HBO_RECLAIM";
- break;
-
- case SPINEL_CMD_HBO_DROP:
- ret = "HBO_DROP";
- break;
-
- case SPINEL_CMD_HBO_OFFLOADED:
- ret = "HBO_OFFLOADED";
- break;
-
- case SPINEL_CMD_HBO_RECLAIMED:
- ret = "HBO_RECLAIMED";
- break;
-
- case SPINEL_CMD_HBO_DROPPED:
- ret = "HBO_DROPPED";
- break;
-
- case SPINEL_CMD_PEEK:
- ret = "PEEK";
- break;
-
- case SPINEL_CMD_PEEK_RET:
- ret = "PEEK_RET";
- break;
-
- case SPINEL_CMD_POKE:
- ret = "POKE";
- break;
-
- case SPINEL_CMD_PROP_VALUE_MULTI_GET:
- ret = "PROP_VALUE_MULTI_GET";
- break;
-
- case SPINEL_CMD_PROP_VALUE_MULTI_SET:
- ret = "PROP_VALUE_MULTI_SET";
- break;
-
- case SPINEL_CMD_PROP_VALUES_ARE:
- ret = "PROP_VALUES_ARE";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_commands_cstr, command);
}
+#define SPINEL_PROP_CSTR(VALUE) __SPINEL_CSTR(SPINEL_PROP_, VALUE)
const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
{
- const char *ret = "UNKNOWN";
+ static const struct spinel_cstr spinel_prop_cstr[] = {
+ SPINEL_PROP_CSTR(LAST_STATUS),
+ SPINEL_PROP_CSTR(PROTOCOL_VERSION),
+ SPINEL_PROP_CSTR(NCP_VERSION),
+ SPINEL_PROP_CSTR(INTERFACE_TYPE),
+ SPINEL_PROP_CSTR(VENDOR_ID),
+ SPINEL_PROP_CSTR(CAPS),
+ SPINEL_PROP_CSTR(INTERFACE_COUNT),
+ SPINEL_PROP_CSTR(POWER_STATE),
+ SPINEL_PROP_CSTR(HWADDR),
+ SPINEL_PROP_CSTR(LOCK),
+ SPINEL_PROP_CSTR(HBO_MEM_MAX),
+ SPINEL_PROP_CSTR(HBO_BLOCK_MAX),
+ SPINEL_PROP_CSTR(HOST_POWER_STATE),
+ SPINEL_PROP_CSTR(MCU_POWER_STATE),
+ SPINEL_PROP_CSTR(GPIO_CONFIG),
+ SPINEL_PROP_CSTR(GPIO_STATE),
+ SPINEL_PROP_CSTR(GPIO_STATE_SET),
+ SPINEL_PROP_CSTR(GPIO_STATE_CLEAR),
+ SPINEL_PROP_CSTR(TRNG_32),
+ SPINEL_PROP_CSTR(TRNG_128),
+ SPINEL_PROP_CSTR(TRNG_RAW_32),
+ SPINEL_PROP_CSTR(UNSOL_UPDATE_FILTER),
+ SPINEL_PROP_CSTR(UNSOL_UPDATE_LIST),
+ SPINEL_PROP_CSTR(PHY_ENABLED),
+ SPINEL_PROP_CSTR(PHY_CHAN),
+ SPINEL_PROP_CSTR(PHY_CHAN_SUPPORTED),
+ SPINEL_PROP_CSTR(PHY_FREQ),
+ SPINEL_PROP_CSTR(PHY_CCA_THRESHOLD),
+ SPINEL_PROP_CSTR(PHY_TX_POWER),
+ SPINEL_PROP_CSTR(PHY_FEM_LNA_GAIN),
+ SPINEL_PROP_CSTR(PHY_RSSI),
+ SPINEL_PROP_CSTR(PHY_RX_SENSITIVITY),
+ SPINEL_PROP_CSTR(PHY_PCAP_ENABLED),
+ SPINEL_PROP_CSTR(PHY_CHAN_PREFERRED),
+ SPINEL_PROP_CSTR(PHY_CHAN_MAX_POWER),
+ SPINEL_PROP_CSTR(JAM_DETECT_ENABLE),
+ SPINEL_PROP_CSTR(JAM_DETECTED),
+ SPINEL_PROP_CSTR(JAM_DETECT_RSSI_THRESHOLD),
+ SPINEL_PROP_CSTR(JAM_DETECT_WINDOW),
+ SPINEL_PROP_CSTR(JAM_DETECT_BUSY),
+ SPINEL_PROP_CSTR(JAM_DETECT_HISTORY_BITMAP),
+ SPINEL_PROP_CSTR(CHANNEL_MONITOR_SAMPLE_INTERVAL),
+ SPINEL_PROP_CSTR(CHANNEL_MONITOR_RSSI_THRESHOLD),
+ SPINEL_PROP_CSTR(CHANNEL_MONITOR_SAMPLE_WINDOW),
+ SPINEL_PROP_CSTR(CHANNEL_MONITOR_SAMPLE_COUNT),
+ SPINEL_PROP_CSTR(CHANNEL_MONITOR_CHANNEL_OCCUPANCY),
+ SPINEL_PROP_CSTR(RADIO_CAPS),
+ SPINEL_PROP_CSTR(RADIO_COEX_METRICS),
+ SPINEL_PROP_CSTR(RADIO_COEX_ENABLE),
+ SPINEL_PROP_CSTR(MAC_SCAN_STATE),
+ SPINEL_PROP_CSTR(MAC_SCAN_MASK),
+ SPINEL_PROP_CSTR(MAC_SCAN_PERIOD),
+ SPINEL_PROP_CSTR(MAC_SCAN_BEACON),
+ SPINEL_PROP_CSTR(MAC_15_4_LADDR),
+ SPINEL_PROP_CSTR(MAC_15_4_SADDR),
+ SPINEL_PROP_CSTR(MAC_15_4_PANID),
+ SPINEL_PROP_CSTR(MAC_RAW_STREAM_ENABLED),
+ SPINEL_PROP_CSTR(MAC_PROMISCUOUS_MODE),
+ SPINEL_PROP_CSTR(MAC_ENERGY_SCAN_RESULT),
+ SPINEL_PROP_CSTR(MAC_DATA_POLL_PERIOD),
+ SPINEL_PROP_CSTR(MAC_ALLOWLIST),
+ SPINEL_PROP_CSTR(MAC_ALLOWLIST_ENABLED),
+ SPINEL_PROP_CSTR(MAC_EXTENDED_ADDR),
+ SPINEL_PROP_CSTR(MAC_SRC_MATCH_ENABLED),
+ SPINEL_PROP_CSTR(MAC_SRC_MATCH_SHORT_ADDRESSES),
+ SPINEL_PROP_CSTR(MAC_SRC_MATCH_EXTENDED_ADDRESSES),
+ SPINEL_PROP_CSTR(MAC_DENYLIST),
+ SPINEL_PROP_CSTR(MAC_DENYLIST_ENABLED),
+ SPINEL_PROP_CSTR(MAC_FIXED_RSS),
+ SPINEL_PROP_CSTR(MAC_CCA_FAILURE_RATE),
+ SPINEL_PROP_CSTR(MAC_MAX_RETRY_NUMBER_DIRECT),
+ SPINEL_PROP_CSTR(MAC_MAX_RETRY_NUMBER_INDIRECT),
+ SPINEL_PROP_CSTR(NET_SAVED),
+ SPINEL_PROP_CSTR(NET_IF_UP),
+ SPINEL_PROP_CSTR(NET_STACK_UP),
+ SPINEL_PROP_CSTR(NET_ROLE),
+ SPINEL_PROP_CSTR(NET_NETWORK_NAME),
+ SPINEL_PROP_CSTR(NET_XPANID),
+ SPINEL_PROP_CSTR(NET_MASTER_KEY),
+ SPINEL_PROP_CSTR(NET_KEY_SEQUENCE_COUNTER),
+ SPINEL_PROP_CSTR(NET_PARTITION_ID),
+ SPINEL_PROP_CSTR(NET_REQUIRE_JOIN_EXISTING),
+ SPINEL_PROP_CSTR(NET_KEY_SWITCH_GUARDTIME),
+ SPINEL_PROP_CSTR(NET_PSKC),
+ SPINEL_PROP_CSTR(THREAD_LEADER_ADDR),
+ SPINEL_PROP_CSTR(THREAD_PARENT),
+ SPINEL_PROP_CSTR(THREAD_CHILD_TABLE),
+ SPINEL_PROP_CSTR(THREAD_LEADER_RID),
+ SPINEL_PROP_CSTR(THREAD_LEADER_WEIGHT),
+ SPINEL_PROP_CSTR(THREAD_LOCAL_LEADER_WEIGHT),
+ SPINEL_PROP_CSTR(THREAD_NETWORK_DATA),
+ SPINEL_PROP_CSTR(THREAD_NETWORK_DATA_VERSION),
+ SPINEL_PROP_CSTR(THREAD_STABLE_NETWORK_DATA),
+ SPINEL_PROP_CSTR(THREAD_STABLE_NETWORK_DATA_VERSION),
+ SPINEL_PROP_CSTR(THREAD_ON_MESH_NETS),
+ SPINEL_PROP_CSTR(THREAD_OFF_MESH_ROUTES),
+ SPINEL_PROP_CSTR(THREAD_ASSISTING_PORTS),
+ SPINEL_PROP_CSTR(THREAD_ALLOW_LOCAL_NET_DATA_CHANGE),
+ SPINEL_PROP_CSTR(THREAD_MODE),
+ SPINEL_PROP_CSTR(THREAD_CHILD_TIMEOUT),
+ SPINEL_PROP_CSTR(THREAD_RLOC16),
+ SPINEL_PROP_CSTR(THREAD_ROUTER_UPGRADE_THRESHOLD),
+ SPINEL_PROP_CSTR(THREAD_CONTEXT_REUSE_DELAY),
+ SPINEL_PROP_CSTR(THREAD_NETWORK_ID_TIMEOUT),
+ SPINEL_PROP_CSTR(THREAD_ACTIVE_ROUTER_IDS),
+ SPINEL_PROP_CSTR(THREAD_RLOC16_DEBUG_PASSTHRU),
+ SPINEL_PROP_CSTR(THREAD_ROUTER_ROLE_ENABLED),
+ SPINEL_PROP_CSTR(THREAD_ROUTER_DOWNGRADE_THRESHOLD),
+ SPINEL_PROP_CSTR(THREAD_ROUTER_SELECTION_JITTER),
+ SPINEL_PROP_CSTR(THREAD_PREFERRED_ROUTER_ID),
+ SPINEL_PROP_CSTR(THREAD_NEIGHBOR_TABLE),
+ SPINEL_PROP_CSTR(THREAD_CHILD_COUNT_MAX),
+ SPINEL_PROP_CSTR(THREAD_LEADER_NETWORK_DATA),
+ SPINEL_PROP_CSTR(THREAD_STABLE_LEADER_NETWORK_DATA),
+ SPINEL_PROP_CSTR(THREAD_JOINERS),
+ SPINEL_PROP_CSTR(THREAD_COMMISSIONER_ENABLED),
+ SPINEL_PROP_CSTR(THREAD_TMF_PROXY_ENABLED),
+ SPINEL_PROP_CSTR(THREAD_TMF_PROXY_STREAM),
+ SPINEL_PROP_CSTR(THREAD_UDP_FORWARD_STREAM),
+ SPINEL_PROP_CSTR(THREAD_DISCOVERY_SCAN_JOINER_FLAG),
+ SPINEL_PROP_CSTR(THREAD_DISCOVERY_SCAN_ENABLE_FILTERING),
+ SPINEL_PROP_CSTR(THREAD_DISCOVERY_SCAN_PANID),
+ SPINEL_PROP_CSTR(THREAD_STEERING_DATA),
+ SPINEL_PROP_CSTR(THREAD_ROUTER_TABLE),
+ SPINEL_PROP_CSTR(THREAD_ACTIVE_DATASET),
+ SPINEL_PROP_CSTR(THREAD_PENDING_DATASET),
+ SPINEL_PROP_CSTR(THREAD_MGMT_SET_ACTIVE_DATASET),
+ SPINEL_PROP_CSTR(THREAD_MGMT_SET_PENDING_DATASET),
+ SPINEL_PROP_CSTR(DATASET_ACTIVE_TIMESTAMP),
+ SPINEL_PROP_CSTR(DATASET_PENDING_TIMESTAMP),
+ SPINEL_PROP_CSTR(DATASET_DELAY_TIMER),
+ SPINEL_PROP_CSTR(DATASET_SECURITY_POLICY),
+ SPINEL_PROP_CSTR(DATASET_RAW_TLVS),
+ SPINEL_PROP_CSTR(THREAD_CHILD_TABLE_ADDRESSES),
+ SPINEL_PROP_CSTR(THREAD_NEIGHBOR_TABLE_ERROR_RATES),
+ SPINEL_PROP_CSTR(THREAD_ADDRESS_CACHE_TABLE),
+ SPINEL_PROP_CSTR(THREAD_MGMT_GET_ACTIVE_DATASET),
+ SPINEL_PROP_CSTR(THREAD_MGMT_GET_PENDING_DATASET),
+ SPINEL_PROP_CSTR(DATASET_DEST_ADDRESS),
+ SPINEL_PROP_CSTR(THREAD_NEW_DATASET),
+ SPINEL_PROP_CSTR(THREAD_CSL_PERIOD),
+ SPINEL_PROP_CSTR(THREAD_CSL_TIMEOUT),
+ SPINEL_PROP_CSTR(THREAD_CSL_CHANNEL),
+ SPINEL_PROP_CSTR(THREAD_DOMAIN_NAME),
+ SPINEL_PROP_CSTR(THREAD_MLR_REQUEST),
+ SPINEL_PROP_CSTR(THREAD_MLR_RESPONSE),
+ SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_PRIMARY),
+ SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_STATE),
+ SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_CONFIG),
+ SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_REGISTER),
+ SPINEL_PROP_CSTR(THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER),
+ SPINEL_PROP_CSTR(MESHCOP_JOINER_STATE),
+ SPINEL_PROP_CSTR(MESHCOP_JOINER_COMMISSIONING),
+ SPINEL_PROP_CSTR(IPV6_LL_ADDR),
+ SPINEL_PROP_CSTR(IPV6_ML_ADDR),
+ SPINEL_PROP_CSTR(IPV6_ML_PREFIX),
+ SPINEL_PROP_CSTR(IPV6_ADDRESS_TABLE),
+ SPINEL_PROP_CSTR(IPV6_ROUTE_TABLE),
+ SPINEL_PROP_CSTR(IPV6_ICMP_PING_OFFLOAD),
+ SPINEL_PROP_CSTR(IPV6_MULTICAST_ADDRESS_TABLE),
+ SPINEL_PROP_CSTR(IPV6_ICMP_PING_OFFLOAD_MODE),
+ SPINEL_PROP_CSTR(STREAM_DEBUG),
+ SPINEL_PROP_CSTR(STREAM_RAW),
+ SPINEL_PROP_CSTR(STREAM_NET),
+ SPINEL_PROP_CSTR(STREAM_NET_INSECURE),
+ SPINEL_PROP_CSTR(STREAM_LOG),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_STATE),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_JOINERS),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_PROVISIONING_URL),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_SESSION_ID),
+ SPINEL_PROP_CSTR(MESHCOP_JOINER_DISCERNER),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_ENERGY_SCAN),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_PAN_ID_QUERY),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_MGMT_GET),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_MGMT_SET),
+ SPINEL_PROP_CSTR(MESHCOP_COMMISSIONER_GENERATE_PSKC),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_NEW_CHANNEL),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_DELAY),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_SUPPORTED_CHANNELS),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_FAVORED_CHANNELS),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_CHANNEL_SELECT),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_AUTO_SELECT_ENABLED),
+ SPINEL_PROP_CSTR(CHANNEL_MANAGER_AUTO_SELECT_INTERVAL),
+ SPINEL_PROP_CSTR(THREAD_NETWORK_TIME),
+ SPINEL_PROP_CSTR(TIME_SYNC_PERIOD),
+ SPINEL_PROP_CSTR(TIME_SYNC_XTAL_THRESHOLD),
+ SPINEL_PROP_CSTR(CHILD_SUPERVISION_INTERVAL),
+ SPINEL_PROP_CSTR(CHILD_SUPERVISION_CHECK_TIMEOUT),
+ SPINEL_PROP_CSTR(RCP_VERSION),
+ SPINEL_PROP_CSTR(PARENT_RESPONSE_INFO),
+ SPINEL_PROP_CSTR(SLAAC_ENABLED),
+ SPINEL_PROP_CSTR(SUPPORTED_RADIO_LINKS),
+ SPINEL_PROP_CSTR(NEIGHBOR_TABLE_MULTI_RADIO_INFO),
+ SPINEL_PROP_CSTR(SRP_CLIENT_START),
+ SPINEL_PROP_CSTR(SRP_CLIENT_LEASE_INTERVAL),
+ SPINEL_PROP_CSTR(SRP_CLIENT_KEY_LEASE_INTERVAL),
+ SPINEL_PROP_CSTR(SRP_CLIENT_HOST_INFO),
+ SPINEL_PROP_CSTR(SRP_CLIENT_HOST_NAME),
+ SPINEL_PROP_CSTR(SRP_CLIENT_HOST_ADDRESSES),
+ SPINEL_PROP_CSTR(SRP_CLIENT_SERVICES),
+ SPINEL_PROP_CSTR(SRP_CLIENT_HOST_SERVICES_REMOVE),
+ SPINEL_PROP_CSTR(SRP_CLIENT_HOST_SERVICES_CLEAR),
+ SPINEL_PROP_CSTR(SRP_CLIENT_EVENT),
+ SPINEL_PROP_CSTR(SERVER_ALLOW_LOCAL_DATA_CHANGE),
+ SPINEL_PROP_CSTR(SERVER_SERVICES),
+ SPINEL_PROP_CSTR(SERVER_LEADER_SERVICES),
+ SPINEL_PROP_CSTR(RCP_API_VERSION),
+ SPINEL_PROP_CSTR(UART_BITRATE),
+ SPINEL_PROP_CSTR(UART_XON_XOFF),
+ SPINEL_PROP_CSTR(15_4_PIB_PHY_CHANNELS_SUPPORTED),
+ SPINEL_PROP_CSTR(15_4_PIB_MAC_PROMISCUOUS_MODE),
+ SPINEL_PROP_CSTR(15_4_PIB_MAC_SECURITY_ENABLED),
+ SPINEL_PROP_CSTR(CNTR_RESET),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_ACK_REQ),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_ACKED),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_NO_ACK_REQ),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_DATA),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_DATA_POLL),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_BEACON),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_BEACON_REQ),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_OTHER),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_RETRY),
+ SPINEL_PROP_CSTR(CNTR_TX_ERR_CCA),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_UNICAST),
+ SPINEL_PROP_CSTR(CNTR_TX_PKT_BROADCAST),
+ SPINEL_PROP_CSTR(CNTR_TX_ERR_ABORT),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_DATA),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_DATA_POLL),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_BEACON),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_BEACON_REQ),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_OTHER),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_FILT_WL),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_FILT_DA),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_EMPTY),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_UKWN_NBR),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_NVLD_SADDR),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_SECURITY),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_BAD_FCS),
+ SPINEL_PROP_CSTR(CNTR_RX_ERR_OTHER),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_DUP),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_UNICAST),
+ SPINEL_PROP_CSTR(CNTR_RX_PKT_BROADCAST),
+ SPINEL_PROP_CSTR(CNTR_TX_IP_SEC_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_TX_IP_INSEC_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_TX_IP_DROPPED),
+ SPINEL_PROP_CSTR(CNTR_RX_IP_SEC_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_RX_IP_INSEC_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_RX_IP_DROPPED),
+ SPINEL_PROP_CSTR(CNTR_TX_SPINEL_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_RX_SPINEL_TOTAL),
+ SPINEL_PROP_CSTR(CNTR_RX_SPINEL_ERR),
+ SPINEL_PROP_CSTR(CNTR_RX_SPINEL_OUT_OF_ORDER_TID),
+ SPINEL_PROP_CSTR(CNTR_IP_TX_SUCCESS),
+ SPINEL_PROP_CSTR(CNTR_IP_RX_SUCCESS),
+ SPINEL_PROP_CSTR(CNTR_IP_TX_FAILURE),
+ SPINEL_PROP_CSTR(CNTR_IP_RX_FAILURE),
+ SPINEL_PROP_CSTR(MSG_BUFFER_COUNTERS),
+ SPINEL_PROP_CSTR(CNTR_ALL_MAC_COUNTERS),
+ SPINEL_PROP_CSTR(CNTR_MLE_COUNTERS),
+ SPINEL_PROP_CSTR(CNTR_ALL_IP_COUNTERS),
+ SPINEL_PROP_CSTR(CNTR_MAC_RETRY_HISTOGRAM),
+ SPINEL_PROP_CSTR(NEST_STREAM_MFG),
+ SPINEL_PROP_CSTR(NEST_LEGACY_ULA_PREFIX),
+ SPINEL_PROP_CSTR(NEST_LEGACY_LAST_NODE_JOINED),
+ SPINEL_PROP_CSTR(DEBUG_TEST_ASSERT),
+ SPINEL_PROP_CSTR(DEBUG_NCP_LOG_LEVEL),
+ SPINEL_PROP_CSTR(DEBUG_TEST_WATCHDOG),
+ SPINEL_PROP_CSTR(RCP_MAC_FRAME_COUNTER),
+ SPINEL_PROP_CSTR(RCP_MAC_KEY),
+ SPINEL_PROP_CSTR(DEBUG_LOG_TIMESTAMP_BASE),
+ SPINEL_PROP_CSTR(DEBUG_TREL_TEST_MODE_ENABLE),
+ {0},
+ };
- switch (prop_key)
- {
- case SPINEL_PROP_LAST_STATUS:
- ret = "LAST_STATUS";
- break;
-
- case SPINEL_PROP_PROTOCOL_VERSION:
- ret = "PROTOCOL_VERSION";
- break;
-
- case SPINEL_PROP_NCP_VERSION:
- ret = "NCP_VERSION";
- break;
-
- case SPINEL_PROP_INTERFACE_TYPE:
- ret = "INTERFACE_TYPE";
- break;
-
- case SPINEL_PROP_VENDOR_ID:
- ret = "VENDOR_ID";
- break;
-
- case SPINEL_PROP_CAPS:
- ret = "CAPS";
- break;
-
- case SPINEL_PROP_INTERFACE_COUNT:
- ret = "INTERFACE_COUNT";
- break;
-
- case SPINEL_PROP_POWER_STATE:
- ret = "POWER_STATE";
- break;
-
- case SPINEL_PROP_HWADDR:
- ret = "HWADDR";
- break;
-
- case SPINEL_PROP_LOCK:
- ret = "LOCK";
- break;
-
- case SPINEL_PROP_HBO_MEM_MAX:
- ret = "HBO_MEM_MAX";
- break;
-
- case SPINEL_PROP_HBO_BLOCK_MAX:
- ret = "HBO_BLOCK_MAX";
- break;
-
- case SPINEL_PROP_HOST_POWER_STATE:
- ret = "HOST_POWER_STATE";
- break;
-
- case SPINEL_PROP_MCU_POWER_STATE:
- ret = "MCU_POWER_STATE";
- break;
-
- case SPINEL_PROP_GPIO_CONFIG:
- ret = "GPIO_CONFIG";
- break;
-
- case SPINEL_PROP_GPIO_STATE:
- ret = "GPIO_STATE";
- break;
-
- case SPINEL_PROP_GPIO_STATE_SET:
- ret = "GPIO_STATE_SET";
- break;
-
- case SPINEL_PROP_GPIO_STATE_CLEAR:
- ret = "GPIO_STATE_CLEAR";
- break;
-
- case SPINEL_PROP_TRNG_32:
- ret = "TRNG_32";
- break;
-
- case SPINEL_PROP_TRNG_128:
- ret = "TRNG_128";
- break;
-
- case SPINEL_PROP_TRNG_RAW_32:
- ret = "TRNG_RAW_32";
- break;
-
- case SPINEL_PROP_UNSOL_UPDATE_FILTER:
- ret = "UNSOL_UPDATE_FILTER";
- break;
-
- case SPINEL_PROP_UNSOL_UPDATE_LIST:
- ret = "UNSOL_UPDATE_LIST";
- break;
-
- case SPINEL_PROP_PHY_ENABLED:
- ret = "PHY_ENABLED";
- break;
-
- case SPINEL_PROP_PHY_CHAN:
- ret = "PHY_CHAN";
- break;
-
- case SPINEL_PROP_PHY_CHAN_SUPPORTED:
- ret = "PHY_CHAN_SUPPORTED";
- break;
-
- case SPINEL_PROP_PHY_FREQ:
- ret = "PHY_FREQ";
- break;
-
- case SPINEL_PROP_PHY_CCA_THRESHOLD:
- ret = "PHY_CCA_THRESHOLD";
- break;
-
- case SPINEL_PROP_PHY_TX_POWER:
- ret = "PHY_TX_POWER";
- break;
-
- case SPINEL_PROP_PHY_FEM_LNA_GAIN:
- ret = "PHY_FEM_LNA_GAIN";
- break;
-
- case SPINEL_PROP_PHY_RSSI:
- ret = "PHY_RSSI";
- break;
-
- case SPINEL_PROP_PHY_RX_SENSITIVITY:
- ret = "PHY_RX_SENSITIVITY";
- break;
-
- case SPINEL_PROP_PHY_PCAP_ENABLED:
- ret = "PHY_PCAP_ENABLED";
- break;
-
- case SPINEL_PROP_PHY_CHAN_PREFERRED:
- ret = "PHY_CHAN_PREFERRED";
- break;
-
- case SPINEL_PROP_PHY_CHAN_MAX_POWER:
- ret = "PHY_CHAN_MAX_POWER";
- break;
-
- case SPINEL_PROP_JAM_DETECT_ENABLE:
- ret = "JAM_DETECT_ENABLE";
- break;
-
- case SPINEL_PROP_JAM_DETECTED:
- ret = "JAM_DETECTED";
- break;
-
- case SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD:
- ret = "JAM_DETECT_RSSI_THRESHOLD";
- break;
-
- case SPINEL_PROP_JAM_DETECT_WINDOW:
- ret = "JAM_DETECT_WINDOW";
- break;
-
- case SPINEL_PROP_JAM_DETECT_BUSY:
- ret = "JAM_DETECT_BUSY";
- break;
-
- case SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP:
- ret = "JAM_DETECT_HISTORY_BITMAP";
- break;
-
- case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_INTERVAL:
- ret = "CHANNEL_MONITOR_SAMPLE_INTERVAL";
- break;
-
- case SPINEL_PROP_CHANNEL_MONITOR_RSSI_THRESHOLD:
- ret = "CHANNEL_MONITOR_RSSI_THRESHOLD";
- break;
-
- case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_WINDOW:
- ret = "CHANNEL_MONITOR_SAMPLE_WINDOW";
- break;
-
- case SPINEL_PROP_CHANNEL_MONITOR_SAMPLE_COUNT:
- ret = "CHANNEL_MONITOR_SAMPLE_COUNT";
- break;
-
- case SPINEL_PROP_CHANNEL_MONITOR_CHANNEL_OCCUPANCY:
- ret = "CHANNEL_MONITOR_CHANNEL_OCCUPANCY";
- break;
-
- case SPINEL_PROP_RADIO_CAPS:
- ret = "RADIO_CAPS";
- break;
-
- case SPINEL_PROP_RADIO_COEX_METRICS:
- ret = "RADIO_COEX_METRICS";
- break;
-
- case SPINEL_PROP_RADIO_COEX_ENABLE:
- ret = "RADIO_COEX_ENABLE";
- break;
-
- case SPINEL_PROP_MAC_SCAN_STATE:
- ret = "MAC_SCAN_STATE";
- break;
-
- case SPINEL_PROP_MAC_SCAN_MASK:
- ret = "MAC_SCAN_MASK";
- break;
-
- case SPINEL_PROP_MAC_SCAN_PERIOD:
- ret = "MAC_SCAN_PERIOD";
- break;
-
- case SPINEL_PROP_MAC_SCAN_BEACON:
- ret = "MAC_SCAN_BEACON";
- break;
-
- case SPINEL_PROP_MAC_15_4_LADDR:
- ret = "MAC_15_4_LADDR";
- break;
-
- case SPINEL_PROP_MAC_15_4_SADDR:
- ret = "MAC_15_4_SADDR";
- break;
-
- case SPINEL_PROP_MAC_15_4_PANID:
- ret = "MAC_15_4_PANID";
- break;
-
- case SPINEL_PROP_MAC_RAW_STREAM_ENABLED:
- ret = "MAC_RAW_STREAM_ENABLED";
- break;
-
- case SPINEL_PROP_MAC_PROMISCUOUS_MODE:
- ret = "MAC_PROMISCUOUS_MODE";
- break;
-
- case SPINEL_PROP_MAC_ENERGY_SCAN_RESULT:
- ret = "MAC_ENERGY_SCAN_RESULT";
- break;
-
- case SPINEL_PROP_MAC_DATA_POLL_PERIOD:
- ret = "MAC_DATA_POLL_PERIOD";
- break;
-
- case SPINEL_PROP_MAC_ALLOWLIST:
- ret = "MAC_ALLOWLIST";
- break;
-
- case SPINEL_PROP_MAC_ALLOWLIST_ENABLED:
- ret = "MAC_ALLOWLIST_ENABLED";
- break;
-
- case SPINEL_PROP_MAC_EXTENDED_ADDR:
- ret = "MAC_EXTENDED_ADDR";
- break;
-
- case SPINEL_PROP_MAC_SRC_MATCH_ENABLED:
- ret = "MAC_SRC_MATCH_ENABLED";
- break;
-
- case SPINEL_PROP_MAC_SRC_MATCH_SHORT_ADDRESSES:
- ret = "MAC_SRC_MATCH_SHORT_ADDRESSES";
- break;
-
- case SPINEL_PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES:
- ret = "MAC_SRC_MATCH_EXTENDED_ADDRESSES";
- break;
-
- case SPINEL_PROP_MAC_DENYLIST:
- ret = "MAC_DENYLIST";
- break;
-
- case SPINEL_PROP_MAC_DENYLIST_ENABLED:
- ret = "MAC_DENYLIST_ENABLED";
- break;
-
- case SPINEL_PROP_MAC_FIXED_RSS:
- ret = "MAC_FIXED_RSS";
- break;
-
- case SPINEL_PROP_MAC_CCA_FAILURE_RATE:
- ret = "MAC_CCA_FAILURE_RATE";
- break;
-
- case SPINEL_PROP_MAC_MAX_RETRY_NUMBER_DIRECT:
- ret = "MAC_MAX_RETRY_NUMBER_DIRECT";
- break;
-
- case SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT:
- ret = "MAC_MAX_RETRY_NUMBER_INDIRECT";
- break;
-
- case SPINEL_PROP_NET_SAVED:
- ret = "NET_SAVED";
- break;
-
- case SPINEL_PROP_NET_IF_UP:
- ret = "NET_IF_UP";
- break;
-
- case SPINEL_PROP_NET_STACK_UP:
- ret = "NET_STACK_UP";
- break;
-
- case SPINEL_PROP_NET_ROLE:
- ret = "NET_ROLE";
- break;
-
- case SPINEL_PROP_NET_NETWORK_NAME:
- ret = "NET_NETWORK_NAME";
- break;
-
- case SPINEL_PROP_NET_XPANID:
- ret = "NET_XPANID";
- break;
-
- case SPINEL_PROP_NET_MASTER_KEY:
- ret = "NET_MASTER_KEY";
- break;
-
- case SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER:
- ret = "NET_KEY_SEQUENCE_COUNTER";
- break;
-
- case SPINEL_PROP_NET_PARTITION_ID:
- ret = "NET_PARTITION_ID";
- break;
-
- case SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING:
- ret = "NET_REQUIRE_JOIN_EXISTING";
- break;
-
- case SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME:
- ret = "NET_KEY_SWITCH_GUARDTIME";
- break;
-
- case SPINEL_PROP_NET_PSKC:
- ret = "NET_PSKC";
- break;
-
- case SPINEL_PROP_THREAD_LEADER_ADDR:
- ret = "THREAD_LEADER_ADDR";
- break;
-
- case SPINEL_PROP_THREAD_PARENT:
- ret = "THREAD_PARENT";
- break;
-
- case SPINEL_PROP_THREAD_CHILD_TABLE:
- ret = "THREAD_CHILD_TABLE";
- break;
-
- case SPINEL_PROP_THREAD_LEADER_RID:
- ret = "THREAD_LEADER_RID";
- break;
-
- case SPINEL_PROP_THREAD_LEADER_WEIGHT:
- ret = "THREAD_LEADER_WEIGHT";
- break;
-
- case SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT:
- ret = "THREAD_LOCAL_LEADER_WEIGHT";
- break;
-
- case SPINEL_PROP_THREAD_NETWORK_DATA:
- ret = "THREAD_NETWORK_DATA";
- break;
-
- case SPINEL_PROP_THREAD_NETWORK_DATA_VERSION:
- ret = "THREAD_NETWORK_DATA_VERSION";
- break;
-
- case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA:
- ret = "THREAD_STABLE_NETWORK_DATA";
- break;
-
- case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION:
- ret = "THREAD_STABLE_NETWORK_DATA_VERSION";
- break;
-
- case SPINEL_PROP_THREAD_ON_MESH_NETS:
- ret = "THREAD_ON_MESH_NETS";
- break;
-
- case SPINEL_PROP_THREAD_OFF_MESH_ROUTES:
- ret = "THREAD_OFF_MESH_ROUTES";
- break;
-
- case SPINEL_PROP_THREAD_ASSISTING_PORTS:
- ret = "THREAD_ASSISTING_PORTS";
- break;
-
- case SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE:
- ret = "THREAD_ALLOW_LOCAL_NET_DATA_CHANGE";
- break;
-
- case SPINEL_PROP_THREAD_MODE:
- ret = "THREAD_MODE";
- break;
-
- case SPINEL_PROP_THREAD_CHILD_TIMEOUT:
- ret = "THREAD_CHILD_TIMEOUT";
- break;
-
- case SPINEL_PROP_THREAD_RLOC16:
- ret = "THREAD_RLOC16";
- break;
-
- case SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD:
- ret = "THREAD_ROUTER_UPGRADE_THRESHOLD";
- break;
-
- case SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY:
- ret = "THREAD_CONTEXT_REUSE_DELAY";
- break;
-
- case SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT:
- ret = "THREAD_NETWORK_ID_TIMEOUT";
- break;
-
- case SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS:
- ret = "THREAD_ACTIVE_ROUTER_IDS";
- break;
-
- case SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU:
- ret = "THREAD_RLOC16_DEBUG_PASSTHRU";
- break;
-
- case SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED:
- ret = "THREAD_ROUTER_ROLE_ENABLED";
- break;
-
- case SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD:
- ret = "THREAD_ROUTER_DOWNGRADE_THRESHOLD";
- break;
-
- case SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER:
- ret = "THREAD_ROUTER_SELECTION_JITTER";
- break;
-
- case SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID:
- ret = "THREAD_PREFERRED_ROUTER_ID";
- break;
-
- case SPINEL_PROP_THREAD_NEIGHBOR_TABLE:
- ret = "THREAD_NEIGHBOR_TABLE";
- break;
-
- case SPINEL_PROP_THREAD_CHILD_COUNT_MAX:
- ret = "THREAD_CHILD_COUNT_MAX";
- break;
-
- case SPINEL_PROP_THREAD_LEADER_NETWORK_DATA:
- ret = "THREAD_LEADER_NETWORK_DATA";
- break;
-
- case SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA:
- ret = "THREAD_STABLE_LEADER_NETWORK_DATA";
- break;
-
- case SPINEL_PROP_THREAD_JOINERS:
- ret = "THREAD_JOINERS";
- break;
-
- case SPINEL_PROP_THREAD_COMMISSIONER_ENABLED:
- ret = "THREAD_COMMISSIONER_ENABLED";
- break;
-
- case SPINEL_PROP_THREAD_TMF_PROXY_ENABLED:
- ret = "THREAD_TMF_PROXY_ENABLED";
- break;
-
- case SPINEL_PROP_THREAD_TMF_PROXY_STREAM:
- ret = "THREAD_TMF_PROXY_STREAM";
- break;
-
- case SPINEL_PROP_THREAD_UDP_FORWARD_STREAM:
- ret = "THREAD_UDP_FORWARD_STREAM";
- break;
-
- case SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG:
- ret = "THREAD_DISCOVERY_SCAN_JOINER_FLAG";
- break;
-
- case SPINEL_PROP_THREAD_DISCOVERY_SCAN_ENABLE_FILTERING:
- ret = "THREAD_DISCOVERY_SCAN_ENABLE_FILTERING";
- break;
-
- case SPINEL_PROP_THREAD_DISCOVERY_SCAN_PANID:
- ret = "THREAD_DISCOVERY_SCAN_PANID";
- break;
-
- case SPINEL_PROP_THREAD_STEERING_DATA:
- ret = "THREAD_STEERING_DATA";
- break;
-
- case SPINEL_PROP_THREAD_ROUTER_TABLE:
- ret = "THREAD_ROUTER_TABLE";
- break;
-
- case SPINEL_PROP_THREAD_ACTIVE_DATASET:
- ret = "THREAD_ACTIVE_DATASET";
- break;
-
- case SPINEL_PROP_THREAD_PENDING_DATASET:
- ret = "THREAD_PENDING_DATASET";
- break;
-
- case SPINEL_PROP_THREAD_MGMT_SET_ACTIVE_DATASET:
- ret = "THREAD_MGMT_SET_ACTIVE_DATASET";
- break;
-
- case SPINEL_PROP_THREAD_MGMT_SET_PENDING_DATASET:
- ret = "THREAD_MGMT_SET_PENDING_DATASET";
- break;
-
- case SPINEL_PROP_DATASET_ACTIVE_TIMESTAMP:
- ret = "DATASET_ACTIVE_TIMESTAMP";
- break;
-
- case SPINEL_PROP_DATASET_PENDING_TIMESTAMP:
- ret = "DATASET_PENDING_TIMESTAMP";
- break;
-
- case SPINEL_PROP_DATASET_DELAY_TIMER:
- ret = "DATASET_DELAY_TIMER";
- break;
-
- case SPINEL_PROP_DATASET_SECURITY_POLICY:
- ret = "DATASET_SECURITY_POLICY";
- break;
-
- case SPINEL_PROP_DATASET_RAW_TLVS:
- ret = "DATASET_RAW_TLVS";
- break;
-
- case SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES:
- ret = "THREAD_CHILD_TABLE_ADDRESSES";
- break;
-
- case SPINEL_PROP_THREAD_NEIGHBOR_TABLE_ERROR_RATES:
- ret = "THREAD_NEIGHBOR_TABLE_ERROR_RATES";
- break;
-
- case SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE:
- ret = "THREAD_ADDRESS_CACHE_TABLE";
- break;
-
- case SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET:
- ret = "THREAD_MGMT_GET_ACTIVE_DATASET";
- break;
-
- case SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET:
- ret = "THREAD_MGMT_GET_PENDING_DATASET";
- break;
-
- case SPINEL_PROP_DATASET_DEST_ADDRESS:
- ret = "DATASET_DEST_ADDRESS";
- break;
-
- case SPINEL_PROP_THREAD_NEW_DATASET:
- ret = "THREAD_NEW_DATASET";
- break;
-
- case SPINEL_PROP_MESHCOP_JOINER_STATE:
- ret = "MESHCOP_JOINER_STATE";
- break;
-
- case SPINEL_PROP_MESHCOP_JOINER_COMMISSIONING:
- ret = "MESHCOP_JOINER_COMMISSIONING";
- break;
-
- case SPINEL_PROP_IPV6_LL_ADDR:
- ret = "IPV6_LL_ADDR";
- break;
-
- case SPINEL_PROP_IPV6_ML_ADDR:
- ret = "IPV6_ML_ADDR";
- break;
-
- case SPINEL_PROP_IPV6_ML_PREFIX:
- ret = "IPV6_ML_PREFIX";
- break;
-
- case SPINEL_PROP_IPV6_ADDRESS_TABLE:
- ret = "IPV6_ADDRESS_TABLE";
- break;
-
- case SPINEL_PROP_IPV6_ROUTE_TABLE:
- ret = "IPV6_ROUTE_TABLE";
- break;
-
- case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD:
- ret = "IPV6_ICMP_PING_OFFLOAD";
- break;
-
- case SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE:
- ret = "IPV6_MULTICAST_ADDRESS_TABLE";
- break;
-
- case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE:
- ret = "IPV6_ICMP_PING_OFFLOAD_MODE";
- break;
-
- case SPINEL_PROP_STREAM_DEBUG:
- ret = "STREAM_DEBUG";
- break;
-
- case SPINEL_PROP_STREAM_RAW:
- ret = "STREAM_RAW";
- break;
-
- case SPINEL_PROP_STREAM_NET:
- ret = "STREAM_NET";
- break;
-
- case SPINEL_PROP_STREAM_NET_INSECURE:
- ret = "STREAM_NET_INSECURE";
- break;
-
- case SPINEL_PROP_STREAM_LOG:
- ret = "STREAM_LOG";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_STATE:
- ret = "MESHCOP_COMMISSIONER_STATE";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS:
- ret = "MESHCOP_COMMISSIONER_JOINERS";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL:
- ret = "MESHCOP_COMMISSIONER_PROVISIONING_URL";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID:
- ret = "MESHCOP_COMMISSIONER_SESSION_ID";
- break;
-
- case SPINEL_PROP_MESHCOP_JOINER_DISCERNER:
- ret = "MESHCOP_JOINER_DISCERNER";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN:
- ret = "MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN:
- ret = "MESHCOP_COMMISSIONER_ENERGY_SCAN";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT:
- ret = "MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_QUERY:
- ret = "MESHCOP_COMMISSIONER_PAN_ID_QUERY";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT:
- ret = "MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET:
- ret = "MESHCOP_COMMISSIONER_MGMT_GET";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET:
- ret = "MESHCOP_COMMISSIONER_MGMT_SET";
- break;
-
- case SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC:
- ret = "MESHCOP_COMMISSIONER_GENERATE_PSKC";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL:
- ret = "CHANNEL_MANAGER_NEW_CHANNEL";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_DELAY:
- ret = "CHANNEL_MANAGER_DELAY";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS:
- ret = "CHANNEL_MANAGER_SUPPORTED_CHANNELS";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS:
- ret = "CHANNEL_MANAGER_FAVORED_CHANNELS";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT:
- ret = "CHANNEL_MANAGER_CHANNEL_SELECT";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED:
- ret = "CHANNEL_MANAGER_AUTO_SELECT_ENABLED";
- break;
-
- case SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL:
- ret = "CHANNEL_MANAGER_AUTO_SELECT_INTERVAL";
- break;
-
- case SPINEL_PROP_THREAD_NETWORK_TIME:
- ret = "THREAD_NETWORK_TIME";
- break;
-
- case SPINEL_PROP_TIME_SYNC_PERIOD:
- ret = "TIME_SYNC_PERIOD";
- break;
-
- case SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD:
- ret = "TIME_SYNC_XTAL_THRESHOLD";
- break;
-
- case SPINEL_PROP_CHILD_SUPERVISION_INTERVAL:
- ret = "CHILD_SUPERVISION_INTERVAL";
- break;
-
- case SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT:
- ret = "CHILD_SUPERVISION_CHECK_TIMEOUT";
- break;
-
- case SPINEL_PROP_RCP_VERSION:
- ret = "RCP_VERSION";
- break;
-
- case SPINEL_PROP_PARENT_RESPONSE_INFO:
- ret = "PARENT_RESPONSE_INFO";
- break;
-
- case SPINEL_PROP_SLAAC_ENABLED:
- ret = "SLAAC_ENABLED";
- break;
-
- case SPINEL_PROP_SUPPORTED_RADIO_LINKS:
- ret = "SUPPORTED_RADIO_LINKS";
- break;
-
- case SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO:
- ret = "NEIGHBOR_TABLE_MULTI_RADIO_INFO";
- break;
-
- case SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE:
- ret = "SERVER_ALLOW_LOCAL_DATA_CHANGE";
- break;
-
- case SPINEL_PROP_SERVER_SERVICES:
- ret = "SERVER_SERVICES";
- break;
-
- case SPINEL_PROP_SERVER_LEADER_SERVICES:
- ret = "SERVER_LEADER_SERVICES";
- break;
-
- case SPINEL_PROP_RCP_API_VERSION:
- ret = "RCP_API_VERSION";
- break;
-
- case SPINEL_PROP_UART_BITRATE:
- ret = "UART_BITRATE";
- break;
-
- case SPINEL_PROP_UART_XON_XOFF:
- ret = "UART_XON_XOFF";
- break;
-
- case SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED:
- ret = "15_4_PIB_PHY_CHANNELS_SUPPORTED";
- break;
-
- case SPINEL_PROP_15_4_PIB_MAC_PROMISCUOUS_MODE:
- ret = "15_4_PIB_MAC_PROMISCUOUS_MODE";
- break;
-
- case SPINEL_PROP_15_4_PIB_MAC_SECURITY_ENABLED:
- ret = "15_4_PIB_MAC_SECURITY_ENABLED";
- break;
-
- case SPINEL_PROP_CNTR_RESET:
- ret = "CNTR_RESET";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_TOTAL:
- ret = "CNTR_TX_PKT_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_ACK_REQ:
- ret = "CNTR_TX_PKT_ACK_REQ";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_ACKED:
- ret = "CNTR_TX_PKT_ACKED";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ:
- ret = "CNTR_TX_PKT_NO_ACK_REQ";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_DATA:
- ret = "CNTR_TX_PKT_DATA";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_DATA_POLL:
- ret = "CNTR_TX_PKT_DATA_POLL";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BEACON:
- ret = "CNTR_TX_PKT_BEACON";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ:
- ret = "CNTR_TX_PKT_BEACON_REQ";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_OTHER:
- ret = "CNTR_TX_PKT_OTHER";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_RETRY:
- ret = "CNTR_TX_PKT_RETRY";
- break;
-
- case SPINEL_PROP_CNTR_TX_ERR_CCA:
- ret = "CNTR_TX_ERR_CCA";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_UNICAST:
- ret = "CNTR_TX_PKT_UNICAST";
- break;
-
- case SPINEL_PROP_CNTR_TX_PKT_BROADCAST:
- ret = "CNTR_TX_PKT_BROADCAST";
- break;
-
- case SPINEL_PROP_CNTR_TX_ERR_ABORT:
- ret = "CNTR_TX_ERR_ABORT";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_TOTAL:
- ret = "CNTR_RX_PKT_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DATA:
- ret = "CNTR_RX_PKT_DATA";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DATA_POLL:
- ret = "CNTR_RX_PKT_DATA_POLL";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BEACON:
- ret = "CNTR_RX_PKT_BEACON";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ:
- ret = "CNTR_RX_PKT_BEACON_REQ";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_OTHER:
- ret = "CNTR_RX_PKT_OTHER";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_FILT_WL:
- ret = "CNTR_RX_PKT_FILT_WL";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_FILT_DA:
- ret = "CNTR_RX_PKT_FILT_DA";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_EMPTY:
- ret = "CNTR_RX_ERR_EMPTY";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR:
- ret = "CNTR_RX_ERR_UKWN_NBR";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR:
- ret = "CNTR_RX_ERR_NVLD_SADDR";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_SECURITY:
- ret = "CNTR_RX_ERR_SECURITY";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_BAD_FCS:
- ret = "CNTR_RX_ERR_BAD_FCS";
- break;
-
- case SPINEL_PROP_CNTR_RX_ERR_OTHER:
- ret = "CNTR_RX_ERR_OTHER";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_DUP:
- ret = "CNTR_RX_PKT_DUP";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_UNICAST:
- ret = "CNTR_RX_PKT_UNICAST";
- break;
-
- case SPINEL_PROP_CNTR_RX_PKT_BROADCAST:
- ret = "CNTR_RX_PKT_BROADCAST";
- break;
-
- case SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL:
- ret = "CNTR_TX_IP_SEC_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL:
- ret = "CNTR_TX_IP_INSEC_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_TX_IP_DROPPED:
- ret = "CNTR_TX_IP_DROPPED";
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL:
- ret = "CNTR_RX_IP_SEC_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL:
- ret = "CNTR_RX_IP_INSEC_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_RX_IP_DROPPED:
- ret = "CNTR_RX_IP_DROPPED";
- break;
-
- case SPINEL_PROP_CNTR_TX_SPINEL_TOTAL:
- ret = "CNTR_TX_SPINEL_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_TOTAL:
- ret = "CNTR_RX_SPINEL_TOTAL";
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_ERR:
- ret = "CNTR_RX_SPINEL_ERR";
- break;
-
- case SPINEL_PROP_CNTR_RX_SPINEL_OUT_OF_ORDER_TID:
- ret = "CNTR_RX_SPINEL_OUT_OF_ORDER_TID";
- break;
-
- case SPINEL_PROP_CNTR_IP_TX_SUCCESS:
- ret = "CNTR_IP_TX_SUCCESS";
- break;
-
- case SPINEL_PROP_CNTR_IP_RX_SUCCESS:
- ret = "CNTR_IP_RX_SUCCESS";
- break;
-
- case SPINEL_PROP_CNTR_IP_TX_FAILURE:
- ret = "CNTR_IP_TX_FAILURE";
- break;
-
- case SPINEL_PROP_CNTR_IP_RX_FAILURE:
- ret = "CNTR_IP_RX_FAILURE";
- break;
-
- case SPINEL_PROP_MSG_BUFFER_COUNTERS:
- ret = "MSG_BUFFER_COUNTERS";
- break;
-
- case SPINEL_PROP_CNTR_ALL_MAC_COUNTERS:
- ret = "CNTR_ALL_MAC_COUNTERS";
- break;
-
- case SPINEL_PROP_CNTR_MLE_COUNTERS:
- ret = "CNTR_MLE_COUNTERS";
- break;
-
- case SPINEL_PROP_CNTR_ALL_IP_COUNTERS:
- ret = "CNTR_ALL_IP_COUNTERS";
- break;
-
- case SPINEL_PROP_CNTR_MAC_RETRY_HISTOGRAM:
- ret = "CNTR_MAC_RETRY_HISTOGRAM";
- break;
-
- case SPINEL_PROP_NEST_STREAM_MFG:
- ret = "NEST_STREAM_MFG";
- break;
-
- case SPINEL_PROP_NEST_LEGACY_ULA_PREFIX:
- ret = "NEST_LEGACY_ULA_PREFIX";
- break;
-
- case SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED:
- ret = "NEST_LEGACY_LAST_NODE_JOINED";
- break;
-
- case SPINEL_PROP_DEBUG_TEST_ASSERT:
- ret = "DEBUG_TEST_ASSERT";
- break;
-
- case SPINEL_PROP_DEBUG_NCP_LOG_LEVEL:
- ret = "DEBUG_NCP_LOG_LEVEL";
- break;
-
- case SPINEL_PROP_DEBUG_TEST_WATCHDOG:
- ret = "DEBUG_TEST_WATCHDOG";
- break;
-
- case SPINEL_PROP_RCP_MAC_FRAME_COUNTER:
- ret = "RCP_MAC_FRAME_COUNTER";
- break;
-
- case SPINEL_PROP_RCP_MAC_KEY:
- ret = "RCP_MAC_KEY";
- break;
-
- case SPINEL_PROP_DEBUG_LOG_TIMESTAMP_BASE:
- ret = "DEBUG_LOG_TIMESTAMP_BASE";
- break;
-
- case SPINEL_PROP_DEBUG_TREL_TEST_MODE_ENABLE:
- ret = "DEBUG_TREL_TEST_MODE_ENABLE";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_prop_cstr, prop_key);
}
+#define SPINEL_NET_CSTR(VALUE) __SPINEL_CSTR(SPINEL_, VALUE)
const char *spinel_net_role_to_cstr(uint8_t net_role)
{
- const char *ret = "NET_ROLE_UNKNOWN";
+ static const struct spinel_cstr spinel_net_cstr[] = {
+ SPINEL_NET_CSTR(NET_ROLE_DETACHED),
+ SPINEL_NET_CSTR(NET_ROLE_CHILD),
+ SPINEL_NET_CSTR(NET_ROLE_ROUTER),
+ SPINEL_NET_CSTR(NET_ROLE_LEADER),
+ {0},
+ };
- switch (net_role)
- {
- case SPINEL_NET_ROLE_DETACHED:
- ret = "NET_ROLE_DETACHED";
- break;
-
- case SPINEL_NET_ROLE_CHILD:
- ret = "NET_ROLE_CHILD";
- break;
-
- case SPINEL_NET_ROLE_ROUTER:
- ret = "NET_ROLE_ROUTER";
- break;
-
- case SPINEL_NET_ROLE_LEADER:
- ret = "NET_ROLE_LEADER";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_net_cstr, net_role);
}
+#define SPINEL_MCU_CSTR(VALUE) __SPINEL_CSTR(SPINEL_, VALUE)
const char *spinel_mcu_power_state_to_cstr(uint8_t mcu_power_state)
{
- const char *ret = "MCU_POWER_STATE_UNKNOWN";
+ static const struct spinel_cstr spinel_mcu_power_state_cstr[] = {
+ SPINEL_MCU_CSTR(MCU_POWER_STATE_ON),
+ SPINEL_MCU_CSTR(MCU_POWER_STATE_LOW_POWER),
+ SPINEL_MCU_CSTR(MCU_POWER_STATE_OFF),
+ {0},
+ };
- switch (mcu_power_state)
- {
- case SPINEL_MCU_POWER_STATE_ON:
- ret = "MCU_POWER_STATE_ON";
- break;
-
- case SPINEL_MCU_POWER_STATE_LOW_POWER:
- ret = "MCU_POWER_STATE_LOW_POWER";
- break;
-
- case SPINEL_MCU_POWER_STATE_OFF:
- ret = "MCU_POWER_STATE_OFF";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_mcu_power_state_cstr, mcu_power_state);
}
+#define SPINEL_STATUS_CSTR(VALUE) __SPINEL_CSTR(SPINEL_STATUS_, VALUE)
const char *spinel_status_to_cstr(spinel_status_t status)
{
- const char *ret = "UNKNOWN";
+ static const struct spinel_cstr spinel_status_cstr[] = {
+ SPINEL_STATUS_CSTR(OK),
+ SPINEL_STATUS_CSTR(FAILURE),
+ SPINEL_STATUS_CSTR(UNIMPLEMENTED),
+ SPINEL_STATUS_CSTR(INVALID_ARGUMENT),
+ SPINEL_STATUS_CSTR(INVALID_STATE),
+ SPINEL_STATUS_CSTR(INVALID_COMMAND),
+ SPINEL_STATUS_CSTR(INVALID_INTERFACE),
+ SPINEL_STATUS_CSTR(INTERNAL_ERROR),
+ SPINEL_STATUS_CSTR(SECURITY_ERROR),
+ SPINEL_STATUS_CSTR(PARSE_ERROR),
+ SPINEL_STATUS_CSTR(IN_PROGRESS),
+ SPINEL_STATUS_CSTR(NOMEM),
+ SPINEL_STATUS_CSTR(BUSY),
+ SPINEL_STATUS_CSTR(PROP_NOT_FOUND),
+ SPINEL_STATUS_CSTR(DROPPED),
+ SPINEL_STATUS_CSTR(EMPTY),
+ SPINEL_STATUS_CSTR(CMD_TOO_BIG),
+ SPINEL_STATUS_CSTR(NO_ACK),
+ SPINEL_STATUS_CSTR(CCA_FAILURE),
+ SPINEL_STATUS_CSTR(ALREADY),
+ SPINEL_STATUS_CSTR(ITEM_NOT_FOUND),
+ SPINEL_STATUS_CSTR(INVALID_COMMAND_FOR_PROP),
+ SPINEL_STATUS_CSTR(RESPONSE_TIMEOUT),
+ SPINEL_STATUS_CSTR(JOIN_FAILURE),
+ SPINEL_STATUS_CSTR(JOIN_SECURITY),
+ SPINEL_STATUS_CSTR(JOIN_NO_PEERS),
+ SPINEL_STATUS_CSTR(JOIN_INCOMPATIBLE),
+ SPINEL_STATUS_CSTR(JOIN_RSP_TIMEOUT),
+ SPINEL_STATUS_CSTR(JOIN_SUCCESS),
+ SPINEL_STATUS_CSTR(RESET_POWER_ON),
+ SPINEL_STATUS_CSTR(RESET_EXTERNAL),
+ SPINEL_STATUS_CSTR(RESET_SOFTWARE),
+ SPINEL_STATUS_CSTR(RESET_FAULT),
+ SPINEL_STATUS_CSTR(RESET_CRASH),
+ SPINEL_STATUS_CSTR(RESET_ASSERT),
+ SPINEL_STATUS_CSTR(RESET_OTHER),
+ SPINEL_STATUS_CSTR(RESET_UNKNOWN),
+ SPINEL_STATUS_CSTR(RESET_WATCHDOG),
+ {0},
+ };
- switch (status)
- {
- case SPINEL_STATUS_OK:
- ret = "OK";
- break;
-
- case SPINEL_STATUS_FAILURE:
- ret = "FAILURE";
- break;
-
- case SPINEL_STATUS_UNIMPLEMENTED:
- ret = "UNIMPLEMENTED";
- break;
-
- case SPINEL_STATUS_INVALID_ARGUMENT:
- ret = "INVALID_ARGUMENT";
- break;
-
- case SPINEL_STATUS_INVALID_STATE:
- ret = "INVALID_STATE";
- break;
-
- case SPINEL_STATUS_INVALID_COMMAND:
- ret = "INVALID_COMMAND";
- break;
-
- case SPINEL_STATUS_INVALID_INTERFACE:
- ret = "INVALID_INTERFACE";
- break;
-
- case SPINEL_STATUS_INTERNAL_ERROR:
- ret = "INTERNAL_ERROR";
- break;
-
- case SPINEL_STATUS_SECURITY_ERROR:
- ret = "SECURITY_ERROR";
- break;
-
- case SPINEL_STATUS_PARSE_ERROR:
- ret = "PARSE_ERROR";
- break;
-
- case SPINEL_STATUS_IN_PROGRESS:
- ret = "IN_PROGRESS";
- break;
-
- case SPINEL_STATUS_NOMEM:
- ret = "NOMEM";
- break;
-
- case SPINEL_STATUS_BUSY:
- ret = "BUSY";
- break;
-
- case SPINEL_STATUS_PROP_NOT_FOUND:
- ret = "PROP_NOT_FOUND";
- break;
-
- case SPINEL_STATUS_DROPPED:
- ret = "DROPPED";
- break;
-
- case SPINEL_STATUS_EMPTY:
- ret = "EMPTY";
- break;
-
- case SPINEL_STATUS_CMD_TOO_BIG:
- ret = "CMD_TOO_BIG";
- break;
-
- case SPINEL_STATUS_NO_ACK:
- ret = "NO_ACK";
- break;
-
- case SPINEL_STATUS_CCA_FAILURE:
- ret = "CCA_FAILURE";
- break;
-
- case SPINEL_STATUS_ALREADY:
- ret = "ALREADY";
- break;
-
- case SPINEL_STATUS_ITEM_NOT_FOUND:
- ret = "ITEM_NOT_FOUND";
- break;
-
- case SPINEL_STATUS_INVALID_COMMAND_FOR_PROP:
- ret = "INVALID_COMMAND_FOR_PROP";
- break;
-
- case SPINEL_STATUS_JOIN_FAILURE:
- ret = "JOIN_FAILURE";
- break;
-
- case SPINEL_STATUS_JOIN_SECURITY:
- ret = "JOIN_SECURITY";
- break;
-
- case SPINEL_STATUS_JOIN_NO_PEERS:
- ret = "JOIN_NO_PEERS";
- break;
-
- case SPINEL_STATUS_JOIN_INCOMPATIBLE:
- ret = "JOIN_INCOMPATIBLE";
- break;
-
- case SPINEL_STATUS_JOIN_RSP_TIMEOUT:
- ret = "JOIN_RSP_TIMEOUT";
- break;
-
- case SPINEL_STATUS_JOIN_SUCCESS:
- ret = "JOIN_SUCCESS";
- break;
-
- case SPINEL_STATUS_RESET_POWER_ON:
- ret = "RESET_POWER_ON";
- break;
-
- case SPINEL_STATUS_RESET_EXTERNAL:
- ret = "RESET_EXTERNAL";
- break;
-
- case SPINEL_STATUS_RESET_SOFTWARE:
- ret = "RESET_SOFTWARE";
- break;
-
- case SPINEL_STATUS_RESET_FAULT:
- ret = "RESET_FAULT";
- break;
-
- case SPINEL_STATUS_RESET_CRASH:
- ret = "RESET_CRASH";
- break;
-
- case SPINEL_STATUS_RESET_ASSERT:
- ret = "RESET_ASSERT";
- break;
-
- case SPINEL_STATUS_RESET_OTHER:
- ret = "RESET_OTHER";
- break;
-
- case SPINEL_STATUS_RESET_UNKNOWN:
- ret = "RESET_UNKNOWN";
- break;
-
- case SPINEL_STATUS_RESET_WATCHDOG:
- ret = "RESET_WATCHDOG";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_status_cstr, status);
}
+#define SPINEL_CAP_CSTR(VALUE) __SPINEL_CSTR(SPINEL_CAP_, VALUE)
const char *spinel_capability_to_cstr(spinel_capability_t capability)
{
- const char *ret = "UNKNOWN";
+ static const struct spinel_cstr spinel_cap_cstr[] = {
+ SPINEL_CAP_CSTR(LOCK),
+ SPINEL_CAP_CSTR(NET_SAVE),
+ SPINEL_CAP_CSTR(HBO),
+ SPINEL_CAP_CSTR(POWER_SAVE),
+ SPINEL_CAP_CSTR(COUNTERS),
+ SPINEL_CAP_CSTR(JAM_DETECT),
+ SPINEL_CAP_CSTR(PEEK_POKE),
+ SPINEL_CAP_CSTR(WRITABLE_RAW_STREAM),
+ SPINEL_CAP_CSTR(GPIO),
+ SPINEL_CAP_CSTR(TRNG),
+ SPINEL_CAP_CSTR(CMD_MULTI),
+ SPINEL_CAP_CSTR(UNSOL_UPDATE_FILTER),
+ SPINEL_CAP_CSTR(MCU_POWER_STATE),
+ SPINEL_CAP_CSTR(PCAP),
+ SPINEL_CAP_CSTR(802_15_4_2003),
+ SPINEL_CAP_CSTR(802_15_4_2006),
+ SPINEL_CAP_CSTR(802_15_4_2011),
+ SPINEL_CAP_CSTR(802_15_4_PIB),
+ SPINEL_CAP_CSTR(802_15_4_2450MHZ_OQPSK),
+ SPINEL_CAP_CSTR(802_15_4_915MHZ_OQPSK),
+ SPINEL_CAP_CSTR(802_15_4_868MHZ_OQPSK),
+ SPINEL_CAP_CSTR(802_15_4_915MHZ_BPSK),
+ SPINEL_CAP_CSTR(802_15_4_868MHZ_BPSK),
+ SPINEL_CAP_CSTR(802_15_4_915MHZ_ASK),
+ SPINEL_CAP_CSTR(802_15_4_868MHZ_ASK),
+ SPINEL_CAP_CSTR(CONFIG_FTD),
+ SPINEL_CAP_CSTR(CONFIG_MTD),
+ SPINEL_CAP_CSTR(CONFIG_RADIO),
+ SPINEL_CAP_CSTR(ROLE_ROUTER),
+ SPINEL_CAP_CSTR(ROLE_SLEEPY),
+ SPINEL_CAP_CSTR(NET_THREAD_1_0),
+ SPINEL_CAP_CSTR(NET_THREAD_1_1),
+ SPINEL_CAP_CSTR(NET_THREAD_1_2),
+ SPINEL_CAP_CSTR(RCP_API_VERSION),
+ SPINEL_CAP_CSTR(MAC_ALLOWLIST),
+ SPINEL_CAP_CSTR(MAC_RAW),
+ SPINEL_CAP_CSTR(OOB_STEERING_DATA),
+ SPINEL_CAP_CSTR(CHANNEL_MONITOR),
+ SPINEL_CAP_CSTR(CHANNEL_MANAGER),
+ SPINEL_CAP_CSTR(OPENTHREAD_LOG_METADATA),
+ SPINEL_CAP_CSTR(TIME_SYNC),
+ SPINEL_CAP_CSTR(CHILD_SUPERVISION),
+ SPINEL_CAP_CSTR(POSIX),
+ SPINEL_CAP_CSTR(SLAAC),
+ SPINEL_CAP_CSTR(RADIO_COEX),
+ SPINEL_CAP_CSTR(MAC_RETRY_HISTOGRAM),
+ SPINEL_CAP_CSTR(MULTI_RADIO),
+ SPINEL_CAP_CSTR(SRP_CLIENT),
+ SPINEL_CAP_CSTR(ERROR_RATE_TRACKING),
+ SPINEL_CAP_CSTR(THREAD_COMMISSIONER),
+ SPINEL_CAP_CSTR(THREAD_TMF_PROXY),
+ SPINEL_CAP_CSTR(THREAD_UDP_FORWARD),
+ SPINEL_CAP_CSTR(THREAD_JOINER),
+ SPINEL_CAP_CSTR(THREAD_BORDER_ROUTER),
+ SPINEL_CAP_CSTR(THREAD_SERVICE),
+ SPINEL_CAP_CSTR(THREAD_CSL_RECEIVER),
+ SPINEL_CAP_CSTR(THREAD_BACKBONE_ROUTER),
+ SPINEL_CAP_CSTR(NEST_LEGACY_INTERFACE),
+ SPINEL_CAP_CSTR(NEST_LEGACY_NET_WAKE),
+ SPINEL_CAP_CSTR(NEST_TRANSMIT_HOOK),
+ {0},
+ };
- switch (capability)
- {
- case SPINEL_CAP_LOCK:
- ret = "LOCK";
- break;
-
- case SPINEL_CAP_NET_SAVE:
- ret = "NET_SAVE";
- break;
-
- case SPINEL_CAP_HBO:
- ret = "HBO";
- break;
-
- case SPINEL_CAP_POWER_SAVE:
- ret = "POWER_SAVE";
- break;
-
- case SPINEL_CAP_COUNTERS:
- ret = "COUNTERS";
- break;
-
- case SPINEL_CAP_JAM_DETECT:
- ret = "JAM_DETECT";
- break;
-
- case SPINEL_CAP_PEEK_POKE:
- ret = "PEEK_POKE";
- break;
-
- case SPINEL_CAP_WRITABLE_RAW_STREAM:
- ret = "WRITABLE_RAW_STREAM";
- break;
-
- case SPINEL_CAP_GPIO:
- ret = "GPIO";
- break;
-
- case SPINEL_CAP_TRNG:
- ret = "TRNG";
- break;
-
- case SPINEL_CAP_CMD_MULTI:
- ret = "CMD_MULTI";
- break;
-
- case SPINEL_CAP_UNSOL_UPDATE_FILTER:
- ret = "UNSOL_UPDATE_FILTER";
- break;
-
- case SPINEL_CAP_MCU_POWER_STATE:
- ret = "MCU_POWER_STATE";
- break;
-
- case SPINEL_CAP_PCAP:
- ret = "PCAP";
- break;
-
- case SPINEL_CAP_802_15_4_2003:
- ret = "802_15_4_2003";
- break;
-
- case SPINEL_CAP_802_15_4_2006:
- ret = "802_15_4_2006";
- break;
-
- case SPINEL_CAP_802_15_4_2011:
- ret = "802_15_4_2011";
- break;
-
- case SPINEL_CAP_802_15_4_PIB:
- ret = "802_15_4_PIB";
- break;
-
- case SPINEL_CAP_802_15_4_2450MHZ_OQPSK:
- ret = "802_15_4_2450MHZ_OQPSK";
- break;
-
- case SPINEL_CAP_802_15_4_915MHZ_OQPSK:
- ret = "802_15_4_915MHZ_OQPSK";
- break;
-
- case SPINEL_CAP_802_15_4_868MHZ_OQPSK:
- ret = "802_15_4_868MHZ_OQPSK";
- break;
-
- case SPINEL_CAP_802_15_4_915MHZ_BPSK:
- ret = "802_15_4_915MHZ_BPSK";
- break;
-
- case SPINEL_CAP_802_15_4_868MHZ_BPSK:
- ret = "802_15_4_868MHZ_BPSK";
- break;
-
- case SPINEL_CAP_802_15_4_915MHZ_ASK:
- ret = "802_15_4_915MHZ_ASK";
- break;
-
- case SPINEL_CAP_802_15_4_868MHZ_ASK:
- ret = "802_15_4_868MHZ_ASK";
- break;
-
- case SPINEL_CAP_CONFIG_FTD:
- ret = "CONFIG_FTD";
- break;
-
- case SPINEL_CAP_CONFIG_MTD:
- ret = "CONFIG_MTD";
- break;
-
- case SPINEL_CAP_CONFIG_RADIO:
- ret = "CONFIG_RADIO";
- break;
-
- case SPINEL_CAP_ROLE_ROUTER:
- ret = "ROLE_ROUTER";
- break;
-
- case SPINEL_CAP_ROLE_SLEEPY:
- ret = "ROLE_SLEEPY";
- break;
-
- case SPINEL_CAP_NET_THREAD_1_0:
- ret = "NET_THREAD_1_0";
- break;
-
- case SPINEL_CAP_NET_THREAD_1_1:
- ret = "NET_THREAD_1_1";
- break;
-
- case SPINEL_CAP_RCP_API_VERSION:
- ret = "RCP_API_VERSION";
- break;
-
- case SPINEL_CAP_MAC_ALLOWLIST:
- ret = "MAC_ALLOWLIST";
- break;
-
- case SPINEL_CAP_MAC_RAW:
- ret = "MAC_RAW";
- break;
-
- case SPINEL_CAP_OOB_STEERING_DATA:
- ret = "OOB_STEERING_DATA";
- break;
-
- case SPINEL_CAP_CHANNEL_MONITOR:
- ret = "CHANNEL_MONITOR";
- break;
-
- case SPINEL_CAP_CHANNEL_MANAGER:
- ret = "CHANNEL_MANAGER";
- break;
-
- case SPINEL_CAP_OPENTHREAD_LOG_METADATA:
- ret = "OPENTHREAD_LOG_METADATA";
- break;
-
- case SPINEL_CAP_TIME_SYNC:
- ret = "TIME_SYNC";
- break;
-
- case SPINEL_CAP_CHILD_SUPERVISION:
- ret = "CHILD_SUPERVISION";
- break;
-
- case SPINEL_CAP_POSIX:
- ret = "POSIX";
- break;
-
- case SPINEL_CAP_SLAAC:
- ret = "SLAAC";
- break;
-
- case SPINEL_CAP_RADIO_COEX:
- ret = "RADIO_COEX";
- break;
-
- case SPINEL_CAP_MAC_RETRY_HISTOGRAM:
- ret = "MAC_RETRY_HISTOGRAM";
- break;
-
- case SPINEL_CAP_MULTI_RADIO:
- ret = "MULTI_RADIO";
- break;
-
- case SPINEL_CAP_ERROR_RATE_TRACKING:
- ret = "ERROR_RATE_TRACKING";
- break;
-
- case SPINEL_CAP_THREAD_COMMISSIONER:
- ret = "THREAD_COMMISSIONER";
- break;
-
- case SPINEL_CAP_THREAD_TMF_PROXY:
- ret = "THREAD_TMF_PROXY";
- break;
-
- case SPINEL_CAP_THREAD_UDP_FORWARD:
- ret = "THREAD_UDP_FORWARD";
- break;
-
- case SPINEL_CAP_THREAD_JOINER:
- ret = "THREAD_JOINER";
- break;
-
- case SPINEL_CAP_THREAD_BORDER_ROUTER:
- ret = "THREAD_BORDER_ROUTER";
- break;
-
- case SPINEL_CAP_THREAD_SERVICE:
- ret = "THREAD_SERVICE";
- break;
-
- case SPINEL_CAP_NEST_LEGACY_INTERFACE:
- ret = "NEST_LEGACY_INTERFACE";
- break;
-
- case SPINEL_CAP_NEST_LEGACY_NET_WAKE:
- ret = "NEST_LEGACY_NET_WAKE";
- break;
-
- case SPINEL_CAP_NEST_TRANSMIT_HOOK:
- ret = "NEST_TRANSMIT_HOOK";
- break;
-
- default:
- break;
- }
-
- return ret;
-}
-
-const char *spinel_radio_link_to_cstr(uint32_t radio)
-{
- const char *ret = "UNKNOWN";
-
- switch (radio)
- {
- case SPINEL_RADIO_LINK_IEEE_802_15_4:
- ret = "IEEE_802_15_4";
- break;
-
- case SPINEL_RADIO_LINK_TREL_UDP6:
- ret = "TREL_UDP6";
- break;
-
- default:
- break;
- }
-
- return ret;
+ return spinel_to_cstr(spinel_cap_cstr, capability);
}
// LCOV_EXCL_STOP
diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h
index 5452682..4732569 100644
--- a/src/lib/spinel/spinel.h
+++ b/src/lib/spinel/spinel.h
@@ -377,7 +377,7 @@
* Please see section "Spinel definition compatibility guideline" for more details.
*
*/
-#define SPINEL_RCP_API_VERSION 2
+#define SPINEL_RCP_API_VERSION 3
/**
* @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION
@@ -466,6 +466,7 @@
SPINEL_STATUS_ALREADY = 19, ///< The operation is already in progress.
SPINEL_STATUS_ITEM_NOT_FOUND = 20, ///< The given item could not be found.
SPINEL_STATUS_INVALID_COMMAND_FOR_PROP = 21, ///< The given command cannot be performed on this property.
+ SPINEL_STATUS_RESPONSE_TIMEOUT = 24, ///< No response received from remote node
SPINEL_STATUS_JOIN__BEGIN = 104,
@@ -618,6 +619,12 @@
enum
{
+ SPINEL_NET_FLAG_EXT_DP = (1 << 6),
+ SPINEL_NET_FLAG_EXT_DNS = (1 << 7),
+};
+
+enum
+{
SPINEL_ROUTE_PREFERENCE_HIGH = (1 << SPINEL_NET_FLAG_PREFERENCE_OFFSET),
SPINEL_ROUTE_PREFERENCE_MEDIUM = (0 << SPINEL_NET_FLAG_PREFERENCE_OFFSET),
SPINEL_ROUTE_PREFERENCE_LOW = (3 << SPINEL_NET_FLAG_PREFERENCE_OFFSET),
@@ -692,6 +699,9 @@
SPINEL_NCP_LOG_REGION_OT_BBR = 17,
SPINEL_NCP_LOG_REGION_OT_MLR = 18,
SPINEL_NCP_LOG_REGION_OT_DUA = 19,
+ SPINEL_NCP_LOG_REGION_OT_BR = 20,
+ SPINEL_NCP_LOG_REGION_OT_SRP = 21,
+ SPINEL_NCP_LOG_REGION_OT_DNS = 22,
};
enum
@@ -715,6 +725,48 @@
SPINEL_RADIO_LINK_TREL_UDP6 = 1,
};
+// Parameter ids used for:
+// @ref SPINEL_PROP_THREAD_MLR_REQUEST
+enum
+{
+ SPINEL_THREAD_MLR_PARAMID_TIMEOUT = 0
+};
+
+// Backbone Router states used for:
+// @ref SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE
+enum
+{
+ SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED = 0,
+ SPINEL_THREAD_BACKBONE_ROUTER_STATE_SECONDARY = 1,
+ SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY = 2,
+};
+
+typedef enum
+{
+ SPINEL_SRP_CLIENT_ITEM_STATE_TO_ADD = 0, // Item to be added/registered.
+ SPINEL_SRP_CLIENT_ITEM_STATE_ADDING = 1, // Item is being added/registered.
+ SPINEL_SRP_CLIENT_ITEM_STATE_TO_REFRESH = 2, // Item to be refreshed (re-register to renew lease).
+ SPINEL_SRP_CLIENT_ITEM_STATE_REFRESHING = 3, // Item is being refreshed.
+ SPINEL_SRP_CLIENT_ITEM_STATE_TO_REMOVE = 4, // Item to be removed.
+ SPINEL_SRP_CLIENT_ITEM_STATE_REMOVING = 5, // Item is being removed.
+ SPINEL_SRP_CLIENT_ITEM_STATE_REGISTERED = 6, // Item is registered with server.
+ SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED = 7, // Item is removed.
+} spinel_srp_client_item_state_t;
+
+typedef enum
+{
+ SPINEL_SRP_CLIENT_ERROR_NONE = 0, // No error.
+ SPINEL_SRP_CLIENT_ERROR_PARSE = 1, // Server unable to interpret due to format error.
+ SPINEL_SRP_CLIENT_ERROR_FAILED = 2, // Server encountered an internal failure.
+ SPINEL_SRP_CLIENT_ERROR_NOT_FOUND = 3, // Name that ought to exist, does not exists.
+ SPINEL_SRP_CLIENT_ERROR_NOT_IMPLEMENTED = 4, // Server does not support the query type.
+ SPINEL_SRP_CLIENT_ERROR_SECURITY = 5, // Service is not authoritative for zone.
+ SPINEL_SRP_CLIENT_ERROR_DUPLICATED = 6, // Some name that ought not to exist, does exist.
+ SPINEL_SRP_CLIENT_ERROR_RESPONSE_TIMEOUT = 7, // Timed out waiting for response from server (client would retry).
+ SPINEL_SRP_CLIENT_ERROR_INVALID_ARGS = 8, // Invalid args (e.g., bad service name or TXT-DATA).
+ SPINEL_SRP_CLIENT_ERROR_NO_BUFS = 9, // No buffer to send the SRP update message.
+} spinel_srp_client_error_t;
+
typedef struct
{
uint8_t bytes[8];
@@ -1129,6 +1181,7 @@
SPINEL_CAP_NET__BEGIN = 52,
SPINEL_CAP_NET_THREAD_1_0 = (SPINEL_CAP_NET__BEGIN + 0),
SPINEL_CAP_NET_THREAD_1_1 = (SPINEL_CAP_NET__BEGIN + 1),
+ SPINEL_CAP_NET_THREAD_1_2 = (SPINEL_CAP_NET__BEGIN + 2),
SPINEL_CAP_NET__END = 64,
SPINEL_CAP_RCP__BEGIN = 64,
@@ -1150,16 +1203,20 @@
SPINEL_CAP_RADIO_COEX = (SPINEL_CAP_OPENTHREAD__BEGIN + 11),
SPINEL_CAP_MAC_RETRY_HISTOGRAM = (SPINEL_CAP_OPENTHREAD__BEGIN + 12),
SPINEL_CAP_MULTI_RADIO = (SPINEL_CAP_OPENTHREAD__BEGIN + 13),
+ SPINEL_CAP_SRP_CLIENT = (SPINEL_CAP_OPENTHREAD__BEGIN + 14),
+ SPINEL_CAP_DUA = (SPINEL_CAP_OPENTHREAD__BEGIN + 15),
SPINEL_CAP_OPENTHREAD__END = 640,
- SPINEL_CAP_THREAD__BEGIN = 1024,
- SPINEL_CAP_THREAD_COMMISSIONER = (SPINEL_CAP_THREAD__BEGIN + 0),
- SPINEL_CAP_THREAD_TMF_PROXY = (SPINEL_CAP_THREAD__BEGIN + 1),
- SPINEL_CAP_THREAD_UDP_FORWARD = (SPINEL_CAP_THREAD__BEGIN + 2),
- SPINEL_CAP_THREAD_JOINER = (SPINEL_CAP_THREAD__BEGIN + 3),
- SPINEL_CAP_THREAD_BORDER_ROUTER = (SPINEL_CAP_THREAD__BEGIN + 4),
- SPINEL_CAP_THREAD_SERVICE = (SPINEL_CAP_THREAD__BEGIN + 5),
- SPINEL_CAP_THREAD__END = 1152,
+ SPINEL_CAP_THREAD__BEGIN = 1024,
+ SPINEL_CAP_THREAD_COMMISSIONER = (SPINEL_CAP_THREAD__BEGIN + 0),
+ SPINEL_CAP_THREAD_TMF_PROXY = (SPINEL_CAP_THREAD__BEGIN + 1),
+ SPINEL_CAP_THREAD_UDP_FORWARD = (SPINEL_CAP_THREAD__BEGIN + 2),
+ SPINEL_CAP_THREAD_JOINER = (SPINEL_CAP_THREAD__BEGIN + 3),
+ SPINEL_CAP_THREAD_BORDER_ROUTER = (SPINEL_CAP_THREAD__BEGIN + 4),
+ SPINEL_CAP_THREAD_SERVICE = (SPINEL_CAP_THREAD__BEGIN + 5),
+ SPINEL_CAP_THREAD_CSL_RECEIVER = (SPINEL_CAP_THREAD__BEGIN + 6),
+ SPINEL_CAP_THREAD_BACKBONE_ROUTER = (SPINEL_CAP_THREAD__BEGIN + 8),
+ SPINEL_CAP_THREAD__END = 1152,
SPINEL_CAP_NEST__BEGIN = 15296,
SPINEL_CAP_NEST_LEGACY_INTERFACE = (SPINEL_CAP_NEST__BEGIN + 0),
@@ -1582,6 +1639,13 @@
* First byte is the channel then the max transmit power, write-only.
*/
SPINEL_PROP_PHY_CHAN_MAX_POWER = SPINEL_PROP_PHY__BEGIN + 11,
+ /// Region code
+ /** Format: `S`
+ *
+ * The ascii representation of the ISO 3166 alpha-2 code.
+ *
+ */
+ SPINEL_PROP_PHY_REGION_CODE = SPINEL_PROP_PHY__BEGIN + 12,
SPINEL_PROP_PHY__END = 0x30,
@@ -2255,7 +2319,7 @@
SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION = SPINEL_PROP_THREAD__BEGIN + 9,
/// On-Mesh Prefixes
- /** Format: `A(t(6CbCbS))`
+ /** Format: `A(t(6CbCbSC))`
*
* Data per item is:
*
@@ -2266,8 +2330,11 @@
* `b`: "Is defined locally" flag. Set if this network was locally
* defined. Assumed to be true for set, insert and replace. Clear if
* the on mesh network was defined by another node.
+ * This field is ignored for INSERT and REMOVE commands.
* `S`: The RLOC16 of the device that registered this on-mesh prefix entry.
* This value is not used and ignored when adding an on-mesh prefix.
+ * This field is ignored for INSERT and REMOVE commands.
+ * `C`: TLV flags extended (additional field for Thread 1.2 features).
*
*/
SPINEL_PROP_THREAD_ON_MESH_NETS = SPINEL_PROP_THREAD__BEGIN + 10,
@@ -2860,6 +2927,154 @@
*/
SPINEL_PROP_THREAD_NEW_DATASET = SPINEL_PROP_THREAD_EXT__BEGIN + 40,
+ /// MAC CSL Period
+ /** Format: `S`
+ * Required capability: `SPINEL_CAP_THREAD_CSL_RECEIVER`
+ *
+ * The CSL period in units of 10 symbols. Value of 0 indicates that CSL should be disabled.
+ */
+ SPINEL_PROP_THREAD_CSL_PERIOD = SPINEL_PROP_THREAD_EXT__BEGIN + 41,
+
+ /// MAC CSL Timeout
+ /** Format: `L`
+ * Required capability: `SPINEL_CAP_THREAD_CSL_RECEIVER`
+ *
+ * The CSL timeout in seconds.
+ */
+ SPINEL_PROP_THREAD_CSL_TIMEOUT = SPINEL_PROP_THREAD_EXT__BEGIN + 42,
+
+ /// MAC CSL Channel
+ /** Format: `C`
+ * Required capability: `SPINEL_CAP_THREAD_CSL_RECEIVER`
+ *
+ * The CSL channel as described in chapter 4.6.5.1.2 of the Thread v1.2.0 Specification.
+ * Value of 0 means that CSL reception (if enabled) occurs on the Thread Network channel.
+ * Value from range [11,26] is an alternative channel on which a CSL reception occurs.
+ */
+ SPINEL_PROP_THREAD_CSL_CHANNEL = SPINEL_PROP_THREAD_EXT__BEGIN + 43,
+
+ /// Thread Domain Name
+ /** Format `U` - Read-write
+ * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+ *
+ * This property is available since Thread 1.2.0.
+ * Write to this property succeeds only when Thread protocols are disabled.
+ *
+ */
+ SPINEL_PROP_THREAD_DOMAIN_NAME = SPINEL_PROP_THREAD_EXT__BEGIN + 44,
+
+ /// Multicast Listeners Register Request
+ /** Format `t(A(6))A(t(CD))` - Write-only
+ * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+ *
+ * `t(A(6))`: Array of IPv6 multicast addresses
+ * `A(t(CD))`: Array of structs holding optional parameters as follows
+ * `C`: Parameter id
+ * `D`: Parameter value
+ *
+ * +----------------------------------------------------------------+
+ * | Id: SPINEL_THREAD_MLR_PARAMID_TIMEOUT |
+ * | Type: `L` |
+ * | Description: Timeout in seconds. If this optional parameter is |
+ * | omitted, the default value of the BBR will be used. |
+ * | Special values: |
+ * | 0 causes given addresses to be removed |
+ * | 0xFFFFFFFF is permanent and persistent registration |
+ * +----------------------------------------------------------------+
+ *
+ * Write to this property initiates update of Multicast Listeners Table on the primary BBR.
+ * If the write succeeded, the result of network operation will be notified later by the
+ * SPINEL_PROP_THREAD_MLR_RESPONSE property. If the write fails, no MLR.req is issued and
+ * notifiaction through the SPINEL_PROP_THREAD_MLR_RESPONSE property will not occur.
+ *
+ */
+ SPINEL_PROP_THREAD_MLR_REQUEST = SPINEL_PROP_THREAD_EXT__BEGIN + 52,
+
+ /// Multicast Listeners Register Response
+ /** Format `CCt(A(6))` - Unsolicited notifications only
+ * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+ *
+ * `C`: Status
+ * `C`: MlrStatus (The Multicast Listener Registration Status)
+ * `A(6)`: Array of IPv6 addresses that failed to be updated on the primary BBR
+ *
+ * This property is notified asynchronously when the NCP receives MLR.rsp following
+ * previous write to the SPINEL_PROP_THREAD_MLR_REQUEST property.
+ */
+ SPINEL_PROP_THREAD_MLR_RESPONSE = SPINEL_PROP_THREAD_EXT__BEGIN + 53,
+
+ /// Interface Identifier specified for Thread Domain Unicast Address.
+ /** Format: `A(C)` - Read-write
+ *
+ * `A(C)`: Interface Identifier (8 bytes).
+ *
+ * Required capability: SPINEL_CAP_DUA
+ *
+ * If write to this property is performed without specified parameter
+ * the Interface Identifier of the Thread Domain Unicast Address will be cleared.
+ * If the DUA Interface Identifier is cleared on the NCP device,
+ * the get spinel property command will be returned successfully without specified parameter.
+ *
+ */
+ SPINEL_PROP_THREAD_DUA_ID = SPINEL_PROP_THREAD_EXT__BEGIN + 54,
+
+ /// Thread 1.2 Primary Backbone Router information in the Thread Network.
+ /** Format: `SSLC` - Read-Only
+ *
+ * Required capability: `SPINEL_CAP_NET_THREAD_1_2`
+ *
+ * `S`: Server.
+ * `S`: Reregistration Delay (in seconds).
+ * `L`: Multicast Listener Registration Timeout (in seconds).
+ * `C`: Sequence Number.
+ *
+ */
+ SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY = SPINEL_PROP_THREAD_EXT__BEGIN + 55,
+
+ /// Thread 1.2 Backbone Router local state.
+ /** Format: `C` - Read-Write
+ *
+ * Required capability: `SPINEL_CAP_THREAD_BACKBONE_ROUTER`
+ *
+ * The valid values are specified by SPINEL_THREAD_BACKBONE_ROUTER_STATE_<state> enumeration.
+ * Backbone functionality will be disabled if SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED
+ * is writted to this property, enabled otherwise.
+ *
+ */
+ SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE = SPINEL_PROP_THREAD_EXT__BEGIN + 56,
+
+ /// Local Thread 1.2 Backbone Router configuration.
+ /** Format: SLC - Read-Write
+ *
+ * Required capability: `SPINEL_CAP_THREAD_BACKBONE_ROUTER`
+ *
+ * `S`: Reregistration Delay (in seconds).
+ * `L`: Multicast Listener Registration Timeout (in seconds).
+ * `C`: Sequence Number.
+ *
+ */
+ SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG = SPINEL_PROP_THREAD_EXT__BEGIN + 57,
+
+ /// Register local Thread 1.2 Backbone Router configuration.
+ /** Format: Empty (Write only).
+ *
+ * Required capability: `SPINEL_CAP_THREAD_BACKBONE_ROUTER`
+ *
+ * Writing to this property (with any value) will register local Backbone Router configuration.
+ *
+ */
+ SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER = SPINEL_PROP_THREAD_EXT__BEGIN + 58,
+
+ /// Thread 1.2 Backbone Router registration jitter.
+ /** Format: `C` - Read-Write
+ *
+ * Required capability: `SPINEL_CAP_THREAD_BACKBONE_ROUTER`
+ *
+ * `C`: Backbone Router registration jitter.
+ *
+ */
+ SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER = SPINEL_PROP_THREAD_EXT__BEGIN + 59,
+
SPINEL_PROP_THREAD_EXT__END = 0x1600,
SPINEL_PROP_IPV6__BEGIN = 0x60,
@@ -3627,6 +3842,143 @@
*/
SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO = SPINEL_PROP_OPENTHREAD__BEGIN + 16,
+ /// SRP Client Start
+ /** Format: `b(6Sb)` - Write only
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * Writing to this property allows user to start or stop the SRP client operation with a given SRP server.
+ *
+ * Written value format is:
+ *
+ * `b` : TRUE to start the client, FALSE to stop the client.
+ *
+ * When used to start the SRP client, the following fields should also be included:
+ *
+ * `6` : SRP server IPv6 address.
+ * `U` : SRP server port number.
+ * `b` : Boolean to indicate whether or not to emit SRP client events (using `SPINEL_PROP_SRP_CLIENT_EVENT`).
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_START = SPINEL_PROP_OPENTHREAD__BEGIN + 17,
+
+ /// SRP Client Lease Interval
+ /** Format: `L` - Read/Write
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * The lease interval used in SRP update requests (in seconds).
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL = SPINEL_PROP_OPENTHREAD__BEGIN + 18,
+
+ /// SRP Client Key Lease Interval
+ /** Format: `L` - Read/Write
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * The key lease interval used in SRP update requests (in seconds).
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL = SPINEL_PROP_OPENTHREAD__BEGIN + 19,
+
+ /// SRP Client Host Info
+ /** Format: `UCt(A(6))` - Read only
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * Format is:
+ *
+ * `U` : The host name.
+ * `C` : The host state (values from `spinel_srp_client_item_state_t`).
+ * `t(A(6))` : Structure containing array of host IPv6 addresses.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_HOST_INFO = SPINEL_PROP_OPENTHREAD__BEGIN + 20,
+
+ /// SRP Client Host Name (label).
+ /** Format: `U` - Read/Write
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_HOST_NAME = SPINEL_PROP_OPENTHREAD__BEGIN + 21,
+
+ /// SRP Client Host Addresses
+ /** Format: `A(6)` - Read/Write
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES = SPINEL_PROP_OPENTHREAD__BEGIN + 22,
+
+ /// SRP Client Services
+ /** Format: `A(t(UUSSSd))` - Read/Insert/Remove
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * This property provide a list/array of services. Data per item is
+ *
+ * `U` : The service name labels (e.g., "_chip._udp", not the full domain name.
+ * `U` : The service instance name label (not the full name).
+ * `S` : The service port number.
+ * `S` : The service priority.
+ * `S` : The service weight.
+ *
+ * During remove operation, only service name and service instance name would be used.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_SERVICES = SPINEL_PROP_OPENTHREAD__BEGIN + 23,
+
+ /// SRP Client Host And Services Remove
+ /** Format: `b` : Write only
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * Writing to this property starts the remove process of the host info and all services.
+ * Please see `otSrpClientRemoveHostAndServices()` for more details.
+ *
+ * Format is:
+ *
+ * `b` : A boolean indicating whether or not the host key lease should also be removed.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE = SPINEL_PROP_OPENTHREAD__BEGIN + 24,
+
+ /// SRP Client Host And Services Clear
+ /** Format: Empty : Write only
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * Writing to this property clears all host info and all the services.
+ * Please see `otSrpClientClearHostAndServices()` for more details.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR = SPINEL_PROP_OPENTHREAD__BEGIN + 25,
+
+ /// SRP Client Event
+ /** Format: t() : Asynchronous event only
+ * Required capability: `SPINEL_CAP_SRP_CLIENT`.
+ *
+ * This property is asynchronously emitted when there is an event from SRP client notifying some state changes or
+ * errors.
+ *
+ * The general format of this property is as follows:
+ *
+ * `S` : Error code (see `spinel_srp_client_error_t` enumeration).
+ * `d` : Host info data.
+ * `d` : Active services.
+ * `d` : Removed services.
+ *
+ * The host info data contains:
+ *
+ * `U` : The host name.
+ * `C` : The host state (values from `spinel_srp_client_item_state_t`).
+ * `t(A(6))` : Structure containing array of host IPv6 addresses.
+ *
+ * The active or removed services data is an array of services `A(t(UUSSSd))` with each service format:
+ *
+ * `U` : The service name labels (e.g., "_chip._udp", not the full domain name.
+ * `U` : The service instance name label (not the full name).
+ * `S` : The service port number.
+ * `S` : The service priority.
+ * `S` : The service weight.
+ * `d` : The encoded TXT-DATA.
+ *
+ */
+ SPINEL_PROP_SRP_CLIENT_EVENT = SPINEL_PROP_OPENTHREAD__BEGIN + 26,
+
SPINEL_PROP_OPENTHREAD__END = 0x2000,
SPINEL_PROP_SERVER__BEGIN = 0xA0,
diff --git a/src/lib/spinel/spinel_buffer.cpp b/src/lib/spinel/spinel_buffer.cpp
index 93b198b..abaa2af 100644
--- a/src/lib/spinel/spinel_buffer.cpp
+++ b/src/lib/spinel/spinel_buffer.cpp
@@ -717,8 +717,7 @@
switch (mReadState)
{
case kReadStateNotActive:
-
- // Fall through
+ OT_FALL_THROUGH;
case kReadStateDone:
diff --git a/src/lib/url/url.cpp b/src/lib/url/url.cpp
index f15a7c8..659c525 100644
--- a/src/lib/url/url.cpp
+++ b/src/lib/url/url.cpp
@@ -98,7 +98,7 @@
}
else if (start[len] == '\0')
{
- ExitNow(rval = "");
+ ExitNow(rval = &start[len]);
}
}
last = start;
@@ -153,6 +153,24 @@
printf("PASS %s\r\n", __func__);
}
+void TestEmptyValue(void)
+{
+ char url[] = "spinel:///dev/ttyUSB0?rtscts&baudrate=115200&verbose&verbose&verbose";
+ ot::Url::Url args;
+ const char * arg = nullptr;
+
+ assert(!args.Init(url));
+ assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
+ assert((arg = args.GetValue("rtscts")) != nullptr);
+ assert(args.GetValue("rtscts", arg) == nullptr);
+ assert((arg = args.GetValue("verbose", arg)) != nullptr);
+ assert((arg = args.GetValue("verbose", arg)) != nullptr);
+ assert((arg = args.GetValue("verbose", arg)) != nullptr);
+ assert((arg = args.GetValue("verbose", arg)) == nullptr);
+
+ printf("PASS %s\r\n", __func__);
+}
+
void TestMultipleProtocols(void)
{
char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
@@ -196,6 +214,7 @@
{
TestSimple();
TestSimpleNoQueryString();
+ TestEmptyValue();
TestMultipleProtocols();
TestMultipleProtocolsAndDuplicateParameters();
diff --git a/src/ncp/BUILD.gn b/src/ncp/BUILD.gn
index 5e25ecc..2adfdec 100644
--- a/src/ncp/BUILD.gn
+++ b/src/ncp/BUILD.gn
@@ -38,10 +38,10 @@
"ncp_base_mtd.cpp",
"ncp_base_radio.cpp",
"ncp_config.h",
+ "ncp_hdlc.cpp",
+ "ncp_hdlc.hpp",
"ncp_spi.cpp",
"ncp_spi.hpp",
- "ncp_uart.cpp",
- "ncp_uart.hpp",
]
config("ncp_config") {
diff --git a/src/ncp/CMakeLists.txt b/src/ncp/CMakeLists.txt
index 8c0134a..76bf8d3 100644
--- a/src/ncp/CMakeLists.txt
+++ b/src/ncp/CMakeLists.txt
@@ -37,7 +37,7 @@
ncp_base_dispatcher.cpp
ncp_base_radio.cpp
ncp_spi.cpp
- ncp_uart.cpp
+ ncp_hdlc.cpp
)
set(OT_NCP_VENDOR_HOOK_SOURCE "" CACHE STRING "set vendor hook source file for NCP")
@@ -51,6 +51,12 @@
ncp_base_ftd.cpp
ncp_base_mtd.cpp
)
+option(OT_NCP_SPI "enable NCP SPI support")
+if(OT_NCP_SPI)
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NCP_SPI_ENABLE=1")
+else()
+ target_compile_definitions(ot-config INTERFACE "OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1")
+endif()
if(OT_FTD)
include(ftd.cmake)
diff --git a/src/ncp/Makefile.am b/src/ncp/Makefile.am
index 7733e9f..fff99af 100644
--- a/src/ncp/Makefile.am
+++ b/src/ncp/Makefile.am
@@ -37,6 +37,7 @@
lib_LIBRARIES = $(NULL)
+if OPENTHREAD_ENABLE_NCP
if OPENTHREAD_ENABLE_FTD
lib_LIBRARIES += libopenthread-ncp-ftd.a
endif
@@ -44,6 +45,7 @@
if OPENTHREAD_ENABLE_MTD
lib_LIBRARIES += libopenthread-ncp-mtd.a
endif
+endif
if OPENTHREAD_ENABLE_RADIO_ONLY
lib_LIBRARIES += libopenthread-rcp.a
@@ -110,8 +112,8 @@
ncp_config.h \
ncp_spi.cpp \
ncp_spi.hpp \
- ncp_uart.cpp \
- ncp_uart.hpp \
+ ncp_hdlc.cpp \
+ ncp_hdlc.hpp \
$(NULL)
if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
diff --git a/src/ncp/example_vendor_hook.cpp b/src/ncp/example_vendor_hook.cpp
index 195e084..4c0b72d 100644
--- a/src/ncp/example_vendor_hook.cpp
+++ b/src/ncp/example_vendor_hook.cpp
@@ -118,20 +118,27 @@
//-------------------------------------------------------------------------------------------------------------------
// When OPENTHREAD_ENABLE_NCP_VENDOR_HOOK is enabled, vendor code is
-// expected to provide the `otNcpInit()` function. The reason behind
+// expected to provide the `otAppNcpInit()` function. The reason behind
// this is to enable vendor code to define its own sub-class of
-// `NcpBase` or `NcpUart`/`NcpSpi`.
+// `NcpBase` or `NcpHdlc`/`NcpSpi`.
//
-// Example below show how to add a vendor sub-class over `NcpUart`.
+// Example below show how to add a vendor sub-class over `NcpHdlc`.
-#include "ncp_uart.hpp"
+#include "ncp_hdlc.hpp"
#include "common/new.hpp"
-class NcpVendorUart : public ot::Ncp::NcpUart
+class NcpVendorUart : public ot::Ncp::NcpHdlc
{
+ static int SendHdlc(const uint8_t *aBuf, uint16_t aBufLength)
+ {
+ OT_UNUSED_VARIABLE(aBuf);
+ OT_UNUSED_VARIABLE(aBufLength);
+ return 0;
+ }
+
public:
NcpVendorUart(ot::Instance *aInstance)
- : ot::Ncp::NcpUart(aInstance)
+ : ot::Ncp::NcpHdlc(aInstance, &NcpVendorUart::SendHdlc)
{
}
@@ -140,7 +147,7 @@
static OT_DEFINE_ALIGNED_VAR(sNcpVendorRaw, sizeof(NcpVendorUart), uint64_t);
-extern "C" void otNcpInit(otInstance *aInstance)
+extern "C" void otAppNcpInit(otInstance *aInstance)
{
NcpVendorUart *ncpVendor = nullptr;
ot::Instance * instance = static_cast<ot::Instance *>(aInstance);
diff --git a/src/ncp/ftd.cmake b/src/ncp/ftd.cmake
index afa685c..020c4d2 100644
--- a/src/ncp/ftd.cmake
+++ b/src/ncp/ftd.cmake
@@ -37,7 +37,7 @@
target_compile_definitions(openthread-ncp-ftd PRIVATE
OPENTHREAD_FTD=1
- OPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+ OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
)
target_compile_options(openthread-ncp-ftd PRIVATE
diff --git a/src/ncp/mtd.cmake b/src/ncp/mtd.cmake
index aa4f274..81a377c 100644
--- a/src/ncp/mtd.cmake
+++ b/src/ncp/mtd.cmake
@@ -37,7 +37,7 @@
target_compile_definitions(openthread-ncp-mtd PRIVATE
OPENTHREAD_MTD=1
- OPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+ OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
)
target_compile_options(openthread-ncp-mtd PRIVATE
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 3ef0445..4fbb8f6 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -135,6 +135,10 @@
ret = SPINEL_STATUS_ITEM_NOT_FOUND;
break;
+ case OT_ERROR_RESPONSE_TIMEOUT:
+ ret = SPINEL_STATUS_RESPONSE_TIMEOUT;
+ break;
+
default:
// Unknown error code. Wrap it as a Spinel status and return that.
ret = static_cast<spinel_status_t>(SPINEL_STATUS_STACK_NATIVE__BEGIN + static_cast<uint32_t>(aError));
@@ -207,7 +211,7 @@
, mDiscoveryScanJoinerFlag(false)
, mDiscoveryScanEnableFiltering(false)
, mDiscoveryScanPanId(0xffff)
- , mUpdateChangedPropsTask(*aInstance, NcpBase::UpdateChangedProps, this)
+ , mUpdateChangedPropsTask(*aInstance, NcpBase::UpdateChangedProps)
, mThreadChangedFlags(0)
, mHostPowerState(SPINEL_HOST_POWER_STATE_ONLINE)
, mHostPowerReplyFrameTag(Spinel::Buffer::kInvalidTag)
@@ -243,6 +247,10 @@
, mOutboundInsecureIpFrameCounter(0)
, mDroppedOutboundIpFrameCounter(0)
, mDroppedInboundIpFrameCounter(0)
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ , mSrpClientNumHostAddresses(0)
+ , mSrpClientCallbackEnabled(false)
+#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
, mFramingErrorCounter(0)
, mRxSpinelFrameCounter(0)
@@ -281,6 +289,9 @@
#endif
otThreadRegisterParentResponseCallback(mInstance, &NcpBase::HandleParentResponseInfo, static_cast<void *>(this));
#endif // OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ otSrpClientSetCallback(mInstance, HandleSrpClientCallback, this);
+#endif
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
mLegacyNodeDidJoin = false;
mLegacyHandlers = nullptr;
@@ -624,6 +635,18 @@
case OT_LOG_REGION_DUA:
spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_DUA;
break;
+
+ case OT_LOG_REGION_BR:
+ spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_BR;
+ break;
+
+ case OT_LOG_REGION_SRP:
+ spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_SRP;
+ break;
+
+ case OT_LOG_REGION_DNS:
+ spinelLogRegion = SPINEL_NCP_LOG_REGION_OT_DNS;
+ break;
}
return spinelLogRegion;
@@ -1195,14 +1218,6 @@
IgnoreError(otIp6SetEnabled(mInstance, false));
#endif
- error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_RESET_SOFTWARE);
-
- if (error != OT_ERROR_NONE)
- {
- mChangedPropsSet.AddLastStatus(SPINEL_STATUS_RESET_UNKNOWN);
- mUpdateChangedPropsTask.Post();
- }
-
sNcpInstance = nullptr;
return error;
@@ -1817,6 +1832,11 @@
#if OPENTHREAD_MTD || OPENTHREAD_FTD
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_1));
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NET_THREAD_1_2));
+#endif
+
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_PCAP));
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
@@ -1895,10 +1915,26 @@
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_SERVICE));
#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_CSL_RECEIVER));
+#endif
+
#if OPENTHREAD_CONFIG_MULTI_RADIO
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MULTI_RADIO));
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_SRP_CLIENT));
+#endif
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_DUA));
+#endif
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_BACKBONE_ROUTER));
+#endif
+
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
exit:
@@ -2262,6 +2298,36 @@
return error;
}
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_REGION_CODE>(void)
+{
+ uint16_t regionCode;
+ otError error = OT_ERROR_NONE;
+
+ error = otPlatRadioGetRegion(mInstance, ®ionCode);
+ if (error == OT_ERROR_NONE)
+ {
+ error = mEncoder.WriteUint16(regionCode);
+ }
+ else
+ {
+ error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
+ }
+
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_REGION_CODE>(void)
+{
+ uint16_t regionCode;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint16(regionCode));
+ error = otPlatRadioSetRegion(mInstance, regionCode);
+
+exit:
+ return error;
+}
+
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_DEBUG_TEST_ASSERT>(void)
{
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index acb2ca4..990c514 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -50,6 +50,9 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
#include <openthread/multi_radio.h>
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+#include <openthread/srp_client.h>
+#endif
#include "changed_props_set.hpp"
#include "common/instance.hpp"
@@ -334,6 +337,16 @@
void HandleJoinerCallback(otError aError);
#endif
+ static void HandleMlrRegResult_Jump(void * aContext,
+ otError aError,
+ uint8_t aMlrStatus,
+ const otIp6Address *aFailedAddresses,
+ uint8_t aFailedAddressNum);
+ void HandleMlrRegResult(otError aError,
+ uint8_t aMlrStatus,
+ const otIp6Address *aFailedAddresses,
+ uint8_t aFailedAddressNum);
+
otError EncodeOperationalDataset(const otOperationalDataset &aDataset);
otError DecodeOperationalDataset(otOperationalDataset &aDataset,
@@ -423,7 +436,7 @@
#if OPENTHREAD_CONFIG_DIAG_ENABLE
static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <=
OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE - kSpinelCmdHeaderSize - kSpinelPropIdSize,
- "diag output buffer should be smaller than NCP UART tx buffer");
+ "diag output buffer should be smaller than NCP HDLC tx buffer");
otError HandlePropertySet_SPINEL_PROP_NEST_STREAM_MFG(uint8_t aHeader);
#endif
@@ -594,6 +607,45 @@
uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames.
uint32_t mDroppedOutboundIpFrameCounter; // Number of dropped outbound data/IP frames.
uint32_t mDroppedInboundIpFrameCounter; // Number of dropped inbound data/IP frames.
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ enum : uint8_t
+ {
+ kSrpClientMaxServices = OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES,
+ kSrpClientMaxHostAddresses = OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES,
+ kSrpClientNameSize = 64,
+ };
+
+ struct SrpClientService
+ {
+ void MarkAsNotInUse(void) { mService.mNext = &mService; }
+ bool IsInUse(void) const { return (mService.mNext != &mService); }
+
+ otSrpClientService mService;
+ char mInstanceName[kSrpClientNameSize];
+ char mServiceName[kSrpClientNameSize];
+ };
+
+ otError EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo);
+ otError EncodeSrpClientServices(const otSrpClientService *aServices);
+
+ static void HandleSrpClientCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices,
+ void * aContext);
+ void HandleSrpClientCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices);
+
+ char mSrpClientHostName[kSrpClientNameSize];
+ SrpClientService mSrpClientServicePool[kSrpClientMaxServices];
+ otIp6Address mSrpClientHostAddresses[kSrpClientMaxHostAddresses];
+ uint8_t mSrpClientNumHostAddresses;
+ bool mSrpClientCallbackEnabled;
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
const otNcpLegacyHandlers *mLegacyHandlers;
uint8_t mLegacyUlaPrefix[OT_NCP_LEGACY_ULA_PREFIX_LENGTH];
diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp
index 01dec49..313a6a3 100644
--- a/src/ncp/ncp_base_dispatcher.cpp
+++ b/src/ncp/ncp_base_dispatcher.cpp
@@ -75,6 +75,7 @@
#endif
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_CHAN_PREFERRED),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_FEM_LNA_GAIN),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_PHY_REGION_CODE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_STATE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_MASK),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_PERIOD),
@@ -299,6 +300,29 @@
#if OPENTHREAD_FTD
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_NEW_DATASET),
+#endif
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_PERIOD),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_TIMEOUT),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_CHANNEL),
+#endif
+#if OPENTHREAD_FTD
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DOMAIN_NAME),
+#endif
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DUA_ID),
+#endif
+#endif // OPENTHREAD_FTD
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY),
+#endif
+#if OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER),
+#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_CHANNEL_MANAGER_DELAY),
@@ -328,6 +352,15 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO),
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_INFO),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_NAME),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES),
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
+#endif
+
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED),
@@ -376,6 +409,7 @@
#endif
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_FEM_LNA_GAIN),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_CHAN_MAX_POWER),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_PHY_REGION_CODE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_STATE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_MASK),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_SCAN_PERIOD),
@@ -511,7 +545,27 @@
#endif
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MGMT_GET_ACTIVE_DATASET),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MGMT_GET_PENDING_DATASET),
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_PERIOD),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_TIMEOUT),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_CSL_CHANNEL),
+#endif
#if OPENTHREAD_FTD
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DOMAIN_NAME),
+#endif
+#if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_MLR_REQUEST),
+#endif
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_DUA_ID),
+#endif
+#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER),
+#endif
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN),
@@ -542,6 +596,15 @@
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SLAAC_ENABLED),
#endif
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_START),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_NAME),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR),
+#endif
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX),
#endif
@@ -601,6 +664,11 @@
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_INSERT_HANDLER_ENTRY(SPINEL_PROP_THREAD_JOINERS),
#endif
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ OT_NCP_INSERT_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
+#endif
+#endif
};
#undef OT_NCP_INSERT_HANDLER_ENTRY
@@ -649,6 +717,11 @@
#if OPENTHREAD_FTD
OT_NCP_REMOVE_HANDLER_ENTRY(SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS),
#endif
+#if OPENTHREAD_FTD || OPENTHREAD_MTD
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ OT_NCP_REMOVE_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
+#endif
+#endif
};
#undef OT_NCP_REMOVE_HANDLER_ENTRY
diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp
index 72f6718..a62ae8b 100644
--- a/src/ncp/ncp_base_ftd.cpp
+++ b/src/ncp/ncp_base_ftd.cpp
@@ -33,6 +33,9 @@
#include "ncp_base.hpp"
#include <openthread/config.h>
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+#include <openthread/backbone_router_ftd.h>
+#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
#include <openthread/channel_manager.h>
#endif
@@ -131,7 +134,9 @@
{
case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
command = SPINEL_CMD_PROP_VALUE_INSERTED;
- // Fall through
+
+ OT_FALL_THROUGH;
+
case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
property = SPINEL_PROP_THREAD_CHILD_TABLE;
VerifyOrExit(!aEntry.mInfo.mChild.mIsStateRestoring);
@@ -139,7 +144,9 @@
case OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED:
command = SPINEL_CMD_PROP_VALUE_INSERTED;
- // Fall through
+
+ OT_FALL_THROUGH;
+
case OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED:
property = SPINEL_PROP_THREAD_NEIGHBOR_TABLE;
break;
@@ -327,6 +334,172 @@
return error;
}
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
+{
+ return mEncoder.WriteUtf8(otThreadGetDomainName(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
+{
+ otError error = OT_ERROR_NONE;
+ const char *domainName;
+
+ SuccessOrExit(error = mDecoder.ReadUtf8(domainName));
+
+ error = otThreadSetDomainName(mInstance, domainName);
+
+exit:
+ return error;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_DUA_ENABLE
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DUA_ID>(void)
+{
+ const otIp6InterfaceIdentifier *iid = otThreadGetFixedDuaInterfaceIdentifier(mInstance);
+ otError error = OT_ERROR_NONE;
+
+ if (iid == nullptr)
+ {
+ // send empty response
+ }
+ else
+ {
+ for (size_t i = 0; i < sizeof(otIp6InterfaceIdentifier); i++)
+ {
+ SuccessOrExit(error = mEncoder.WriteUint8(iid->mFields.m8[i]));
+ }
+ }
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DUA_ID>(void)
+{
+ otError error = OT_ERROR_NONE;
+
+ if (mDecoder.GetRemainingLength() == 0)
+ {
+ SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, nullptr));
+ }
+ else
+ {
+ otIp6InterfaceIdentifier iid;
+
+ for (size_t i = 0; i < sizeof(otIp6InterfaceIdentifier); i++)
+ {
+ SuccessOrExit(error = mDecoder.ReadUint8(iid.mFields.m8[i]));
+ }
+
+ SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, &iid));
+ }
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_DUA_ENABLE
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
+{
+ uint8_t state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;
+
+ switch (otBackboneRouterGetState(mInstance))
+ {
+ case OT_BACKBONE_ROUTER_STATE_DISABLED:
+ state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;
+ break;
+
+ case OT_BACKBONE_ROUTER_STATE_SECONDARY:
+ state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_SECONDARY;
+ break;
+
+ case OT_BACKBONE_ROUTER_STATE_PRIMARY:
+ state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY;
+ break;
+ }
+
+ return mEncoder.WriteUint8(state);
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
+{
+ uint8_t state;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint8(state));
+
+ if (state)
+ {
+ otBackboneRouterSetEnabled(mInstance, true);
+ }
+ else
+ {
+ otBackboneRouterSetEnabled(mInstance, false);
+ }
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
+{
+ otError error = OT_ERROR_NONE;
+ otBackboneRouterConfig bbrConfig;
+
+ otBackboneRouterGetConfig(mInstance, &bbrConfig);
+
+ SuccessOrExit(error = mEncoder.WriteUint16(bbrConfig.mReregistrationDelay));
+ SuccessOrExit(error = mEncoder.WriteUint32(bbrConfig.mMlrTimeout));
+ SuccessOrExit(error = mEncoder.WriteUint8(bbrConfig.mSequenceNumber));
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
+{
+ otError error = OT_ERROR_NONE;
+ otBackboneRouterConfig bbrConfig;
+
+ SuccessOrExit(error = mDecoder.ReadUint16(bbrConfig.mReregistrationDelay));
+ SuccessOrExit(error = mDecoder.ReadUint32(bbrConfig.mMlrTimeout));
+ SuccessOrExit(error = mDecoder.ReadUint8(bbrConfig.mSequenceNumber));
+
+ SuccessOrExit(error = otBackboneRouterSetConfig(mInstance, &bbrConfig));
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER>(void)
+{
+ return otBackboneRouterRegister(mInstance);
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
+{
+ uint8_t jitter = otBackboneRouterGetRegistrationJitter(mInstance);
+
+ return mEncoder.WriteUint8(jitter);
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
+{
+ otError error = OT_ERROR_NONE;
+ uint8_t jitter;
+
+ SuccessOrExit(error = mDecoder.ReadUint8(jitter));
+
+ otBackboneRouterSetRegistrationJitter(mInstance, jitter);
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_PSKC>(void)
{
return mEncoder.WriteData(otThreadGetPskc(mInstance)->m8, sizeof(spinel_net_pskc_t));
diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp
index 77d0b05..3c0faab 100644
--- a/src/ncp/ncp_base_mtd.cpp
+++ b/src/ncp/ncp_base_mtd.cpp
@@ -60,10 +60,14 @@
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
#include <openthread/server.h>
#endif
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+#include "openthread/backbone_router.h"
+#endif
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
+#include "common/string.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_MTD || OPENTHREAD_FTD
@@ -110,6 +114,23 @@
return flags;
}
+static uint8_t BorderRouterConfigToFlagByteExtended(const otBorderRouterConfig &aConfig)
+{
+ uint8_t flags(0);
+
+ if (aConfig.mNdDns)
+ {
+ flags |= SPINEL_NET_FLAG_EXT_DNS;
+ }
+
+ if (aConfig.mDp)
+ {
+ flags |= SPINEL_NET_FLAG_EXT_DP;
+ }
+
+ return flags;
+}
+
static uint8_t ExternalRoutePreferenceToFlagByte(int aPreference)
{
uint8_t flags;
@@ -125,7 +146,8 @@
break;
case OT_ROUTE_PREFERENCE_MED:
- // fall through
+
+ OT_FALL_THROUGH;
default:
flags = SPINEL_ROUTE_PREFERENCE_MEDIUM;
@@ -184,6 +206,168 @@
return error;
}
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CSL_PERIOD>(void)
+{
+ uint16_t cslPeriod;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint16(cslPeriod));
+
+ error = otLinkCslSetPeriod(mInstance, cslPeriod);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CSL_PERIOD>(void)
+{
+ return mEncoder.WriteUint16(otLinkCslGetPeriod(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CSL_TIMEOUT>(void)
+{
+ uint32_t cslTimeout;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint32(cslTimeout));
+
+ error = otLinkCslSetTimeout(mInstance, cslTimeout);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CSL_TIMEOUT>(void)
+{
+ return mEncoder.WriteUint32(otLinkCslGetTimeout(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CSL_CHANNEL>(void)
+{
+ uint8_t cslChannel;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint8(cslChannel));
+
+ error = otLinkCslSetChannel(mInstance, cslChannel);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CSL_CHANNEL>(void)
+{
+ return mEncoder.WriteUint8(otLinkCslGetChannel(mInstance));
+}
+#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MLR_REQUEST>(void)
+{
+ otError error = OT_ERROR_NONE;
+ otIp6Address addresses[kIp6AddressesNumMax];
+ uint8_t addressesCount = 0U;
+ bool timeoutPresent = false;
+ uint32_t timeout;
+
+ SuccessOrExit(error = mDecoder.OpenStruct());
+
+ while (mDecoder.GetRemainingLengthInStruct())
+ {
+ VerifyOrExit(addressesCount < kIp6AddressesNumMax, error = OT_ERROR_NO_BUFS);
+ SuccessOrExit(error = mDecoder.ReadIp6Address(addresses[addressesCount]));
+ ++addressesCount;
+ }
+
+ SuccessOrExit(error = mDecoder.CloseStruct());
+
+ while (mDecoder.GetRemainingLengthInStruct())
+ {
+ uint8_t paramId;
+
+ SuccessOrExit(error = mDecoder.OpenStruct());
+
+ SuccessOrExit(error = mDecoder.ReadUint8(paramId));
+
+ switch (paramId)
+ {
+ case SPINEL_THREAD_MLR_PARAMID_TIMEOUT:
+ SuccessOrExit(error = mDecoder.ReadUint32(timeout));
+ timeoutPresent = true;
+ break;
+
+ default:
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+
+ SuccessOrExit(error = mDecoder.CloseStruct());
+ }
+
+ SuccessOrExit(error = otIp6RegisterMulticastListeners(mInstance, addresses, addressesCount,
+ timeoutPresent ? &timeout : nullptr,
+ &NcpBase::HandleMlrRegResult_Jump, this));
+exit:
+ return error;
+}
+
+void NcpBase::HandleMlrRegResult_Jump(void * aContext,
+ otError aError,
+ uint8_t aMlrStatus,
+ const otIp6Address *aFailedAddresses,
+ uint8_t aFailedAddressNum)
+{
+ static_cast<NcpBase *>(aContext)->HandleMlrRegResult(aError, aMlrStatus, aFailedAddresses, aFailedAddressNum);
+}
+
+void NcpBase::HandleMlrRegResult(otError aError,
+ uint8_t aMlrStatus,
+ const otIp6Address *aFailedAddresses,
+ uint8_t aFailedAddressNum)
+{
+ SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
+ SPINEL_PROP_THREAD_MLR_RESPONSE));
+
+ SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(ThreadErrorToSpinelStatus(aError))));
+ SuccessOrExit(mEncoder.WriteUint8(aMlrStatus));
+
+ SuccessOrExit(mEncoder.OpenStruct());
+
+ if (aError == OT_ERROR_NONE)
+ {
+ for (size_t i = 0U; i < aFailedAddressNum; ++i)
+ {
+ SuccessOrExit(mEncoder.WriteIp6Address(aFailedAddresses[i]));
+ }
+ }
+
+ SuccessOrExit(mEncoder.CloseStruct());
+
+ SuccessOrExit(mEncoder.EndFrame());
+
+exit:
+ return;
+}
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+
+#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_PRIMARY>(void)
+{
+ otError error = OT_ERROR_NONE;
+ otBackboneRouterConfig bbrConfig;
+
+ SuccessOrExit(error = otBackboneRouterGetPrimary(mInstance, &bbrConfig));
+
+ SuccessOrExit(error = mEncoder.WriteUint16(bbrConfig.mServer16));
+ SuccessOrExit(error = mEncoder.WriteUint16(bbrConfig.mReregistrationDelay));
+ SuccessOrExit(error = mEncoder.WriteUint32(bbrConfig.mMlrTimeout));
+ SuccessOrExit(error = mEncoder.WriteUint8(bbrConfig.mSequenceNumber));
+
+exit:
+ return error;
+}
+#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
+
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>(void)
{
return mEncoder.WriteUint32(otLinkGetPollPeriod(mInstance));
@@ -710,6 +894,7 @@
SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
SuccessOrExit(error = mEncoder.WriteBool(false)); // isLocal
SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
+ SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByteExtended(borderRouterConfig)));
SuccessOrExit(error = mEncoder.CloseStruct());
}
@@ -729,6 +914,7 @@
SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByte(borderRouterConfig)));
SuccessOrExit(error = mEncoder.WriteBool(true)); // isLocal
SuccessOrExit(error = mEncoder.WriteUint16(borderRouterConfig.mRloc16));
+ SuccessOrExit(error = mEncoder.WriteUint8(BorderRouterConfigToFlagByteExtended(borderRouterConfig)));
SuccessOrExit(error = mEncoder.CloseStruct());
}
@@ -744,8 +930,11 @@
otError error = OT_ERROR_NONE;
otBorderRouterConfig borderRouterConfig;
bool stable = false;
- uint8_t flags = 0;
+ bool isLocal;
+ uint8_t flags = 0;
+ uint8_t flagsExtended = 0;
uint8_t prefixLength;
+ uint16_t rloc16;
memset(&borderRouterConfig, 0, sizeof(otBorderRouterConfig));
@@ -766,6 +955,16 @@
borderRouterConfig.mDefaultRoute = ((flags & SPINEL_NET_FLAG_DEFAULT_ROUTE) != 0);
borderRouterConfig.mOnMesh = ((flags & SPINEL_NET_FLAG_ON_MESH) != 0);
+ // A new field 'TLV flags extended' has been added to the SPINEL_PROP_THREAD_ON_MESH_NETS property.
+ // To correctly handle a new field for INSERT command, the additional fields 'isLocal' and 'rloc16' are read and
+ // ignored.
+ if ((mDecoder.ReadBool(isLocal) == OT_ERROR_NONE) && (mDecoder.ReadUint16(rloc16) == OT_ERROR_NONE) &&
+ (mDecoder.ReadUint8(flagsExtended) == OT_ERROR_NONE))
+ {
+ borderRouterConfig.mNdDns = ((flagsExtended & SPINEL_NET_FLAG_EXT_DNS) != 0);
+ borderRouterConfig.mDp = ((flagsExtended & SPINEL_NET_FLAG_EXT_DP) != 0);
+ }
+
error = otBorderRouterAddOnMeshPrefix(mInstance, &borderRouterConfig);
exit:
@@ -2749,7 +2948,7 @@
SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
SuccessOrExit(error = mDecoder.CloseStruct());
- otLinkFilterRemoveAddress(mInstance, extAddress);
+ SuccessOrExit(error = otLinkFilterAddAddress(mInstance, extAddress));
}
exit:
@@ -3212,6 +3411,432 @@
}
#endif // OPENTHREAD_CONFIG_MULTI_RADIO
+// ----------------------------------------------------------------------------
+// SRP Client
+// ----------------------------------------------------------------------------
+
+#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_START>(void)
+{
+ otError error = OT_ERROR_NONE;
+ bool start;
+ bool callbackEnabled;
+ otSockAddr serverAddr;
+
+ SuccessOrExit(error = mDecoder.ReadBool(start));
+
+ if (!start)
+ {
+ otSrpClientStop(mInstance);
+ ExitNow();
+ }
+
+ SuccessOrExit(error = mDecoder.ReadIp6Address(serverAddr.mAddress));
+ SuccessOrExit(error = mDecoder.ReadUint16(serverAddr.mPort));
+ SuccessOrExit(error = mDecoder.ReadBool(callbackEnabled));
+
+ SuccessOrExit(error = otSrpClientStart(mInstance, &serverAddr));
+ mSrpClientCallbackEnabled = callbackEnabled;
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL>(void)
+{
+ return mEncoder.WriteUint32(otSrpClientGetLeaseInterval(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL>(void)
+{
+ otError error;
+ uint32_t interval;
+
+ SuccessOrExit(error = mDecoder.ReadUint32(interval));
+ otSrpClientSetLeaseInterval(mInstance, interval);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL>(void)
+{
+ return mEncoder.WriteUint32(otSrpClientGetKeyLeaseInterval(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL>(void)
+{
+ otError error;
+ uint32_t interval;
+
+ SuccessOrExit(error = mDecoder.ReadUint32(interval));
+ otSrpClientSetKeyLeaseInterval(mInstance, interval);
+
+exit:
+ return error;
+}
+
+static spinel_srp_client_item_state_t SrpClientItemStatetoSpinel(otSrpClientItemState aItemState)
+{
+ spinel_srp_client_item_state_t state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED;
+
+ switch (aItemState)
+ {
+ case OT_SRP_CLIENT_ITEM_STATE_TO_ADD:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_ADD;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_ADDING:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_ADDING;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_REFRESH;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_REFRESHING:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_REFRESHING;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_REMOVE;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_REMOVING:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVING;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_REGISTERED:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_REGISTERED;
+ break;
+ case OT_SRP_CLIENT_ITEM_STATE_REMOVED:
+ state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED;
+ break;
+ }
+
+ return state;
+}
+
+otError NcpBase::EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo)
+{
+ otError error;
+
+ SuccessOrExit(error = mEncoder.WriteUtf8(aHostInfo.mName != nullptr ? aHostInfo.mName : ""));
+ SuccessOrExit(error = mEncoder.WriteUint8(SrpClientItemStatetoSpinel(aHostInfo.mState)));
+
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
+ {
+ SuccessOrExit(error = mEncoder.WriteIp6Address(aHostInfo.mAddresses[index]));
+ }
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_INFO>(void)
+{
+ return EncodeSrpClientHostInfo(*otSrpClientGetHostInfo(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_NAME>(void)
+{
+ const char *name = otSrpClientGetHostInfo(mInstance)->mName;
+
+ return mEncoder.WriteUtf8(name != nullptr ? name : "");
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_NAME>(void)
+{
+ otError error;
+ const char *name;
+
+ SuccessOrExit(error = mDecoder.ReadUtf8(name));
+
+ VerifyOrExit(StringLength(name, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS);
+
+ // We first make sure we can set the name, and if so
+ // we copy it to the `mSrpClientHostName` buffer and set
+ // the host name again now with the persisted buffer
+ // This ensures that we do not overwrite a previous
+ // `mSrpClientHostName` when host name cannot be set.
+
+ SuccessOrExit(error = otSrpClientSetHostName(mInstance, name));
+
+ strcpy(mSrpClientHostName, name);
+ error = otSrpClientSetHostName(mInstance, mSrpClientHostName);
+ OT_ASSERT(error == OT_ERROR_NONE);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES>(void)
+{
+ otError error = OT_ERROR_NONE;
+ const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(mInstance);
+
+ for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
+ {
+ SuccessOrExit(error = mEncoder.WriteIp6Address(hostInfo->mAddresses[index]));
+ }
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES>(void)
+{
+ otError error;
+ otIp6Address addresses[kSrpClientMaxHostAddresses];
+ uint8_t numAddresses = 0;
+
+ while (!mDecoder.IsAllReadInStruct())
+ {
+ VerifyOrExit(numAddresses < kSrpClientMaxHostAddresses, error = OT_ERROR_NO_BUFS);
+
+ SuccessOrExit(error = mDecoder.ReadIp6Address(addresses[numAddresses]));
+ numAddresses++;
+ }
+
+ // We first make sure we can set the addresses, and if so
+ // we copy the address list into `mSrpClientHostAddresses`
+ // and set it again. This ensures that we do not overwrite
+ // a previous list before we know it is safe to set/change
+ // the address list.
+
+ SuccessOrExit(error = otSrpClientSetHostAddresses(mInstance, addresses, numAddresses));
+
+ memcpy(mSrpClientHostAddresses, addresses, sizeof(addresses));
+ mSrpClientNumHostAddresses = numAddresses;
+
+ error = otSrpClientSetHostAddresses(mInstance, mSrpClientHostAddresses, numAddresses);
+ OT_ASSERT(error == OT_ERROR_NONE);
+
+exit:
+ return error;
+}
+
+otError NcpBase::EncodeSrpClientServices(const otSrpClientService *aServices)
+{
+ otError error = OT_ERROR_NONE;
+
+ for (; aServices != nullptr; aServices = aServices->mNext)
+ {
+ SuccessOrExit(error = mEncoder.OpenStruct());
+
+ SuccessOrExit(error = mEncoder.WriteUtf8(aServices->mName));
+ SuccessOrExit(error = mEncoder.WriteUtf8(aServices->mInstanceName));
+ SuccessOrExit(error = mEncoder.WriteUint16(aServices->mPort));
+ SuccessOrExit(error = mEncoder.WriteUint16(aServices->mPriority));
+ SuccessOrExit(error = mEncoder.WriteUint16(aServices->mWeight));
+
+ SuccessOrExit(error = mEncoder.CloseStruct());
+ }
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_SERVICES>(void)
+{
+ return EncodeSrpClientServices(otSrpClientGetServices(mInstance));
+}
+
+template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_SRP_CLIENT_SERVICES>(void)
+{
+ otError error = OT_ERROR_NONE;
+ SrpClientService *entry = nullptr;
+ const char * serviceName;
+ const char * instanceName;
+
+ for (SrpClientService &poolEntry : mSrpClientServicePool)
+ {
+ if (!poolEntry.IsInUse())
+ {
+ entry = &poolEntry;
+ break;
+ }
+ }
+
+ VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
+
+ SuccessOrExit(error = mDecoder.ReadUtf8(serviceName));
+ VerifyOrExit(StringLength(serviceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS);
+ strcpy(entry->mServiceName, serviceName);
+ entry->mService.mName = entry->mServiceName;
+
+ SuccessOrExit(error = mDecoder.ReadUtf8(instanceName));
+ VerifyOrExit(StringLength(instanceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS);
+ strcpy(entry->mInstanceName, instanceName);
+ entry->mService.mInstanceName = entry->mInstanceName;
+
+ SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mPort));
+ SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mPriority));
+ SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mWeight));
+
+ error = otSrpClientAddService(mInstance, &entry->mService);
+
+ if (error != OT_ERROR_NONE)
+ {
+ entry->MarkAsNotInUse();
+ }
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_SRP_CLIENT_SERVICES>(void)
+{
+ otError error = OT_ERROR_NONE;
+ const char *serviceName;
+ const char *instanceName;
+
+ SuccessOrExit(error = mDecoder.ReadUtf8(serviceName));
+ SuccessOrExit(error = mDecoder.ReadUtf8(instanceName));
+
+ for (SrpClientService &poolEntry : mSrpClientServicePool)
+ {
+ if (!poolEntry.IsInUse() || (strcmp(serviceName, poolEntry.mServiceName) != 0) ||
+ (strcmp(instanceName, poolEntry.mInstanceName) != 0))
+ {
+ continue;
+ }
+
+ error = otSrpClientRemoveService(mInstance, &poolEntry.mService);
+ ExitNow();
+ }
+
+ error = OT_ERROR_NOT_FOUND;
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE>(void)
+{
+ otError error = OT_ERROR_NONE;
+ bool removeKeyLease;
+
+ SuccessOrExit(error = mDecoder.ReadBool(removeKeyLease));
+
+ error = otSrpClientRemoveHostAndServices(mInstance, removeKeyLease);
+
+exit:
+ return error;
+}
+
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR>(void)
+{
+ otSrpClientClearHostAndServices(mInstance);
+
+ return OT_ERROR_NONE;
+}
+
+static spinel_srp_client_error_t SrpClientErrorToSpinelError(otError aError)
+{
+ spinel_srp_client_error_t error = SPINEL_SRP_CLIENT_ERROR_FAILED;
+
+ switch (aError)
+ {
+ case OT_ERROR_NONE:
+ error = SPINEL_SRP_CLIENT_ERROR_NONE;
+ break;
+ case OT_ERROR_PARSE:
+ error = SPINEL_SRP_CLIENT_ERROR_PARSE;
+ break;
+ case OT_ERROR_NOT_FOUND:
+ error = SPINEL_SRP_CLIENT_ERROR_NOT_FOUND;
+ break;
+ case OT_ERROR_NOT_IMPLEMENTED:
+ error = SPINEL_SRP_CLIENT_ERROR_NOT_IMPLEMENTED;
+ break;
+ case OT_ERROR_SECURITY:
+ error = SPINEL_SRP_CLIENT_ERROR_SECURITY;
+ break;
+ case OT_ERROR_DUPLICATED:
+ error = SPINEL_SRP_CLIENT_ERROR_DUPLICATED;
+ break;
+ case OT_ERROR_RESPONSE_TIMEOUT:
+ error = SPINEL_SRP_CLIENT_ERROR_RESPONSE_TIMEOUT;
+ break;
+ case OT_ERROR_INVALID_ARGS:
+ error = SPINEL_SRP_CLIENT_ERROR_INVALID_ARGS;
+ break;
+ case OT_ERROR_NO_BUFS:
+ error = SPINEL_SRP_CLIENT_ERROR_NO_BUFS;
+ break;
+ case OT_ERROR_FAILED:
+ default:
+ error = SPINEL_SRP_CLIENT_ERROR_FAILED;
+ break;
+ }
+
+ return error;
+}
+
+void NcpBase::HandleSrpClientCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices,
+ void * aContext)
+{
+ static_cast<NcpBase *>(aContext)->HandleSrpClientCallback(aError, aHostInfo, aServices, aRemovedServices);
+}
+
+void NcpBase::HandleSrpClientCallback(otError aError,
+ const otSrpClientHostInfo *aHostInfo,
+ const otSrpClientService * aServices,
+ const otSrpClientService * aRemovedServices)
+{
+ otError error = OT_ERROR_NONE;
+ const otSrpClientService *service;
+ const otSrpClientService *next;
+
+ VerifyOrExit(mSrpClientCallbackEnabled);
+
+ SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
+ SPINEL_PROP_SRP_CLIENT_EVENT));
+
+ SuccessOrExit(error = mEncoder.WriteUint16(SrpClientErrorToSpinelError(aError)));
+
+ SuccessOrExit(error = mEncoder.OpenStruct());
+ SuccessOrExit(error = EncodeSrpClientHostInfo(*aHostInfo));
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+ SuccessOrExit(error = mEncoder.OpenStruct());
+ SuccessOrExit(error = EncodeSrpClientServices(aServices));
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+ SuccessOrExit(error = mEncoder.OpenStruct());
+ SuccessOrExit(error = EncodeSrpClientServices(aRemovedServices));
+ SuccessOrExit(error = mEncoder.CloseStruct());
+
+ SuccessOrExit(error = mEncoder.EndFrame());
+
+exit:
+
+ if (error != OT_ERROR_NONE)
+ {
+ // Emit a NONMEM status if we fail to send the event.
+ mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
+ mUpdateChangedPropsTask.Post();
+ }
+
+ for (service = aRemovedServices; service != nullptr; service = next)
+ {
+ next = service->mNext;
+
+ for (SrpClientService &poolEntry : mSrpClientServicePool)
+ {
+ if (&poolEntry.mService == service)
+ {
+ poolEntry.MarkAsNotInUse();
+ }
+ }
+ }
+}
+
+#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
diff --git a/src/ncp/ncp_config.h b/src/ncp/ncp_config.h
index cc584c1..60ab9c6 100644
--- a/src/ncp/ncp_config.h
+++ b/src/ncp/ncp_config.h
@@ -50,13 +50,13 @@
#endif
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#ifndef OPENTHREAD_CONFIG_NCP_UART_ENABLE
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 0
+#ifndef OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 0
#endif
/**
@@ -66,32 +66,32 @@
*
*/
#ifndef OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE
-#define OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE 512
+#define OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE 2048
#endif
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_TX_CHUNK_SIZE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE
*
- * The size of NCP UART TX chunk in bytes.
+ * The size of NCP HDLC TX chunk in bytes.
*
*/
-#ifndef OPENTHREAD_CONFIG_NCP_UART_TX_CHUNK_SIZE
-#define OPENTHREAD_CONFIG_NCP_UART_TX_CHUNK_SIZE 128
+#ifndef OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE
+#define OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE 2048
#endif
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE
*
- * The size of NCP UART RX buffer in bytes.
+ * The size of NCP HDLC RX buffer in bytes.
*
*/
-#ifndef OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE
+#ifndef OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE
#if OPENTHREAD_RADIO
-#define OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE 512
+#define OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE 512
#else
-#define OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE 1300
+#define OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE 1300
#endif
-#endif // OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE
+#endif // OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE
/**
* @def OPENTHREAD_CONFIG_NCP_SPI_BUFFER_SIZE
@@ -189,4 +189,28 @@
#define OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 0
#endif
+/**
+ * @def OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES
+ *
+ * The maximum number of service entries supported by SRP client.
+ *
+ * This is only applicable when SRP client is enabled, i.e., OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES
+#define OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES 2
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES
+ *
+ * The maximum number of host IPv6 address entries supported by SRP client.
+ *
+ * This is only applicable when SRP client is enabled, i.e., OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES
+#define OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES 2
+#endif
+
#endif // CONFIG_NCP_H_
diff --git a/src/ncp/ncp_uart.cpp b/src/ncp/ncp_hdlc.cpp
similarity index 73%
rename from src/ncp/ncp_uart.cpp
rename to src/ncp/ncp_hdlc.cpp
index e5d0e1c..b1a56c3 100644
--- a/src/ncp/ncp_uart.cpp
+++ b/src/ncp/ncp_hdlc.cpp
@@ -27,17 +27,16 @@
/**
* @file
- * This file contains definitions for a UART based NCP interface to the OpenThread stack.
+ * This file contains definitions for a HDLC based NCP interface to the OpenThread stack.
*/
-#include "ncp_uart.hpp"
+#include "ncp_hdlc.hpp"
#include <stdio.h>
#include <openthread/ncp.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/misc.h>
-#include <openthread/platform/uart.h>
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
@@ -46,16 +45,16 @@
#include "common/new.hpp"
#include "net/ip6.hpp"
-#if OPENTHREAD_CONFIG_NCP_UART_ENABLE
+#if OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
#if OPENTHREAD_CONFIG_DIAG_ENABLE
-static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <= OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE -
+static_assert(OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE <= OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE -
ot::Ncp::NcpBase::kSpinelCmdHeaderSize -
ot::Ncp::NcpBase::kSpinelPropIdSize,
- "diag output should be smaller than NCP UART rx buffer");
+ "diag output should be smaller than NCP HDLC rx buffer");
-static_assert(OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE <= OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE,
- "diag command line should be smaller than NCP UART rx buffer");
+static_assert(OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE <= OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE,
+ "diag command line should be smaller than NCP HDLC rx buffer");
#endif
namespace ot {
@@ -63,16 +62,16 @@
#if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK == 0
-static OT_DEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpUart), uint64_t);
+static OT_DEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpHdlc), uint64_t);
-extern "C" void otNcpInit(otInstance *aInstance)
+extern "C" void otNcpHdlcInit(otInstance *aInstance, otNcpHdlcSendCallback aSendCallback)
{
- NcpUart * ncpUart = nullptr;
+ NcpHdlc * ncpHdlc = nullptr;
Instance *instance = static_cast<Instance *>(aInstance);
- ncpUart = new (&sNcpRaw) NcpUart(instance);
+ ncpHdlc = new (&sNcpRaw) NcpHdlc(instance, aSendCallback);
- if (ncpUart == nullptr || ncpUart != NcpBase::GetNcpInstance())
+ if (ncpHdlc == nullptr || ncpHdlc != NcpBase::GetNcpInstance())
{
OT_ASSERT(false);
}
@@ -80,24 +79,23 @@
#endif // OPENTHREAD_ENABLE_NCP_VENDOR_HOOK == 0
-NcpUart::NcpUart(Instance *aInstance)
+NcpHdlc::NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback)
: NcpBase(aInstance)
- , mFrameEncoder(mUartBuffer)
- , mFrameDecoder(mRxBuffer, &NcpUart::HandleFrame, this)
+ , mSendCallback(aSendCallback)
+ , mFrameEncoder(mHdlcBuffer)
+ , mFrameDecoder(mRxBuffer, &NcpHdlc::HandleFrame, this)
, mState(kStartingFrame)
, mByte(0)
- , mUartSendImmediate(false)
- , mUartSendTask(*aInstance, EncodeAndSendToUart, this)
+ , mHdlcSendImmediate(false)
+ , mHdlcSendTask(*aInstance, EncodeAndSend)
#if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
, mTxFrameBufferEncrypterReader(mTxFrameBuffer)
#endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
{
mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this);
-
- IgnoreError(otPlatUartEnable());
}
-void NcpUart::HandleFrameAddedToNcpBuffer(void * aContext,
+void NcpHdlc::HandleFrameAddedToNcpBuffer(void * aContext,
Spinel::Buffer::FrameTag aTag,
Spinel::Buffer::Priority aPriority,
Spinel::Buffer * aBuffer)
@@ -106,27 +104,27 @@
OT_UNUSED_VARIABLE(aTag);
OT_UNUSED_VARIABLE(aPriority);
- static_cast<NcpUart *>(aContext)->HandleFrameAddedToNcpBuffer();
+ static_cast<NcpHdlc *>(aContext)->HandleFrameAddedToNcpBuffer();
}
-void NcpUart::HandleFrameAddedToNcpBuffer(void)
+void NcpHdlc::HandleFrameAddedToNcpBuffer(void)
{
- if (mUartBuffer.IsEmpty())
+ if (mHdlcBuffer.IsEmpty())
{
- mUartSendTask.Post();
+ mHdlcSendTask.Post();
}
}
-void NcpUart::EncodeAndSendToUart(Tasklet &aTasklet)
+void NcpHdlc::EncodeAndSend(Tasklet &aTasklet)
{
OT_UNUSED_VARIABLE(aTasklet);
- static_cast<NcpUart *>(GetNcpInstance())->EncodeAndSendToUart();
+ static_cast<NcpHdlc *>(GetNcpInstance())->EncodeAndSend();
}
// This method encodes a frame from the tx frame buffer (mTxFrameBuffer) into the uart buffer and sends it over uart.
// If the uart buffer gets full, it sends the current encoded portion. This method remembers current state, so on
// sub-sequent calls, it restarts encoding the bytes from where it left of in the frame .
-void NcpUart::EncodeAndSendToUart(void)
+void NcpHdlc::EncodeAndSend(void)
{
uint16_t len;
bool prevHostPowerState;
@@ -158,6 +156,8 @@
{
mByte = txFrameBuffer.OutFrameReadByte();
+ OT_FALL_THROUGH;
+
case kEncodingFrame:
SuccessOrExit(mFrameEncoder.Encode(mByte));
@@ -173,15 +173,15 @@
{
// If mHostPowerStateInProgress transitioned from true -> false
// in the call to OutFrameRemove, then the frame should be sent
- // out the UART without attempting to push any new frames into
- // the mUartBuffer. This is necessary to avoid prematurely calling
+ // out without attempting to push any new frames into the
+ // mHdlcBuffer. This is necessary to avoid prematurely calling
// otPlatWakeHost.
- mUartSendImmediate = true;
+ mHdlcSendImmediate = true;
}
mState = kFinalizingFrame;
- // fall through
+ OT_FALL_THROUGH;
case kFinalizingFrame:
@@ -189,64 +189,63 @@
mState = kStartingFrame;
- if (mUartSendImmediate)
+ if (mHdlcSendImmediate)
{
// clear state and break;
- mUartSendImmediate = false;
+ mHdlcSendImmediate = false;
break;
}
}
}
exit:
- len = mUartBuffer.GetLength();
+ len = mHdlcBuffer.GetLength();
if (len > 0)
{
- if (otPlatUartSend(mUartBuffer.GetFrame(), len) != OT_ERROR_NONE)
- {
- OT_ASSERT(false);
- }
+ int rval = mSendCallback(mHdlcBuffer.GetFrame(), len);
+ OT_UNUSED_VARIABLE(rval);
+ OT_ASSERT(rval == static_cast<int>(len));
}
}
-extern "C" void otPlatUartSendDone(void)
+extern "C" void otNcpHdlcSendDone(void)
{
- NcpUart *ncpUart = static_cast<NcpUart *>(NcpBase::GetNcpInstance());
+ NcpHdlc *ncpHdlc = static_cast<NcpHdlc *>(NcpBase::GetNcpInstance());
- if (ncpUart != nullptr)
+ if (ncpHdlc != nullptr)
{
- ncpUart->HandleUartSendDone();
+ ncpHdlc->HandleHdlcSendDone();
}
}
-void NcpUart::HandleUartSendDone(void)
+void NcpHdlc::HandleHdlcSendDone(void)
{
- mUartBuffer.Clear();
- mUartSendTask.Post();
+ mHdlcBuffer.Clear();
+ mHdlcSendTask.Post();
}
-extern "C" void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
+extern "C" void otNcpHdlcReceive(const uint8_t *aBuf, uint16_t aBufLength)
{
- NcpUart *ncpUart = static_cast<NcpUart *>(NcpBase::GetNcpInstance());
+ NcpHdlc *ncpHdlc = static_cast<NcpHdlc *>(NcpBase::GetNcpInstance());
- if (ncpUart != nullptr)
+ if (ncpHdlc != nullptr)
{
- ncpUart->HandleUartReceiveDone(aBuf, aBufLength);
+ ncpHdlc->HandleHdlcReceiveDone(aBuf, aBufLength);
}
}
-void NcpUart::HandleUartReceiveDone(const uint8_t *aBuf, uint16_t aBufLength)
+void NcpHdlc::HandleHdlcReceiveDone(const uint8_t *aBuf, uint16_t aBufLength)
{
mFrameDecoder.Decode(aBuf, aBufLength);
}
-void NcpUart::HandleFrame(void *aContext, otError aError)
+void NcpHdlc::HandleFrame(void *aContext, otError aError)
{
- static_cast<NcpUart *>(aContext)->HandleFrame(aError);
+ static_cast<NcpHdlc *>(aContext)->HandleFrame(aError);
}
-void NcpUart::HandleFrame(otError aError)
+void NcpHdlc::HandleFrame(otError aError)
{
uint8_t *buf = mRxBuffer.GetFrame();
uint16_t bufLength = mRxBuffer.GetLength();
@@ -271,7 +270,7 @@
mRxBuffer.Clear();
}
-void NcpUart::HandleError(otError aError, uint8_t *aBuf, uint16_t aBufLength)
+void NcpHdlc::HandleError(otError aError, uint8_t *aBuf, uint16_t aBufLength)
{
char hexbuf[128];
uint16_t i = 0;
@@ -306,19 +305,19 @@
#if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
-NcpUart::BufferEncrypterReader::BufferEncrypterReader(Spinel::Buffer &aTxFrameBuffer)
+NcpHdlc::BufferEncrypterReader::BufferEncrypterReader(Spinel::Buffer &aTxFrameBuffer)
: mTxFrameBuffer(aTxFrameBuffer)
, mDataBufferReadIndex(0)
, mOutputDataLength(0)
{
}
-bool NcpUart::BufferEncrypterReader::IsEmpty(void) const
+bool NcpHdlc::BufferEncrypterReader::IsEmpty(void) const
{
return mTxFrameBuffer.IsEmpty() && !mOutputDataLength;
}
-otError NcpUart::BufferEncrypterReader::OutFrameBegin(void)
+otError NcpHdlc::BufferEncrypterReader::OutFrameBegin(void)
{
otError status = OT_ERROR_FAILED;
@@ -348,22 +347,22 @@
return status;
}
-bool NcpUart::BufferEncrypterReader::OutFrameHasEnded(void)
+bool NcpHdlc::BufferEncrypterReader::OutFrameHasEnded(void)
{
return (mDataBufferReadIndex >= mOutputDataLength);
}
-uint8_t NcpUart::BufferEncrypterReader::OutFrameReadByte(void)
+uint8_t NcpHdlc::BufferEncrypterReader::OutFrameReadByte(void)
{
return mDataBuffer[mDataBufferReadIndex++];
}
-otError NcpUart::BufferEncrypterReader::OutFrameRemove(void)
+otError NcpHdlc::BufferEncrypterReader::OutFrameRemove(void)
{
return mTxFrameBuffer.OutFrameRemove();
}
-void NcpUart::BufferEncrypterReader::Reset(void)
+void NcpHdlc::BufferEncrypterReader::Reset(void)
{
mOutputDataLength = 0;
mDataBufferReadIndex = 0;
@@ -374,4 +373,4 @@
} // namespace Ncp
} // namespace ot
-#endif // OPENTHREAD_CONFIG_NCP_UART_ENABLE
+#endif // OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
diff --git a/src/ncp/ncp_uart.hpp b/src/ncp/ncp_hdlc.hpp
similarity index 76%
rename from src/ncp/ncp_uart.hpp
rename to src/ncp/ncp_hdlc.hpp
index 5892c2f..e3c489f 100644
--- a/src/ncp/ncp_uart.hpp
+++ b/src/ncp/ncp_hdlc.hpp
@@ -27,11 +27,11 @@
/**
* @file
- * This file contains definitions for a UART based NCP interface to the OpenThread stack.
+ * This file contains definitions for a HDLC based NCP interface to the OpenThread stack.
*/
-#ifndef NCP_UART_HPP_
-#define NCP_UART_HPP_
+#ifndef NCP_HDLC_HPP_
+#define NCP_HDLC_HPP_
#include "openthread-core-config.h"
@@ -45,7 +45,7 @@
namespace ot {
namespace Ncp {
-class NcpUart : public NcpBase
+class NcpHdlc : public NcpBase
{
typedef NcpBase super_t;
@@ -56,29 +56,29 @@
* @param[in] aInstance The OpenThread instance structure.
*
*/
- explicit NcpUart(Instance *aInstance);
+ explicit NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback);
/**
* This method is called when uart tx is finished. It prepares and sends the next data chunk (if any) to uart.
*
*/
- void HandleUartSendDone(void);
+ void HandleHdlcSendDone(void);
/**
* This method is called when uart received a data buffer.
*
*/
- void HandleUartReceiveDone(const uint8_t *aBuf, uint16_t aBufLength);
+ void HandleHdlcReceiveDone(const uint8_t *aBuf, uint16_t aBufLength);
private:
enum
{
- kUartTxBufferSize = OPENTHREAD_CONFIG_NCP_UART_TX_CHUNK_SIZE, // Uart tx buffer size.
- kRxBufferSize = OPENTHREAD_CONFIG_NCP_UART_RX_BUFFER_SIZE + // Rx buffer size (should be large enough to fit
+ kHdlcTxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_TX_CHUNK_SIZE, // HDLC tx buffer size.
+ kRxBufferSize = OPENTHREAD_CONFIG_NCP_HDLC_RX_BUFFER_SIZE + // Rx buffer size (should be large enough to fit
OPENTHREAD_CONFIG_NCP_SPINEL_ENCRYPTER_EXTRA_DATA_SIZE, // one whole (decoded) received frame).
};
- enum UartTxState
+ enum HdlcTxState
{
kStartingFrame, // Starting a new frame.
kEncodingFrame, // In middle of encoding a frame.
@@ -114,27 +114,28 @@
};
#endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
- void EncodeAndSendToUart(void);
+ void EncodeAndSend(void);
void HandleFrame(otError aError);
void HandleError(otError aError, uint8_t *aBuf, uint16_t aBufLength);
void TxFrameBufferHasData(void);
void HandleFrameAddedToNcpBuffer(void);
- static void EncodeAndSendToUart(Tasklet &aTasklet);
- static void HandleFrame(void *aContext, otError aError);
- static void HandleFrameAddedToNcpBuffer(void * aContext,
- Spinel::Buffer::FrameTag aTag,
- Spinel::Buffer::Priority aPriority,
- Spinel::Buffer * aBuffer);
+ static void EncodeAndSend(Tasklet &aTasklet);
+ static void HandleFrame(void *aContext, otError aError);
+ static void HandleFrameAddedToNcpBuffer(void * aContext,
+ Spinel::Buffer::FrameTag aTag,
+ Spinel::Buffer::Priority aPriority,
+ Spinel::Buffer * aBuffer);
+ otNcpHdlcSendCallback mSendCallback;
Hdlc::Encoder mFrameEncoder;
Hdlc::Decoder mFrameDecoder;
- Hdlc::FrameBuffer<kUartTxBufferSize> mUartBuffer;
- UartTxState mState;
+ Hdlc::FrameBuffer<kHdlcTxBufferSize> mHdlcBuffer;
+ HdlcTxState mState;
uint8_t mByte;
Hdlc::FrameBuffer<kRxBufferSize> mRxBuffer;
- bool mUartSendImmediate;
- Tasklet mUartSendTask;
+ bool mHdlcSendImmediate;
+ Tasklet mHdlcSendTask;
#if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
BufferEncrypterReader mTxFrameBufferEncrypterReader;
@@ -144,4 +145,4 @@
} // namespace Ncp
} // namespace ot
-#endif // NCP_UART_HPP_
+#endif // NCP_HDLC_HPP_
diff --git a/src/ncp/ncp_spi.cpp b/src/ncp/ncp_spi.cpp
index aa044c5..618769b 100644
--- a/src/ncp/ncp_spi.cpp
+++ b/src/ncp/ncp_spi.cpp
@@ -62,7 +62,7 @@
static OT_DEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpSpi), uint64_t);
-extern "C" void otNcpInit(otInstance *aInstance)
+extern "C" void otNcpSpiInit(otInstance *aInstance)
{
NcpSpi * ncpSpi = nullptr;
Instance *instance = static_cast<Instance *>(aInstance);
@@ -82,7 +82,7 @@
, mTxState(kTxStateIdle)
, mHandlingRxFrame(false)
, mResetFlag(true)
- , mPrepareTxFrameTask(*aInstance, NcpSpi::PrepareTxFrame, this)
+ , mPrepareTxFrameTask(*aInstance, NcpSpi::PrepareTxFrame)
, mSendFrameLength(0)
{
SpiFrame sendFrame(mSendFrame);
@@ -326,7 +326,7 @@
case kTxStateHandlingSendDone:
mTxState = kTxStateIdle;
- // Fall through
+ OT_FALL_THROUGH;
// to next case to prepare the next frame (if any).
case kTxStateIdle:
diff --git a/src/ncp/radio.cmake b/src/ncp/radio.cmake
index 212a8c0..502961a 100644
--- a/src/ncp/radio.cmake
+++ b/src/ncp/radio.cmake
@@ -37,7 +37,7 @@
target_compile_definitions(openthread-rcp PRIVATE
OPENTHREAD_RADIO=1
- OPENTHREAD_CONFIG_NCP_UART_ENABLE=1
+ OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1
)
target_compile_options(openthread-rcp PRIVATE
diff --git a/src/posix/CMakeLists.txt b/src/posix/CMakeLists.txt
index 978bb9f..575271a 100644
--- a/src/posix/CMakeLists.txt
+++ b/src/posix/CMakeLists.txt
@@ -26,10 +26,6 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-target_compile_definitions(ot-config INTERFACE
- OPENTHREAD_CONFIG_UART_CLI_RAW=1
-)
-
set(COMMON_INCLUDES
${OT_PUBLIC_INCLUDES}
${PROJECT_SOURCE_DIR}/src
@@ -38,15 +34,32 @@
${PROJECT_SOURCE_DIR}/src/posix/platform/include
)
-set(OT_READLINE "readline" CACHE STRING "set readline library name")
-set_property(CACHE OT_READLINE PROPERTY STRINGS "readline" "edit")
+set(OT_READLINE_VALUES
+ "readline"
+ "edit"
+)
-if(OT_READLINE)
+set(OT_READLINE "" CACHE STRING "set readline library name")
+set_property(CACHE OT_READLINE PROPERTY STRINGS ${OT_READLINE_VALUES})
+
+if(OT_READLINE STREQUAL "")
+ foreach(X IN LISTS OT_READLINE_VALUES)
+ find_library(READLINE ${X})
+ if (READLINE)
+ set(OT_READLINE ${X})
+ break()
+ endif()
+ endforeach()
+elseif(OT_READLINE)
find_library(READLINE ${OT_READLINE})
if (NOT READLINE)
message(FATAL_ERROR "Failed to find ${OT_READLINE}")
endif()
+endif()
+
+if (READLINE)
+ message(STATUS "Readline: ${OT_READLINE}")
find_library(NCURSES ncurses)
if (NOT NCURSES)
diff --git a/src/posix/Makefile-posix b/src/posix/Makefile-posix
index 31a071a..b4c9783 100644
--- a/src/posix/Makefile-posix
+++ b/src/posix/Makefile-posix
@@ -45,10 +45,12 @@
CHANNEL_MONITOR ?= 1
CHILD_SUPERVISION ?= 1
DAEMON ?= 0
+DATASET_UPDATER ?= 1
DHCP6_CLIENT ?= 1
DHCP6_SERVER ?= 1
DIAGNOSTIC ?= 1
DNS_CLIENT ?= 1
+DNSSD_SERVER ?= 1
DYNAMIC_LOG_LEVEL ?= 1
ECDSA ?= 1
IP6_FRAGM ?= 1
@@ -60,17 +62,19 @@
MAC_FILTER ?= 1
MAX_POWER_TABLE ?= 1
MTD_NETDIAG ?= 1
+PING_SENDER ?= 1
READLINE ?= readline
REFERENCE_DEVICE ?= 1
SERVICE ?= 1
SNTP_CLIENT ?= 1
+SRP_CLIENT ?= 1
+SRP_SERVER ?= 1
ifneq ($(DAEMON),1)
UDP_FORWARD ?= 1
endif
COMMONCFLAGS := \
-g \
- -DOPENTHREAD_CONFIG_UART_CLI_RAW=1 \
$(NULL)
# If the user has asserted COVERAGE, alter the configuration options
@@ -109,7 +113,6 @@
ifneq ($(READLINE),)
configure_OPTIONS += --with-readline=$(READLINE)
-CLI_TRANSPORT = $(if $(and $(filter-out no,$(READLINE)),$(filter 0,$(DAEMON))),CONSOLE,UART)
endif
ifeq ($(RCP_BUS),spi)
diff --git a/src/posix/Makefile.am b/src/posix/Makefile.am
index d9e17d4..e20aa6c 100644
--- a/src/posix/Makefile.am
+++ b/src/posix/Makefile.am
@@ -82,6 +82,7 @@
ot_ncp_SOURCES = \
main.c \
+ ncp.cpp \
$(NULL)
ot_ncp_LDADD = \
@@ -162,7 +163,7 @@
ot_cli_SOURCES = \
main.c \
- console_cli.cpp \
+ cli.cpp \
$(NULL)
ot_cli_LDADD = \
@@ -198,8 +199,4 @@
endif # OPENTHREAD_BUILD_COVERAGE
endif # OPENTHREAD_ENABLE_EXECUTABLE
-noinst_HEADERS = \
- console_cli.h \
- $(NULL)
-
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/src/posix/cli.cmake b/src/posix/cli.cmake
index eef034e..cfb5dc3 100644
--- a/src/posix/cli.cmake
+++ b/src/posix/cli.cmake
@@ -28,7 +28,7 @@
add_executable(ot-cli
main.c
- $<$<BOOL:${READLINE}>:console_cli.cpp>
+ cli.cpp
)
set_target_properties(
@@ -40,10 +40,6 @@
target_include_directories(ot-cli PRIVATE ${COMMON_INCLUDES})
-if(OT_READLINE)
- set(OT_CLI_TRANSPORT "CONSOLE" CACHE STRING "set CLI to use console interpreter" FORCE)
-endif()
-
target_compile_definitions(ot-cli PRIVATE
$<$<BOOL:${READLINE}>:HAVE_LIB$<UPPER_CASE:${OT_READLINE}>=1>
OPENTHREAD_POSIX_APP_TYPE=OT_POSIX_APP_TYPE_CLI
diff --git a/src/posix/console_cli.cpp b/src/posix/cli.cpp
similarity index 61%
rename from src/posix/console_cli.cpp
rename to src/posix/cli.cpp
index 735e983..4949de5 100644
--- a/src/posix/console_cli.cpp
+++ b/src/posix/cli.cpp
@@ -26,13 +26,15 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "console_cli.h"
+#include "platform/openthread-posix-config.h"
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_CONSOLE
+#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
#include <openthread/config.h>
+#include <openthread/openthread-system.h>
#include <assert.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -46,34 +48,36 @@
#endif
#if HAVE_LIBEDIT || HAVE_LIBREADLINE
+#define OPENTHREAD_USE_READLINE 1
#if HAVE_LIBEDIT
#include <editline/readline.h>
#elif HAVE_LIBREADLINE
#include <readline/history.h>
#include <readline/readline.h>
+#endif
#else
-#error "Missing readline library"
+#define OPENTHREAD_USE_READLINE 0
#endif
#include <openthread/cli.h>
+#include "cli/cli_config.h"
+#include "common/code_utils.hpp"
+
#include "openthread-core-config.h"
#include "platform-posix.h"
static const char sPrompt[] = "> ";
-static int sReadFd;
-
+#if OPENTHREAD_USE_READLINE
static void InputCallback(char *aLine)
{
if (aLine != nullptr)
{
- size_t len;
-
- if ((len = strlen(aLine)) > 0)
+ if (aLine[0] != '\0')
{
add_history(aLine);
- otCliConsoleInputLine(aLine, (uint16_t)len);
+ otCliInputLine(aLine);
}
free(aLine);
}
@@ -82,54 +86,72 @@
exit(OT_EXIT_SUCCESS);
}
}
+#endif
-static int OutputCallback(const char *aBuffer, uint16_t aLength, void *aContext)
+static int OutputCallback(void *aContext, const char *aFormat, va_list aArguments)
{
- (void)aContext;
+ OT_UNUSED_VARIABLE(aContext);
- return (int)write(STDOUT_FILENO, aBuffer, aLength);
+ return vdprintf(STDOUT_FILENO, aFormat, aArguments);
}
-void otxConsoleInit(otInstance *aInstance)
+extern "C" void otAppCliInit(otInstance *aInstance)
{
+#if OPENTHREAD_USE_READLINE
rl_instream = stdin;
rl_outstream = stdout;
rl_inhibit_completion = true;
- sReadFd = fileno(rl_instream);
+
+ rl_set_screen_size(0, OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH);
+
rl_callback_handler_install(sPrompt, InputCallback);
- otCliConsoleInit(aInstance, OutputCallback, nullptr);
+#endif
+ otCliInit(aInstance, OutputCallback, nullptr);
}
-void otxConsoleDeinit(void)
+extern "C" void otAppCliDeinit(void)
{
+#if OPENTHREAD_USE_READLINE
rl_callback_handler_remove();
+#endif
}
-void otxConsoleUpdate(otSysMainloopContext *aMainloop)
+extern "C" void otAppCliUpdate(otSysMainloopContext *aMainloop)
{
- FD_SET(sReadFd, &aMainloop->mReadFdSet);
- FD_SET(sReadFd, &aMainloop->mErrorFdSet);
+ FD_SET(STDIN_FILENO, &aMainloop->mReadFdSet);
+ FD_SET(STDIN_FILENO, &aMainloop->mErrorFdSet);
- if (aMainloop->mMaxFd < sReadFd)
+ if (aMainloop->mMaxFd < STDIN_FILENO)
{
- aMainloop->mMaxFd = sReadFd;
+ aMainloop->mMaxFd = STDIN_FILENO;
}
}
-void otxConsoleProcess(const otSysMainloopContext *aMainloop)
+extern "C" void otAppCliProcess(const otSysMainloopContext *aMainloop)
{
- if (FD_ISSET(sReadFd, &aMainloop->mErrorFdSet))
+ if (FD_ISSET(STDIN_FILENO, &aMainloop->mErrorFdSet))
{
- perror("console error");
exit(OT_EXIT_FAILURE);
}
- if (FD_ISSET(sReadFd, &aMainloop->mReadFdSet))
+ if (FD_ISSET(STDIN_FILENO, &aMainloop->mReadFdSet))
{
+#if OPENTHREAD_USE_READLINE
rl_callback_read_char();
+#else
+ char buffer[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH];
+
+ if (fgets(buffer, sizeof(buffer), stdin) != nullptr)
+ {
+ otCliInputLine(buffer);
+ dprintf(STDOUT_FILENO, "%s", sPrompt);
+ }
+ else
+ {
+ exit(OT_EXIT_SUCCESS);
+ }
+#endif
}
}
-#endif // HAVE_LIBEDIT || HAVE_LIBREADLINE
-
-#endif // OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_CONSOLE
+#endif // !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
diff --git a/src/posix/client.cpp b/src/posix/client.cpp
index 860b228..1491b0b 100644
--- a/src/posix/client.cpp
+++ b/src/posix/client.cpp
@@ -28,6 +28,8 @@
#include "platform/openthread-posix-config.h"
+#include "cli/cli_config.h"
+
#include <openthread/platform/toolchain.h>
#ifndef HAVE_LIBEDIT
@@ -62,7 +64,7 @@
enum
{
- kLineBufferSize = 256,
+ kLineBufferSize = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH,
};
static_assert(kLineBufferSize >= sizeof("> "), "kLineBufferSize is too small");
@@ -161,23 +163,28 @@
int main(int argc, char *argv[])
{
- int ret;
- bool isInteractive = true;
- bool isFinished = false;
- char lineBuffer[kLineBufferSize];
- size_t lineBufferWritePos = 0;
- bool isBeginOfLine = true;
+ int ret;
+ bool isInteractive = true;
+ bool isFinished = false;
VerifyOrExit(ConnectSession() != -1, perror("connect session failed"); ret = OT_EXIT_FAILURE);
if (argc > 1)
{
+ char buffer[kLineBufferSize];
+ size_t count = 0;
+
for (int i = 1; i < argc; i++)
{
- VerifyOrExit(DoWrite(sSessionFd, argv[i], strlen(argv[i])), ret = OT_EXIT_FAILURE);
- VerifyOrExit(DoWrite(sSessionFd, " ", 1), ret = OT_EXIT_FAILURE);
+ int rval = snprintf(&buffer[count], (sizeof(buffer) - count), "%s ", argv[i]);
+
+ VerifyOrExit(rval > 0 && static_cast<size_t>(rval) < (sizeof(buffer) - count), ret = OT_EXIT_FAILURE);
+ count += static_cast<size_t>(rval);
}
- VerifyOrExit(DoWrite(sSessionFd, "\n", 1), ret = OT_EXIT_FAILURE);
+
+ // replace the trailing space with newline
+ buffer[count - 1] = '\n';
+ VerifyOrExit(DoWrite(sSessionFd, buffer, count), ret = OT_EXIT_FAILURE);
isInteractive = false;
}
@@ -195,8 +202,11 @@
while (!isFinished)
{
fd_set readFdSet;
- char buffer[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE];
- int maxFd = sSessionFd;
+ char lineBuffer[kLineBufferSize];
+ char buffer[kLineBufferSize];
+ size_t lineBufferWritePos = 0;
+ bool isBeginOfLine = true;
+ int maxFd = sSessionFd;
FD_ZERO(&readFdSet);
diff --git a/src/posix/console_cli.h b/src/posix/console_cli.h
deleted file mode 100644
index 16682d5..0000000
--- a/src/posix/console_cli.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2019, 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_CONSOLE_CLI_H_
-#define OPENTHREAD_CONSOLE_CLI_H_
-
-#include "platform/openthread-posix-config.h"
-
-#include <stdint.h>
-
-#include <openthread/openthread-system.h>
-
-#include "cli/cli_config.h"
-
-#ifndef HAVE_LIBEDIT
-#define HAVE_LIBEDIT 0
-#endif
-
-#ifndef HAVE_LIBREADLINE
-#define HAVE_LIBREADLINE 0
-#endif
-
-#if OPENTHREAD_CONFIG_CLI_TRANSPORT == OT_CLI_TRANSPORT_CONSOLE
-#define OPENTHREAD_USE_CONSOLE 1
-#if !(HAVE_LIBEDIT || HAVE_LIBREADLINE) || OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-#error \
- "When OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_CONSOLE, HAVE_LIBEDIT or HAVE_LIBREADLINE MUST be defined and OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE MUST be 0"
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * This function initializes CLI console.
- *
- * @param[in] aInstance A pointer to the OpenThread instance.
- *
- */
-void otxConsoleInit(otInstance *aInstance);
-
-/**
- * This function deinitializes CLI console
- *
- */
-void otxConsoleDeinit(void);
-
-/**
- * This function updates the file descriptor sets with file descriptors used by console.
- *
- * @param[inout] aMainloop A pointer to the mainloop context.
- *
- */
-void otxConsoleUpdate(otSysMainloopContext *aMainloop);
-
-/**
- * This function performs console driver processing.
- *
- * @param[in] aMainloop A pointer to the mainloop context.
- *
- */
-void otxConsoleProcess(const otSysMainloopContext *aMainloop);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // OPENTHREAD_CONSOLE_CLI_H_
diff --git a/src/posix/main.c b/src/posix/main.c
index dc61485..da5006a 100644
--- a/src/posix/main.c
+++ b/src/posix/main.c
@@ -67,7 +67,6 @@
#elif OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_CLI
#include <openthread/cli.h>
-#include "console_cli.h"
#include "cli/cli_config.h"
#else
#error "Unknown posix app type!"
@@ -82,6 +81,58 @@
#define OPENTHREAD_ENABLE_COVERAGE 0
#endif
+/**
+ * This function initializes NCP app.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ */
+void otAppNcpInit(otInstance *aInstance);
+
+/**
+ * This function deinitializes NCP app.
+ *
+ */
+void otAppNcpUpdate(otSysMainloopContext *aContext);
+
+/**
+ * This function updates the file descriptor sets with file descriptors used by console.
+ *
+ * @param[inout] aMainloop A pointer to the mainloop context.
+ *
+ */
+void otAppNcpProcess(const otSysMainloopContext *aContext);
+
+/**
+ * This function initializes CLI app.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ *
+ */
+void otAppCliInit(otInstance *aInstance);
+
+/**
+ * This function deinitializes CLI app.
+ *
+ */
+void otAppCliDeinit(void);
+
+/**
+ * This function updates the file descriptor sets with file descriptors used by console.
+ *
+ * @param[inout] aMainloop A pointer to the mainloop context.
+ *
+ */
+void otAppCliUpdate(otSysMainloopContext *aMainloop);
+
+/**
+ * This function performs console driver processing.
+ *
+ * @param[in] aMainloop A pointer to the mainloop context.
+ *
+ */
+void otAppCliProcess(const otSysMainloopContext *aMainloop);
+
typedef struct PosixConfig
{
otPlatformConfig mPlatformConfig; ///< Platform configuration.
@@ -330,12 +381,10 @@
instance = InitInstance(&config);
#if OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
- otNcpInit(instance);
+ otAppNcpInit(instance);
#elif OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_CLI
-#ifdef OPENTHREAD_USE_CONSOLE
- otxConsoleInit(instance);
-#else
- otCliUartInit(instance);
+#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ otAppCliInit(instance);
#endif
otCliSetUserCommands(&radioUrlCommand, 1, &config.mPlatformConfig);
#endif
@@ -354,8 +403,12 @@
mainloop.mTimeout.tv_sec = 10;
mainloop.mTimeout.tv_usec = 0;
-#ifdef OPENTHREAD_USE_CONSOLE
- otxConsoleUpdate(&mainloop);
+#if OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
+ otAppNcpUpdate(&mainloop);
+#elif OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_CLI
+#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ otAppCliUpdate(&mainloop);
+#endif
#endif
otSysMainloopUpdate(instance, &mainloop);
@@ -363,8 +416,12 @@
if (otSysMainloopPoll(&mainloop) >= 0)
{
otSysMainloopProcess(instance, &mainloop);
-#ifdef OPENTHREAD_USE_CONSOLE
- otxConsoleProcess(&mainloop);
+#if OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
+ otAppNcpProcess(&mainloop);
+#elif OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_CLI
+#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ otAppCliProcess(&mainloop);
+#endif
#endif
}
else if (errno != EINTR)
@@ -374,8 +431,12 @@
}
}
-#ifdef OPENTHREAD_USE_CONSOLE
- otxConsoleDeinit();
+#if OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
+ // disable ncp
+#elif OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_CLI
+#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ otAppCliDeinit();
+#endif
#endif
exit:
diff --git a/src/posix/ncp.cmake b/src/posix/ncp.cmake
index 651b80b..e313059 100644
--- a/src/posix/ncp.cmake
+++ b/src/posix/ncp.cmake
@@ -28,6 +28,7 @@
add_executable(ot-ncp
main.c
+ ncp.cpp
)
set_target_properties(
diff --git a/src/posix/ncp.cpp b/src/posix/ncp.cpp
new file mode 100644
index 0000000..868b71c
--- /dev/null
+++ b/src/posix/ncp.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-posix-config.h"
+#include "platform-posix.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <openthread/ncp.h>
+#include <openthread/platform/misc.h>
+
+#include "common/code_utils.hpp"
+
+#if OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
+static const uint8_t *sWriteBuffer = nullptr;
+static uint16_t sWriteLength = 0;
+
+static int ncpHdlcSend(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ sWriteBuffer = aBuf;
+ sWriteLength = aBufLength;
+
+ return aBufLength;
+}
+
+extern "C" void otAppNcpInit(otInstance *aInstance)
+{
+ otNcpHdlcInit(aInstance, ncpHdlcSend);
+}
+
+extern "C" void otAppNcpUpdate(otSysMainloopContext *aContext)
+{
+ FD_SET(STDIN_FILENO, &aContext->mReadFdSet);
+ FD_SET(STDIN_FILENO, &aContext->mErrorFdSet);
+
+ if (aContext->mMaxFd < STDIN_FILENO)
+ {
+ aContext->mMaxFd = STDIN_FILENO;
+ }
+
+ if (sWriteLength > 0)
+ {
+ FD_SET(STDOUT_FILENO, &aContext->mWriteFdSet);
+ FD_SET(STDOUT_FILENO, &aContext->mErrorFdSet);
+
+ if (aContext->mMaxFd < STDOUT_FILENO)
+ {
+ aContext->mMaxFd = STDOUT_FILENO;
+ }
+ }
+}
+
+extern "C" void otAppNcpProcess(const otSysMainloopContext *aContext)
+{
+ ssize_t rval;
+
+ if (FD_ISSET(STDIN_FILENO, &aContext->mErrorFdSet))
+ {
+ DieNowWithMessage("stdin", OT_EXIT_FAILURE);
+ }
+
+ if (FD_ISSET(STDOUT_FILENO, &aContext->mErrorFdSet))
+ {
+ DieNowWithMessage("stdout", OT_EXIT_FAILURE);
+ }
+
+ if (FD_ISSET(STDIN_FILENO, &aContext->mReadFdSet))
+ {
+ uint8_t buffer[256];
+
+ rval = read(STDIN_FILENO, buffer, sizeof(buffer));
+
+ if (rval > 0)
+ {
+ otNcpHdlcReceive(buffer, static_cast<uint16_t>(rval));
+ }
+ else if (rval <= 0)
+ {
+ DieNowWithMessage("UART read", (rval < 0) ? OT_EXIT_ERROR_ERRNO : OT_EXIT_FAILURE);
+ }
+ }
+
+ if ((FD_ISSET(STDOUT_FILENO, &aContext->mWriteFdSet)))
+ {
+ if (sWriteLength > 0)
+ {
+ rval = write(STDOUT_FILENO, sWriteBuffer, sWriteLength);
+
+ if (rval < 0)
+ {
+ DieNow(OT_EXIT_ERROR_ERRNO);
+ }
+
+ sWriteBuffer += rval;
+ sWriteLength -= static_cast<uint16_t>(rval);
+ }
+
+ if (sWriteLength == 0)
+ {
+ otNcpHdlcSendDone();
+ }
+ }
+}
+#endif // OPENTHREAD_POSIX_APP_TYPE == OT_POSIX_APP_TYPE_NCP
diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt
index c90f340..33dbebf 100644
--- a/src/posix/platform/CMakeLists.txt
+++ b/src/posix/platform/CMakeLists.txt
@@ -53,8 +53,6 @@
set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
endif()
-list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_POSIX=1")
-
set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
@@ -62,9 +60,12 @@
add_library(openthread-posix
alarm.cpp
backbone.cpp
+ daemon.cpp
entropy.cpp
hdlc_interface.cpp
+ infra_if.cpp
logging.cpp
+ memory.cpp
misc.cpp
multicast_routing.cpp
netif.cpp
@@ -74,7 +75,6 @@
spi_interface.cpp
system.cpp
trel_udp6.cpp
- uart.cpp
udp.cpp
virtual_time.cpp
)
diff --git a/src/posix/platform/Makefile.am b/src/posix/platform/Makefile.am
index 9285284..24c39a6 100644
--- a/src/posix/platform/Makefile.am
+++ b/src/posix/platform/Makefile.am
@@ -46,9 +46,12 @@
libopenthread_posix_a_SOURCES = \
alarm.cpp \
backbone.cpp \
+ daemon.cpp \
entropy.cpp \
hdlc_interface.cpp \
+ infra_if.cpp \
logging.cpp \
+ memory.cpp \
misc.cpp \
multicast_routing.cpp \
netif.cpp \
@@ -58,7 +61,6 @@
spi_interface.cpp \
system.cpp \
trel_udp6.cpp \
- uart.cpp \
udp.cpp \
virtual_time.cpp \
$(NULL)
diff --git a/src/posix/platform/daemon.cpp b/src/posix/platform/daemon.cpp
new file mode 100644
index 0000000..16576e2
--- /dev/null
+++ b/src/posix/platform/daemon.cpp
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-posix-config.h"
+#include "platform-posix.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <openthread/cli.h>
+
+#include "cli/cli_config.h"
+#include "common/code_utils.hpp"
+
+#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+
+#define OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME ".lock"
+static_assert(sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME) < sizeof(sockaddr_un::sun_path),
+ "OpenThread daemon socket name too long!");
+
+static int sListenSocket = -1;
+static int sDaemonLock = -1;
+static int sSessionSocket = -1;
+
+static int OutputFormatV(void *aContext, const char *aFormat, va_list aArguments)
+{
+ OT_UNUSED_VARIABLE(aContext);
+
+ char buf[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH + 1];
+ int rval;
+
+ buf[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH] = '\0';
+
+ rval = vsnprintf(buf, sizeof(buf) - 1, aFormat, aArguments);
+
+ VerifyOrExit(rval >= 0, otLogWarnPlat("Failed to format CLI output: %s", strerror(errno)));
+
+ VerifyOrExit(sSessionSocket != -1, otLogDebgPlat("%s", buf));
+
+#if defined(__linux__)
+ // Don't die on SIGPIPE
+ rval = send(sSessionSocket, buf, static_cast<size_t>(rval), MSG_NOSIGNAL);
+#else
+ rval = write(sSessionSocket, buf, static_cast<size_t>(rval));
+#endif
+
+ if (rval < 0)
+ {
+ otLogWarnPlat("Failed to write CLI output: %s", strerror(errno));
+ close(sSessionSocket);
+ sSessionSocket = -1;
+ }
+
+exit:
+ return rval;
+}
+
+static void InitializeSessionSocket(void)
+{
+ int newSessionSocket;
+ int rval;
+
+ VerifyOrExit((newSessionSocket = accept(sListenSocket, nullptr, nullptr)) != -1, rval = -1);
+
+ VerifyOrExit((rval = fcntl(newSessionSocket, F_GETFD, 0)) != -1);
+
+ rval |= FD_CLOEXEC;
+
+ VerifyOrExit((rval = fcntl(newSessionSocket, F_SETFD, rval)) != -1);
+
+#ifndef __linux__
+ // some platforms (macOS, Solaris) don't have MSG_NOSIGNAL
+ // SOME of those (macOS, but NOT Solaris) support SO_NOSIGPIPE
+ // if we have SO_NOSIGPIPE, then set it. Otherwise, we're going
+ // to simply ignore it.
+#if defined(SO_NOSIGPIPE)
+ rval = setsockopt(newSessionSocket, SOL_SOCKET, SO_NOSIGPIPE, &rval, sizeof(rval));
+ VerifyOrExit(rval != -1);
+#else
+#warning "no support for MSG_NOSIGNAL or SO_NOSIGPIPE"
+#endif
+#endif // __linux__
+
+ if (sSessionSocket != -1)
+ {
+ close(sSessionSocket);
+ }
+ sSessionSocket = newSessionSocket;
+
+exit:
+ if (rval == -1)
+ {
+ otLogWarnPlat("Failed to initialize session socket: %s", strerror(errno));
+ if (newSessionSocket != -1)
+ {
+ close(newSessionSocket);
+ }
+ }
+ else
+ {
+ otLogInfoPlat("Session socket is ready", strerror(errno));
+ }
+}
+
+void platformDaemonEnable(otInstance *aInstance)
+{
+ struct sockaddr_un sockname;
+ int ret;
+
+ // This allows implementing pseudo reset.
+ VerifyOrExit(sListenSocket == -1);
+
+ sListenSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock);
+
+ if (sListenSocket == -1)
+ {
+ DieNow(OT_EXIT_FAILURE);
+ }
+
+ sDaemonLock = open(OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK, O_CREAT | O_RDONLY | O_CLOEXEC, 0600);
+
+ if (sDaemonLock == -1)
+ {
+ DieNowWithMessage("open", OT_EXIT_ERROR_ERRNO);
+ }
+
+ if (flock(sDaemonLock, LOCK_EX | LOCK_NB) == -1)
+ {
+ DieNowWithMessage("flock", OT_EXIT_ERROR_ERRNO);
+ }
+
+ memset(&sockname, 0, sizeof(struct sockaddr_un));
+
+ (void)unlink(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
+
+ sockname.sun_family = AF_UNIX;
+ strncpy(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME, sizeof(sockname.sun_path) - 1);
+
+ ret = bind(sListenSocket, (const struct sockaddr *)&sockname, sizeof(struct sockaddr_un));
+
+ if (ret == -1)
+ {
+ DieNowWithMessage("bind", OT_EXIT_ERROR_ERRNO);
+ }
+
+ //
+ // only accept 1 connection.
+ //
+ ret = listen(sListenSocket, 1);
+ if (ret == -1)
+ {
+ DieNowWithMessage("listen", OT_EXIT_ERROR_ERRNO);
+ }
+
+ otCliInit(aInstance, OutputFormatV, aInstance);
+
+exit:
+ return;
+}
+
+void platformDaemonDisable(void)
+{
+ if (sSessionSocket != -1)
+ {
+ close(sSessionSocket);
+ sSessionSocket = -1;
+ }
+
+ if (sListenSocket != -1)
+ {
+ close(sListenSocket);
+ sListenSocket = -1;
+ }
+
+ if (gPlatResetReason != OT_PLAT_RESET_REASON_SOFTWARE)
+ {
+ otLogCritPlat("Removing daemon socket: %s", OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
+ (void)unlink(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
+ }
+
+ if (sDaemonLock != -1)
+ {
+ (void)flock(sDaemonLock, LOCK_UN);
+ close(sDaemonLock);
+ sDaemonLock = -1;
+ }
+}
+
+void platformDaemonUpdate(otSysMainloopContext *aContext)
+{
+ if (sListenSocket != -1)
+ {
+ FD_SET(sListenSocket, &aContext->mReadFdSet);
+ FD_SET(sListenSocket, &aContext->mErrorFdSet);
+
+ if (aContext->mMaxFd < sListenSocket)
+ {
+ aContext->mMaxFd = sListenSocket;
+ }
+ }
+
+ if (sSessionSocket != -1)
+ {
+ FD_SET(sSessionSocket, &aContext->mReadFdSet);
+ FD_SET(sSessionSocket, &aContext->mErrorFdSet);
+
+ if (aContext->mMaxFd < sSessionSocket)
+ {
+ aContext->mMaxFd = sSessionSocket;
+ }
+ }
+
+ return;
+}
+
+void platformDaemonProcess(const otSysMainloopContext *aContext)
+{
+ ssize_t rval;
+
+ VerifyOrExit(sListenSocket != -1);
+
+ if (FD_ISSET(sListenSocket, &aContext->mErrorFdSet))
+ {
+ DieNowWithMessage("daemon socket error", OT_EXIT_FAILURE);
+ }
+ else if (FD_ISSET(sListenSocket, &aContext->mReadFdSet))
+ {
+ InitializeSessionSocket();
+ }
+
+ VerifyOrExit(sSessionSocket != -1);
+
+ if (FD_ISSET(sSessionSocket, &aContext->mErrorFdSet))
+ {
+ close(sSessionSocket);
+ sSessionSocket = -1;
+ }
+ else if (FD_ISSET(sSessionSocket, &aContext->mReadFdSet))
+ {
+ uint8_t buffer[OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH];
+
+ rval = read(sSessionSocket, buffer, sizeof(buffer));
+
+ if (rval > 0)
+ {
+ buffer[rval] = '\0';
+ otLogInfoPlat("> %s", reinterpret_cast<const char *>(buffer));
+ otCliInputLine(reinterpret_cast<char *>(buffer));
+ otCliOutputFormat("> ");
+ }
+ else
+ {
+ if (rval < 0)
+ {
+ otLogWarnPlat("Daemon read: %s", strerror(errno));
+ }
+ close(sSessionSocket);
+ sSessionSocket = -1;
+ }
+ }
+
+exit:
+ return;
+}
+
+#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
diff --git a/src/posix/platform/include/openthread/platform/secure_settings.h b/src/posix/platform/include/openthread/platform/secure_settings.h
new file mode 100644
index 0000000..90ce5c3
--- /dev/null
+++ b/src/posix/platform/include/openthread/platform/secure_settings.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2021, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file includes platform abstraction for secure non-volatile storage of settings.
+ */
+
+#ifndef OPENTHREAD_POSIX_SECURE_SETTINGS_H_
+#define OPENTHREAD_POSIX_SECURE_SETTINGS_H_
+
+#include <openthread/instance.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup plat-settings
+ *
+ * @brief
+ * This module includes the platform abstraction for secure non-volatile storage of settings.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This function performs any initialization for the secure settings subsystem, if necessary.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+void otPosixSecureSettingsInit(otInstance *aInstance);
+
+/**
+ * This function performs any de-initialization for the secure settings subsystem, if necessary.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+void otPosixSecureSettingsDeinit(otInstance *aInstance);
+
+/**
+ * This function fetches the value of the setting identified by aKey and write it to the memory pointed to by aValue.
+ * It then writes the length to the integer pointed to by aValueLength. The initial value of aValueLength is the
+ * maximum number of bytes to be written to aValue.
+ *
+ * This function can be used to check for the existence of a key without fetching the value by setting aValue and
+ * aValueLength to NULL. You can also check the length of the setting without fetching it by setting only aValue
+ * to NULL.
+ *
+ * Note that the underlying storage implementation is not required to maintain the order of settings with multiple
+ * values. The order of such values MAY change after ANY write operation to the store.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aKey The key associated with the requested setting.
+ * @param[in] aIndex The index of the specific item to get.
+ * @param[out] aValue A pointer to where the value of the setting should be written. May be set to NULL if
+ * just testing for the presence or length of a setting.
+ * @param[inout] aValueLength A pointer to the length of the value. When called, this pointer should point to an
+ * integer containing the maximum value size that can be written to aValue. At return,
+ * the actual length of the setting is written. This may be set to NULL if performing
+ * a presence check.
+ *
+ * @retval OT_ERROR_NONE The given setting was found and fetched successfully.
+ * @retval OT_ERROR_NOT_FOUND The given setting was not found in the setting store.
+ * @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
+ *
+ */
+otError otPosixSecureSettingsGet(otInstance *aInstance,
+ uint16_t aKey,
+ int aIndex,
+ uint8_t * aValue,
+ uint16_t * aValueLength);
+
+/**
+ * This function sets or replaces the value of a setting identified by aKey. If there was more than one value
+ * previously associated with aKey, then they are all deleted and replaced with this single entry.
+ *
+ * Calling this function successfully may cause unrelated settings with multiple values to be reordered.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aKey The key associated with the setting to change.
+ * @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL if
+ * aValueLength is non-zero.
+ * @param[in] aValueLength The length of the data pointed to by aValue. May be zero.
+ *
+ * @retval OT_ERROR_NONE The given setting was changed or staged.
+ * @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
+ * @retval OT_ERROR_NO_BUFS No space remaining to store the given setting.
+ *
+ */
+otError otPosixSecureSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+
+/**
+ * This function adds the value to a setting identified by aKey, without replacing any existing values.
+ *
+ * Note that the underlying implementation is not required to maintain the order of the items associated with a
+ * specific key. The added value may be added to the end, the beginning, or even somewhere in the middle. The order
+ * of any pre-existing values may also change.
+ *
+ * Calling this function successfully may cause unrelated settings with multiple values to be reordered.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aKey The key associated with the setting to change.
+ * @param[in] aValue A pointer to where the new value of the setting should be read from. MUST NOT be NULL
+ * if aValueLength is non-zero.
+ * @param[in] aValueLength The length of the data pointed to by aValue. May be zero.
+ *
+ * @retval OT_ERROR_NONE The given setting was added or staged to be added.
+ * @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
+ * @retval OT_ERROR_NO_BUFS No space remaining to store the given setting.
+ *
+ */
+otError otPosixSecureSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
+
+/**
+ * This function deletes a specific value from the setting identified by aKey from the secure settings store.
+ *
+ * Note that the underlying implementation is not required to maintain the order of the items associated with a
+ * specific key.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aKey The key associated with the requested setting.
+ * @param[in] aIndex The index of the value to be removed. If set to -1, all values for this aKey will be removed.
+ *
+ * @retval OT_ERROR_NONE The given key and index was found and removed successfully.
+ * @retval OT_ERROR_NOT_FOUND The given key or index was not found in the setting store.
+ * @retval OT_ERROR_NOT_IMPLEMENTED This function is not implemented on this platform.
+ *
+ */
+otError otPosixSecureSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex);
+
+/**
+ * This function deletes all settings from the secure settings store, resetting it to its initial factory state.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+void otPosixSecureSettingsWipe(otInstance *aInstance);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // OPENTHREAD_POSIX_SECURE_SETTINGS_H_
diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp
new file mode 100644
index 0000000..17bcaed
--- /dev/null
+++ b/src/posix/platform/infra_if.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2020, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements the infrastructure interface for posix.
+ */
+
+#include "platform-posix.h"
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
+#ifdef __APPLE__
+#define __APPLE_USE_RFC_3542
+#endif
+
+#include <errno.h>
+#include <ifaddrs.h>
+// clang-format off
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+// clang-format on
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef __linux__
+#include <linux/rtnetlink.h>
+#endif
+
+#include <openthread/border_router.h>
+#include <openthread/platform/infra_if.h>
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "lib/platform/exit_code.h"
+
+static char sInfraIfName[IFNAMSIZ];
+static uint32_t sInfraIfIndex = 0;
+static int sInfraIfIcmp6Socket = -1;
+static int sNetLinkSocket = -1;
+static otIp6Address sInfraIfLinkLocalAddr;
+
+static int CreateIcmp6Socket(void);
+static int CreateNetLinkSocket(void);
+static void ReceiveNetLinkMessage(otInstance *aInstance);
+static void ReceiveIcmp6Message(otInstance *aInstance);
+
+otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
+ const otIp6Address *aDestAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ otError error = OT_ERROR_NONE;
+
+ struct iovec iov;
+ struct in6_pktinfo *packetInfo;
+
+ int hopLimit = 255;
+ uint8_t cmsgBuffer[CMSG_SPACE(sizeof(*packetInfo)) + CMSG_SPACE(sizeof(hopLimit))];
+ struct msghdr msgHeader;
+ struct cmsghdr * cmsgPointer;
+ ssize_t rval;
+ struct sockaddr_in6 dest;
+
+ VerifyOrExit(sInfraIfIcmp6Socket >= 0, error = OT_ERROR_FAILED);
+ VerifyOrExit(aInfraIfIndex == sInfraIfIndex, error = OT_ERROR_DROP);
+
+ memset(cmsgBuffer, 0, sizeof(cmsgBuffer));
+
+ // Send the message
+ memset(&dest, 0, sizeof(dest));
+ dest.sin6_family = AF_INET6;
+ memcpy(&dest.sin6_addr, aDestAddress, sizeof(*aDestAddress));
+ if (IN6_IS_ADDR_LINKLOCAL(&dest.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&dest.sin6_addr))
+ {
+ dest.sin6_scope_id = sInfraIfIndex;
+ }
+
+ iov.iov_base = const_cast<uint8_t *>(aBuffer);
+ iov.iov_len = aBufferLength;
+
+ msgHeader.msg_namelen = sizeof(dest);
+ msgHeader.msg_name = &dest;
+ msgHeader.msg_iov = &iov;
+ msgHeader.msg_iovlen = 1;
+ msgHeader.msg_control = cmsgBuffer;
+ msgHeader.msg_controllen = sizeof(cmsgBuffer);
+
+ // Specify the interface.
+ cmsgPointer = CMSG_FIRSTHDR(&msgHeader);
+ cmsgPointer->cmsg_level = IPPROTO_IPV6;
+ cmsgPointer->cmsg_type = IPV6_PKTINFO;
+ cmsgPointer->cmsg_len = CMSG_LEN(sizeof(*packetInfo));
+ packetInfo = (struct in6_pktinfo *)CMSG_DATA(cmsgPointer);
+ memset(packetInfo, 0, sizeof(*packetInfo));
+ packetInfo->ipi6_ifindex = sInfraIfIndex;
+
+ // Per section 6.1.2 of RFC 4861, we need to send the ICMPv6 message with IP Hop Limit 255.
+ cmsgPointer = CMSG_NXTHDR(&msgHeader, cmsgPointer);
+ cmsgPointer->cmsg_level = IPPROTO_IPV6;
+ cmsgPointer->cmsg_type = IPV6_HOPLIMIT;
+ cmsgPointer->cmsg_len = CMSG_LEN(sizeof(hopLimit));
+ memcpy(CMSG_DATA(cmsgPointer), &hopLimit, sizeof(hopLimit));
+
+ rval = sendmsg(sInfraIfIcmp6Socket, &msgHeader, 0);
+ if (rval < 0)
+ {
+ otLogWarnPlat("failed to send ICMPv6 message: %s", strerror(errno));
+ ExitNow(error = OT_ERROR_FAILED);
+ }
+
+ if (static_cast<size_t>(rval) != iov.iov_len)
+ {
+ otLogWarnPlat("failed to send ICMPv6 message: partially sent");
+ ExitNow(error = OT_ERROR_FAILED);
+ }
+
+exit:
+ return error;
+}
+
+const otIp6Address *platformInfraIfGetLinkLocalAddress(void)
+{
+ const otIp6Address *ret = nullptr;
+ struct ifaddrs * ifAddrs = nullptr;
+
+ VerifyOrDie(getifaddrs(&ifAddrs) != -1, OT_EXIT_ERROR_ERRNO);
+
+ for (struct ifaddrs *addr = ifAddrs; addr != nullptr; addr = addr->ifa_next)
+ {
+ struct sockaddr_in6 *ip6Addr;
+
+ if (strncmp(addr->ifa_name, sInfraIfName, sizeof(sInfraIfName)) != 0 || addr->ifa_addr->sa_family != AF_INET6)
+ {
+ continue;
+ }
+
+ ip6Addr = reinterpret_cast<sockaddr_in6 *>(addr->ifa_addr);
+ if (IN6_IS_ADDR_LINKLOCAL(&ip6Addr->sin6_addr))
+ {
+ memcpy(&sInfraIfLinkLocalAddr, &ip6Addr->sin6_addr, sizeof(sInfraIfLinkLocalAddr));
+ ExitNow(ret = &sInfraIfLinkLocalAddr);
+ }
+ }
+
+ otLogWarnPlat("cannot find IPv6 link-local address for interface %s", sInfraIfName);
+
+exit:
+ freeifaddrs(ifAddrs);
+ return ret;
+}
+
+bool platformInfraIfIsRunning(void)
+{
+ int sock;
+ struct ifreq ifReq;
+
+ OT_ASSERT(sInfraIfIndex != 0);
+
+ sock = SocketWithCloseExec(AF_INET6, SOCK_DGRAM, IPPROTO_IP, kSocketBlock);
+ VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
+
+ memset(&ifReq, 0, sizeof(ifReq));
+ strncpy(ifReq.ifr_name, sInfraIfName, sizeof(ifReq.ifr_name));
+ VerifyOrDie(ioctl(sock, SIOCGIFFLAGS, &ifReq) != -1, OT_EXIT_ERROR_ERRNO);
+
+ close(sock);
+
+ return (ifReq.ifr_flags & IFF_RUNNING);
+}
+
+static int CreateIcmp6Socket(void)
+{
+ int sock;
+ int rval;
+ struct icmp6_filter filter;
+ const int kEnable = 1;
+ const int kIpv6ChecksumOffset = 2;
+ const int kHopLimit = 255;
+
+ // Initializes the ICMPv6 socket.
+ sock = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketBlock);
+ VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
+
+ // Only accept router advertisements and solicitations.
+ ICMP6_FILTER_SETBLOCKALL(&filter);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
+
+ rval = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ // We want a source address and interface index.
+ rval = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &kEnable, sizeof(kEnable));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+#ifdef __linux__
+ rval = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &kIpv6ChecksumOffset, sizeof(kIpv6ChecksumOffset));
+#else
+ rval = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &kIpv6ChecksumOffset, sizeof(kIpv6ChecksumOffset));
+#endif
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ // We need to be able to reject RAs arriving from off-link.
+ rval = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &kEnable, sizeof(kEnable));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ rval = setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ rval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kHopLimit, sizeof(kHopLimit));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ return sock;
+}
+
+uint32_t platformInfraIfInit(otInstance *aInstance, const char *aIfName)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ ssize_t rval;
+ uint32_t ifIndex = 0;
+
+ if (strlen(aIfName) >= sizeof(sInfraIfName))
+ {
+ otLogCritPlat("infra interface name '%s' is too long", aIfName);
+ DieNow(OT_EXIT_INVALID_ARGUMENTS);
+ }
+ strcpy(sInfraIfName, aIfName);
+
+ // Initializes the infra interface.
+ ifIndex = if_nametoindex(aIfName);
+ if (ifIndex == 0)
+ {
+ otLogCritPlat("failed to get the index for infra interface %s", aIfName);
+ DieNow(OT_EXIT_INVALID_ARGUMENTS);
+ }
+ sInfraIfIndex = ifIndex;
+
+ sInfraIfIcmp6Socket = CreateIcmp6Socket();
+#ifdef __linux__
+ rval = setsockopt(sInfraIfIcmp6Socket, SOL_SOCKET, SO_BINDTODEVICE, sInfraIfName, strlen(sInfraIfName));
+#else // __NetBSD__ || __FreeBSD__ || __APPLE__
+ rval = setsockopt(sInfraIfIcmp6Socket, IPPROTO_IP, IP_BOUND_IF, &sInfraIfIndex, sizeof(sInfraIfIndex));
+#endif // __linux__
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ sNetLinkSocket = CreateNetLinkSocket();
+
+ return sInfraIfIndex;
+}
+
+void platformInfraIfDeinit(void)
+{
+ if (sInfraIfIcmp6Socket != -1)
+ {
+ close(sInfraIfIcmp6Socket);
+ sInfraIfIcmp6Socket = -1;
+ }
+
+ if (sNetLinkSocket != -1)
+ {
+ close(sNetLinkSocket);
+ sNetLinkSocket = -1;
+ }
+
+ sInfraIfIndex = 0;
+}
+
+void platformInfraIfUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd)
+{
+ VerifyOrExit(sInfraIfIcmp6Socket != -1);
+ VerifyOrExit(sNetLinkSocket != -1);
+
+ FD_SET(sInfraIfIcmp6Socket, &aReadFdSet);
+ aMaxFd = OT_MAX(aMaxFd, sInfraIfIcmp6Socket);
+
+ FD_SET(sNetLinkSocket, &aReadFdSet);
+ aMaxFd = OT_MAX(aMaxFd, sNetLinkSocket);
+
+exit:
+ return;
+}
+
+// Create a net-link socket that subscribes to link & addresses events.
+static int CreateNetLinkSocket(void)
+{
+ int sock;
+ int rval;
+ struct sockaddr_nl addr;
+
+ sock = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketBlock);
+ VerifyOrDie(sock != -1, OT_EXIT_ERROR_ERRNO);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
+ addr.nl_pid = getpid();
+
+ rval = bind(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr));
+ VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO);
+
+ return sock;
+}
+
+static void ReceiveNetLinkMessage(otInstance *aInstance)
+{
+ const size_t kMaxNetLinkBufSize = 8192;
+ ssize_t len;
+ union
+ {
+ nlmsghdr mHeader;
+ uint8_t mBuffer[kMaxNetLinkBufSize];
+ } msgBuffer;
+
+ len = recv(sNetLinkSocket, msgBuffer.mBuffer, sizeof(msgBuffer.mBuffer), 0);
+ if (len < 0)
+ {
+ otLogCritPlat("failed to receive netlink message: %s", strerror(errno));
+ ExitNow();
+ }
+
+ for (struct nlmsghdr *header = &msgBuffer.mHeader; NLMSG_OK(header, static_cast<size_t>(len));
+ header = NLMSG_NEXT(header, len))
+ {
+ switch (header->nlmsg_type)
+ {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ SuccessOrDie(otPlatInfraIfStateChanged(aInstance, sInfraIfIndex, platformInfraIfIsRunning(),
+ platformInfraIfGetLinkLocalAddress()));
+ break;
+ case NLMSG_ERROR:
+ {
+ struct nlmsgerr *errMsg = reinterpret_cast<struct nlmsgerr *>(NLMSG_DATA(header));
+
+ OT_UNUSED_VARIABLE(errMsg);
+ otLogWarnPlat("netlink NLMSG_ERROR response: seq=%u, error=%d", header->nlmsg_seq, errMsg->error);
+ }
+ default:
+ break;
+ }
+ }
+
+exit:
+ return;
+}
+
+static void ReceiveIcmp6Message(otInstance *aInstance)
+{
+ otError error = OT_ERROR_NONE;
+ uint8_t buffer[1500];
+ uint16_t bufferLength;
+
+ ssize_t rval;
+ struct msghdr msg;
+ struct iovec bufp;
+ char cmsgbuf[128];
+ struct cmsghdr *cmh;
+ uint32_t ifIndex = 0;
+ int hopLimit = -1;
+
+ struct sockaddr_in6 srcAddr;
+ struct in6_addr dstAddr;
+
+ memset(&srcAddr, 0, sizeof(srcAddr));
+ memset(&dstAddr, 0, sizeof(dstAddr));
+
+ bufp.iov_base = buffer;
+ bufp.iov_len = sizeof(buffer);
+ msg.msg_iov = &bufp;
+ msg.msg_iovlen = 1;
+ msg.msg_name = &srcAddr;
+ msg.msg_namelen = sizeof(srcAddr);
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+
+ rval = recvmsg(sInfraIfIcmp6Socket, &msg, 0);
+ if (rval < 0)
+ {
+ otLogWarnPlat("failed to receive ICMPv6 message: %s", strerror(errno));
+ ExitNow(error = OT_ERROR_DROP);
+ }
+
+ bufferLength = static_cast<uint16_t>(rval);
+
+ for (cmh = CMSG_FIRSTHDR(&msg); cmh; cmh = CMSG_NXTHDR(&msg, cmh))
+ {
+ if (cmh->cmsg_level == IPPROTO_IPV6 && cmh->cmsg_type == IPV6_PKTINFO &&
+ cmh->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
+ {
+ struct in6_pktinfo pktinfo;
+
+ memcpy(&pktinfo, CMSG_DATA(cmh), sizeof pktinfo);
+ ifIndex = pktinfo.ipi6_ifindex;
+ dstAddr = pktinfo.ipi6_addr;
+ }
+ else if (cmh->cmsg_level == IPPROTO_IPV6 && cmh->cmsg_type == IPV6_HOPLIMIT &&
+ cmh->cmsg_len == CMSG_LEN(sizeof(int)))
+ {
+ hopLimit = *(int *)CMSG_DATA(cmh);
+ }
+ }
+
+ VerifyOrExit(ifIndex == sInfraIfIndex, error = OT_ERROR_DROP);
+
+ // We currently accept only RA & RS messages for the Border Router and it requires that
+ // the hoplimit must be 255 and the source address must be a link-local address.
+ VerifyOrExit(hopLimit == 255 && IN6_IS_ADDR_LINKLOCAL(&srcAddr.sin6_addr), error = OT_ERROR_DROP);
+
+ otPlatInfraIfRecvIcmp6Nd(aInstance, ifIndex, reinterpret_cast<otIp6Address *>(&srcAddr.sin6_addr), buffer,
+ bufferLength);
+
+exit:
+ if (error != OT_ERROR_NONE)
+ {
+ otLogDebgPlat("failed to handle ICMPv6 message: %s", otThreadErrorToString(error));
+ }
+}
+
+void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet)
+{
+ VerifyOrExit(sInfraIfIcmp6Socket != -1);
+ VerifyOrExit(sNetLinkSocket != -1);
+
+ if (FD_ISSET(sInfraIfIcmp6Socket, &aReadFdSet))
+ {
+ ReceiveIcmp6Message(aInstance);
+ }
+
+ if (FD_ISSET(sNetLinkSocket, &aReadFdSet))
+ {
+ ReceiveNetLinkMessage(aInstance);
+ }
+
+exit:
+ return;
+}
+
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
diff --git a/src/posix/platform/ip6_utils.hpp b/src/posix/platform/ip6_utils.hpp
new file mode 100644
index 0000000..15d4ef6
--- /dev/null
+++ b/src/posix/platform/ip6_utils.hpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-posix-config.h"
+#include "platform-posix.h"
+
+#include <arpa/inet.h>
+
+namespace ot {
+namespace Posix {
+namespace Ip6Utils {
+
+/**
+ * This utility class converts binary IPv6 address to text format.
+ *
+ */
+class Ip6AddressString
+{
+public:
+ /**
+ * The constructor of this converter.
+ *
+ * @param[in] aAddress A pointer to a buffer holding an IPv6 address.
+ *
+ */
+ Ip6AddressString(const void *aAddress)
+ {
+ VerifyOrDie(inet_ntop(AF_INET6, aAddress, mBuffer, sizeof(mBuffer)) != nullptr, OT_EXIT_ERROR_ERRNO);
+ }
+
+ /**
+ * This method returns the string as a null-terminated C string.
+ *
+ * @returns The null-terminated C string.
+ *
+ */
+ const char *AsCString(void) const { return mBuffer; }
+
+private:
+ char mBuffer[INET6_ADDRSTRLEN];
+};
+
+} // namespace Ip6Utils
+} // namespace Posix
+} // namespace ot
diff --git a/src/posix/platform/memory.cpp b/src/posix/platform/memory.cpp
new file mode 100644
index 0000000..5132c3f
--- /dev/null
+++ b/src/posix/platform/memory.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, 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.
+ */
+
+#include "openthread-posix-config.h"
+#include "platform-posix.h"
+
+#include <stdlib.h>
+
+#include <openthread/platform/memory.h>
+
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+void *otPlatCAlloc(size_t aNum, size_t aSize)
+{
+ return calloc(aNum, aSize);
+}
+
+void otPlatFree(void *aPtr)
+{
+ free(aPtr);
+}
+#endif
diff --git a/src/posix/platform/multicast_routing.cpp b/src/posix/platform/multicast_routing.cpp
index 988aa05..ff9b79f 100644
--- a/src/posix/platform/multicast_routing.cpp
+++ b/src/posix/platform/multicast_routing.cpp
@@ -171,7 +171,7 @@
struct mif6ctl mif6ctl;
// Create a Multicast Routing socket
- mMulticastRouterSock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ mMulticastRouterSock = SocketWithCloseExec(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, kSocketBlock);
VerifyOrDie(mMulticastRouterSock != -1, OT_EXIT_ERROR_ERRNO);
// Enable Multicast Forwarding in Kernel
diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp
index c84c21c..63c7c72 100644
--- a/src/posix/platform/netif.cpp
+++ b/src/posix/platform/netif.cpp
@@ -151,40 +151,9 @@
char gNetifName[IFNAMSIZ];
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
+#include "posix/platform/ip6_utils.hpp"
-namespace {
-
-/**
- * This utility class converts binary IPv6 address to text format.
- *
- */
-class Ip6AddressString
-{
-public:
- /**
- * The constructor of this converter.
- *
- * @param[in] aAddress A pointer to a buffer holding an IPv6 address.
- *
- */
- Ip6AddressString(const void *aAddress)
- {
- VerifyOrDie(inet_ntop(AF_INET6, aAddress, mBuffer, sizeof(mBuffer)) != nullptr, OT_EXIT_ERROR_ERRNO);
- }
-
- /**
- * This method returns the string as a null-terminated C string.
- *
- * @returns The null-terminated C string.
- *
- */
- const char *AsCString(void) const { return mBuffer; }
-
-private:
- char mBuffer[INET6_ADDRSTRLEN];
-};
-
-} // namespace
+using namespace ot::Posix::Ip6Utils;
#ifndef OPENTHREAD_POSIX_TUN_DEVICE
diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h
index 55c11da..1a46017 100644
--- a/src/posix/platform/openthread-core-posix-config.h
+++ b/src/posix/platform/openthread-core-posix-config.h
@@ -35,6 +35,16 @@
#define OPENTHREAD_CORE_POSIX_CONFIG_H_
/**
+ * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
+ *
+ * The number of message buffers in the buffer pool.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
+#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 256
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_LOG_PLATFORM
*
* Define to enable platform region logging.
@@ -87,12 +97,12 @@
#endif
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
@@ -126,4 +136,84 @@
#define OPENTHREAD_CONFIG_LOG_MAX_SIZE 1024
#endif
+/**
+ * @def OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES
+ *
+ * The maximum number of Joiner entries maintained by the Commissioner.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES
+#define OPENTHREAD_CONFIG_COMMISSIONER_MAX_JOINER_ENTRIES 4
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES
+ *
+ * The number of EID-to-RLOC cache entries.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES
+#define OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES 32
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
+ *
+ * The maximum number of children.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MLE_MAX_CHILDREN
+#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN 64
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD
+ *
+ * The maximum number of supported IPv6 address registrations per child.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD
+#define OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD 16
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS
+ *
+ * The maximum number of supported IPv6 addresses allows to be externally added.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS
+#define OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS 8
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS
+ *
+ * The maximum number of supported IPv6 multicast addresses allows to be externally added.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS
+#define OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS 8
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE
+ *
+ * The size of heap buffer when DTLS is enabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE (63 * 1024)
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS
+ *
+ * The size of heap buffer when DTLS is disabled.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS
+#define OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS (63 * 1024)
+#endif
+
#endif // OPENTHREAD_CORE_POSIX_CONFIG_H_
diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h
index 321dd2e..5d55527 100644
--- a/src/posix/platform/openthread-posix-config.h
+++ b/src/posix/platform/openthread-posix-config.h
@@ -58,6 +58,25 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+ *
+ * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()`
+ * command.
+ *
+ * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif.
+ *
+ * Use of netlink is enabled by default on linux-based platforms.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+#ifdef __linux__
+#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1
+#else
+#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0
+#endif
+#endif
+
+/**
* @def OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME
*
* Define socket basename used by POSIX app daemon.
@@ -121,6 +140,17 @@
#define OPENTHREAD_POSIX_CONFIG_MAX_MULTICAST_FORWARDING_CACHE_TABLE (OPENTHREAD_CONFIG_MAX_MULTICAST_LISTENERS * 10)
#endif
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ *
+ * Define as 1 to enable the secure settings. When defined to 1, the platform MUST implement the otPosixSecureSetting*
+ * APIs defined in 'src/posix/platform/include/openthread/platform/secure_settings.h'.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE 0
+#endif
+
#ifdef __APPLE__
/**
diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h
index ff01947..835bd0c 100644
--- a/src/posix/platform/platform-posix.h
+++ b/src/posix/platform/platform-posix.h
@@ -39,6 +39,7 @@
#include <errno.h>
#include <net/if.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
@@ -46,6 +47,7 @@
#include <openthread/error.h>
#include <openthread/instance.h>
+#include <openthread/ip6.h>
#include <openthread/openthread-system.h>
#include <openthread/platform/time.h>
@@ -498,6 +500,87 @@
*/
extern unsigned int gBackboneNetifIndex;
+/**
+ * This function initializes the infrastructure interface.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aIfName The name of the infrastructure interface.
+ *
+ * @returns The index of the infrastructure interface.
+ *
+ */
+uint32_t platformInfraIfInit(otInstance *aInstance, const char *aIfName);
+
+/**
+ * This function deinitializes the infrastructure interface.
+ *
+ */
+void platformInfraIfDeinit(void);
+
+/**
+ * This function tells if the infrastructure interface is running.
+ *
+ * @returns TRUE if the infrastructure interface is running, FALSE if not.
+ *
+ */
+bool platformInfraIfIsRunning(void);
+
+/**
+ * this function returns the IPv6 link-local address of the infrastructure interface.
+ *
+ * @returns A pointer to the link-local address; NULL if no link-local address is present.
+ *
+ */
+const otIp6Address *platformInfraIfGetLinkLocalAddress(void);
+
+/**
+ * This function updates the read fd set.
+ *
+ * @param[out] aReadFdSet The fd set to be updated.
+ * @param[out] aMaxFd The maximum fd to be updated.
+ *
+ */
+void platformInfraIfUpdateFdSet(fd_set &aReadFdSet, int &aMaxFd);
+
+/**
+ * This function processes possible events on the infrastructure interface.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in] aReadFdSet The fd set which may contain read vents.
+ *
+ */
+void platformInfraIfProcess(otInstance *aInstance, const fd_set &aReadFdSet);
+
+/**
+ * This function enables daemon.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ */
+void platformDaemonEnable(otInstance *aInstance);
+
+/**
+ * This function disables daemon.
+ *
+ */
+void platformDaemonDisable(void);
+
+/**
+ * This function updates the file descriptor sets with file descriptors used by daemon.
+ *
+ * @param[inout] aMainloop A pointer to the mainloop context.
+ *
+ */
+void platformDaemonUpdate(otSysMainloopContext *aContext);
+
+/**
+ * This function performs daemon processing.
+ *
+ * @param[in] aMainloop A pointer to the mainloop context.
+ *
+ */
+void platformDaemonProcess(const otSysMainloopContext *aContext);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index 09d2b4f..0c2ea12 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -33,6 +33,8 @@
#include "platform-posix.h"
+#include <string.h>
+
#include "lib/spinel/radio_spinel.hpp"
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_UART
@@ -90,16 +92,18 @@
void platformRadioInit(otUrl *aRadioUrl)
{
- ot::Posix::RadioUrl &radioUrl = *static_cast<ot::Posix::RadioUrl *>(aRadioUrl);
- bool resetRadio = (radioUrl.GetValue("no-reset") == nullptr);
- bool restoreDataset = (radioUrl.GetValue("ncp-dataset") != nullptr);
+ ot::Posix::RadioUrl &radioUrl = *static_cast<ot::Posix::RadioUrl *>(aRadioUrl);
+ bool resetRadio = (radioUrl.GetValue("no-reset") == nullptr);
+ bool restoreDataset = (radioUrl.GetValue("ncp-dataset") != nullptr);
+ bool skipCompatibilityCheck = (radioUrl.GetValue("skip-rcp-compatibility-check") != nullptr);
const char * parameterValue;
+ const char * region;
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
const char *maxPowerTable;
#endif
SuccessOrDie(sRadioSpinel.GetSpinelInterface().Init(radioUrl));
- sRadioSpinel.Init(resetRadio, restoreDataset);
+ sRadioSpinel.Init(resetRadio, restoreDataset, skipCompatibilityCheck);
parameterValue = radioUrl.GetValue("fem-lnagain");
if (parameterValue != nullptr)
@@ -119,6 +123,16 @@
SuccessOrDie(sRadioSpinel.SetCcaEnergyDetectThreshold(static_cast<int8_t>(ccaThreshold)));
}
+ region = radioUrl.GetValue("region");
+ if (region != nullptr)
+ {
+ uint16_t regionCode;
+
+ VerifyOrDie(strnlen(region, 3) == 2, OT_EXIT_INVALID_ARGUMENTS);
+ regionCode = static_cast<uint16_t>(static_cast<uint16_t>(region[0]) << 8) + static_cast<uint16_t>(region[1]);
+ SuccessOrDie(sRadioSpinel.SetRadioRegion(regionCode));
+ }
+
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
maxPowerTable = radioUrl.GetValue("max-power-table");
if (maxPowerTable != nullptr)
@@ -546,3 +560,15 @@
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.SetChannelMaxTransmitPower(aChannel, aMaxPower);
}
+
+otError otPlatRadioSetRegion(otInstance *aInstance, uint16_t aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return sRadioSpinel.SetRadioRegion(aRegionCode);
+}
+
+otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ return sRadioSpinel.GetRadioRegion(aRegionCode);
+}
diff --git a/src/posix/platform/radio_url.cpp b/src/posix/platform/radio_url.cpp
index 7c80f1e..ca0f160 100644
--- a/src/posix/platform/radio_url.cpp
+++ b/src/posix/platform/radio_url.cpp
@@ -88,10 +88,12 @@
#endif
return "RadioURL:\n" OT_RADIO_URL_HELP_BUS OT_RADIO_URL_HELP_MAX_POWER_TABLE
+ " region[=region-code] Set the radio's region code.\n"
" cca-threshold[=dbm] Set the radio's CCA ED threshold in dBm measured at antenna connector.\n"
" fem-lnagain[=dbm] Set the Rx LNA gain in dBm of the external FEM.\n"
" ncp-dataset Retrieve dataset from ncp.\n"
- " no-reset Do not send Spinel reset command to RCP on initialization.\n";
+ " no-reset Do not send Spinel reset command to RCP on initialization.\n"
+ " skip-rcp-compatibility-check Skip checking RCP API version and capabilities during initialization.\n";
}
namespace ot {
diff --git a/src/posix/platform/settings.cpp b/src/posix/platform/settings.cpp
index ec6aa79..c2750ff 100644
--- a/src/posix/platform/settings.cpp
+++ b/src/posix/platform/settings.cpp
@@ -47,6 +47,9 @@
#include <openthread/platform/misc.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/settings.h>
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+#include <openthread/platform/secure_settings.h>
+#endif
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
@@ -57,6 +60,34 @@
static otError platformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex, int *aSwapFd);
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+static const uint16_t *sKeys = nullptr;
+static uint16_t sKeysLength = 0;
+
+void otPlatSettingsSetCriticalKeys(otInstance *aInstance, const uint16_t *aKeys, uint16_t aKeysLength)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ sKeys = aKeys;
+ sKeysLength = aKeysLength;
+}
+
+static bool isCriticalKey(uint16_t aKey)
+{
+ bool ret = false;
+
+ VerifyOrExit(sKeys != nullptr);
+
+ for (uint16_t i = 0; i < sKeysLength; i++)
+ {
+ VerifyOrExit(aKey != sKeys[i], ret = true);
+ }
+
+exit:
+ return ret;
+}
+#endif
+
static void getSettingsFileName(otInstance *aInstance, char aFileName[kMaxFileNameSize], bool aSwap)
{
const char *offset = getenv("PORT_OFFSET");
@@ -137,6 +168,10 @@
{
otError error = OT_ERROR_NONE;
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ otPosixSecureSettingsInit(aInstance);
+#endif
+
{
struct stat st;
@@ -182,6 +217,10 @@
{
OT_UNUSED_VARIABLE(aInstance);
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ otPosixSecureSettingsDeinit(aInstance);
+#endif
+
assert(sSettingsFd != -1);
VerifyOrDie(close(sSettingsFd) == 0, OT_EXIT_ERROR_ERRNO);
}
@@ -194,6 +233,13 @@
const off_t size = lseek(sSettingsFd, 0, SEEK_END);
off_t offset = lseek(sSettingsFd, 0, SEEK_SET);
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ if (isCriticalKey(aKey))
+ {
+ ExitNow(error = otPosixSecureSettingsGet(aInstance, aKey, aIndex, aValue, aValueLength));
+ }
+#endif
+
VerifyOrExit(offset == 0 && size >= 0, error = OT_ERROR_PARSE);
while (offset < size)
@@ -245,7 +291,15 @@
otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
- int swapFd = -1;
+ int swapFd = -1;
+ otError error = OT_ERROR_NONE;
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ if (isCriticalKey(aKey))
+ {
+ ExitNow(error = otPosixSecureSettingsSet(aInstance, aKey, aValue, aValueLength));
+ }
+#endif
switch (platformSettingsDelete(aInstance, aKey, -1, &swapFd))
{
@@ -265,15 +319,26 @@
swapPersist(aInstance, swapFd);
- return OT_ERROR_NONE;
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+exit:
+#endif
+ return error;
}
otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
{
OT_UNUSED_VARIABLE(aInstance);
- off_t size = lseek(sSettingsFd, 0, SEEK_END);
- int swapFd = swapOpen(aInstance);
+ otError error = OT_ERROR_NONE;
+ off_t size = lseek(sSettingsFd, 0, SEEK_END);
+ int swapFd = swapOpen(aInstance);
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ if (isCriticalKey(aKey))
+ {
+ ExitNow(error = otPosixSecureSettingsAdd(aInstance, aKey, aValue, aValueLength));
+ }
+#endif
if (size > 0)
{
@@ -288,12 +353,28 @@
swapPersist(aInstance, swapFd);
- return OT_ERROR_NONE;
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+exit:
+#endif
+ return error;
}
otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
{
- return platformSettingsDelete(aInstance, aKey, aIndex, nullptr);
+ otError error;
+
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ if (isCriticalKey(aKey))
+ {
+ error = otPosixSecureSettingsDelete(aInstance, aKey, aIndex);
+ }
+ else
+#endif
+ {
+ error = platformSettingsDelete(aInstance, aKey, aIndex, nullptr);
+ }
+
+ return error;
}
/**
@@ -393,6 +474,10 @@
void otPlatSettingsWipe(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
+#if OPENTHREAD_POSIX_CONFIG_SECURE_SETTINGS_ENABLE
+ otPosixSecureSettingsWipe(aInstance);
+#endif
+
VerifyOrDie(0 == ftruncate(sSettingsFd, 0), OT_EXIT_ERROR_ERRNO);
}
diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp
index 1824fe1..3bb55f9 100644
--- a/src/posix/platform/system.cpp
+++ b/src/posix/platform/system.cpp
@@ -38,11 +38,13 @@
#include <assert.h>
#include <openthread-core-config.h>
+#include <openthread/border_router.h>
+#include <openthread/heap.h>
#include <openthread/tasklet.h>
#include <openthread/platform/alarm-milli.h>
+#include <openthread/platform/infra_if.h>
#include <openthread/platform/otns.h>
#include <openthread/platform/radio.h>
-#include <openthread/platform/uart.h>
#include "common/code_utils.hpp"
@@ -97,6 +99,24 @@
platformBackboneInit(instance, aPlatformConfig->mBackboneInterfaceName);
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ {
+ uint32_t infraIfIndex;
+
+ // Reuse the backbone interface name.
+ if (aPlatformConfig->mBackboneInterfaceName == nullptr || strlen(aPlatformConfig->mBackboneInterfaceName) == 0)
+ {
+ DieNowWithMessage("no infra interface is specified", OT_EXIT_INVALID_ARGUMENTS);
+ }
+
+ infraIfIndex = platformInfraIfInit(instance, aPlatformConfig->mBackboneInterfaceName);
+
+ SuccessOrDie(otBorderRoutingInit(instance, infraIfIndex, platformInfraIfIsRunning(),
+ platformInfraIfGetLinkLocalAddress()));
+ SuccessOrDie(otBorderRoutingSetEnabled(instance, /* aEnabled */ true));
+ }
+#endif
+
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifInit(instance, aPlatformConfig->mInterfaceName);
#elif OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
@@ -107,11 +127,17 @@
SuccessOrDie(otSetStateChangedCallback(instance, processStateChange, instance));
#endif
+#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ platformDaemonEnable(instance);
+#endif
return instance;
}
void otSysDeinit(void)
{
+#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ platformDaemonDisable();
+#endif
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeDeinit();
#endif
@@ -122,7 +148,10 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelDeinit();
#endif
- IgnoreError(otPlatUartDisable());
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ platformInfraIfDeinit();
+#endif
}
#if OPENTHREAD_POSIX_VIRTUAL_TIME
@@ -161,8 +190,6 @@
void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop)
{
platformAlarmUpdateTimeout(&aMainloop->mTimeout);
- platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
- &aMainloop->mMaxFd);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd);
#endif
@@ -173,6 +200,9 @@
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
platformBackboneUpdateFdSet(aMainloop->mReadFdSet, aMainloop->mMaxFd);
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ platformInfraIfUpdateFdSet(aMainloop->mReadFdSet, aMainloop->mMaxFd);
+#endif
#if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd,
&aMainloop->mTimeout);
@@ -183,6 +213,10 @@
platformTrelUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout);
#endif
+#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ platformDaemonUpdate(aMainloop);
+#endif
+
if (otTaskletsArePending(aInstance))
{
aMainloop->mTimeout.tv_sec = 0;
@@ -243,7 +277,6 @@
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
platformTrelProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet);
#endif
- platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
platformAlarmProcess(aInstance);
#if OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE
platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
@@ -254,6 +287,12 @@
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
platformBackboneProcess(aMainloop->mReadFdSet);
#endif
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ platformInfraIfProcess(aInstance, aMainloop->mReadFdSet);
+#endif
+#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
+ platformDaemonProcess(aMainloop);
+#endif
}
#if OPENTHREAD_CONFIG_OTNS_ENABLE
diff --git a/src/posix/platform/trel_udp6.cpp b/src/posix/platform/trel_udp6.cpp
index 1b3ff0c..5b224b6 100644
--- a/src/posix/platform/trel_udp6.cpp
+++ b/src/posix/platform/trel_udp6.cpp
@@ -35,6 +35,10 @@
#include "platform-posix.h"
+#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET && !defined(__linux__)
+#error "netlink socket use is only supported on linux platform"
+#endif
+
#include <arpa/inet.h>
#include <assert.h>
#include <fcntl.h>
@@ -43,6 +47,11 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
+#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+#include <linux/if_tun.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#endif
#include <openthread/platform/trel-udp6.h>
@@ -57,6 +66,9 @@
#define USEC_PER_MSEC 1000u
#define TREL_SOCKET_BIND_MAX_WAIT_TIME_MSEC 4000u
+#define TREL_UNICAST_ADDRESS_PREFIX_LEN 64
+#define TREL_UNICAST_ADDRESS_SCOPE 2 // The unicast address is link-local
+
typedef struct TxPacket
{
struct TxPacket *mNext;
@@ -126,6 +138,66 @@
#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG)
#endif // OPENTHREAD_CONFIG_LOG_PLATFORM
+#if OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+
+static void UpdateUnicastAddress(const otIp6Address *aUnicastAddress, bool aToAdd)
+{
+ int netlinkSocket;
+ int ret;
+ struct rtattr *rta;
+
+ struct
+ {
+ struct nlmsghdr nh;
+ struct ifaddrmsg ifa;
+ char buf[64];
+ } request;
+
+ netlinkSocket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+ VerifyOrDie(netlinkSocket >= 0, OT_EXIT_ERROR_ERRNO);
+
+ memset(&request, 0, sizeof(request));
+
+ request.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
+ request.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
+ request.nh.nlmsg_type = aToAdd ? RTM_NEWADDR : RTM_DELADDR;
+ request.nh.nlmsg_pid = 0;
+ request.nh.nlmsg_seq = 0;
+
+ request.ifa.ifa_family = AF_INET6;
+ request.ifa.ifa_prefixlen = TREL_UNICAST_ADDRESS_PREFIX_LEN;
+ request.ifa.ifa_flags = IFA_F_NODAD;
+ request.ifa.ifa_scope = TREL_UNICAST_ADDRESS_SCOPE;
+ request.ifa.ifa_index = sInterfaceIndex;
+
+ rta = reinterpret_cast<struct rtattr *>((reinterpret_cast<char *>(&request)) + NLMSG_ALIGN(request.nh.nlmsg_len));
+ rta->rta_type = IFA_LOCAL;
+ rta->rta_len = RTA_LENGTH(sizeof(otIp6Address));
+
+ memcpy(RTA_DATA(rta), aUnicastAddress, sizeof(otIp6Address));
+
+ request.nh.nlmsg_len = NLMSG_ALIGN(request.nh.nlmsg_len) + rta->rta_len;
+
+ ret = send(netlinkSocket, &request, request.nh.nlmsg_len, 0);
+ VerifyOrDie(ret != -1, OT_EXIT_ERROR_ERRNO);
+
+ close(netlinkSocket);
+}
+
+static void AddUnicastAddress(const otIp6Address *aUnicastAddress)
+{
+ otLogDebgPlat("[trel] AddUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
+ UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ true);
+}
+
+static void RemoveUnicastAddress(const otIp6Address *aUnicastAddress)
+{
+ otLogDebgPlat("[trel] RemoveUnicastAddress(%s)", Ip6AddrToString(aUnicastAddress));
+ UpdateUnicastAddress(aUnicastAddress, /* aToAdd */ false);
+}
+
+#else // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+
static void AddUnicastAddress(const otIp6Address *aUnicastAddress)
{
int mgmtFd;
@@ -185,6 +257,8 @@
close(mgmtFd);
}
+#endif // OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+
static void PrepareSocket(void)
{
int val;
diff --git a/src/posix/platform/uart.cpp b/src/posix/platform/uart.cpp
deleted file mode 100644
index d2b47fa..0000000
--- a/src/posix/platform/uart.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- */
-
-#include "openthread-posix-config.h"
-#include "platform-posix.h"
-
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/file.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <openthread/platform/misc.h>
-#include <openthread/platform/uart.h>
-
-#include "common/code_utils.hpp"
-
-#define OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK OPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME ".lock"
-
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-static int sUartSocket = -1;
-static int sUartLock = -1;
-static int sSessionSocket = -1;
-#endif
-
-static bool sEnabled = false;
-static const uint8_t *sWriteBuffer = nullptr;
-static uint16_t sWriteLength = 0;
-
-otError otPlatUartEnable(void)
-{
- otError error = OT_ERROR_NONE;
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- struct sockaddr_un sockname;
- int ret;
-
- // This allows implementing pseudo reset.
- VerifyOrExit(sUartSocket == -1);
-
- sUartSocket = SocketWithCloseExec(AF_UNIX, SOCK_STREAM, 0, kSocketNonBlock);
-
- if (sUartSocket == -1)
- {
- DieNow(OT_EXIT_FAILURE);
- }
-
- sUartLock = open(OPENTHREAD_POSIX_DAEMON_SOCKET_LOCK, O_CREAT | O_RDONLY | O_CLOEXEC, 0600);
-
- if (sUartLock == -1)
- {
- DieNowWithMessage("open", OT_EXIT_ERROR_ERRNO);
- }
-
- if (flock(sUartLock, LOCK_EX | LOCK_NB) == -1)
- {
- DieNowWithMessage("flock", OT_EXIT_ERROR_ERRNO);
- }
-
- memset(&sockname, 0, sizeof(struct sockaddr_un));
-
- (void)unlink(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
-
- sockname.sun_family = AF_UNIX;
- assert(sizeof(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME) < sizeof(sockname.sun_path));
- strncpy(sockname.sun_path, OPENTHREAD_POSIX_DAEMON_SOCKET_NAME, sizeof(sockname.sun_path) - 1);
-
- ret = bind(sUartSocket, (const struct sockaddr *)&sockname, sizeof(struct sockaddr_un));
-
- if (ret == -1)
- {
- DieNowWithMessage("bind", OT_EXIT_ERROR_ERRNO);
- }
-
- //
- // only accept 1 connection.
- //
- ret = listen(sUartSocket, 1);
- if (ret == -1)
- {
- DieNowWithMessage("listen", OT_EXIT_ERROR_ERRNO);
- }
-
-exit:
-#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-
- sEnabled = true;
- return error;
-}
-
-otError otPlatUartDisable(void)
-{
- otError error = OT_ERROR_NONE;
- sEnabled = false;
-
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- if (sSessionSocket != -1)
- {
- close(sSessionSocket);
- sSessionSocket = -1;
- }
-
- if (sUartSocket != -1)
- {
- close(sUartSocket);
- sUartSocket = -1;
- }
-
- if (gPlatResetReason != OT_PLAT_RESET_REASON_SOFTWARE)
- {
- otLogCritPlat("Removing daemon socket: %s", OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
- (void)unlink(OPENTHREAD_POSIX_DAEMON_SOCKET_NAME);
- }
-
- if (sUartLock != -1)
- {
- (void)flock(sUartLock, LOCK_UN);
- close(sUartLock);
- sUartLock = -1;
- }
-#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-
- return error;
-}
-
-otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
-{
- otError error = OT_ERROR_NONE;
-
- assert(sEnabled);
- VerifyOrExit(sWriteLength == 0, error = OT_ERROR_BUSY);
-
- sWriteBuffer = aBuf;
- sWriteLength = aBufLength;
-
-exit:
- return error;
-}
-
-void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
-{
- VerifyOrExit(sEnabled);
-
- if (aReadFdSet != nullptr)
- {
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- int fd = (sSessionSocket == -1 ? sUartSocket : sSessionSocket);
-#else
- int fd = STDIN_FILENO;
-#endif
-
- FD_SET(fd, aReadFdSet);
-
- if (aErrorFdSet != nullptr)
- {
- FD_SET(fd, aErrorFdSet);
- }
-
- if (aMaxFd != nullptr && *aMaxFd < fd)
- {
- *aMaxFd = fd;
- }
- }
- if ((aWriteFdSet != nullptr) && (sWriteLength > 0))
- {
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- int fd = (sSessionSocket == -1 ? sUartSocket : sSessionSocket);
-#else
- int fd = STDOUT_FILENO;
-#endif
-
- FD_SET(fd, aWriteFdSet);
-
- if (aErrorFdSet != nullptr)
- {
- FD_SET(fd, aErrorFdSet);
- }
-
- if (aMaxFd != nullptr && *aMaxFd < fd)
- {
- *aMaxFd = fd;
- }
- }
-
-exit:
- return;
-}
-
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-static void InitializeSessionSocket(void)
-{
- int newSessionSocket;
- int rval;
-
- VerifyOrExit((newSessionSocket = accept(sUartSocket, nullptr, nullptr)) != -1, rval = -1);
-
- VerifyOrExit((rval = fcntl(newSessionSocket, F_GETFD, 0)) != -1);
-
- rval |= FD_CLOEXEC;
-
- VerifyOrExit((rval = fcntl(newSessionSocket, F_SETFD, rval)) != -1);
-
-#ifndef __linux__
- // some platforms (macOS, Solaris) don't have MSG_NOSIGNAL
- // SOME of those (macOS, but NOT Solaris) support SO_NOSIGPIPE
- // if we have SO_NOSIGPIPE, then set it. Otherwise, we're going
- // to simply ignore it.
-#if defined(SO_NOSIGPIPE)
- rval = setsockopt(newSessionSocket, SOL_SOCKET, SO_NOSIGPIPE, &rval, sizeof(rval));
- VerifyOrExit(rval != -1);
-#else
-#warning "no support for MSG_NOSIGNAL or SO_NOSIGPIPE"
-#endif
-#endif // __linux__
-
- if (sSessionSocket != -1)
- {
- close(sSessionSocket);
- }
- sSessionSocket = newSessionSocket;
-
-exit:
- if (rval == -1)
- {
- otLogWarnPlat("Failed to initialize session socket: %s", strerror(errno));
- if (newSessionSocket != -1)
- {
- close(newSessionSocket);
- }
- }
- else
- {
- otLogInfoPlat("Session socket is ready", strerror(errno));
- }
-}
-#endif
-
-static otError UartWrite(int aFd)
-{
- otError error = OT_ERROR_NONE;
- ssize_t rval;
-
- VerifyOrExit(sWriteLength > 0, error = OT_ERROR_INVALID_STATE);
-
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE && defined(__linux__)
- if (aFd == sSessionSocket)
- {
- // Don't die on SIGPIPE
- rval = send(aFd, sWriteBuffer, sWriteLength, MSG_NOSIGNAL);
- }
- else
-#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE && defined(__linux__)
- {
- rval = write(aFd, sWriteBuffer, sWriteLength);
- }
-
- if (rval < 0)
- {
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- otLogWarnPlat("UART write: %s", strerror(errno));
- if (aFd == sSessionSocket)
- {
- close(sSessionSocket);
- sSessionSocket = -1;
- }
- ExitNow();
-#else
- DieNow(OT_EXIT_ERROR_ERRNO);
-#endif
- }
-
- sWriteBuffer += rval;
- sWriteLength -= static_cast<uint16_t>(rval);
-
-exit:
- return error;
-}
-
-void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, const fd_set *aErrorFdSet)
-{
- ssize_t rval;
- int fd;
-
- VerifyOrExit(sEnabled);
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- if (FD_ISSET(sUartSocket, aErrorFdSet))
- {
- DieNowWithMessage("socket", OT_EXIT_FAILURE);
- }
- else if (FD_ISSET(sUartSocket, aReadFdSet))
- {
- InitializeSessionSocket();
- }
-
- if (sSessionSocket == -1 && sWriteBuffer != nullptr)
- {
- IgnoreReturnValue(write(STDERR_FILENO, sWriteBuffer, sWriteLength));
- sWriteBuffer = nullptr;
- sWriteLength = 0;
- otPlatUartSendDone();
- }
-
- VerifyOrExit(sSessionSocket != -1);
-
- if (FD_ISSET(sSessionSocket, aErrorFdSet))
- {
- close(sSessionSocket);
- sSessionSocket = -1;
- }
-
- VerifyOrExit(sSessionSocket != -1);
-
- fd = sSessionSocket;
-#else // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- if (FD_ISSET(STDIN_FILENO, aErrorFdSet))
- {
- DieNowWithMessage("stdin", OT_EXIT_FAILURE);
- }
-
- if (FD_ISSET(STDOUT_FILENO, aErrorFdSet))
- {
- DieNowWithMessage("stdout", OT_EXIT_FAILURE);
- }
-
- fd = STDIN_FILENO;
-#endif // OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
-
- if (FD_ISSET(fd, aReadFdSet))
- {
- uint8_t buffer[256];
-
- rval = read(fd, buffer, sizeof(buffer));
-
- if (rval > 0)
- {
- otPlatUartReceived(buffer, (uint16_t)rval);
- }
- else if (rval <= 0)
- {
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- if (rval < 0)
- {
- perror("UART read");
- }
- close(sSessionSocket);
- sSessionSocket = -1;
- ExitNow();
-#else
- DieNowWithMessage("UART read", (rval < 0) ? OT_EXIT_ERROR_ERRNO : OT_EXIT_FAILURE);
-#endif
- }
- }
-
-#if !OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- fd = STDOUT_FILENO;
-#endif
-
- if ((FD_ISSET(fd, aWriteFdSet)))
- {
- otError error = UartWrite(fd);
-
- VerifyOrExit(error == OT_ERROR_NONE, otLogWarnPlat("UART write: %s", otThreadErrorToString(error)));
-
- if (sWriteLength == 0)
- {
- otPlatUartSendDone();
- }
- }
-
-exit:
- return;
-}
-
-otError otPlatUartFlush(void)
-{
- otError error = OT_ERROR_NONE;
-
- while (sWriteLength > 0)
- {
- int fd =
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- sSessionSocket != -1 ? sSessionSocket :
-#endif
- STDOUT_FILENO;
- int rval;
-
- fd_set writeFdSet;
- FD_ZERO(&writeFdSet);
- FD_SET(fd, &writeFdSet);
-
- rval = select(fd + 1, nullptr, &writeFdSet, nullptr, nullptr);
-
- assert(rval != 0);
-
- if (rval > 0)
- {
- assert(FD_ISSET(fd, &writeFdSet));
- SuccessOrExit(error = UartWrite(fd));
- }
- else if (errno != EINTR)
- {
-#if OPENTHREAD_POSIX_CONFIG_DAEMON_ENABLE
- if (sSessionSocket == fd)
- {
- close(sSessionSocket);
- sSessionSocket = -1;
- }
- else
-#endif
- {
- DieNow(OT_EXIT_ERROR_ERRNO);
- }
- }
- }
-
-exit:
- return error;
-}
diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp
index 1d0307c..96b3b97 100644
--- a/src/posix/platform/udp.cpp
+++ b/src/posix/platform/udp.cpp
@@ -55,6 +55,10 @@
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
+#include "posix/platform/ip6_utils.hpp"
+
+using namespace ot::Posix::Ip6Utils;
+
static const size_t kMaxUdpSize = 1280;
static void *FdToHandle(int aFd)
@@ -319,7 +323,7 @@
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &gNetifName, strlen(gNetifName)) == 0,
error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
- VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0,
+ VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0,
error = OT_ERROR_FAILED);
#endif // __linux__
break;
@@ -331,7 +335,8 @@
VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, gBackboneNetifName, strlen(gBackboneNetifName)) == 0,
error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
- VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) == 0,
+ VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) ==
+ 0,
error = OT_ERROR_FAILED);
#endif // __linux__
#else
@@ -392,26 +397,24 @@
if (len > 0 && netifName[0] != '\0')
{
fd = FdFromHandle(aUdpSocket->mHandle);
- VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &netifName, len) == 0, error = OT_ERROR_FAILED);
+ VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &netifName, len) == 0, {
+ otLogWarnPlat("Failed to bind to device: %s", strerror(errno));
+ error = OT_ERROR_FAILED;
+ });
}
ExitNow();
#endif
}
- switch (connect(fd, reinterpret_cast<struct sockaddr *>(&sin6), sizeof(sin6)))
+ if (connect(fd, reinterpret_cast<struct sockaddr *>(&sin6), sizeof(sin6)) != 0)
{
- case 0:
- break;
#ifdef __APPLE__
- case EAFNOSUPPORT:
- VerifyOrExit(isDisconnect, error = OT_ERROR_FAILED);
- break;
+ VerifyOrExit(errno == EAFNOSUPPORT && isDisconnect);
#endif
-
- default:
+ otLogWarnPlat("Failed to connect to [%s]:%u: %s", Ip6AddressString(&aUdpSocket->mPeerName.mAddress).AsCString(),
+ aUdpSocket->mPeerName.mPort, strerror(errno));
error = OT_ERROR_FAILED;
- break;
}
exit:
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 65feb22..2b00f1c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -26,4 +26,14 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-add_subdirectory(unit)
+if(OT_PLATFORM STREQUAL "simulation")
+ if(OT_FTD)
+ add_subdirectory(unit)
+ endif()
+endif()
+
+option(OT_FUZZ_TARGETS "enable fuzz targets" OFF)
+
+if(OT_FUZZ_TARGETS)
+ add_subdirectory(fuzz)
+endif()
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..08b7375
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2021, 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.
+#
+
+set(COMMON_INCLUDES
+ ${PROJECT_SOURCE_DIR}/include
+ ${PROJECT_SOURCE_DIR}/src/core
+)
+
+set(COMMON_COMPILE_OPTIONS
+ -DOPENTHREAD_FTD=1
+ -DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
+)
+
+set(COMMON_SOURCES
+ fuzzer_platform.cpp
+)
+
+set(COMMON_LIBS
+ openthread-ftd
+ ${OT_MBEDTLS}
+ $ENV{LIB_FUZZING_ENGINE}
+ ot-config
+)
+
+add_executable(cli-received-fuzzer
+ cli_received.cpp
+ ${COMMON_SOURCES}
+)
+
+target_compile_options(cli-received-fuzzer
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS}
+)
+
+target_include_directories(cli-received-fuzzer
+ PRIVATE
+ ${COMMON_INCLUDES}
+)
+
+target_link_libraries(cli-received-fuzzer
+ PRIVATE
+ openthread-cli-ftd
+ ${COMMON_LIBS}
+)
+
+add_executable(ip6-send-fuzzer
+ ip6_send.cpp
+ ${COMMON_SOURCES}
+)
+
+target_compile_options(ip6-send-fuzzer
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS}
+)
+
+target_include_directories(ip6-send-fuzzer
+ PRIVATE
+ ${COMMON_INCLUDES}
+)
+
+target_link_libraries(ip6-send-fuzzer
+ PRIVATE
+ ${COMMON_LIBS}
+)
+
+add_executable(radio-receive-done-fuzzer
+ radio_receive_done.cpp
+ ${COMMON_SOURCES}
+)
+
+target_compile_options(radio-receive-done-fuzzer
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS}
+)
+
+target_include_directories(radio-receive-done-fuzzer
+ PRIVATE
+ ${COMMON_INCLUDES}
+)
+
+target_link_libraries(radio-receive-done-fuzzer
+ PRIVATE
+ ${COMMON_LIBS}
+)
+
+add_executable(ncp-hdlc-received-fuzzer
+ ncp_hdlc_received.cpp
+ ${COMMON_SOURCES}
+)
+
+target_compile_options(ncp-hdlc-received-fuzzer
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS}
+)
+
+target_include_directories(ncp-hdlc-received-fuzzer
+ PRIVATE
+ ${COMMON_INCLUDES}
+)
+
+target_link_libraries(ncp-hdlc-received-fuzzer
+ PRIVATE
+ openthread-ncp-ftd
+ ${COMMON_LIBS}
+)
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
index bce0e31..0b2f1f4 100644
--- a/tests/fuzz/Makefile.am
+++ b/tests/fuzz/Makefile.am
@@ -29,10 +29,10 @@
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
bin_PROGRAMS = \
- cli-uart-received-fuzzer \
+ cli-received-fuzzer \
ip6-send-fuzzer \
radio-receive-done-fuzzer \
- ncp-uart-received-fuzzer \
+ ncp-hdlc-received-fuzzer \
$(NULL)
AM_CPPFLAGS = \
@@ -51,14 +51,14 @@
fuzzer_platform.h \
$(NULL)
-cli_uart_received_fuzzer_LDADD = \
+cli_received_fuzzer_LDADD = \
$(top_builddir)/src/cli/libopenthread-cli-ftd.a \
$(COMMON_LDADD) \
$(NULL)
-cli_uart_received_fuzzer_SOURCES = \
+cli_received_fuzzer_SOURCES = \
$(COMMON_SOURCES) \
- cli_uart_received.cpp \
+ cli_received.cpp \
$(NULL)
ip6_send_fuzzer_LDADD = \
@@ -79,14 +79,14 @@
radio_receive_done.cpp \
$(NULL)
-ncp_uart_received_fuzzer_LDADD = \
+ncp_hdlc_received_fuzzer_LDADD = \
$(top_builddir)/src/ncp/libopenthread-ncp-ftd.a \
$(COMMON_LDADD) \
$(NULL)
-ncp_uart_received_fuzzer_SOURCES = \
+ncp_hdlc_received_fuzzer_SOURCES = \
$(COMMON_SOURCES) \
- ncp_uart_received.cpp \
+ ncp_hdlc_received.cpp \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
diff --git a/tests/fuzz/cli_uart_received.cpp b/tests/fuzz/cli_received.cpp
similarity index 86%
rename from tests/fuzz/cli_uart_received.cpp
rename to tests/fuzz/cli_received.cpp
index 83f77fe..2dcbbd8 100644
--- a/tests/fuzz/cli_uart_received.cpp
+++ b/tests/fuzz/cli_received.cpp
@@ -28,6 +28,8 @@
#define MAX_ITERATIONS 100
+#include <stdarg.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -38,11 +40,19 @@
#include <openthread/tasklet.h>
#include <openthread/thread.h>
#include <openthread/thread_ftd.h>
-#include <openthread/platform/uart.h>
#include "fuzzer_platform.h"
#include "common/code_utils.hpp"
+static int CliOutput(void *aContext, const char *aFormat, va_list aArguments)
+{
+ OT_UNUSED_VARIABLE(aContext);
+ OT_UNUSED_VARIABLE(aFormat);
+ OT_UNUSED_VARIABLE(aArguments);
+
+ return vsnprintf(nullptr, 0, aFormat, aArguments);
+}
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
const otPanId panId = 0xdead;
@@ -55,17 +65,18 @@
FuzzerPlatformInit();
instance = otInstanceInitSingle();
- otCliUartInit(instance);
+ otCliInit(instance, CliOutput, nullptr);
IgnoreError(otLinkSetPanId(instance, panId));
IgnoreError(otIp6SetEnabled(instance, true));
IgnoreError(otThreadSetEnabled(instance, true));
IgnoreError(otThreadBecomeLeader(instance));
- buf = static_cast<uint8_t *>(malloc(size));
+ buf = static_cast<uint8_t *>(malloc(size + 1));
memcpy(buf, data, size);
+ buf[size] = '\0';
- otPlatUartReceived(buf, (uint16_t)size);
+ otCliInputLine(reinterpret_cast<char *>(buf));
VerifyOrExit(!FuzzerPlatformResetWasRequested());
diff --git a/tests/fuzz/fuzzer_platform.cpp b/tests/fuzz/fuzzer_platform.cpp
index 463a6d4..a8ae28b 100644
--- a/tests/fuzz/fuzzer_platform.cpp
+++ b/tests/fuzz/fuzzer_platform.cpp
@@ -40,7 +40,6 @@
#include <openthread/platform/misc.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/settings.h>
-#include <openthread/platform/uart.h>
#include "mac/mac_frame.hpp"
@@ -493,28 +492,6 @@
OT_UNUSED_VARIABLE(aInstance);
}
-otError otPlatUartEnable(void)
-{
- return OT_ERROR_NONE;
-}
-
-otError otPlatUartDisable(void)
-{
- return OT_ERROR_NONE;
-}
-
-otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
-{
- OT_UNUSED_VARIABLE(aBuf);
- OT_UNUSED_VARIABLE(aBufLength);
- return OT_ERROR_NONE;
-}
-
-otError otPlatUartFlush(void)
-{
- return OT_ERROR_NOT_IMPLEMENTED;
-}
-
otError otPlatDiagProcess(otInstance *aInstance,
uint8_t aArgsLength,
char * aArgs[],
diff --git a/tests/fuzz/ncp_uart_received.cpp b/tests/fuzz/ncp_hdlc_received.cpp
similarity index 91%
rename from tests/fuzz/ncp_uart_received.cpp
rename to tests/fuzz/ncp_hdlc_received.cpp
index 9f20aba..a61b0fa 100644
--- a/tests/fuzz/ncp_uart_received.cpp
+++ b/tests/fuzz/ncp_hdlc_received.cpp
@@ -38,11 +38,18 @@
#include <openthread/tasklet.h>
#include <openthread/thread.h>
#include <openthread/thread_ftd.h>
-#include <openthread/platform/uart.h>
#include "fuzzer_platform.h"
#include "common/code_utils.hpp"
+static int HdlcSend(const uint8_t *aBuf, uint16_t aBufLength)
+{
+ OT_UNUSED_VARIABLE(aBuf);
+ OT_UNUSED_VARIABLE(aBufLength);
+
+ return aBufLength;
+}
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
const otPanId panId = 0xdead;
@@ -55,7 +62,7 @@
FuzzerPlatformInit();
instance = otInstanceInitSingle();
- otNcpInit(instance);
+ otNcpHdlcInit(instance, HdlcSend);
IgnoreError(otLinkSetPanId(instance, panId));
IgnoreError(otIp6SetEnabled(instance, true));
IgnoreError(otThreadSetEnabled(instance, true));
@@ -65,7 +72,7 @@
memcpy(buf, data, size);
- otPlatUartReceived(buf, (uint16_t)size);
+ otNcpHdlcReceive(buf, static_cast<uint16_t>(size));
VerifyOrExit(!FuzzerPlatformResetWasRequested());
diff --git a/tests/fuzz/oss-fuzz-build b/tests/fuzz/oss-fuzz-build
new file mode 100755
index 0000000..cbfba51
--- /dev/null
+++ b/tests/fuzz/oss-fuzz-build
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# Copyright (c) 2021, 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.
+#
+
+(
+ mkdir build
+ cd build || exit
+
+ cmake -GNinja \
+ -DCMAKE_C_FLAGS="${CFLAGS}" \
+ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
+ -DOT_BUILD_EXECUTABLES=OFF \
+ -DOT_FUZZ_TARGETS=ON \
+ -DOT_MTD=OFF \
+ -DOT_PLATFORM=external \
+ -DOT_RCP=OFF \
+ -DOT_BORDER_AGENT=ON \
+ -DOT_BORDER_ROUTER=ON \
+ -DOT_CHANNEL_MANAGER=ON \
+ -DOT_CHANNEL_MONITOR=ON \
+ -DOT_CHILD_SUPERVISION=ON \
+ -DOT_COAP=ON \
+ -DOT_COAPS=ON \
+ -DOT_COAP_BLOCK=ON \
+ -DOT_COAP_OBSERVE=ON \
+ -DOT_COMMISSIONER=ON \
+ -DOT_DATASET_UPDATER=ON \
+ -DOT_DHCP6_CLIENT=ON \
+ -DOT_DHCP6_SERVER=ON \
+ -DOT_DNS_CLIENT=ON \
+ -DOT_ECDSA=ON \
+ -DOT_IP6_FRAGM=ON \
+ -DOT_JAM_DETECTION=ON \
+ -DOT_JOINER=ON \
+ -DOT_LINK_RAW=ON \
+ -DOT_LOG_OUTPUT=APP \
+ -DOT_MAC_FILTER=ON \
+ -DOT_MTD_NETDIAG=ON \
+ -DOT_PING_SENDER=ON \
+ -DOT_SERVICE=ON \
+ -DOT_SLAAC=ON \
+ -DOT_SNTP_CLIENT=ON \
+ -DOT_SRP_CLIENT=ON \
+ -DOT_SRP_SERVER=ON \
+ -DOT_THREAD_VERSION=1.2 \
+ ..
+ ninja
+)
+
+find . -name '*-fuzzer' -exec cp -v '{}' "$OUT" ';'
+find . -name '*-fuzzer.dict' -exec cp -v '{}' "$OUT" ';'
+find . -name '*-fuzzer.options' -exec cp -v '{}' "$OUT" ';'
+
+fuzzers=$(find build/tests/fuzz -name "*-fuzzer")
+for f in $fuzzers; do
+ fuzzer=$(basename "$f" -fuzzer)
+
+ if [ -d "tests/fuzz/corpora/${fuzzer}" ]; then
+ zip -j "$OUT/$(basename "$f")"_seed_corpus.zip tests/fuzz/corpora/"${fuzzer}"/*
+ fi
+done
diff --git a/tests/scripts/expect/_common.exp b/tests/scripts/expect/_common.exp
index 25b04ed..c97f211 100644
--- a/tests/scripts/expect/_common.exp
+++ b/tests/scripts/expect/_common.exp
@@ -27,8 +27,15 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+proc skip_on_macos {} {
+ set OSTYPE [lindex $::tcl_platform(os) 0]
+
+ if { $OSTYPE == "Darwin" } {
+ exit 77
+ }
+}
+
proc wait_for {command success {failure {[\r\n]FAILURE_NOT_EXPECTED[\r\n]}}} {
- set result 0
set timeout 1
for {set i 0} {$i < 20} {incr i} {
if {$command != ""} {
@@ -37,22 +44,22 @@
expect {
-re $success {
- set result 1
+ return 0
}
-re $failure {
- error "Got failure in wait_for"
+ fail "Failed due to '$failure' found"
}
timeout {
# Do nothing
}
}
- if {$result == 1} {
- break
- }
}
- if {$result == 0} {
- error "Timed out in wait_for"
- }
+ fail "Failed due to '$success' not found"
+}
+
+proc expect_line {line} {
+ expect -re "\[\r\n \]($line)(?=\[\r\n>\])"
+ return $expect_out(1,string)
}
proc spawn_node {id {type ""} {radio_url ""}} {
@@ -81,28 +88,28 @@
spawn /usr/bin/env GCOV_PREFIX=$gcov_prefix $::env(OT_POSIX_APPS)/ot-cli $radio_url
send "factoryreset\n"
wait_for "state" "disabled"
- expect "Done"
+ expect_line "Done"
send "routerselectionjitter 1\n"
- expect "Done"
+ expect_line "Done"
}
cli {
spawn /usr/bin/env GCOV_PREFIX=$gcov_prefix $::env(OT_SIMULATION_APPS)/cli/ot-cli-ftd $id
send "factoryreset\n"
wait_for "state" "disabled"
- expect "Done"
+ expect_line "Done"
send "routerselectionjitter 1\n"
- expect "Done"
+ expect_line "Done"
}
mtd {
spawn /usr/bin/env GCOV_PREFIX=$gcov_prefix $::env(OT_SIMULATION_APPS)/cli/ot-cli-mtd $id
send "factoryreset\n"
wait_for "state" "disabled"
- expect "Done"
+ expect_line "Done"
}
}
expect_after {
- timeout { error "Timed out" }
+ timeout { fail "Timed out" }
}
set spawn_ids($id) $spawn_id
@@ -118,25 +125,27 @@
set spawn_id $spawn_ids($id)
}
+proc setup_leader {} {
+ send "dataset init new\n"
+ expect_line "Done"
+ send "dataset masterkey 00112233445566778899aabbccddeeff\n"
+ expect_line "Done"
+ send "dataset commit active\n"
+ expect_line "Done"
+ send "ifconfig up\n"
+ expect_line "Done"
+ send "thread start\n"
+ expect_line "Done"
+ wait_for "state" "leader"
+ expect_line "Done"
+}
+
proc dispose_node {id} {
switch_node $id
send "\x04"
expect eof
}
-proc setup_leader {} {
- send "dataset init new\n"
- expect "Done"
- send "dataset commit active\n"
- expect "Done"
- send "ifconfig up\n"
- expect "Done"
- send "thread start\n"
- expect "Done"
- wait_for "state" "leader"
- expect "Done"
-}
-
proc dispose_all {} {
global spawn_ids
set max_node [array size spawn_ids]
@@ -149,18 +158,16 @@
proc get_ipaddr {type} {
send "ipaddr $type\n"
expect "ipaddr $type"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set rval $expect_out(1,string)
- expect "Done"
+ set rval [expect_line {([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}}]
+ expect_line "Done"
return $rval
}
proc get_extaddr {} {
send "extaddr\n"
- expect -re {([0-9a-fA-F]{16})}
- set rval $expect_out(1,string)
- expect "Done"
+ set rval [expect_line {[0-9a-fA-F]{16}}]
+ expect_line "Done"
return $rval
}
@@ -168,11 +175,24 @@
proc get_rloc16 {} {
send "rloc16\n"
expect "rloc16"
- expect -re {([0-9a-fA-F]{4})}
- set rval $expect_out(1,string)
- expect "Done"
+ set rval [expect_line {[0-9a-fA-F]{4}}]
+ expect_line "Done"
return $rval
}
+proc setup_default_network {} {
+ send "channel 11\n"
+ expect_line "Done"
+ send "panid 0xface\n"
+ expect_line "Done"
+ send "masterkey 00112233445566778899aabbccddeeff\n"
+ expect_line "Done"
+}
+
+proc fail {message} {
+ dispose_all
+ error $message
+}
+
set timeout 10
diff --git a/tests/scripts/expect/_multinode.exp b/tests/scripts/expect/_multinode.exp
index 4d068d5..9170c3f 100644
--- a/tests/scripts/expect/_multinode.exp
+++ b/tests/scripts/expect/_multinode.exp
@@ -29,50 +29,61 @@
source "tests/scripts/expect/_common.exp"
-proc setup_two_nodes {{childmode {r}} {should_spawn_node true}} {
+set JOINER_PSK "J01NME"
+
+proc setup_two_nodes {{childmode "r"} {should_spawn_node true}} {
# Sets up a Thread network with 2 nodes, spawn_1 as the leader and spawn_2
# as a child.
- set psk "J01NME"
if {$should_spawn_node} {
spawn_node 2
- } else {
- switch_node 2
- }
- send "eui64\n"
- expect -re {([0-9a-f]{16})}
- set eui64 $expect_out(1,string)
- expect "Done"
-
- # Sets up a Thread network with node 1 as the leader.
- if {$should_spawn_node} {
spawn_node 1
} else {
switch_node 1
}
setup_leader
+ setup_node 2 $childmode "child"
+}
- send "commissioner start\n"
- expect "Done"
- expect "Commissioner: active"
- send "commissioner joiner add $eui64 $psk\n"
- expect "Done"
+proc setup_node {node {mode "r"} {role "child"}} {
+ switch_node $node
+ send "eui64\n"
+ expect "eui64"
+ expect -re {([0-9a-f]{16})}
+ set eui64 $expect_out(1,string)
+ expect_line "Done"
+
+ switch_node 1
+ send "commissioner state\n"
+ expect {
+ "disabled" {
+ expect_line "Done"
+ send "commissioner start\n"
+ expect_line "Done"
+ expect "Commissioner: active"
+ }
+ "active" {
+ expect_line "Done"
+ }
+ }
+ send "commissioner joiner add $eui64 $::JOINER_PSK\n"
+ expect_line "Done"
wait_for "netdata steeringdata check $eui64" "Done"
- send "channel\n"
- expect -re {(\d+)}
- set channel $expect_out(1,string)
- expect "Done"
- switch_node 2
- send "mode $childmode\n"
- expect "Done"
+ switch_node $node
+ send "mode $mode\n"
+ expect_line "Done"
send "ifconfig up\n"
- expect "Done"
- send "joiner start $psk\n"
- expect "Done"
- wait_for "" "Join success"
+ expect_line "Done"
+ send "joiner start $::JOINER_PSK\n"
+ expect_line "Done"
+ wait_for "" "Join success" "Join failed"
send "thread start\n"
- expect "Done"
- wait_for "state" "child"
- expect "Done"
+ expect_line "Done"
+ wait_for "state" $role
+ expect_line "Done"
+
+ switch_node 1
+ send "commissioner joiner remove $eui64\n"
+ expect_line "Done"
}
diff --git a/tests/scripts/expect/cli-big-table.exp b/tests/scripts/expect/cli-big-table.exp
index e8ae9b9..a1fd28e 100755
--- a/tests/scripts/expect/cli-big-table.exp
+++ b/tests/scripts/expect/cli-big-table.exp
@@ -28,34 +28,19 @@
#
source "tests/scripts/expect/_common.exp"
+source "tests/scripts/expect/_multinode.exp"
set max_node 15
spawn_node 1
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "leader"
-expect "Done"
+setup_leader
for {set i 2} {$i <= $max_node} {incr i} {
spawn_node $i
- send "mode r\n"
- expect "Done"
- send "panid 0xface\n"
- expect "Done"
- send "ifconfig up\n"
- expect "Done"
- send "thread start\n"
- expect "Done"
- wait_for "state" "child"
- expect "Done"
+ setup_node $i
}
set spawn_id $spawn_ids(1)
send "child table\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-channel.exp b/tests/scripts/expect/cli-channel.exp
index e6ef4ef..238bac9 100755
--- a/tests/scripts/expect/cli-channel.exp
+++ b/tests/scripts/expect/cli-channel.exp
@@ -32,17 +32,17 @@
spawn_node 1
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
send "channel monitor stop\n"
-expect "Done"
+expect_line "Done"
send "channel monitor\n"
expect "enabled: 0"
-expect "Done"
+expect_line "Done"
send "channel monitor start\n"
-expect "Done"
+expect_line "Done"
send "channel monitor\n"
expect "enabled: 1"
expect -re {interval: \d+}
@@ -53,28 +53,28 @@
for {set i 11} {$i <= 26} {incr i} {
expect -re "ch $i \\(0x\[0-9a-f\]{4}\\) +\\d+\\.\\d+% busy"
}
-expect "Done"
+expect_line "Done"
send "channel monitor something_invalid\n"
expect "Error 7: InvalidArgs"
send "channel manager change 15\n"
-expect "Done"
+expect_line "Done"
send "channel manager\n"
expect "channel: 15"
expect "auto: 0"
-expect "Done"
+expect_line "Done"
send "channel manager select 1\n"
expect "Error 13: InvalidState" # Because of insufficient channel monitor samples
send "channel manager delay 200\n"
-expect "Done"
+expect_line "Done"
send "channel manager interval 20000\n"
-expect "Done"
+expect_line "Done"
send "channel manager supported 0x7fff800\n"
-expect "Done"
+expect_line "Done"
send "channel manager favored 0x7fff800\n"
-expect "Done"
+expect_line "Done"
send "channel manager auto 1\n"
-expect "Done"
+expect_line "Done"
send "channel manager\n"
expect "channel: 15"
expect "auto: 1"
@@ -82,7 +82,7 @@
expect "interval: 20000"
expect "supported: { 11-26}"
expect "favored: { 11-26}"
-expect "Done"
+expect_line "Done"
send "channel manager something_invalid\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/cli-child-supervision.exp b/tests/scripts/expect/cli-child-supervision.exp
index 1c8bf7f..6c8f1c1 100755
--- a/tests/scripts/expect/cli-child-supervision.exp
+++ b/tests/scripts/expect/cli-child-supervision.exp
@@ -34,14 +34,14 @@
switch_node 1
send "childsupervision interval 30\n"
-expect "Done"
+expect_line "Done"
send "childsupervision interval\n"
-expect "Done"
+expect_line "Done"
switch_node 2
send "childsupervision checktimeout 30\n"
-expect "Done"
+expect_line "Done"
send "childsupervision checktimeout\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-child.exp b/tests/scripts/expect/cli-child.exp
index 9ac2a5c..1e73099 100755
--- a/tests/scripts/expect/cli-child.exp
+++ b/tests/scripts/expect/cli-child.exp
@@ -33,16 +33,8 @@
setup_two_nodes
switch_node 2
-send "extaddr\n"
-expect "extaddr"
-expect -re {([0-9a-f]{16})}
-set extaddr $expect_out(1,string)
-expect "Done"
-send "rloc16\n"
-expect "rloc16"
-expect -re {([0-9a-f]{4})}
-set rloc $expect_out(1,string)
-expect "Done"
+set extaddr [get_extaddr]
+set rloc [get_rloc16]
switch_node 1
send "child table\n"
@@ -50,13 +42,13 @@
expect "+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+------------------+"
expect -re "\\| +(\\d+) \\| 0x$rloc \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| +\\d+ \\|\\d\\|\\d\\|\\d\\| *\\d+\\| \\d \\| +\\d+ \\| $extaddr \\|"
set child_id $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "child list\n"
expect "child list"
expect $child_id
-expect "Done"
+expect_line "Done"
send "child $child_id\n"
expect "Ext Addr: $extaddr"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-childip.exp b/tests/scripts/expect/cli-childip.exp
index 9a6d06a..294324d 100755
--- a/tests/scripts/expect/cli-childip.exp
+++ b/tests/scripts/expect/cli-childip.exp
@@ -33,26 +33,18 @@
setup_two_nodes
switch_node 2
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
-send "rloc16\n"
-expect "rloc16"
-expect -re {([0-9a-f]{4})}
-set rloc $expect_out(1,string)
-expect "Done"
+set addr [get_ipaddr mleid]
+set rloc [get_rloc16]
switch_node 1
send "childip\n"
expect "$rloc: $addr"
-expect "Done"
+expect_line "Done"
send "childip max 2\n"
-expect "Done"
+expect_line "Done"
send "childip max\n"
expect "2"
-expect "Done"
+expect_line "Done"
send "childip max something_invalid\n"
expect "Error 7: InvalidArgs"
send "childip something_invalid\n"
diff --git a/tests/scripts/expect/cli-coap.exp b/tests/scripts/expect/cli-coap.exp
index 871da39..f7bb654 100755
--- a/tests/scripts/expect/cli-coap.exp
+++ b/tests/scripts/expect/cli-coap.exp
@@ -34,47 +34,39 @@
switch_node 1
send "coap start\n"
-expect "Done"
+expect_line "Done"
send "coap resource test/resource\n"
-expect "Done"
+expect_line "Done"
send "coap set Testing123\n"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_1 $expect_out(1,string)
-expect "Done"
+expect_line "Done"
+set addr_1 [get_ipaddr mleid]
switch_node 2
send "coap start\n"
-expect "Done"
+expect_line "Done"
send "coap parameters request 3000 4 3 5\n"
expect "Transmission parameters for request:"
expect "ACK_TIMEOUT=3000 ms, ACK_RANDOM_FACTOR=4/3, MAX_RETRANSMIT=5"
-expect "Done"
+expect_line "Done"
send "coap parameters response 2500 4 3 3\n"
expect "Transmission parameters for response:"
expect "ACK_TIMEOUT=2500 ms, ACK_RANDOM_FACTOR=4/3, MAX_RETRANSMIT=3"
-expect "Done"
+expect_line "Done"
send "coap get $addr_1 test/resource\n"
-expect "Done"
+expect_line "Done"
expect "coap response from $addr_1 with payload: 54657374696e67313233" # ASCII of "Testing123"
send "coap post $addr_1 test/resource con Testing123\n"
-expect "Done"
+expect_line "Done"
expect "coap response from $addr_1"
send "coap put $addr_1 test/resource con Testing123\n"
-expect "Done"
+expect_line "Done"
expect "coap response from $addr_1"
send "coap delete $addr_1 test/resource con\n"
-expect "Done"
+expect_line "Done"
expect "coap response from $addr_1"
send "coap post $addr_1 test/resource none Testing123\n"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_2 $expect_out(1,string)
-expect "Done"
+expect_line "Done"
+set addr_2 [get_ipaddr mleid]
switch_node 1
expect "coap request from $addr_2 GET"
@@ -88,20 +80,20 @@
expect "coap request from $addr_2 POST with payload: 54657374696e67313233"
send "coap resource\n"
expect "test/resource"
-expect "Done"
+expect_line "Done"
send "coap set\n"
expect "Testing123"
-expect "Done"
+expect_line "Done"
send "coap parameters request default\n"
expect "Transmission parameters for request:"
expect "default"
-expect "Done"
+expect_line "Done"
send "coap parameters response default\n"
expect "Transmission parameters for response:"
expect "default"
-expect "Done"
+expect_line "Done"
send "coap help\n"
-expect "Done"
+expect_line "Done"
send "coap parameters something_invalid\n"
expect "Error 7: InvalidArgs"
send "coap get\n"
diff --git a/tests/scripts/expect/cli-coaps.exp b/tests/scripts/expect/cli-coaps.exp
index e2ee895..6a95212 100755
--- a/tests/scripts/expect/cli-coaps.exp
+++ b/tests/scripts/expect/cli-coaps.exp
@@ -34,49 +34,42 @@
switch_node 1
send "coaps x509\n"
-expect "Done"
+expect_line "Done"
send "coaps start\n"
-expect "Done"
+expect_line "Done"
send "coaps resource test/resource\n"
-expect "Done"
+expect_line "Done"
send "coaps set Testing123\n"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_1 $expect_out(1,string)
-expect "Done"
+expect_line "Done"
+
+set addr_1 [get_ipaddr mleid]
switch_node 2
send "coaps x509\n"
-expect "Done"
+expect_line "Done"
send "coaps start\n"
-expect "Done"
+expect_line "Done"
send "coaps connect $addr_1 5684\n"
-expect "Done"
+expect_line "Done"
expect "coaps connected"
send "coaps get $addr_1 test/resource\n"
-expect "Done"
+expect_line "Done"
expect "coaps response from $addr_1 with payload: 54657374696e67313233" # ASCII of "Testing123"
send "coaps post $addr_1 test/resource con Testing123\n"
-expect "Done"
+expect_line "Done"
expect "coaps response from $addr_1"
send "coaps put $addr_1 test/resource con Testing123\n"
-expect "Done"
+expect_line "Done"
expect "coaps response from $addr_1"
send "coaps delete $addr_1 test/resource con\n"
-expect "Done"
+expect_line "Done"
expect "coaps response from $addr_1"
send "coaps post $addr_1 test/resource none Testing123\n"
-expect "Done"
+expect_line "Done"
send "coaps get $addr_1 default\n"
-expect "Done"
+expect_line "Done"
expect "coaps response from $addr_1"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_2 $expect_out(1,string)
-expect "Done"
+set addr_2 [get_ipaddr mleid]
switch_node 1
expect "coaps request from $addr_2 GET"
@@ -90,12 +83,12 @@
expect "coaps request from $addr_2 POST with payload: 54657374696e67313233"
send "coaps resource\n"
expect "test/resource"
-expect "Done"
+expect_line "Done"
send "coaps set\n"
expect "Testing123"
-expect "Done"
+expect_line "Done"
send "coaps help\n"
-expect "Done"
+expect_line "Done"
send "coaps get\n"
expect "Error 7: InvalidArgs"
send "coaps\n"
@@ -107,10 +100,10 @@
switch_node 2
send "coaps stop\n"
-expect "Done"
+expect_line "Done"
switch_node 1
send "coaps stop\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-coex.exp b/tests/scripts/expect/cli-coex.exp
index ca26b37..9bfbfb6 100755
--- a/tests/scripts/expect/cli-coex.exp
+++ b/tests/scripts/expect/cli-coex.exp
@@ -32,15 +32,15 @@
spawn_node 1
send "coex disable\n"
-expect "Done"
+expect_line "Done"
send "coex\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "coex enable\n"
-expect "Done"
+expect_line "Done"
send "coex\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "coex metrics\n"
expect -re {Stopped: (true|false)}
expect -re {Grant Glitch: \d+}
@@ -63,7 +63,7 @@
expect -re { Delayed Grant: \d+}
expect -re { Average Request To Grant Time: \d+}
expect -re { Grant None: \d+}
-expect "Done"
+expect_line "Done"
send "coex something_invalid\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/cli-commissioner.exp b/tests/scripts/expect/cli-commissioner.exp
index f4b4e16..1474d2f 100755
--- a/tests/scripts/expect/cli-commissioner.exp
+++ b/tests/scripts/expect/cli-commissioner.exp
@@ -35,46 +35,46 @@
set eui64 "d45e64fa83f81cf7"
switch_node 1
send "commissioner joiner add $eui64 J01NME\n"
-expect "Done"
+expect_line "Done"
wait_for "netdata steeringdata check $eui64" "Done"
send "commissioner joiner remove $eui64\n"
-expect "Done"
+expect_line "Done"
wait_for "netdata steeringdata check $eui64" "NotFound"
switch_node 2
send "commissioner state\n"
expect "disabled"
-expect "Done"
+expect_line "Done"
send "commissioner start\n"
-expect "Done"
+expect_line "Done"
expect "Commissioner: active"
send "commissioner state\n"
expect "active"
-expect "Done"
+expect_line "Done"
send "commissioner provisioningurl openthread.io\n"
-expect "Done"
+expect_line "Done"
send "commissioner joiner add * J01NME 1\n"
-expect "Done"
+expect_line "Done"
send "commissioner joiner remove *\n"
-expect "Done"
+expect_line "Done"
send "commissioner sessionid\n"
expect "commissioner sessionid"
expect -re {(\d+)}
set sessionid $expect_out(1,string)
send "commissioner mgmtset sessionid $sessionid steeringdata ffffffff joinerudpport 10001\n"
-expect "Done"
+expect_line "Done"
send "commissioner mgmtset sessionid $sessionid locator 0x0100\n"
-expect "Done"
+expect_line "Done"
send "commissioner mgmtget sessionid steeringdata joinerudpport locator binary 0b081209\n"
-expect "Done"
+expect_line "Done"
send "commissioner stop\n"
expect "Commissioner: disabled"
-expect "Done"
+expect_line "Done"
send "commissioner state\n"
expect "disabled"
-expect "Done"
+expect_line "Done"
send "commissioner help\n"
-expect "Done"
+expect_line "Done"
send "commissioner joiner something_invalid\n"
expect "Error 7: InvalidArgs"
send "commissioner mgmtget something_invalid\n"
diff --git a/tests/scripts/expect/cli-counters.exp b/tests/scripts/expect/cli-counters.exp
index eda2de1..359d3b4 100755
--- a/tests/scripts/expect/cli-counters.exp
+++ b/tests/scripts/expect/cli-counters.exp
@@ -34,15 +34,15 @@
send "counters\n"
expect "mac"
expect "mle"
-expect "Done"
+expect_line "Done"
send "counters mac\n"
-expect "Done"
+expect_line "Done"
send "counters mle\n"
-expect "Done"
+expect_line "Done"
send "counters mac reset\n"
-expect "Done"
+expect_line "Done"
send "counters mle reset\n"
-expect "Done"
+expect_line "Done"
send "counters mac 1\n"
expect "Error 7: InvalidArgs"
send "counters mle 1\n"
diff --git a/tests/scripts/expect/cli-dataset.exp b/tests/scripts/expect/cli-dataset.exp
index 259f9cf..5af33eb 100755
--- a/tests/scripts/expect/cli-dataset.exp
+++ b/tests/scripts/expect/cli-dataset.exp
@@ -48,77 +48,77 @@
send "dataset pending\n"
expect "Error 23: NotFound"
send "dataset init active\n"
-expect "Done"
+expect_line "Done"
send "dataset activetimestamp 100\n"
-expect "Done"
+expect_line "Done"
send "dataset activetimestamp\n"
expect "100"
-expect "Done"
+expect_line "Done"
if {$channel == 11} {
send "dataset channel 18\n"
- expect "Done"
+ expect_line "Done"
send "dataset channel\n"
expect "18"
- expect "Done"
+ expect_line "Done"
} else {
send "dataset channel 11\n"
- expect "Done"
+ expect_line "Done"
send "dataset channel\n"
expect "11"
- expect "Done"
+ expect_line "Done"
}
send "dataset channelmask 0x03fff800\n"
-expect "Done"
+expect_line "Done"
send "dataset channelmask\n"
expect "0x03fff800"
-expect "Done"
+expect_line "Done"
send "dataset extpanid aabbccddeeff0011\n"
-expect "Done"
+expect_line "Done"
send "dataset extpanid\n"
expect "aabbccddeeff0011"
-expect "Done"
+expect_line "Done"
send "dataset masterkey aabbccddeeff00112233445566778899\n"
-expect "Done"
+expect_line "Done"
send "dataset masterkey\n"
expect "aabbccddeeff00112233445566778899"
-expect "Done"
+expect_line "Done"
send "dataset meshlocalprefix fdde:4860::\n"
-expect "Done"
+expect_line "Done"
send "dataset meshlocalprefix\n"
expect "fdde:4860:0:0::/64"
-expect "Done"
+expect_line "Done"
send "dataset networkname OT-network\n"
-expect "Done"
+expect_line "Done"
send "dataset networkname\n"
expect "OT-network"
-expect "Done"
+expect_line "Done"
send "dataset panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "dataset panid\n"
expect "0xface"
-expect "Done"
+expect_line "Done"
send "dataset pskc 00112233445566778899aabbccddeeff\n"
-expect "Done"
+expect_line "Done"
send "dataset pskc\n"
expect "00112233445566778899aabbccddeeff"
-expect "Done"
+expect_line "Done"
send "dataset securitypolicy 678 onrcb\n"
-expect "Done"
+expect_line "Done"
send "dataset securitypolicy\n"
expect "678 onrcb"
-expect "Done"
+expect_line "Done"
send "dataset pendingtimestamp 100\n"
-expect "Done"
+expect_line "Done"
send "dataset pendingtimestamp\n"
expect "100"
-expect "Done"
+expect_line "Done"
send "dataset delay 30000\n"
-expect "Done"
+expect_line "Done"
send "dataset delay\n"
expect "30000"
-expect "Done"
+expect_line "Done"
send "dataset commit pending\n"
-expect "Done"
+expect_line "Done"
send "dataset pending\n"
expect "Pending Timestamp: 100"
expect "Active Timestamp: 100"
@@ -136,13 +136,13 @@
expect "PAN ID: 0xface"
expect "PSKc: 00112233445566778899aabbccddeeff"
expect "Security Policy: 678, onrcb"
-expect "Done"
+expect_line "Done"
sleep 30
switch_node 2
wait_for "dataset active" "Active Timestamp: 100"
-expect "Done"
+expect_line "Done"
send "dataset active\n"
expect "Active Timestamp: 100"
if {$channel == 11} {
@@ -158,11 +158,11 @@
expect "PAN ID: 0xface"
expect "PSKc: 00112233445566778899aabbccddeeff"
expect "Security Policy: 678, onrcb"
-expect "Done"
+expect_line "Done"
send "dataset clear\n"
-expect "Done"
+expect_line "Done"
send "dataset init active\n"
-expect "Done"
+expect_line "Done"
send "dataset\n"
expect "Active Timestamp: 100"
if {$channel == 11} {
@@ -178,16 +178,12 @@
expect "PAN ID: 0xface"
expect "PSKc: 00112233445566778899aabbccddeeff"
expect "Security Policy: 678, onrcb"
-expect "Done"
+expect_line "Done"
send "dataset init pending\n"
expect "Error 23: NotFound"
switch_node 1
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
+set addr [get_ipaddr mleid]
switch_node 2
send "dataset mgmtgetcommand active \
@@ -195,60 +191,60 @@
localprefix delaytimer panid channel \
-x 000102030405060708090a0b0e0f0c333435 \
address $addr\n"
-expect "Done"
+expect_line "Done"
send "dataset mgmtgetcommand pending \
activetimestamp pendingtimestamp masterkey networkname extpanid \
localprefix delaytimer panid channel \
-x 000102030405060708090a0b0e0f0c333435 \
address $addr\n"
-expect "Done"
+expect_line "Done"
switch_node 1
send "dataset init active\n"
-expect "Done"
+expect_line "Done"
send "dataset networkname Thread\\ 网络\n"
-expect "Done"
+expect_line "Done"
send "dataset commit active\n"
-expect "Done"
+expect_line "Done"
send "dataset active -x\n"
expect "54687265616420e7bd91e7bb9c" ;# UTF-8 of "Thread 网络"
-expect "Done"
+expect_line "Done"
send "dataset active -x\n"
expect "dataset active -x"
expect -re {([0-9a-f]+)[\r\n]+Done}
set binary $expect_out(1,string)
send "dataset set pending $binary\n"
-expect "Done"
+expect_line "Done"
send "dataset pending -x\n"
expect $binary
-expect "Done"
+expect_line "Done"
send "dataset pending\n"
expect "Network Name: Thread 网络"
-expect "Done"
+expect_line "Done"
send "dataset set active $binary\n"
-expect "Done"
+expect_line "Done"
send "dataset mgmtsetcommand active activetimestamp 200 -x 030d54687265616420e7bd91e7bb9c\n"
-expect "Done"
+expect_line "Done"
send "dataset active\n"
expect "Network Name: Thread 网络"
-expect "Done"
+expect_line "Done"
send "dataset mgmtsetcommand active activetimestamp 210 -x 0301ff\n"
-expect "Done"
+expect_line "Done"
send "dataset active\n"
expect "Active Timestamp: 200"
expect "Network Name: Thread 网络"
-expect "Done"
+expect_line "Done"
send "dataset set active 03023432\n"
-expect "Done"
+expect_line "Done"
send "dataset active\n"
expect "Network Name: 42"
-expect "Done"
+expect_line "Done"
send "dataset set active 0301bf\n"
expect "Error 7: InvalidArgs"
send "dataset help\n"
-expect "Done"
+expect_line "Done"
send "dataset\n"
-expect "Done"
+expect_line "Done"
send "dataset init something_invalid\n"
expect "Error 7: InvalidArgs"
send "dataset active something_invalid\n"
@@ -266,7 +262,7 @@
send "dataset mgmtgetcommand active something_invalid\n"
expect "Error 7: InvalidArgs"
send "dataset pskc -p 123456\n"
-expect "Done"
+expect_line "Done"
send "dataset securitypolicy 678 something_invalid\n"
expect "Error 7: InvalidArgs"
send "dataset set something_invalid 00\n"
diff --git a/tests/scripts/expect/cli-discerner.exp b/tests/scripts/expect/cli-discerner.exp
index 64f422b..07a9e41 100755
--- a/tests/scripts/expect/cli-discerner.exp
+++ b/tests/scripts/expect/cli-discerner.exp
@@ -44,27 +44,27 @@
send "netdata steeringdata check $discerner\n"
expect "InvalidState"
send "commissioner start\n"
-expect "Done"
+expect_line "Done"
expect "Commissioner: active"
send "commissioner joiner add 1/0 $pskd\n"
expect "InvalidArgs"
send "netdata steeringdata check 0xabc/12\n"
expect "NotFound"
send "commissioner joiner add $discerner $pskd\n"
-expect "Done"
+expect_line "Done"
wait_for "netdata steeringdata check $discerner" "Done"
send "commissioner joiner remove $discerner\n"
-expect "Done"
+expect_line "Done"
wait_for "netdata steeringdata check $discerner" "NotFound"
send "commissioner joiner add $discerner $pskd\n"
-expect "Done"
+expect_line "Done"
spawn_node 2
send "mode r\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "joiner discerner\n"
expect "NotFound"
send "joiner discerner 1/1 2\n"
@@ -82,18 +82,18 @@
send "joiner discerner invalid/20\n"
expect "InvalidArgs"
send "joiner discerner clear\n"
-expect "Done"
+expect_line "Done"
send "joiner discerner $discerner\n"
-expect "Done"
+expect_line "Done"
send "joiner discerner\n"
expect "$discerner"
-expect "Done"
+expect_line "Done"
send "joiner start $pskd\n"
-expect "Done"
+expect_line "Done"
wait_for "" "Join success" "Join failed"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "child"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-extaddr.exp b/tests/scripts/expect/cli-extaddr.exp
index a4fc42d..ca48271 100755
--- a/tests/scripts/expect/cli-extaddr.exp
+++ b/tests/scripts/expect/cli-extaddr.exp
@@ -32,9 +32,9 @@
spawn_node 1
send "extaddr 99aabbccddeeff00\n"
-expect "Done"
+expect_line "Done"
send "extaddr 99AABBCCDDEEFF00\n"
-expect "Done"
+expect_line "Done"
send "extaddr\n"
expect "99aabbccddeeff00"
send "extaddr 1\n"
diff --git a/tests/scripts/expect/cli-ipmaddr.exp b/tests/scripts/expect/cli-ipmaddr.exp
index 5084ca2..a4e324f 100755
--- a/tests/scripts/expect/cli-ipmaddr.exp
+++ b/tests/scripts/expect/cli-ipmaddr.exp
@@ -34,35 +34,32 @@
switch_node 1
send "ipmaddr add ff0e::1\n"
-expect "Done"
+expect_line "Done"
send "ipmaddr\n"
expect "ff0e:0:0:0:0:0:0:1"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
+expect_line "Done"
+set addr [get_ipaddr mleid]
switch_node 2
send "ping ff0e::1\n"
-expect "Done"
+expect_line "Done"
expect "16 bytes from $addr: icmp_seq=1"
switch_node 1
send "ipmaddr del ff0e::1\n"
-expect "Done"
+expect_line "Done"
send "ipmaddr del ff0e::1\n"
expect "Error 23: NotFound"
send "ipmaddr promiscuous enable\n"
-expect "Done"
+expect_line "Done"
send "ipmaddr promiscuous\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "ipmaddr promiscuous disable\n"
-expect "Done"
+expect_line "Done"
send "ipmaddr promiscuous\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "ipmaddr something_invalid\n"
expect "Error 35: InvalidCommand"
diff --git a/tests/scripts/expect/cli-log-level.exp b/tests/scripts/expect/cli-log-level.exp
index c7685fc..8544d5a 100755
--- a/tests/scripts/expect/cli-log-level.exp
+++ b/tests/scripts/expect/cli-log-level.exp
@@ -33,12 +33,12 @@
send "log level\n"
expect -re {\d}
-expect "Done"
+expect_line "Done"
send "log level 5\n"
-expect "Done"
+expect_line "Done"
send "log level\n"
expect "5"
-expect "Done"
+expect_line "Done"
send "log level -1\n"
expect "Error 7: InvalidArgs"
send "log level 6\n"
diff --git a/tests/scripts/expect/cli-mac.exp b/tests/scripts/expect/cli-mac.exp
index 0d6865d..0d30544 100755
--- a/tests/scripts/expect/cli-mac.exp
+++ b/tests/scripts/expect/cli-mac.exp
@@ -32,16 +32,16 @@
spawn_node 1
send "mac retries direct 5\n"
-expect "Done"
+expect_line "Done"
send "mac retries direct\n"
expect "5"
-expect "Done"
+expect_line "Done"
send "mac retries indirect 2\n"
-expect "Done"
+expect_line "Done"
send "mac retries indirect\n"
expect "2"
-expect "Done"
+expect_line "Done"
send "mac\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/cli-macfilter.exp b/tests/scripts/expect/cli-macfilter.exp
index 5892b83..21456b3 100755
--- a/tests/scripts/expect/cli-macfilter.exp
+++ b/tests/scripts/expect/cli-macfilter.exp
@@ -34,108 +34,108 @@
send "macfilter\n"
expect "Address Mode: Disabled"
expect "RssIn List:"
-expect "Done"
+expect_line "Done"
send "macfilter addr add aabbccddeeff0011\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr\n"
expect "Disabled"
expect "aabbccddeeff0011"
-expect "Done"
+expect_line "Done"
send "macfilter addr allowlist\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr\n"
expect "Allowlist"
expect "aabbccddeeff0011"
-expect "Done"
+expect_line "Done"
send "macfilter\n"
expect "Address Mode: Allowlist"
expect "aabbccddeeff0011"
expect "RssIn List:"
-expect "Done"
+expect_line "Done"
send "macfilter addr add 2233445566778899\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr remove aabbccddeeff0011\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr denylist\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr\n"
expect "Denylist"
expect "2233445566778899"
-expect "Done"
+expect_line "Done"
send "macfilter\n"
expect "Address Mode: Denylist"
expect "2233445566778899"
expect "RssIn List:"
-expect "Done"
+expect_line "Done"
send "macfilter addr clear\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr disable\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "macfilter\n"
expect "Address Mode: Disabled"
expect "RssIn List:"
-expect "Done"
+expect_line "Done"
send "macfilter addr something_invalid\n"
expect "Error 35: InvalidCommand"
send "macfilter rss\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss add-lqi * 2\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss add-lqi aabbccddeeff0011 3\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss\n"
expect -re {aabbccddeeff0011 : rss -?\d+ \(lqi 3\)}
expect -re {Default rss: -?\d+ \(lqi 2\)}
-expect "Done"
+expect_line "Done"
send "macfilter\n"
expect "Address Mode: Disabled"
expect "RssIn List:"
expect -re {aabbccddeeff0011 : rss -?\d+ \(lqi 3\)}
expect -re {Default rss : -?\d+ \(lqi 2\)}
-expect "Done"
+expect_line "Done"
send "macfilter rss remove *\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss remove aabbccddeeff0011\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss add 2233445566778899 -70\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss add * -80\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss\n"
expect -re {2233445566778899 : rss -70 \(lqi \d\)}
expect -re {Default rss: -80 \(lqi \d\)}
-expect "Done"
+expect_line "Done"
send "macfilter rss clear\n"
-expect "Done"
+expect_line "Done"
send "macfilter rss something_invalid\n"
expect "Error 35: InvalidCommand"
diff --git a/tests/scripts/expect/cli-misc.exp b/tests/scripts/expect/cli-misc.exp
index 65992bb..98651e8 100755
--- a/tests/scripts/expect/cli-misc.exp
+++ b/tests/scripts/expect/cli-misc.exp
@@ -40,129 +40,129 @@
expect -re {Data Version: \d+}
expect -re {Stable Data Version: \d+}
expect -re {Leader Router ID: \d+}
-expect "Done"
+expect_line "Done"
send "help\n"
-expect "Done"
+expect_line "Done"
send "bufferinfo\n"
-expect "Done"
+expect_line "Done"
send "ccathreshold -62\n"
-expect "Done"
+expect_line "Done"
send "ccathreshold\n"
expect -- "-62 dBm"
-expect "Done"
+expect_line "Done"
send "parent\n"
-expect "Done"
+expect_line "Done"
send "delaytimermin 1\n"
-expect "Done"
+expect_line "Done"
send "delaytimermin\n"
expect "1"
-expect "Done"
+expect_line "Done"
send "delaytimermin 1 2\n"
send "counters mac 1\n"
expect "Error 7: InvalidArgs"
send "fem lnagain 11\n"
-expect "Done"
+expect_line "Done"
send "fem lnagain\n"
expect -- "11"
-expect "Done"
+expect_line "Done"
send "fem\n"
expect -- "LNA gain 11 dBm"
-expect "Done"
+expect_line "Done"
send "ifconfig down\n"
-expect "Done"
+expect_line "Done"
send "ifconfig\n"
expect "down"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "ifconfig\n"
expect "up"
-expect "Done"
+expect_line "Done"
send "ipaddr add ::\n"
-expect "Done"
+expect_line "Done"
send "ipaddr del ::\n"
-expect "Done"
+expect_line "Done"
send "leaderweight 1\n"
-expect "Done"
+expect_line "Done"
send "leaderweight\n"
expect "1"
-expect "Done"
+expect_line "Done"
send "mode rdn\n"
-expect "Done"
+expect_line "Done"
send "mode\n"
expect -re "(?=.*r)(?=.*d)(?=.*n)"
send "parent\n"
-expect "Done"
+expect_line "Done"
send "singleton\n"
expect -re "true|false"
-expect "Done"
+expect_line "Done"
send "state\n"
expect "disabled"
-expect "Done"
+expect_line "Done"
send "txpower -10\n"
-expect "Done"
+expect_line "Done"
send "txpower\n"
expect -- "-10 dBm"
-expect "Done"
+expect_line "Done"
send "thread version\n"
-expect "Done"
+expect_line "Done"
send "version\n"
-expect "Done"
+expect_line "Done"
send "version api\n"
expect -re {\d+}
-expect "Done"
+expect_line "Done"
send "version something_invalid\n"
expect "Error 35: InvalidCommand"
send "joinerport 10001\n"
-expect "Done"
+expect_line "Done"
send "joinerport\n"
expect "10001"
-expect "Done"
+expect_line "Done"
send "parentpriority 1\n"
-expect "Done"
+expect_line "Done"
send "parentpriority\n"
expect "1"
-expect "Done"
+expect_line "Done"
send "pollperiod 100000\n"
-expect "Done"
+expect_line "Done"
send "pollperiod\n"
expect "100000"
-expect "Done"
+expect_line "Done"
send "prefix add ::/64 low pdcrosn\n"
-expect "Done"
+expect_line "Done"
send "prefix\n"
expect "0:0:0:0::/64 pdcrosn low"
-expect "Done"
+expect_line "Done"
send "preferrouterid 1\n"
-expect "Done"
+expect_line "Done"
send "route add ::/64 s low\n"
-expect "Done"
+expect_line "Done"
send "route\n"
expect "0:0:0:0::/64 s low"
send "route remove ::/64\n"
-expect "Done"
+expect_line "Done"
send "diag start\n"
expect ": InvalidState"
diff --git a/tests/scripts/expect/cli-multicast-loop.exp b/tests/scripts/expect/cli-multicast-loop.exp
index 48b91f3..ef6c8b6 100755
--- a/tests/scripts/expect/cli-multicast-loop.exp
+++ b/tests/scripts/expect/cli-multicast-loop.exp
@@ -37,61 +37,64 @@
source "tests/scripts/expect/_common.exp"
spawn_node 1
+setup_default_network
set timeout 1
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
set extaddr1 [get_extaddr]
get_rloc16
spawn_node 2 cli
+setup_default_network
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "router"
-expect "Done"
+expect_line "Done"
sleep 3
get_rloc16
spawn_node 3 cli
+setup_default_network
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr add ${extaddr1}\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr denylist\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "router"
-expect "Done"
+expect_line "Done"
sleep 4
set extaddr3 [get_extaddr]
@@ -99,27 +102,28 @@
get_rloc16
spawn_node 4 cli
+setup_default_network
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "mode rn\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr add ${extaddr3}\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr allowlist\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "child"
-expect "Done"
+expect_line "Done"
get_rloc16
@@ -129,7 +133,7 @@
send "networkdiagnostic get ff03::2 5 16\n"
expect "DIAG_GET.rsp/ans from $rloc(1)"
-expect "Done"
+expect_line "Done"
sleep 5
diff --git a/tests/scripts/expect/cli-neighbor.exp b/tests/scripts/expect/cli-neighbor.exp
index 4af05a2..9f5dd9e 100755
--- a/tests/scripts/expect/cli-neighbor.exp
+++ b/tests/scripts/expect/cli-neighbor.exp
@@ -33,26 +33,18 @@
setup_two_nodes
switch_node 2
-send "rloc16\n"
-expect "rloc16"
-expect -re {([0-9a-f]{4})}
-set rloc $expect_out(1,string)
-expect "Done"
-send "extaddr\n"
-expect "extaddr"
-expect -re {([0-9a-f]{16})}
-set extaddr $expect_out(1,string)
-expect "Done"
+set rloc [get_rloc16]
+set extaddr [get_extaddr]
switch_node 1
send "neighbor table\n"
expect "| Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|D|N| Extended MAC |"
expect "+------+--------+-----+----------+-----------+-+-+-+------------------+"
expect -re "\\| +C +\\| 0x$rloc \\| +\\d+ \\| +-?\\d+ \\| +-?\\d+ \\|1\\|0\\|0\\| $extaddr \\|"
-expect "Done"
+expect_line "Done"
send "neighbor list\n"
expect "0x$rloc"
-expect "Done"
+expect_line "Done"
send "neighbor something_invalid\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/cli-netdata.exp b/tests/scripts/expect/cli-netdata.exp
index faf6537..ff2d62c 100755
--- a/tests/scripts/expect/cli-netdata.exp
+++ b/tests/scripts/expect/cli-netdata.exp
@@ -35,15 +35,15 @@
switch_node 1
send "netdata help\n"
-expect "Done"
+expect_line "Done"
send "netdata register\n"
-expect "Done"
+expect_line "Done"
send "netdata show\n"
-expect "Done"
+expect_line "Done"
send "netdata show -x\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-networkname.exp b/tests/scripts/expect/cli-networkname.exp
index 2b0ce3e..20c09c6 100755
--- a/tests/scripts/expect/cli-networkname.exp
+++ b/tests/scripts/expect/cli-networkname.exp
@@ -34,47 +34,47 @@
switch_node 1
send "networkname Thread\\ Network\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
switch_node 2
send "scan\n"
expect "Thread Network"
-expect "Done"
+expect_line "Done"
switch_node 1
send "thread stop\n"
-expect "Done"
+expect_line "Done"
send "networkname Thread\\ 网络\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
switch_node 2
send "scan\n"
expect "Thread 网络"
-expect "Done"
+expect_line "Done"
switch_node 1
send "thread stop\n"
-expect "Done"
+expect_line "Done"
send "networkname スレッド\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
switch_node 2
send "scan\n"
expect "スレッド"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-partitionid.exp b/tests/scripts/expect/cli-partitionid.exp
old mode 100644
new mode 100755
index e2e0b60..18a5efa
--- a/tests/scripts/expect/cli-partitionid.exp
+++ b/tests/scripts/expect/cli-partitionid.exp
@@ -32,14 +32,14 @@
spawn_node 1
send "partitionid preferred 12345678\n"
-expect "Done"
+expect_line "Done"
send "partitionid preferred\n"
expect "12345678"
-expect "Done"
+expect_line "Done"
send "partitionid invalid\n"
expect "Error 35: InvalidCommand"
send "partitionid\n"
expect "0"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-ping.exp b/tests/scripts/expect/cli-ping.exp
index 1e615ff..db24d47 100755
--- a/tests/scripts/expect/cli-ping.exp
+++ b/tests/scripts/expect/cli-ping.exp
@@ -34,13 +34,13 @@
spawn_node 1
send "ping ::1 1 2 1 1\n"
-expect "Done"
+expect_line "Done"
send "ping stop\n"
-expect "Done"
+expect_line "Done"
send "ping ::1 1 2 0.12345 1\n"
-expect "Done"
+expect_line "Done"
send "ping stop\n"
-expect "Done"
+expect_line "Done"
send "ping ::1 1 2 1 1 1\n"
expect "Error 7: InvalidArgs"
@@ -50,11 +50,7 @@
setup_two_nodes
switch_node 2
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
+set addr [get_ipaddr mleid]
switch_node 1
send "ping $addr\n"
diff --git a/tests/scripts/expect/cli-promiscuous.exp b/tests/scripts/expect/cli-promiscuous.exp
index c2fcf78..61acf49 100755
--- a/tests/scripts/expect/cli-promiscuous.exp
+++ b/tests/scripts/expect/cli-promiscuous.exp
@@ -35,14 +35,14 @@
send "promiscuous\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "promiscuous enable\n"
-expect "Done"
+expect_line "Done"
send "promiscuous\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "promiscuous disable\n"
-expect "Done"
+expect_line "Done"
send "promiscuous a\n"
expect "Error 7: InvalidArgs"
@@ -56,19 +56,19 @@
expect "channel"
expect -re {(\d+)}
set channel $expect_out(1,string)
-expect "Done"
+expect_line "Done"
spawn_node 3
send "channel $channel\n"
-expect "Done"
+expect_line "Done"
send "promiscuous enable\n"
-expect "Done"
+expect_line "Done"
switch_node 2
send "ipaddr\n"
expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
set addr $expect_out(1,string)
-expect "Done"
+expect_line "Done"
switch_node 1
send "ping $addr\n"
@@ -79,6 +79,6 @@
expect -re {\|( ([0-9A-Z]{2}|\.\.)){16}\|( .){16}\|}
expect -- "-----------------------------------------------------------------------------------"
send "promiscuous disable\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-pskc.exp b/tests/scripts/expect/cli-pskc.exp
index 1d211fd..f4de844 100755
--- a/tests/scripts/expect/cli-pskc.exp
+++ b/tests/scripts/expect/cli-pskc.exp
@@ -32,21 +32,21 @@
spawn_node 1
send "pskc 00112233445566778899aabbccddeeff\n"
-expect "Done"
+expect_line "Done"
send "pskc\n"
expect "00112233445566778899aabbccddeeff"
-expect "Done"
+expect_line "Done"
send "factoryreset\n"
sleep 0.1
send "networkname Test\\ Network\n"
-expect "Done"
+expect_line "Done"
send "extpanid 0001020304050607\n"
-expect "Done"
+expect_line "Done"
send "pskc -p 12SECRETPASSWORD34\n"
-expect "Done"
+expect_line "Done"
send "pskc\n"
expect "c3f59368445a1b6106be420a706d4cc9"
-expect "Done"
+expect_line "Done"
send "factoryreset\n"
sleep 0.1
send "pskc -x\n"
diff --git a/tests/scripts/expect/cli-anycast.exp b/tests/scripts/expect/cli-region.exp
old mode 100644
new mode 100755
similarity index 80%
rename from tests/scripts/expect/cli-anycast.exp
rename to tests/scripts/expect/cli-region.exp
index 3081a6b..3c75c40
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/tests/scripts/expect/cli-region.exp
@@ -29,28 +29,12 @@
source "tests/scripts/expect/_common.exp"
+spawn_node 1
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+send "region\n"
+expect_line "Done"
+send "region US\n"
+expect_line "Done"
+send "region\n"
+expect "US"
+expect_line "Done"
diff --git a/tests/scripts/expect/cli-reset.exp b/tests/scripts/expect/cli-reset.exp
index d432d33..dc29441 100755
--- a/tests/scripts/expect/cli-reset.exp
+++ b/tests/scripts/expect/cli-reset.exp
@@ -32,11 +32,11 @@
spawn_node 1
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "panid 0xabcd\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
sleep 3
@@ -45,24 +45,24 @@
send "ifconfig\n"
expect "down"
-expect "Done"
+expect_line "Done"
send "panid\n"
expect "0xabcd"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
send "factoryreset\n"
sleep 3
send "ifconfig\n"
expect "down"
-expect "Done"
+expect_line "Done"
send "panid\n"
expect "0xffff"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-router.exp b/tests/scripts/expect/cli-router.exp
index 028476d..b7f1a56 100755
--- a/tests/scripts/expect/cli-router.exp
+++ b/tests/scripts/expect/cli-router.exp
@@ -33,37 +33,33 @@
setup_two_nodes
switch_node 1
-send "extaddr\n"
-expect "extaddr"
-expect -re {([0-9a-f]{16})}
-set extaddr $expect_out(1,string)
-expect "Done"
+set extaddr [get_extaddr]
send "router list\n"
expect "router list"
expect -re {(\d+)}
set router_id $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "router $router_id\n"
expect -re {Rloc: ([0-9a-f]{4})}
set rloc $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "router table\n"
expect "| ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC |"
expect "+----+--------+----------+-----------+-------+--------+-----+------------------+"
expect -re "\\| +$router_id \\| 0x$rloc \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| $extaddr \\|"
-expect "Done"
+expect_line "Done"
switch_node 2
send "mode rdn\n"
-expect "Done"
+expect_line "Done"
send "state router\n"
-expect "Done"
+expect_line "Done"
wait_for "router list" $router_id
send "router $router_id\n"
expect "Router ID: $router_id"
expect "Rloc: $rloc"
expect -re {Next Hop: [0-9a-f]{4}}
expect -re {Link: [01]}
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/cli-routereligible.exp b/tests/scripts/expect/cli-routereligible.exp
index f18a3d1..821b127 100755
--- a/tests/scripts/expect/cli-routereligible.exp
+++ b/tests/scripts/expect/cli-routereligible.exp
@@ -32,22 +32,22 @@
spawn_node 1
send "routereligible disable\n"
-expect "Done"
+expect_line "Done"
send "routereligible\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "routereligible enable\n"
-expect "Done"
+expect_line "Done"
send "routereligible\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "routereligible something_invalid\n"
expect "Error 7: InvalidArgs"
send "mode r\n"
-expect "Done"
+expect_line "Done"
send "routereligible\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "routereligible enable\n"
expect "Error 27: NotCapable"
diff --git a/tests/scripts/expect/cli-scan-discover.exp b/tests/scripts/expect/cli-scan-discover.exp
index fd9061e..812b882 100755
--- a/tests/scripts/expect/cli-scan-discover.exp
+++ b/tests/scripts/expect/cli-scan-discover.exp
@@ -35,32 +35,28 @@
spawn_node 3
switch_node 1
-send "extaddr\n"
-expect "extaddr"
-expect -re {([0-9a-f]{16})}
-set extaddr $expect_out(1,string)
-expect "Done"
+set extaddr [get_extaddr]
send "panid\n"
expect "panid"
expect -re {([0-9a-f]{4})}
set pan $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "extpanid\n"
expect "extpanid"
expect -re {([0-9a-f]{16})}
set extpan $expect_out(1,string)
-expect "Done"
+expect_line "Done"
expect "> "
send "networkname\n"
expect "networkname"
expect -re {[\r\n]([^\r\n]+?)[\r\n]}
set network $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "channel\n"
expect "channel"
expect -re {(\d+)}
set channel $expect_out(1,string)
-expect "Done"
+expect_line "Done"
switch_node 3
send "scan $channel\n"
@@ -74,16 +70,16 @@
for {set i 11} {$i <= 26} {incr i} {
expect -re "\\| +$i \\| +-?\\d+ \\|"
}
-expect "Done"
+expect_line "Done"
send "scan energy 100 $channel\n"
expect "| Ch | RSSI |"
expect "+----+------+"
expect -re "\\| +$channel \\| +-?\\d+ \\|"
-expect "Done"
+expect_line "Done"
switch_node 3
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "discover $channel\n"
expect "| J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI |"
expect "+---+------------------+------------------+------+------------------+----+-----+-----+"
diff --git a/tests/scripts/expect/cli-udp.exp b/tests/scripts/expect/cli-udp.exp
index e55b458..2a78f7e 100755
--- a/tests/scripts/expect/cli-udp.exp
+++ b/tests/scripts/expect/cli-udp.exp
@@ -34,31 +34,25 @@
switch_node 2
send "udp open\n"
-expect "Done"
+expect_line "Done"
send "udp bind :: 11001\n"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_2 $expect_out(1,string)
+expect_line "Done"
+set addr_2 [get_ipaddr mleid]
switch_node 1
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr_1 $expect_out(1,string)
+set addr_1 [get_ipaddr mleid]
send "udp open\n"
-expect "Done"
+expect_line "Done"
send "udp bind :: 11002\n"
-expect "Done"
+expect_line "Done"
send "udp connect $addr_2 11001\n"
-expect "Done"
+expect_line "Done"
send "udp send -s 10\n"
-expect "Done"
+expect_line "Done"
send "udp send -x a68656c6c6f\n"
-expect "Done"
+expect_line "Done"
send "udp send -t there\n"
-expect "Done"
+expect_line "Done"
switch_node 2
expect "10 bytes from $addr_1 11002 0123456789"
@@ -68,7 +62,7 @@
switch_node 1
send "udp help\n"
-expect "Done"
+expect_line "Done"
send "udp connect something_invalid\n"
expect "Error 7: InvalidArgs"
send "udp send -x something_invalid\n"
@@ -78,17 +72,17 @@
send "udp linksecurity\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "udp linksecurity disable\n"
-expect "Done"
+expect_line "Done"
send "udp linksecurity\n"
expect "Disabled"
-expect "Done"
+expect_line "Done"
send "udp linksecurity enable\n"
-expect "Done"
+expect_line "Done"
send "udp linksecurity\n"
expect "Enabled"
-expect "Done"
+expect_line "Done"
send "udp linksecurity something_invalid\n"
expect "Error 35: InvalidCommand"
diff --git a/tests/scripts/expect/cli-unsecure-port.exp b/tests/scripts/expect/cli-unsecure-port.exp
index bf99d97..51c36d4 100755
--- a/tests/scripts/expect/cli-unsecure-port.exp
+++ b/tests/scripts/expect/cli-unsecure-port.exp
@@ -32,33 +32,33 @@
spawn_node 1
send "unsecureport remove all\n"
-expect "Done"
+expect_line "Done"
send "unsecureport get\n"
-expect "Done"
+expect_line "Done"
send "unsecureport add 123\n"
-expect "Done"
+expect_line "Done"
send "unsecureport add 456\n"
-expect "Done"
+expect_line "Done"
send "unsecureport get\n"
expect "123 456"
-expect "Done"
+expect_line "Done"
send "unsecureport remove 123\n"
-expect "Done"
+expect_line "Done"
send "unsecureport get\n"
expect "456"
-expect "Done"
+expect_line "Done"
send "unsecureport remove all\n"
-expect "Done"
+expect_line "Done"
send "unsecureport get\n"
-expect "Done"
+expect_line "Done"
send "unsecureport invalid_command\n"
expect "Error 35: InvalidCommand"
diff --git a/tests/scripts/expect/posix-ccathreshold.exp b/tests/scripts/expect/posix-ccathreshold.exp
index 34e4d96..0ea5d7c 100755
--- a/tests/scripts/expect/posix-ccathreshold.exp
+++ b/tests/scripts/expect/posix-ccathreshold.exp
@@ -27,13 +27,15 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+source "tests/scripts/expect/_common.exp"
+
spawn $env(OT_POSIX_APPS)/ot-cli "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=1&cca-threshold=-100"
expect_after {
timeout { exit 1 }
}
send "ccathreshold\n"
expect -- "-100"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
@@ -43,7 +45,7 @@
}
send "ccathreshold\n"
expect -- "-128"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
@@ -53,7 +55,7 @@
}
send "ccathreshold\n"
expect "127"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
diff --git a/tests/scripts/expect/posix-diag-rcp.exp b/tests/scripts/expect/posix-diag-rcp.exp
index e933922..2e4732e 100755
--- a/tests/scripts/expect/posix-diag-rcp.exp
+++ b/tests/scripts/expect/posix-diag-rcp.exp
@@ -33,25 +33,25 @@
send "diag rcp\n"
expect "diagnostics mode is disabled"
-expect "Done"
+expect_line "Done"
send "diag start\n"
expect "start diagnostics mode"
expect "status 0x00"
-expect "Done"
+expect_line "Done"
send "diag rcp\n"
expect "diagnostics mode is enabled"
-expect "Done"
+expect_line "Done"
send "diag rcp channel\n"
expect "failed"
expect "status 0x7"
-expect "Done"
+expect_line "Done"
send "diag rcp channel 11\n"
-expect "Done"
+expect_line "Done"
send "diag rcp power\n"
expect "failed"
expect "status 0x7"
-expect "Done"
+expect_line "Done"
send "diag rcp power 10\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/posix-fem-lnagain.exp b/tests/scripts/expect/posix-fem-lnagain.exp
index 77adfaa..f157c24 100755
--- a/tests/scripts/expect/posix-fem-lnagain.exp
+++ b/tests/scripts/expect/posix-fem-lnagain.exp
@@ -27,13 +27,15 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+source "tests/scripts/expect/_common.exp"
+
spawn $env(OT_POSIX_APPS)/ot-cli "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=1&fem-lnagain=10"
expect_after {
timeout { exit 1 }
}
send "fem lnagain\n"
expect "10"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
@@ -43,7 +45,7 @@
}
send "fem lnagain\n"
expect -- "-128"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
diff --git a/tests/scripts/expect/posix-max-power-table.exp b/tests/scripts/expect/posix-max-power-table.exp
index 733edfb..86d3a0f 100755
--- a/tests/scripts/expect/posix-max-power-table.exp
+++ b/tests/scripts/expect/posix-max-power-table.exp
@@ -33,24 +33,24 @@
spawn_node 1 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,-1,0x7f&forkpty-arg=1"
send "channel supported\n"
expect "0x3fff800"
-expect "Done"
+expect_line "Done"
send "channel preferred\n"
expect "0x3fff800"
-expect "Done"
+expect_line "Done"
send "txpower 20\n"
-expect "Done"
+expect_line "Done"
send "txpower\n"
expect "11 dBm"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
# allows all channels by default
spawn_node 1 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=1"
send "channel supported\n"
expect "0x7fff800"
-expect "Done"
+expect_line "Done"
send "channel preferred\n"
expect "0x7fff800"
-expect "Done"
+expect_line "Done"
send "\x04"
expect eof
diff --git a/tests/scripts/expect/posix-rcp-restoration.exp b/tests/scripts/expect/posix-rcp-restoration.exp
index 2222432..c0dac4c 100755
--- a/tests/scripts/expect/posix-rcp-restoration.exp
+++ b/tests/scripts/expect/posix-rcp-restoration.exp
@@ -31,6 +31,9 @@
source "tests/scripts/expect/_multinode.exp"
+# The expect on macOS doesn't support `try` or `file tempfile`.
+skip_on_macos
+
file tempfile socat_out
set socat_pid [exec socat -d -d pty,raw,echo=0 pty,raw,echo=0 >/dev/null 2>$socat_out &]
while {true} {
@@ -70,36 +73,28 @@
setup_two_nodes "-" false
switch_node 2
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr_2 $expect_out(1,string)
- expect "Done"
+ set addr_2 [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11003\n"
- expect "Done"
+ expect_line "Done"
send "pollperiod 100000\n"
- expect "Done"
+ expect_line "Done"
sleep 1
switch_node 1
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr_1 $expect_out(1,string)
- expect "Done"
+ set addr_1 [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11004\n"
- expect "Done"
+ expect_line "Done"
send "udp connect $addr_2 11003\n"
- expect "Done"
+ expect_line "Done"
send "udp send hello\n"
- expect "Done"
+ expect_line "Done"
send "udp send there\n"
- expect "Done"
+ expect_line "Done"
sleep 1
@@ -113,7 +108,7 @@
switch_node 2
send "pollperiod 1000\n"
- expect "Done"
+ expect_line "Done"
expect "5 bytes from $addr_1 11004 hello"
expect "5 bytes from $addr_1 11004 there"
@@ -134,34 +129,26 @@
setup_two_nodes "-" false
switch_node 2
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr_2 $expect_out(1,string)
- expect "Done"
+ set addr_2 [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11003\n"
- expect "Done"
+ expect_line "Done"
send "pollperiod 100000\n"
- expect "Done"
+ expect_line "Done"
sleep 1
switch_node 1
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr_1 $expect_out(1,string)
- expect "Done"
+ set addr_1 [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11004\n"
- expect "Done"
+ expect_line "Done"
send "udp connect $addr_2 11003\n"
- expect "Done"
+ expect_line "Done"
send "udp send hello\n"
- expect "Done"
+ expect_line "Done"
sleep 1
@@ -175,7 +162,7 @@
switch_node 2
send "pollperiod 1000\n"
- expect "Done"
+ expect_line "Done"
expect "5 bytes from $addr_1 11004 hello"
dispose_all
@@ -190,47 +177,25 @@
puts "Many children, queued child-to-child packets"
spawn_node 1 "rcp" "spinel+hdlc_uart://$host_pty"
- send "panid 0xface\n"
- expect "Done"
- send "ifconfig up\n"
- expect "Done"
- send "thread start\n"
- expect "Done"
- wait_for "state" "leader"
- expect "Done"
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr(1) $expect_out(1,string)
- expect "Done"
+ setup_leader
+ set addr(1) [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11004\n"
- expect "Done"
+ expect_line "Done"
- set max_children 15
+ set max_children 10
for {set i 2} {$i <= $max_children + 1} {incr i} {
spawn_node $i
- send "mode -\n"
- expect "Done"
- send "panid 0xface\n"
- expect "Done"
- send "ifconfig up\n"
- expect "Done"
- send "thread start\n"
- expect "Done"
- wait_for "state" "child"
- send "ipaddr mleid\n"
- expect "ipaddr mleid"
- expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
- set addr($i) $expect_out(1,string)
- expect "Done"
+ setup_node $i "-"
+ switch_node $i
+ set addr($i) [get_ipaddr mleid]
send "udp open\n"
- expect "Done"
+ expect_line "Done"
send "udp bind :: 11003\n"
- expect "Done"
+ expect_line "Done"
send "pollperiod 100000\n"
- expect "Done"
+ expect_line "Done"
}
sleep 1
@@ -238,7 +203,7 @@
switch_node 1
for {set i 2} {$i <= $max_children + 1} {incr i} {
send "udp send $addr($i) 11003 hello\n"
- expect "Done"
+ expect_line "Done"
}
sleep 1
@@ -254,13 +219,13 @@
for {set i 7} {$i <= 9} {incr i} {
switch_node $i
send "pollperiod 1000\n"
- expect "Done"
+ expect_line "Done"
expect "5 bytes from $addr(1) 11004 hello"
}
switch_node 4
send "udp send $addr(5) 11003 hello_from_node_4\n"
- expect "Done"
+ expect_line "Done"
if {$::env(THREAD_VERSION) != "1.1"} {
expect "5 bytes from $addr(1) 11004 hello"
}
@@ -277,7 +242,7 @@
switch_node 5
send "pollperiod 1000\n"
- expect "Done"
+ expect_line "Done"
expect "17 bytes from $addr(4) 11003 hello_from_node_4"
dispose_all
@@ -287,11 +252,11 @@
spawn_node 1 "rcp" "spinel+hdlc_uart://$host_pty"
send "ifconfig up\n"
- expect "Done"
+ expect_line "Done"
send "thread start\n"
- expect "Done"
+ expect_line "Done"
wait_for "state" "leader"
- expect "Done"
+ expect_line "Done"
send "scan energy 100\n"
expect "| Ch | RSSI |"
@@ -310,7 +275,7 @@
for {set i 11} {$i <= 26} {incr i} {
expect -re "\\| +$i \\| +-?\\d+ \\|"
}
- expect "Done"
+ expect_line "Done"
dispose_all
} finally {
diff --git a/tests/scripts/expect/posix-rcp.exp b/tests/scripts/expect/posix-rcp.exp
index c6dd51d..d2ccd4d 100755
--- a/tests/scripts/expect/posix-rcp.exp
+++ b/tests/scripts/expect/posix-rcp.exp
@@ -32,7 +32,7 @@
spawn_node 1
send "rcp version\n"
-expect "Done"
+expect_line "Done"
send "rcp something_invalid\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/posix-scan-tx-to-sleep.exp b/tests/scripts/expect/posix-scan-tx-to-sleep.exp
index 7f29714..a613737 100755
--- a/tests/scripts/expect/posix-scan-tx-to-sleep.exp
+++ b/tests/scripts/expect/posix-scan-tx-to-sleep.exp
@@ -31,44 +31,40 @@
spawn_node 1 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=--sleep-to-tx&forkpty-arg=1"
send "dataset init new\n"
-expect "Done"
+expect_line "Done"
send "dataset panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "dataset commit active\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
-send "extaddr\n"
-expect "extaddr"
-expect -re {([0-9a-f]{16})}
-set extaddr $expect_out(1,string)
-expect "Done"
+set extaddr [get_extaddr]
send "panid\n"
expect "panid"
expect -re {([0-9a-f]{4})}
set pan $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "extpanid\n"
expect "extpanid"
expect -re {([0-9a-f]{16})}
set extpan $expect_out(1,string)
-expect "Done"
+expect_line "Done"
expect "> "
send "networkname\n"
expect "networkname"
expect -re {[\r\n]([^\r\n]+)[\r\n]}
set network $expect_out(1,string)
-expect "Done"
+expect_line "Done"
send "channel\n"
expect "channel"
expect -re {(\d+)}
set channel $expect_out(1,string)
-expect "Done"
+expect_line "Done"
spawn_node 2 "rcp" "spinel+hdlc+uart://$env(OT_SIMULATION_APPS)/ncp/ot-rcp?forkpty-arg=--sleep-to-tx&forkpty-arg=2"
send "scan\n"
diff --git a/tests/scripts/expect/simulation-networktime.exp b/tests/scripts/expect/simulation-networktime.exp
index df98db2..ccbe3b5 100755
--- a/tests/scripts/expect/simulation-networktime.exp
+++ b/tests/scripts/expect/simulation-networktime.exp
@@ -32,12 +32,12 @@
spawn_node 1
send "networktime 20 200\n"
-expect "Done"
+expect_line "Done"
send "networktime\n"
expect -re {Network Time: \d+us \((unsynchronized|resync needed|synchronized)\)}
expect "Time Sync Period: 20s"
expect "XTAL Threshold: 200ppm"
-expect "Done"
+expect_line "Done"
send "networktime something_invalid\n"
expect "Error 7: InvalidArgs"
diff --git a/tests/scripts/expect/tun-dns-client.exp b/tests/scripts/expect/tun-dns-client.exp
index ef9c504..36909ba 100755
--- a/tests/scripts/expect/tun-dns-client.exp
+++ b/tests/scripts/expect/tun-dns-client.exp
@@ -32,16 +32,16 @@
spawn_node 1
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
send "dns resolve ipv6.google.com ::1 53\n"
expect "DNS response for ipv6.google.com"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/tun-netif.exp b/tests/scripts/expect/tun-netif.exp
index d9635c7..ad6d956 100755
--- a/tests/scripts/expect/tun-netif.exp
+++ b/tests/scripts/expect/tun-netif.exp
@@ -33,6 +33,6 @@
send "netif\n"
expect -re {[\r\n][^\r\n:]+?:\d+}
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/tun-netstat.exp b/tests/scripts/expect/tun-netstat.exp
index 1e5ed92..bd33388 100755
--- a/tests/scripts/expect/tun-netstat.exp
+++ b/tests/scripts/expect/tun-netstat.exp
@@ -30,33 +30,29 @@
source "tests/scripts/expect/_common.exp"
spawn_node 1
+setup_leader
-send "ifconfig up\n"
-expect "Done"
send "udp open\n"
-expect "Done"
+expect_line "Done"
send "netstat\n"
expect "| Local Address | Peer Address |"
expect "+-----------------------------------------------+-----------------------------------------------+"
expect "| 0:0:0:0:0:0:0:0:* | 0:0:0:0:0:0:0:0:* |"
-expect "Done"
+expect_line "Done"
send "udp bind :: 10001\n"
-expect "Done"
+expect_line "Done"
send "netstat\n"
expect "| Local Address | Peer Address |"
expect "+-----------------------------------------------+-----------------------------------------------+"
expect "| 0:0:0:0:0:0:0:0:10001 | 0:0:0:0:0:0:0:0:* |"
-expect "Done"
-send "ipaddr mleid\n"
-expect "ipaddr mleid"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
+expect_line "Done"
+set addr [get_ipaddr mleid]
send "udp connect $addr 10001\n"
-expect "Done"
+expect_line "Done"
send "netstat\n"
expect "| Local Address | Peer Address |"
expect "+-----------------------------------------------+-----------------------------------------------+"
expect -re "\\| 0:0:0:0:0:0:0:0:10001 +\\| $addr:10001 +\\|"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/tun-realm-local-multicast.exp b/tests/scripts/expect/tun-realm-local-multicast.exp
index daba343..e8c0543 100755
--- a/tests/scripts/expect/tun-realm-local-multicast.exp
+++ b/tests/scripts/expect/tun-realm-local-multicast.exp
@@ -37,53 +37,45 @@
source "tests/scripts/expect/_common.exp"
spawn_node 1
-
-set timeout 1
-
-send "panid 0xface\n"
-expect "Done"
+setup_default_network
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
set extaddr1 [get_extaddr]
spawn_node 2 cli
-
-send "panid 0xface\n"
-expect "Done"
+setup_default_network
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "router"
sleep 3
spawn_node 3 cli
-
-send "panid 0xface\n"
-expect "Done"
+setup_default_network
send "macfilter addr add ${extaddr1}\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr denylist\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "router"
sleep 4
@@ -91,24 +83,22 @@
set extaddr3 [get_extaddr]
spawn_node 4 cli
-
-send "panid 0xface\n"
-expect "Done"
+setup_default_network
send "mode rn\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr add ${extaddr3}\n"
-expect "Done"
+expect_line "Done"
send "macfilter addr allowlist\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "child"
@@ -117,7 +107,7 @@
switch_node 1
send "ping ${mleid4}\n"
-expect "Done"
+expect_line "Done"
expect "16 bytes from $mleid4: icmp_seq=1"
dispose_all
diff --git a/tests/scripts/expect/tun-sntp.exp b/tests/scripts/expect/tun-sntp.exp
index aa920d7..a724390 100755
--- a/tests/scripts/expect/tun-sntp.exp
+++ b/tests/scripts/expect/tun-sntp.exp
@@ -27,27 +27,23 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-set OSTYPE [lindex $tcl_platform(os) 0]
-
-if { $OSTYPE == "Darwin" } {
- exit 77
-}
-
source "tests/scripts/expect/_common.exp"
+skip_on_macos
+
spawn_node 1
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
send "sntp query ::1 123\n"
expect -re {SNTP response - Unix time: \d+ \(era: \d+\)}
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/tun-udp.exp b/tests/scripts/expect/tun-udp.exp
index 2eb4f6e..187bda4 100755
--- a/tests/scripts/expect/tun-udp.exp
+++ b/tests/scripts/expect/tun-udp.exp
@@ -36,30 +36,35 @@
set timeout 1
send "panid 0xface\n"
-expect "Done"
+expect_line "Done"
send "ifconfig up\n"
-expect "Done"
+expect_line "Done"
send "thread start\n"
-expect "Done"
+expect_line "Done"
wait_for "state" "leader"
-expect "Done"
+expect_line "Done"
send "udp open\n"
-expect "Done"
+expect_line "Done"
send "udp bind :: 1234\n"
-expect "Done"
+expect_line "Done"
-send "udp connect fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234\n"
-expect "Done"
+send "dataset active\n"
+expect -re {Mesh Local Prefix: ([0-9a-f:]*)::\/64}
+set prefix $expect_out(1,string)
+expect_line "Done"
+
+send "udp connect $prefix:bb1:ebd6:ad10:f33 1234\n"
+expect_line "Done"
send "udp connect :: 1\n"
-expect "Done"
+expect_line "Done"
send "udp close\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/expect/v1_2-rcp-restoration.exp b/tests/scripts/expect/v1_2-rcp-restoration.exp
old mode 100644
new mode 100755
diff --git a/tests/scripts/expect/v1_2-sed_mac_send.exp b/tests/scripts/expect/v1_2-sed_mac_send.exp
index 4a2e15d..faeeb35 100755
--- a/tests/scripts/expect/v1_2-sed_mac_send.exp
+++ b/tests/scripts/expect/v1_2-sed_mac_send.exp
@@ -34,8 +34,8 @@
switch_node 2
send "mac send emptydata\n"
-expect "Done"
+expect_line "Done"
send "mac send datarequest\n"
-expect "Done"
+expect_line "Done"
dispose_all
diff --git a/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py b/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
index eff1b0b..ba2f4f1 100755
--- a/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
+++ b/tests/scripts/thread-cert/Cert_7_1_05_BorderRouterAsRouter.py
@@ -159,16 +159,17 @@
# Step 5: The DUT MUST send a multicast MLE Data Response,
# including at least three Prefix TLVs (Prefix 1, Prefix2,
# and Prefix 3).
- _dv_pkt = pkts.filter_wpan_src64(ROUTER).\
- filter_LLANMA().\
- filter_mle_cmd(MLE_DATA_RESPONSE).\
- filter(lambda p: {
- Ipv6Addr(PREFIX_2001[:-3]),
- Ipv6Addr(PREFIX_2002[:-3]),
- Ipv6Addr(PREFIX_2003[:-3])
- } == set(p.thread_nwd.tlv.prefix)
- ).\
- must_next()
+ with pkts.save_index():
+ _dv_pkt = pkts.filter_wpan_src64(ROUTER).\
+ filter_LLANMA().\
+ filter_mle_cmd(MLE_DATA_RESPONSE).\
+ filter(lambda p: {
+ Ipv6Addr(PREFIX_2001[:-3]),
+ Ipv6Addr(PREFIX_2002[:-3]),
+ Ipv6Addr(PREFIX_2003[:-3])
+ } <= set(p.thread_nwd.tlv.prefix)
+ ).\
+ must_next()
# Step 6: MED automatically sends MLE Child Update Request to its parent
# (DUT), reporting its configured global addresses in the Address
@@ -183,6 +184,7 @@
_pkt = pkts.filter_wpan_src64(MED).\
filter_wpan_dst64(ROUTER).\
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
+ filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 4).\
must_next()
pkts.filter_wpan_src64(ROUTER).\
filter_wpan_dst64(MED).\
@@ -192,7 +194,7 @@
MODE_TLV,
ADDRESS_REGISTRATION_TLV
} < set(p.mle.tlv.type) and\
- len(p.mle.tlv.addr_reg_iid) > 0 and\
+ len(p.mle.tlv.addr_reg_iid) >= 3 and\
set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid)
).\
must_next()
@@ -240,6 +242,7 @@
_pkt = pkts.filter_wpan_src64(SED).\
filter_wpan_dst64(ROUTER).\
filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\
+ filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 3).\
must_next()
pkts.filter_wpan_src64(ROUTER).\
filter_wpan_dst64(SED).\
@@ -249,7 +252,7 @@
MODE_TLV,
ADDRESS_REGISTRATION_TLV
} < set(p.mle.tlv.type) and\
- len(p.mle.tlv.addr_reg_iid) > 0 and\
+ len(p.mle.tlv.addr_reg_iid) >= 2 and\
set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid)
).\
must_next()
diff --git a/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
index 8a2e742..a1b4a6b 100755
--- a/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
+++ b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py
@@ -119,7 +119,7 @@
# Commissioner ID TLV
pv.verify_attached('COMMISSIONER', 'LEADER')
_pkt = pkts.last()
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _leader_pet_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_wpan_dst16(LEADER_RLOC16).\
filter_coap_request(LEAD_PET_URI).\
filter(lambda p: {
@@ -143,7 +143,7 @@
# - Leader Data TLV
# - Network Data TLV
# - Source Address TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_leader_pet_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(LEAD_PET_URI).\
filter(lambda p: {
NM_STATE_TLV,
@@ -182,7 +182,7 @@
# CoAP Payload
# State TLV (value = Accept)
# Commissioner Session ID TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _leader_ka_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(LEAD_KA_URI).\
filter(lambda p: {
@@ -198,7 +198,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Accept)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_leader_ka_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(LEAD_KA_URI).\
filter(lambda p: {
NM_STATE_TLV
@@ -214,7 +214,7 @@
# CoAP Payload
# Commissioner Session ID TLV
# Steering Data TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -237,7 +237,7 @@
# - Leader Data TLV
# - Network Data TLV
# - Source Address TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
NM_STATE_TLV
@@ -276,7 +276,7 @@
# CoAP Payload
# State TLV (value = Reject)
# Commissioner Session ID TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _leader_ka_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(LEAD_KA_URI).\
filter(lambda p: {
@@ -300,7 +300,7 @@
# - Leader Data TLV
# - Network Data TLV
# - Source Address TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_leader_ka_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(LEAD_KA_URI).\
filter(lambda p: {
NM_STATE_TLV
@@ -334,7 +334,7 @@
# CON POST coap://<L>:MM/c/lp
# CoAP Payload
# Commissioner ID TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _leader_pet_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(LEAD_PET_URI).\
filter(lambda p: {
@@ -352,7 +352,7 @@
# Commissioner ID TLV
# Commissioner Session ID TLV (contains higher Session ID number
# than in Step 9)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_leader_pet_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(LEAD_PET_URI).\
filter(lambda p: {
NM_STATE_TLV,
diff --git a/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py b/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
index 4e6870d..0c8d314 100755
--- a/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_01_MGMTCommissionerGet.py
@@ -56,6 +56,7 @@
class Cert_9_2_01_MGMTCommissionerGet(thread_cert.TestCase):
SUPPORT_NCP = False
+ USE_MESSAGE_FACTORY = True
TOPOLOGY = {
COMMISSIONER: {
@@ -82,7 +83,6 @@
self.nodes[COMMISSIONER].start()
self.simulator.go(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
- self.simulator.get_messages_sent_by(LEADER)
self.collect_leader_aloc(LEADER)
self.collect_rlocs()
@@ -143,7 +143,7 @@
# Border Agent Locator TLV
# Commissioner Session ID TLV
# Steering Data TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
NM_COMMISSIONER_SESSION_ID_TLV,
@@ -163,7 +163,7 @@
# CoAP Payload
# Commissioner Session ID TLV
# Steering Data TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
@@ -181,7 +181,7 @@
# Encoded values for the requested Commissioner Dataset parameters
# Commissioner Session ID TLV
# Steering Data TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
NM_COMMISSIONER_SESSION_ID_TLV,
@@ -199,7 +199,7 @@
# CoAP Payload
# Commissioner Session ID TLV
# PAN ID TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
@@ -217,7 +217,7 @@
# Encoded values for the requested Commissioner Dataset parameters
# Commissioner Session ID TLV
# (PAN ID TLV in Get TLV is ignored)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
NM_COMMISSIONER_SESSION_ID_TLV
@@ -234,7 +234,7 @@
# CoAP Payload
# Border Agent Locator TLV
# Network Name TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
@@ -252,7 +252,7 @@
# Encoded values for the requested Commissioner Dataset parameters
# Border Agent Locator TLV
# (Network Name TLV in Get TLV is ignored)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
filter(lambda p: {
NM_BORDER_AGENT_LOCATOR_TLV
diff --git a/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py b/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
index bb1d998..fde4007 100755
--- a/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_02_MGMTCommissionerSet.py
@@ -152,7 +152,7 @@
# CoAP Payload
# (missing Commissioner Session ID TLV)
# Steering Data TLV (0xFF)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
@@ -167,7 +167,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Reject)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
@@ -182,7 +182,7 @@
# CoAP Payload
# Commissioner Session ID TLV
# Steering Data TLV (0xFF)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -199,7 +199,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Accept)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
@@ -241,7 +241,7 @@
# CoAP Payload
# Commissioner Session ID TLV
# Border Agent Locator TLV (0x0400) (not allowed TLV)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -258,7 +258,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Reject)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
@@ -274,7 +274,7 @@
# Commissioner Session ID TLV
# Steering Data TLV (0xFF)
# Border Agent Locator TLV (0x0400) (not allowed TLV)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -293,7 +293,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Reject)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
@@ -308,7 +308,7 @@
# CoAP Payload
# Commissioner Session ID TLV (0xFFFF) (invalid value)
# Steering Data TLV (0xFF)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -326,7 +326,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Reject)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
@@ -342,7 +342,7 @@
# Commissioner Session ID TLV
# Steering Data TLV (0xFF)
# Channel TLV (not allowed TLV)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p: {
@@ -360,7 +360,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Accept)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
filter(lambda p:
[NM_STATE_TLV] == p.coap.tlv.type and\
diff --git a/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py b/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
index 78b547a..fb12027 100755
--- a/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_03_ActiveDatasetGet.py
@@ -57,6 +57,7 @@
class Cert_9_2_03_ActiveDatasetGet(thread_cert.TestCase):
SUPPORT_NCP = False
+ USE_MESSAGE_FACTORY = False
TOPOLOGY = {
COMMISSIONER: {
@@ -83,7 +84,6 @@
self.nodes[COMMISSIONER].start()
self.simulator.go(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
- self.simulator.get_messages_sent_by(LEADER)
self.collect_rlocs()
self.collect_rloc16s()
@@ -152,7 +152,7 @@
# PAN ID TLV
# PSKc TLV
# Security Policy TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
filter(lambda p: {
NM_ACTIVE_TIMESTAMP_TLV,
diff --git a/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py b/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
index f00f37b..0232355 100755
--- a/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
+++ b/tests/scripts/thread-cert/Cert_9_2_19_PendingDatasetGet.py
@@ -131,7 +131,7 @@
# CON POST coap://<L>:MM/c/pg
# CoAP Payload
# <empty> - get all Active Operational Dataset parameters
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_PENDING_GET_URI).\
filter(lambda p: p.coap.tlv.type is nullField).\
@@ -143,7 +143,7 @@
# 2.04 Changed
# CoAP Payload
# <empty> - (no Pending Operational Dataset)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_PENDING_GET_URI).\
filter(lambda p: p.coap.tlv.type is nullField).\
must_next()
@@ -158,7 +158,7 @@
# Delay Timer TLV: 1 minute
# Pending Timestamp TLV: 30s
# PAN ID TLV: 0xAFCE (new value)
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_pending_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_PENDING_SET_URI).\
filter(lambda p: {
@@ -179,7 +179,7 @@
# 2.04 Changed
# CoAP Payload
# State TLV (value = Accept (01))
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_pending_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_PENDING_SET_URI).\
filter(lambda p:
p.thread_meshcop.tlv.state == 1
@@ -192,7 +192,7 @@
# CON POST coap://<L>:MM/c/pg
# CoAP Payload
# <empty> - get all Active Operational Dataset parameters
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_PENDING_GET_URI).\
filter(lambda p: p.coap.tlv.type is nullField).\
@@ -216,7 +216,7 @@
# Pending Timestamp TLV
# PSKc TLV
# Security Policy TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_PENDING_GET_URI).\
filter(lambda p: {
NM_ACTIVE_TIMESTAMP_TLV,
@@ -241,7 +241,7 @@
# CON POST coap://<L>:MM/c/pg
# CoAP Payload
# PAN ID TLV
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_PENDING_GET_URI).\
filter(lambda p: {
@@ -257,7 +257,7 @@
# CoAP Payload
# PAN ID TLV
# Delay Timer TLV
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_PENDING_GET_URI).\
filter(lambda p: {
NM_DELAY_TIMER_TLV,
@@ -274,7 +274,7 @@
# CON POST coap://<L>:MM/c/pg
# CoAP Payload
# <empty> - get all Active Operational Dataset parameters
- pkts.filter_wpan_src64(COMMISSIONER).\
+ _mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
filter_coap_request(MGMT_PENDING_GET_URI).\
filter(lambda p: p.coap.tlv.type is nullField).\
@@ -286,7 +286,7 @@
# 2.04 Changed
# CoAP Payload
# <empty> - (no Pending Operational Dataset)
- pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
+ pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
filter_coap_ack(MGMT_PENDING_GET_URI).\
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
must_next()
diff --git a/tests/scripts/thread-cert/Makefile.am b/tests/scripts/thread-cert/Makefile.am
index 37b8fcc..b777c7d 100644
--- a/tests/scripts/thread-cert/Makefile.am
+++ b/tests/scripts/thread-cert/Makefile.am
@@ -154,9 +154,12 @@
test_coap.py \
test_coap_observe.py \
test_coaps.py \
+ test_coap_block.py \
test_common.py \
test_crypto.py \
+ test_dataset_updater.py \
test_diag.py \
+ test_dnssd.py \
test_ipv6.py \
test_ipv6_fragmentation.py \
test_ipv6_source_selection.py \
@@ -170,6 +173,10 @@
test_route_table.py \
test_router_reattach.py \
test_service.py \
+ test_srp_auto_start_mode.py \
+ test_srp_lease.py \
+ test_srp_name_conflicts.py \
+ test_srp_register_single_service.py \
thread_cert.py \
tlvs_parsing.py \
thread_cert.py \
@@ -202,9 +209,12 @@
test_coap.py \
test_coap_observe.py \
test_coaps.py \
+ test_coap_block.py \
test_common.py \
test_crypto.py \
+ test_dataset_updater.py \
test_diag.py \
+ test_dnssd.py \
test_ipv6.py \
test_ipv6_fragmentation.py \
test_ipv6_source_selection.py \
@@ -218,6 +228,10 @@
test_route_table.py \
test_router_reattach.py \
test_service.py \
+ test_srp_auto_start_mode.py \
+ test_srp_lease.py \
+ test_srp_name_conflicts.py \
+ test_srp_register_single_service.py \
Cert_5_1_01_RouterAttach.py \
Cert_5_1_02_ChildAddressTimeout.py \
Cert_5_1_03_RouterAddressReallocation.py \
diff --git a/tests/scripts/thread-cert/backbone/bbr_5_11_01.py b/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
index 57f0c47..9c0352a 100755
--- a/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
+++ b/tests/scripts/thread-cert/backbone/bbr_5_11_01.py
@@ -91,6 +91,11 @@
self.simulator.go(5)
self.assertEqual('router', self.nodes[ROUTER2].get_state())
+ # The OTBR docker enables SRP Server by default, lets explicitly
+ # disable SRP server to avoid Network Data population.
+ # TODO: Enhance the test script to tolerate additional Sertivce TLV
+ # in Network Data.
+ self.nodes[BR_1].srp_server_set_enabled(False)
self.nodes[BR_1].start()
self.simulator.go(5)
self.assertEqual('router', self.nodes[BR_1].get_state())
diff --git a/tests/scripts/thread-cert/border_router/test_advertising_proxy.py b/tests/scripts/thread-cert/border_router/test_advertising_proxy.py
new file mode 100755
index 0000000..28e093e
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_advertising_proxy.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+import ipaddress
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# This test verifies the basic functionality of advertising proxy.
+#
+# Topology:
+# ----------------(eth)--------------------
+# | |
+# BR (Leader) HOST (mDNS Browser)
+# |
+# ROUTER
+#
+
+BR = 1
+ROUTER = 2
+HOST = 3
+LEASE = 10 # Seconds
+KEY_LEASE = 20 # Seconds
+
+
+class SingleHostAndService(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR: {
+ 'name': 'BR_1',
+ 'allowlist': [ROUTER],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'router_selection_jitter': 2,
+ },
+ ROUTER: {
+ 'name': 'Router_1',
+ 'allowlist': [BR],
+ 'version': '1.2',
+ 'router_selection_jitter': 2,
+ },
+ HOST: {
+ 'name': 'Host',
+ 'is_host': True
+ },
+ }
+
+ def test(self):
+ host = self.nodes[HOST]
+ server = self.nodes[BR]
+ client = self.nodes[ROUTER]
+
+ host.start(start_radvd=False)
+ self.simulator.go(5)
+
+ server.srp_server_set_enabled(True)
+ server.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
+ server.start()
+ self.simulator.go(5)
+ self.assertEqual('leader', server.get_state())
+
+ client.start()
+ self.simulator.go(5)
+ self.assertEqual('router', client.get_state())
+
+ #
+ # 1. Register a single service.
+ #
+
+ client.srp_client_set_host_name('my-host')
+ client.srp_client_set_host_address('2001::1')
+ client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
+ client.srp_client_enable_auto_start_mode()
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client, '2001::1')
+
+ #
+ # 2. Discover the service by the HOST on the ethernet. This makes sure
+ # the Advertising Proxy multicasts the same service on ethernet.
+ #
+
+ self.host_check_mdns_service(host, '2001::1')
+
+ #
+ # 3. Check if the Advertising Proxy removes the service from ethernet
+ # when the SRP client removes it.
+ #
+
+ client.srp_client_remove_host()
+ self.simulator.go(2)
+
+ self.assertIsNone(host.discover_mdns_service('my-service', '_ipps._tcp', 'my-host'))
+
+ #
+ # 4. Check if we can discover the mDNS service again when re-registering the
+ # service from the SRP client.
+ #
+
+ client.srp_client_set_host_name('my-host')
+ client.srp_client_set_host_address('2001::1')
+ client.srp_client_add_service('my-service', '_ipps._tcp', 12345)
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client, '2001::1')
+ self.host_check_mdns_service(host, '2001::1')
+
+ #
+ # 5. Update the SRP host address and make sure the Advertising Proxy
+ # will follow it.
+ #
+
+ client.srp_client_set_host_address('2001::2')
+ self.simulator.go(8)
+
+ self.check_host_and_service(server, client, '2001::2')
+ self.host_check_mdns_service(host, '2001::2')
+
+ #
+ # 6. Check if the service is removed by the Advertising Proxy when the SRP server is stopped.
+ #
+
+ server.srp_server_set_enabled(False)
+ self.simulator.go(2)
+
+ self.assertEqual(len(server.srp_server_get_hosts()), 0)
+ self.assertEqual(len(server.srp_server_get_services()), 0)
+ self.assertIsNone(host.discover_mdns_service('my-service', '_ipps._tcp', 'my-host'))
+
+ server.srp_server_set_enabled(True)
+ self.simulator.go(LEASE)
+
+ self.check_host_and_service(server, client, '2001::2')
+ self.host_check_mdns_service(host, '2001::2')
+
+ #
+ # 7. Check if the expired service is removed by the Advertising Proxy.
+ #
+
+ client.srp_client_stop()
+ self.simulator.go(LEASE + 2)
+
+ self.assertIsNone(host.discover_mdns_service('my-service', '_ipps._tcp', 'my-host'))
+
+ def host_check_mdns_service(self, host, host_addr):
+ service = host.discover_mdns_service('my-service', '_ipps._tcp', 'my-host')
+ self.assertIsNotNone(service)
+ self.assertEqual(service['instance'], 'my-service')
+ self.assertEqual(service['name'], '_ipps._tcp')
+ self.assertEqual(service['port'], 12345)
+ self.assertEqual(service['priority'], 0)
+ self.assertEqual(service['weight'], 0)
+ self.assertEqual(service['host'], 'my-host')
+ self.assertEqual(ipaddress.ip_address(service['addresses'][0]), ipaddress.ip_address(host_addr))
+ self.assertEqual(len(service['addresses']), 1)
+
+ def check_host_and_service(self, server, client, host_addr):
+ """Check that we have properly registered host and service instance.
+ """
+
+ client_services = client.srp_client_get_services()
+ print(client_services)
+ self.assertEqual(len(client_services), 1)
+ client_service = client_services[0]
+
+ # Verify that the client possesses correct service resources.
+ self.assertEqual(client_service['instance'], 'my-service')
+ self.assertEqual(client_service['name'], '_ipps._tcp')
+ self.assertEqual(int(client_service['port']), 12345)
+ self.assertEqual(int(client_service['priority']), 0)
+ self.assertEqual(int(client_service['weight']), 0)
+
+ # Verify that the client received a SUCCESS response for the server.
+ self.assertEqual(client_service['state'], 'Registered')
+
+ server_services = server.srp_server_get_services()
+ print(server_services)
+ self.assertEqual(len(server_services), 1)
+ server_service = server_services[0]
+
+ # Verify that the server accepted the SRP registration and stores
+ # the same service resources.
+ self.assertEqual(server_service['deleted'], 'false')
+ self.assertEqual(server_service['instance'], client_service['instance'])
+ self.assertEqual(server_service['name'], client_service['name'])
+ self.assertEqual(int(server_service['port']), int(client_service['port']))
+ self.assertEqual(int(server_service['priority']), int(client_service['priority']))
+ self.assertEqual(int(server_service['weight']), int(client_service['weight']))
+ self.assertEqual(server_service['host'], 'my-host')
+
+ server_hosts = server.srp_server_get_hosts()
+ print(server_hosts)
+ self.assertEqual(len(server_hosts), 1)
+ server_host = server_hosts[0]
+
+ self.assertEqual(server_host['deleted'], 'false')
+ self.assertEqual(server_host['fullname'], server_service['host_fullname'])
+ self.assertEqual(len(server_host['addresses']), 1)
+ self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address(host_addr))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_dnssd_server.py b/tests/scripts/thread-cert/border_router/test_dnssd_server.py
new file mode 100644
index 0000000..80282f0
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_dnssd_server.py
@@ -0,0 +1,284 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+import ipaddress
+import json
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# This test verifies DNS-SD server works on a Duckhorn BR and is accessible from a Host.
+#
+# Topology:
+# ----------------(eth)--------------------
+# | |
+# BR1 (Leader, Server) HOST
+# / \
+# CLIENT1 CLIENT2
+
+SERVER = BR1 = 1
+CLIENT1, CLIENT2 = 2, 3
+HOST = 4
+
+DIGGER = HOST
+
+DOMAIN = 'default.service.arpa.'
+SERVICE = '_testsrv._udp'
+SERVICE_FULL_NAME = f'{SERVICE}.{DOMAIN}'
+
+VALID_SERVICE_NAMES = [
+ '_abc._udp.default.service.arpa.',
+ '_abc._tcp.default.service.arpa.',
+]
+
+WRONG_SERVICE_NAMES = [
+ '_testsrv._udp.default.service.xxxx.',
+ '_testsrv._txp,default.service.arpa.',
+]
+
+
+class TestDnssdServerOnBr(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR1: {
+ 'name': 'SERVER',
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'router_selection_jitter': 1,
+ },
+ CLIENT1: {
+ 'name': 'CLIENT1',
+ 'router_selection_jitter': 1,
+ },
+ CLIENT2: {
+ 'name': 'CLIENT2',
+ 'router_selection_jitter': 1,
+ },
+ HOST: {
+ 'name': 'Host',
+ 'is_host': True
+ },
+ }
+
+ def test(self):
+ self.nodes[HOST].start(start_radvd=False)
+ self.simulator.go(5)
+
+ self.nodes[BR1].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR1].get_state())
+ self.nodes[SERVER].srp_server_set_enabled(True)
+
+ self.nodes[CLIENT1].start()
+
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[CLIENT1].get_state())
+
+ self.nodes[CLIENT2].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[CLIENT2].get_state())
+
+ self.simulator.go(10)
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[BR1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0],
+ backbone=True))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ client1_addrs = [
+ self.nodes[CLIENT1].get_mleid(), self.nodes[CLIENT1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+ ]
+ self._config_srp_client_services(CLIENT1, 'ins1', 'host1', 11111, 1, 1, client1_addrs)
+
+ client2_addrs = [
+ self.nodes[CLIENT2].get_mleid(), self.nodes[CLIENT2].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+ ]
+ self._config_srp_client_services(CLIENT2, 'ins2', 'host2', 22222, 2, 2, client2_addrs)
+
+ ins1_full_name = f'ins1.{SERVICE_FULL_NAME}'
+ ins2_full_name = f'ins2.{SERVICE_FULL_NAME}'
+ host1_full_name = f'host1.{DOMAIN}'
+ host2_full_name = f'host2.{DOMAIN}'
+ server_addr = self.nodes[SERVER].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+
+ # check if PTR query works
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, SERVICE_FULL_NAME, 'PTR')
+
+ self._assert_dig_result_matches(
+ dig_result, {
+ 'QUESTION': [(SERVICE_FULL_NAME, 'IN', 'PTR')],
+ 'ANSWER': [(SERVICE_FULL_NAME, 'IN', 'PTR', f'ins1.{SERVICE_FULL_NAME}'),
+ (SERVICE_FULL_NAME, 'IN', 'PTR', f'ins2.{SERVICE_FULL_NAME}')],
+ 'ADDITIONAL': [
+ (ins1_full_name, 'IN', 'SRV', 1, 1, 11111, host1_full_name),
+ (ins1_full_name, 'IN', 'TXT', '""'),
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[0]),
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[1]),
+ (ins2_full_name, 'IN', 'SRV', 2, 2, 22222, host2_full_name),
+ (ins2_full_name, 'IN', 'TXT', '""'),
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[0]),
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[1]),
+ ],
+ })
+
+ # check if SRV query works
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, ins1_full_name, 'SRV')
+ self._assert_dig_result_matches(
+ dig_result, {
+ 'QUESTION': [(ins1_full_name, 'IN', 'SRV')],
+ 'ANSWER': [(ins1_full_name, 'IN', 'SRV', 1, 1, 11111, host1_full_name),],
+ 'ADDITIONAL': [
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[0]),
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[1]),
+ ],
+ })
+
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, ins2_full_name, 'SRV')
+ self._assert_dig_result_matches(
+ dig_result, {
+ 'QUESTION': [(ins2_full_name, 'IN', 'SRV')],
+ 'ANSWER': [(ins2_full_name, 'IN', 'SRV', 2, 2, 22222, host2_full_name),],
+ 'ADDITIONAL': [
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[0]),
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[1]),
+ ],
+ })
+
+ # check if TXT query works
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, ins1_full_name, 'TXT')
+ self._assert_dig_result_matches(dig_result, {
+ 'QUESTION': [(ins1_full_name, 'IN', 'TXT')],
+ 'ANSWER': [(ins1_full_name, 'IN', 'TXT', '""'),],
+ })
+
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, ins2_full_name, 'TXT')
+ self._assert_dig_result_matches(dig_result, {
+ 'QUESTION': [(ins2_full_name, 'IN', 'TXT')],
+ 'ANSWER': [(ins2_full_name, 'IN', 'TXT', '""'),],
+ })
+
+ # check if AAAA query works
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, host1_full_name, 'AAAA')
+ self._assert_dig_result_matches(
+ dig_result, {
+ 'QUESTION': [(host1_full_name, 'IN', 'AAAA'),],
+ 'ANSWER': [
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[0]),
+ (host1_full_name, 'IN', 'AAAA', client1_addrs[1]),
+ ],
+ })
+
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, host2_full_name, 'AAAA')
+ self._assert_dig_result_matches(
+ dig_result, {
+ 'QUESTION': [(host2_full_name, 'IN', 'AAAA'),],
+ 'ANSWER': [
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[0]),
+ (host2_full_name, 'IN', 'AAAA', client2_addrs[1]),
+ ],
+ })
+
+ # check some invalid queries
+ for qtype in ['A', 'CNAME']:
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, host1_full_name, qtype)
+ self._assert_dig_result_matches(dig_result, {
+ 'status': 'NOTIMP',
+ })
+
+ for service_name in WRONG_SERVICE_NAMES:
+ dig_result = self.nodes[DIGGER].dns_dig(server_addr, service_name, 'PTR')
+ self._assert_dig_result_matches(dig_result, {
+ 'status': 'NXDOMAIN',
+ })
+
+ def _config_srp_client_services(self, client, instancename, hostname, port, priority, weight, addrs):
+ self.nodes[client].netdata_show()
+ srp_server_port = self.nodes[client].get_srp_server_port()
+
+ self.nodes[client].srp_client_start(self.nodes[SERVER].get_mleid(), srp_server_port)
+ self.nodes[client].srp_client_set_host_name(hostname)
+ self.nodes[client].srp_client_set_host_address(*addrs)
+ self.nodes[client].srp_client_add_service(instancename, SERVICE, port, priority, weight)
+
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[client].srp_client_get_host_state(), 'Registered')
+
+ def _assert_have_question(self, dig_result, question):
+ self.assertIn(question, dig_result['QUESTION'], (question, dig_result))
+
+ def _assert_have_answer(self, dig_result, record, additional=False):
+ for dig_answer in dig_result['ANSWER' if not additional else 'ADDITIONAL']:
+ dig_answer = list(dig_answer)
+ dig_answer[1:2] = [] # remove TTL from answer
+
+ record = list(record)
+
+ # convert IPv6 addresses to `ipaddress.IPv6Address` before matching
+ if dig_answer[2] == 'AAAA':
+ dig_answer[3] = ipaddress.IPv6Address(dig_answer[3])
+
+ if record[2] == 'AAAA':
+ record[3] = ipaddress.IPv6Address(record[3])
+
+ if dig_answer == record:
+ return
+
+ self.fail((record, dig_result))
+
+ def _assert_dig_result_matches(self, dig_result, expected_result):
+ self.assertEqual(dig_result['opcode'], expected_result.get('opcode', 'QUERY'), dig_result)
+ self.assertEqual(dig_result['status'], expected_result.get('status', 'NOERROR'), dig_result)
+
+ if 'QUESTION' in expected_result:
+ self.assertEqual(len(dig_result['QUESTION']), len(expected_result['QUESTION']), dig_result)
+
+ for question in expected_result['QUESTION']:
+ self._assert_have_question(dig_result, question)
+
+ if 'ANSWER' in expected_result:
+ self.assertEqual(len(dig_result['ANSWER']), len(expected_result['ANSWER']), dig_result)
+
+ for record in expected_result['ANSWER']:
+ self._assert_have_answer(dig_result, record, additional=False)
+
+ if 'ADDITIONAL' in expected_result:
+ self.assertEqual(len(dig_result['ADDITIONAL']), len(expected_result['ADDITIONAL']), dig_result)
+
+ for record in expected_result['ADDITIONAL']:
+ self._assert_have_answer(dig_result, record, additional=True)
+
+ logging.info("dig result matches:\r%s", json.dumps(dig_result, indent=True))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py
new file mode 100755
index 0000000..f67d49b
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# This test verifies that a single OMR and on-link prefix is chosen
+# and advertised when there are multiple Border Routers in the same
+# Thread and infrastructure network.
+#
+# Topology:
+# ----------------(eth)------------------
+# | | |
+# BR1 (Leader) ----- BR2 HOST
+# | |
+# ROUTER1 ROUTER2
+#
+
+BR1 = 1
+ROUTER1 = 2
+BR2 = 3
+ROUTER2 = 4
+HOST = 5
+
+CHANNEL1 = 18
+
+
+class MultiBorderRouters(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR1: {
+ 'name': 'BR_1',
+ 'allowlist': [ROUTER1, BR2],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ ROUTER1: {
+ 'name': 'Router_1',
+ 'allowlist': [BR1],
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ BR2: {
+ 'name': 'BR_2',
+ 'allowlist': [BR1, ROUTER2],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ ROUTER2: {
+ 'name': 'Router_2',
+ 'allowlist': [BR2],
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ HOST: {
+ 'name': 'Host',
+ 'is_host': True
+ },
+ }
+
+ def test(self):
+ self.nodes[HOST].start(start_radvd=False)
+ self.simulator.go(5)
+
+ self.nodes[BR1].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR1].get_state())
+
+ self.nodes[ROUTER1].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER1].get_state())
+
+ self.nodes[BR2].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[BR2].get_state())
+
+ self.nodes[ROUTER2].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER2].get_state())
+
+ #
+ # Case 1. bi-directional connectivity when there are two BRs.
+ #
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("BR2 addrs: %r", self.nodes[BR2].get_addrs())
+ logging.info("ROUTER2 addrs: %r", self.nodes[ROUTER2].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_prefixes()) == 1)
+
+ br1_omr_prefix = self.nodes[BR1].get_prefixes()[0]
+
+ # Each BR should independently register an external route for the on-link prefix.
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[BR2].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[ROUTER2].get_routes()) == 2)
+
+ external_route = self.nodes[BR1].get_routes()[0]
+ br1_on_link_prefix = external_route.split(' ')[0]
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[HOST].get_matched_ula_addresses(br1_on_link_prefix)) == 1)
+
+ # Router1 and Router2 can ping each other inside the Thread network.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+ self.assertTrue(self.nodes[ROUTER2].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+
+ # Both Router1 and Router2 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_matched_ula_addresses(br1_on_link_prefix)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+ self.assertTrue(self.nodes[ROUTER2].ping(self.nodes[HOST].get_matched_ula_addresses(br1_on_link_prefix)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ #
+ # Case 2. Another BR continues providing Border Routing when current one is disabled.
+ #
+
+ self.nodes[BR1].disable_br()
+
+ self.simulator.go(15)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("BR2 addrs: %r", self.nodes[BR2].get_addrs())
+ logging.info("ROUTER2 addrs: %r", self.nodes[ROUTER2].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertGreaterEqual(len(self.nodes[HOST].get_addrs()), 2)
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_prefixes()) == 1)
+
+ br2_omr_prefix = self.nodes[BR1].get_prefixes()[0]
+ self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
+
+ # Only BR2 will register external route for the on-link prefix.
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_routes()) == 1)
+
+ br2_external_route = self.nodes[BR2].get_routes()[0]
+ br2_on_link_prefix = br2_external_route.split(' ')[0]
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+
+ self.assertTrue(len(self.nodes[HOST].get_matched_ula_addresses(br2_on_link_prefix)) == 1)
+
+ # Router1 and Router2 can ping each other inside the Thread network.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+ self.assertTrue(self.nodes[ROUTER2].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+
+ # Both Router1 and Router2 can ping to/from the Host on infra link.
+ for router in [ROUTER1, ROUTER2]:
+ self.assertTrue(self.nodes[router].ping(self.nodes[HOST].get_matched_ula_addresses(br2_on_link_prefix)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[router].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
new file mode 100755
index 0000000..a05432d
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# This test verifies bi-directional connectivity accross multiple Thread networks.
+#
+# Topology:
+# -------------(eth)----------------
+# | |
+# BR1 BR2
+# | |
+# ROUTER1 ROUTER2
+#
+# Thread Net1 Thread Net2
+#
+
+BR1 = 1
+ROUTER1 = 2
+BR2 = 3
+ROUTER2 = 4
+
+CHANNEL1 = 18
+CHANNEL2 = 19
+
+
+class MultiThreadNetworks(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR1: {
+ 'name': 'BR_1',
+ 'allowlist': [ROUTER1],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 1,
+ },
+ ROUTER1: {
+ 'name': 'Router_1',
+ 'allowlist': [BR1],
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 1,
+ },
+ BR2: {
+ 'name': 'BR_2',
+ 'allowlist': [ROUTER2],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'channel': CHANNEL2,
+ 'router_selection_jitter': 1,
+ },
+ ROUTER2: {
+ 'name': 'Router_2',
+ 'allowlist': [BR2],
+ 'version': '1.2',
+ 'channel': CHANNEL2,
+ 'router_selection_jitter': 1,
+ },
+ }
+
+ def test(self):
+ self.nodes[BR1].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR1].get_state())
+
+ self.nodes[ROUTER1].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER1].get_state())
+
+ self.nodes[BR2].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR2].get_state())
+
+ self.nodes[ROUTER2].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER2].get_state())
+
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("BR2 addrs: %r", self.nodes[BR2].get_addrs())
+ logging.info("ROUTER2 addrs: %r", self.nodes[ROUTER2].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR2].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_prefixes()) == 1)
+
+ br1_omr_prefix = self.nodes[BR1].get_prefixes()[0]
+ br2_omr_prefix = self.nodes[BR2].get_prefixes()[0]
+
+ self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
+
+ # Each BR should independently register an external route for the on-link prefix
+ # and OMR prefix in another Thread Network.
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[BR2].get_routes()) == 2)
+ self.assertTrue(len(self.nodes[ROUTER2].get_routes()) == 2)
+
+ br1_external_routes = self.nodes[BR1].get_routes()
+ br2_external_routes = self.nodes[BR2].get_routes()
+
+ br1_external_routes.sort()
+ br2_external_routes.sort()
+ self.assertNotEqual(br1_external_routes, br2_external_routes)
+
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[ROUTER2].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+ self.assertTrue(self.nodes[ROUTER2].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]))
+
+
+if __name__ == '__main__':
+ unittest.main()
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
new file mode 100644
index 0000000..180e70c
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_plat_udp_accessiblity.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+import unittest
+
+import thread_cert
+import config
+
+# Test description:
+# This test verifies UDP servers can be accessible using RLOC/ALOC/MLEID/LINK-LOCAL/OMR when PLAT_UDP is enabled.
+# This test uses SRP server for convince.
+#
+# Topology:
+# -----------(eth)------
+# |
+# BR1 (Leader)
+# |
+# ROUTER1
+#
+
+BR1 = 1
+ROUTER1 = 2
+
+
+class TestPlatUdpAccessibility(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR1: {
+ 'name': 'BR_1',
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'router_selection_jitter': 1,
+ },
+ ROUTER1: {
+ 'name': 'Router_1',
+ 'version': '1.2',
+ 'router_selection_jitter': 1,
+ },
+ }
+
+ def test(self):
+ self.nodes[BR1].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR1].get_state())
+ self.nodes[BR1].srp_server_set_enabled(True)
+
+ self.nodes[ROUTER1].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER1].get_state())
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[BR1].get_rloc()))
+
+ server_port = self.nodes[BR1].get_srp_server_port()
+
+ self._test_srp_server(self.nodes[BR1].get_mleid(), server_port)
+ self._test_srp_server(self.nodes[BR1].get_linklocal(), server_port)
+ self._test_srp_server(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0], server_port)
+ self._test_srp_server(self.nodes[BR1].get_rloc(), server_port)
+ for server_aloc in self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.ALOC):
+ self._test_srp_server(server_aloc, server_port)
+
+ self._testDhcp6ClientAfterReset(BR1, BR1, BR1)
+
+ def _testDhcp6ClientAfterReset(self, server, client, reset_device):
+ DHCP6_PREFIX = '2001::/64'
+
+ # Configure DHCP6 server
+ self.nodes[server].add_prefix(DHCP6_PREFIX, 'pdros')
+ self.simulator.go(3)
+ self.nodes[server].register_netdata()
+ self.simulator.go(10)
+
+ # Verify DHCP6 client works
+ self.assertTrue(self.nodes[client].get_addr(DHCP6_PREFIX))
+ self.simulator.go(3)
+
+ self.nodes[reset_device].reset()
+ self.nodes[reset_device].start()
+ self.simulator.go(5)
+ self.assertIn(self.nodes[reset_device].get_state(), ['leader', 'router'])
+ self.simulator.go(5)
+
+ if reset_device == server:
+ # Reconfigure DHCP6 server if necessary
+ self.nodes[server].add_prefix(DHCP6_PREFIX, 'pdros')
+ self.simulator.go(3)
+ self.nodes[server].register_netdata()
+
+ self.simulator.go(10)
+
+ # Verify DHCP6 client works after reset
+ self.assertTrue(self.nodes[client].get_addr(DHCP6_PREFIX))
+ self.simulator.go(3)
+
+ def _test_srp_server(self, server_addr, server_port):
+ print(f'Testing SRP server: {server_addr}:{server_port}')
+
+ # check if the SRP client can register to the SRP server
+ self.nodes[ROUTER1].srp_client_start(server_addr, server_port)
+ self.nodes[ROUTER1].srp_client_set_host_name('host1')
+ self.nodes[ROUTER1].srp_client_set_host_address(self.nodes[ROUTER1].get_rloc())
+ self.nodes[ROUTER1].srp_client_add_service('ins1', '_ipp._tcp', 11111)
+ self.simulator.go(3)
+ self.assertEqual(self.nodes[ROUTER1].srp_client_get_host_state(), 'Registered')
+
+ # check if the SRP client can remove from the SRP server
+ self.nodes[ROUTER1].srp_client_remove_host('host1')
+ self.nodes[ROUTER1].srp_client_remove_service('ins1', '_ipp._tcp')
+ self.simulator.go(3)
+ self.assertEqual(self.nodes[ROUTER1].srp_client_get_host_state(), 'Removed')
+
+ # stop the SRP client for the next round
+ self.nodes[ROUTER1].srp_client_stop()
+ self.simulator.go(3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/border_router/test_single_border_router.py b/tests/scripts/thread-cert/border_router/test_single_border_router.py
new file mode 100755
index 0000000..dc07be1
--- /dev/null
+++ b/tests/scripts/thread-cert/border_router/test_single_border_router.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import logging
+import unittest
+
+import config
+import thread_cert
+
+# Test description:
+# This test verifies bi-directional connectivity between Thread end device
+# and infra host.
+#
+# Topology:
+# ----------------(eth)--------------------
+# | |
+# BR1 (Leader) HOST
+# |
+# ROUTER1
+#
+
+BR1 = 1
+ROUTER1 = 2
+HOST = 4
+
+CHANNEL1 = 18
+
+# The two prefixes are set small enough that a random-generated OMR prefix is
+# very likely greater than them. So that the duckhorn BR will remove the random-generated one.
+ON_MESH_PREFIX1 = "fd00:00:00:01::/64"
+ON_MESH_PREFIX2 = "fd00:00:00:02::/64"
+
+
+class SingleBorderRouter(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ BR1: {
+ 'name': 'BR_1',
+ 'allowlist': [ROUTER1],
+ 'is_otbr': True,
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ ROUTER1: {
+ 'name': 'Router_1',
+ 'allowlist': [BR1],
+ 'version': '1.2',
+ 'channel': CHANNEL1,
+ 'router_selection_jitter': 2,
+ },
+ HOST: {
+ 'name': 'Host',
+ 'is_host': True
+ },
+ }
+
+ def test(self):
+ self.nodes[HOST].start(start_radvd=False)
+ self.simulator.go(5)
+
+ self.nodes[BR1].start()
+ self.simulator.go(5)
+ self.assertEqual('leader', self.nodes[BR1].get_state())
+
+ self.nodes[ROUTER1].start()
+ self.simulator.go(5)
+ self.assertEqual('router', self.nodes[ROUTER1].get_state())
+
+ #
+ # Case 1. There is no OMR prefix or on-link prefix.
+ #
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+
+ omr_prefix = self.nodes[BR1].get_prefixes()[0]
+ external_route = self.nodes[BR1].get_routes()[0]
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ br1_omr_address = self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+ router1_omr_address = self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
+ host_ula_address = self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ #
+ # Case 2. User adds smaller on-mesh prefix.
+ # 1. Should deregister our local OMR prefix.
+ # 2. Should re-register our local OMR prefix when user prefix
+ # is removed.
+ #
+
+ self.nodes[BR1].add_prefix(ON_MESH_PREFIX1)
+ self.nodes[BR1].add_prefix(ON_MESH_PREFIX2)
+ self.nodes[BR1].register_netdata()
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertGreaterEqual(len(self.nodes[HOST].get_addrs()), 2)
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 2)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 2)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 2)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 2)
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[1],
+ backbone=True))
+
+ # Remove user prefixes, should re-register local OMR prefix.
+ self.nodes[BR1].remove_prefix(ON_MESH_PREFIX1)
+ self.nodes[BR1].remove_prefix(ON_MESH_PREFIX2)
+ self.nodes[BR1].register_netdata()
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+
+ # The same local OMR and on-link prefix should be re-register.
+ self.assertEqual(omr_prefix, self.nodes[BR1].get_prefixes()[0])
+ self.assertEqual(omr_prefix, self.nodes[ROUTER1].get_prefixes()[0])
+ self.assertEqual(external_route, self.nodes[BR1].get_routes()[0])
+ self.assertEqual(external_route, self.nodes[ROUTER1].get_routes()[0])
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ self.assertEqual(br1_omr_address, self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(router1_omr_address, self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(host_ula_address, self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ #
+ # Case 3. OMR and on-link prefixes should be removed when Border Routing is
+ # explicitly disabled and added when Border Routing is enabled again.
+ #
+
+ self.nodes[BR1].disable_br()
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 0)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 0)
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
+
+ # Per RFC 4862, the host will not immediately remove the ULA address, but deprecate it.
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ self.nodes[BR1].enable_br()
+
+ # It takes around 10 seconds to start sending RA messages.
+ self.simulator.go(15)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+
+ # The same local OMR and on-link prefix should be re-registered.
+ self.assertEqual(omr_prefix, self.nodes[BR1].get_prefixes()[0])
+ self.assertEqual(omr_prefix, self.nodes[ROUTER1].get_prefixes()[0])
+ self.assertEqual(external_route, self.nodes[BR1].get_routes()[0])
+ self.assertEqual(external_route, self.nodes[ROUTER1].get_routes()[0])
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ self.assertEqual(br1_omr_address, self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(router1_omr_address, self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(host_ula_address, self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ #
+ # Case 4. The Routing Manager should be stopped if the infra interface went down.
+ #
+
+ self.nodes[BR1].disable_ether()
+
+ self.simulator.go(10)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 0)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 0)
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 0)
+
+ self.nodes[BR1].enable_ether()
+
+ # It takes around 10 seconds to start sending RA messages.
+ self.simulator.go(15)
+ self.collect_ipaddrs()
+
+ logging.info("BR1 addrs: %r", self.nodes[BR1].get_addrs())
+ logging.info("ROUTER1 addrs: %r", self.nodes[ROUTER1].get_addrs())
+ logging.info("HOST addrs: %r", self.nodes[HOST].get_addrs())
+
+ self.assertTrue(len(self.nodes[BR1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_prefixes()) == 1)
+ self.assertTrue(len(self.nodes[BR1].get_routes()) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_routes()) == 1)
+
+ # The same local OMR and on-link prefix should be re-registered.
+ self.assertEqual(omr_prefix, self.nodes[BR1].get_prefixes()[0])
+ self.assertEqual(omr_prefix, self.nodes[ROUTER1].get_prefixes()[0])
+ self.assertEqual(external_route, self.nodes[BR1].get_routes()[0])
+ self.assertEqual(external_route, self.nodes[ROUTER1].get_routes()[0])
+
+ self.assertTrue(len(self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
+ self.assertTrue(len(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)) == 1)
+
+ self.assertEqual(br1_omr_address, self.nodes[BR1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(router1_omr_address, self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0])
+ self.assertEqual(host_ula_address, self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])
+
+ # Router1 can ping to/from the Host on infra link.
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+ #
+ # Case 5. Test if the linux host is still reachable if rejoin the network.
+ #
+
+ self.nodes[HOST].disable_ether()
+ self.simulator.go(10)
+ self.nodes[HOST].enable_ether()
+ self.simulator.go(10)
+
+ self.assertTrue(self.nodes[ROUTER1].ping(self.nodes[HOST].get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))
+ self.assertTrue(self.nodes[HOST].ping(self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.OMR)[0],
+ backbone=True))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/config.py b/tests/scripts/thread-cert/config.py
index a1851c7..eaff213 100644
--- a/tests/scripts/thread-cert/config.py
+++ b/tests/scripts/thread-cert/config.py
@@ -78,6 +78,11 @@
ALL_DOMAIN_BBRS_ADDRESS = 'ff32:40:fd00:7d03:7d03:7d03:0:3'
ALL_DOMAIN_BBRS_ADDRESS_ALTER = 'ff32:40:fd00:7d04:7d04:7d04:0:3'
+ONLINK_PREFIX = 'fd00:dead:face::/64'
+
+# Any address starts with 'fd' are considered on-link address.
+ONLINK_PREFIX_REGEX_PATTERN = '^fd'
+
DEFAULT_MASTER_KEY = bytearray([
0x00,
0x11,
@@ -106,6 +111,8 @@
ML_EID = 'ML_EID'
DUA = 'DUA'
BACKBONE_GUA = 'BACKBONE_GUA'
+ OMR = 'OMR'
+ ONLINK_ULA = 'ONLINK_ULA'
RSSI = {
diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py
index 3f3fc7c..58ab2c4 100755
--- a/tests/scripts/thread-cert/node.py
+++ b/tests/scripts/thread-cert/node.py
@@ -51,6 +51,8 @@
class OtbrDocker:
+ RESET_DELAY = 3
+
_socat_proc = None
_ot_rcp_proc = None
_docker_proc = None
@@ -217,12 +219,94 @@
else:
return lines
+ def dns_dig(self, server: str, name: str, qtype: str):
+ """
+ Run dig command to query a DNS server.
+
+ Args:
+ server: the server address.
+ name: the name to query.
+ qtype: the query type (e.g. AAAA, PTR, TXT, SRV).
+
+ Returns:
+ The dig result similar as below:
+ {
+ "opcode": "QUERY",
+ "status": "NOERROR",
+ "id": "64144",
+ "QUESTION": [
+ ('google.com.', 'IN', 'AAAA')
+ ],
+ "ANSWER": [
+ ('google.com.', 107, 'IN', 'AAAA', '2404:6800:4008:c00::71'),
+ ('google.com.', 107, 'IN', 'AAAA', '2404:6800:4008:c00::8a'),
+ ('google.com.', 107, 'IN', 'AAAA', '2404:6800:4008:c00::66'),
+ ('google.com.', 107, 'IN', 'AAAA', '2404:6800:4008:c00::8b'),
+ ],
+ "ADDITIONAL": [
+ ],
+ }
+ """
+ output = self.bash(f'dig -6 @{server} {name} {qtype}')
+
+ section = None
+ dig_result = {
+ 'QUESTION': [],
+ 'ANSWER': [],
+ 'ADDITIONAL': [],
+ }
+
+ for line in output:
+ line = line.strip()
+
+ if line.startswith(';; ->>HEADER<<- '):
+ headers = line[len(';; ->>HEADER<<- '):].split(', ')
+ for header in headers:
+ key, val = header.split(': ')
+ dig_result[key] = val
+
+ continue
+
+ if line == ';; QUESTION SECTION:':
+ section = 'QUESTION'
+ continue
+ elif line == ';; ANSWER SECTION:':
+ section = 'ANSWER'
+ continue
+ elif line == ';; ADDITIONAL SECTION:':
+ section = 'ADDITIONAL'
+ continue
+ elif section and not line:
+ section = None
+ continue
+
+ if section:
+ assert line
+
+ if section == 'QUESTION':
+ assert line.startswith(';')
+ line = line[1:]
+
+ record = list(line.split())
+
+ if section != 'QUESTION':
+ record[1] = int(record[1])
+ if record[3] == 'SRV':
+ record[4], record[5], record[6] = map(int, [record[4], record[5], record[6]])
+
+ dig_result[section].append(tuple(record))
+
+ return dig_result
+
def _setup_sysctl(self):
self.bash(f'sysctl net.ipv6.conf.{self.ETH_DEV}.accept_ra=2')
+ self.bash(f'sysctl net.ipv6.conf.{self.ETH_DEV}.accept_ra_rt_info_max_plen=64')
class OtCli:
+ RESET_DELAY = 0.1
+
def __init__(self, nodeid, is_mtd=False, version=None, is_bbr=False, **kwargs):
self.verbose = int(float(os.getenv('VERBOSE', 0)))
self.node_type = os.getenv('NODE_TYPE', 'sim')
@@ -261,8 +345,13 @@
# Default command if no match below, will be overridden if below conditions are met.
cmd = './ot-cli-%s' % (mode)
+ # For Thread 1.2 MTD node, use ot-cli-mtd build regardless of OT_CLI_PATH
+ if self.version == '1.2' and mode == 'mtd' and 'top_builddir' in os.environ:
+ srcdir = os.environ['top_builddir']
+ cmd = '%s/examples/apps/cli/ot-cli-%s %d' % (srcdir, mode, nodeid)
+
# If Thread version of node matches the testing environment version.
- if self.version == self.env_version:
+ elif self.version == self.env_version:
# Load Thread 1.2 BBR device when testing Thread 1.2 scenarios
# which requires device with Backbone functionality.
if self.version == '1.2' and self.is_bbr:
@@ -283,6 +372,7 @@
if 'RADIO_DEVICE' in os.environ:
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (os.environ['RADIO_DEVICE'],
nodeid)
+ self.is_posix = True
else:
cmd += ' %d' % nodeid
@@ -298,6 +388,7 @@
if 'RADIO_DEVICE_1_1' in os.environ:
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
os.environ['RADIO_DEVICE_1_1'], nodeid)
+ self.is_posix = True
else:
cmd += ' %d' % nodeid
@@ -326,6 +417,7 @@
if 'RADIO_DEVICE' in os.environ:
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (os.environ['RADIO_DEVICE'],
nodeid)
+ self.is_posix = True
else:
args = ''
@@ -365,6 +457,7 @@
if 'RADIO_DEVICE_1_1' in os.environ:
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (os.environ['RADIO_DEVICE_1_1'],
nodeid)
+ self.is_posix = True
else:
args = ''
@@ -418,6 +511,7 @@
def __init__(self, nodeid, name=None, simulator=None, **kwargs):
self.nodeid = nodeid
self.name = name or ('Node%d' % nodeid)
+ self.is_posix = False
self.simulator = simulator
if self.simulator:
@@ -444,6 +538,9 @@
if timeout <= 0:
raise
+ def _expect_done(self, timeout=-1):
+ self._expect('Done', timeout)
+
def _prepare_pattern(self, pattern):
"""Build a new pexpect pattern matching line by line.
@@ -493,12 +590,12 @@
return results
- def _expect_command_output(self, cmd: str):
+ def _expect_command_output(self, cmd: str, ignore_logs=True):
lines = []
cmd_output_started = False
while True:
- self._expect(r"[^\n]+")
+ self._expect(r"[^\n]+\n")
line = self.pexpect.match.group(0).decode('utf8').strip()
if line.startswith('> '):
@@ -511,7 +608,7 @@
cmd_output_started = True
continue
- if not cmd_output_started:
+ if not cmd_output_started or (ignore_logs and self.__is_logging_line(line)):
continue
if line == 'Done':
@@ -524,6 +621,9 @@
print(f'_expect_command_output({cmd!r}) returns {lines!r}')
return lines
+ def __is_logging_line(self, line: str) -> bool:
+ return len(line) >= 6 and line[:6] in {'[DEBG]', '[INFO]', '[NOTE]', '[WARN]', '[CRIT]', '[NONE]'}
+
def read_cert_messages_in_commissioning_log(self, timeout=-1):
"""Get the log of the traffic after DTLS handshake.
"""
@@ -588,7 +688,7 @@
def set_mode(self, mode):
cmd = 'mode %s' % mode
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def debug(self, level):
# `debug` command will not trigger interaction with simulator
@@ -604,29 +704,29 @@
def interface_up(self):
self.send_command('ifconfig up')
- self._expect('Done')
+ self._expect_done()
def interface_down(self):
self.send_command('ifconfig down')
- self._expect('Done')
+ self._expect_done()
def thread_start(self):
self.send_command('thread start')
- self._expect('Done')
+ self._expect_done()
def thread_stop(self):
self.send_command('thread stop')
- self._expect('Done')
+ self._expect_done()
def commissioner_start(self):
cmd = 'commissioner start'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def commissioner_stop(self):
cmd = 'commissioner stop'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def commissioner_state(self):
states = [r'disabled', r'petitioning', r'active']
@@ -636,32 +736,32 @@
def commissioner_add_joiner(self, addr, psk):
cmd = 'commissioner joiner add %s %s' % (addr, psk)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def commissioner_set_provisioning_url(self, provisioning_url=''):
cmd = 'commissioner provisioningurl %s' % provisioning_url
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def joiner_start(self, pskd='', provisioning_url=''):
cmd = 'joiner start %s %s' % (pskd, provisioning_url)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def clear_allowlist(self):
cmd = 'macfilter addr clear'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def enable_allowlist(self):
cmd = 'macfilter addr allowlist'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def disable_allowlist(self):
cmd = 'macfilter addr disable'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def add_allowlist(self, addr, rssi=None):
cmd = 'macfilter addr add %s' % addr
@@ -670,7 +770,7 @@
cmd += ' %s' % rssi
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_bbr_registration_jitter(self):
self.send_command('bbr jitter')
@@ -679,22 +779,275 @@
def set_bbr_registration_jitter(self, jitter):
cmd = 'bbr jitter %d' % jitter
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
+
+ def srp_server_set_enabled(self, enable):
+ cmd = f'srp server {"enable" if enable else "disable"}'
+ self.send_command(cmd)
+ self._expect_done()
+
+ def srp_server_set_lease_range(self, min_lease, max_lease, min_key_lease, max_key_lease):
+ self.send_command(f'srp server lease {min_lease} {max_lease} {min_key_lease} {max_key_lease}')
+ self._expect_done()
+
+ def srp_server_get_hosts(self):
+ """Returns the host list on the SRP server as a list of property
+ dictionary.
+
+ Example output:
+ [{
+ 'fullname': 'my-host.default.service.arpa.',
+ 'name': 'my-host',
+ 'deleted': 'false',
+ 'addresses': ['2001::1', '2001::2']
+ }]
+ """
+
+ cmd = 'srp server host'
+ self.send_command(cmd)
+ lines = self._expect_command_output(cmd)
+ host_list = []
+ while lines:
+ host = {}
+
+ host['fullname'] = lines.pop(0).strip()
+ host['name'] = host['fullname'].split('.')[0]
+
+ host['deleted'] = lines.pop(0).strip().split(':')[1].strip()
+ if host['deleted'] == 'true':
+ host_list.append(host)
+ continue
+
+ addresses = lines.pop(0).strip().split('[')[1].strip(' ]').split(',')
+ map(str.strip, addresses)
+ host['addresses'] = [addr for addr in addresses if addr]
+
+ host_list.append(host)
+
+ return host_list
+
+ def srp_server_get_host(self, host_name):
+ """Returns host on the SRP server that matches given host name.
+
+ Example usage:
+ self.srp_server_get_host("my-host")
+ """
+
+ for host in self.srp_server_get_hosts():
+ if host_name == host['name']:
+ return host
+
+ def srp_server_get_services(self):
+ """Returns the service list on the SRP server as a list of property
+ dictionary.
+
+ Example output:
+ [{
+ 'fullname': 'my-service._ipps._tcp.default.service.arpa.',
+ 'instance': 'my-service',
+ 'name': '_ipps._tcp',
+ 'deleted': 'false',
+ 'port': '12345',
+ 'priority': '0',
+ 'weight': '0',
+ 'TXT': ['abc=010203'],
+ 'host_fullname': 'my-host.default.service.arpa.',
+ 'host': 'my-host',
+ 'addresses': ['2001::1', '2001::2']
+ }]
+
+ Note that the TXT data is output as a HEX string.
+ """
+
+ cmd = 'srp server service'
+ self.send_command(cmd)
+ lines = self._expect_command_output(cmd)
+ service_list = []
+ while lines:
+ service = {}
+
+ service['fullname'] = lines.pop(0).strip()
+ name_labels = service['fullname'].split('.')
+ service['instance'] = name_labels[0]
+ service['name'] = '.'.join(name_labels[1:3])
+
+ service['deleted'] = lines.pop(0).strip().split(':')[1].strip()
+ if service['deleted'] == 'true':
+ service_list.append(service)
+ continue
+
+ # 'port', 'priority', 'weight'
+ for i in range(0, 3):
+ key_value = lines.pop(0).strip().split(':')
+ service[key_value[0].strip()] = key_value[1].strip()
+
+ txt_entries = lines.pop(0).strip().split('[')[1].strip(' ]').split(',')
+ txt_entries = map(str.strip, txt_entries)
+ service['TXT'] = [txt for txt in txt_entries if txt]
+
+ service['host_fullname'] = lines.pop(0).strip().split(':')[1].strip()
+ service['host'] = service['host_fullname'].split('.')[0]
+
+ addresses = lines.pop(0).strip().split('[')[1].strip(' ]').split(',')
+ addresses = map(str.strip, addresses)
+ service['addresses'] = [addr for addr in addresses if addr]
+
+ service_list.append(service)
+
+ return service_list
+
+ def srp_server_get_service(self, instance_name, service_name):
+ """Returns service on the SRP server that matches given instance
+ name and service name.
+
+ Example usage:
+ self.srp_server_get_service("my-service", "_ipps._tcp")
+ """
+
+ for service in self.srp_server_get_services():
+ if (instance_name == service['instance'] and service_name == service['name']):
+ return service
+
+ def get_srp_server_port(self):
+ """Returns the SRP server UDP port by parsing
+ the SRP Server Data in Network Data.
+ """
+
+ for service in self.get_services():
+ # TODO: for now, we are using 0xfd as the SRP service data.
+ # May use a dedicated bit flag for SRP server.
+ if int(service[1], 16) == 0x5d:
+ # The SRP server data are 2-bytes UDP port number.
+ return int(service[2], 16)
+
+ def srp_client_start(self, server_address, server_port):
+ self.send_command(f'srp client start {server_address} {server_port}')
+ self._expect_done()
+
+ def srp_client_stop(self):
+ self.send_command(f'srp client stop')
+ self._expect_done()
+
+ def srp_client_get_state(self):
+ cmd = 'srp client state'
+ self.send_command(cmd)
+ return self._expect_command_output(cmd)[0]
+
+ def srp_client_get_auto_start_mode(self):
+ cmd = 'srp client autostart'
+ self.send_command(cmd)
+ return self._expect_command_output(cmd)[0]
+
+ def srp_client_enable_auto_start_mode(self):
+ self.send_command(f'srp client autostart enable')
+ self._expect_done()
+
+ def srp_client_disable_auto_start_mode(self):
+ self.send_command(f'srp client autostart able')
+ self._expect_done()
+
+ def srp_client_get_server_address(self):
+ cmd = 'srp client server address'
+ self.send_command(cmd)
+ return self._expect_command_output(cmd)[0]
+
+ def srp_client_get_server_port(self):
+ cmd = 'srp client server port'
+ self.send_command(cmd)
+ return int(self._expect_command_output(cmd)[0])
+
+ def srp_client_get_host_state(self):
+ cmd = 'srp client host state'
+ self.send_command(cmd)
+ return self._expect_command_output(cmd)[0]
+
+ def srp_client_set_host_name(self, name):
+ self.send_command(f'srp client host name {name}')
+ self._expect_done()
+
+ def srp_client_get_host_name(self):
+ self.send_command(f'srp client host name')
+ self._expect_done()
+
+ def srp_client_remove_host(self, remove_key=False):
+ self.send_command(f'srp client host remove {"1" if remove_key else "0"}')
+ self._expect_done()
+
+ def srp_client_clear_host(self):
+ self.send_command(f'srp client host clear')
+ self._expect_done()
+
+ def srp_client_set_host_address(self, *addrs: str):
+ self.send_command(f'srp client host address {" ".join(addrs)}')
+ self._expect_done()
+
+ def srp_client_get_host_address(self):
+ self.send_command(f'srp client host address')
+ self._expect_done()
+
+ def srp_client_add_service(self, instance_name, service_name, port, priority=0, weight=0, txt_entries=[]):
+ txt_record = "".join(self._encode_txt_entry(entry) for entry in txt_entries)
+ self.send_command(
+ f'srp client service add {instance_name} {service_name} {port} {priority} {weight} {txt_record}')
+ self._expect_done()
+
+ def srp_client_remove_service(self, instance_name, service_name):
+ self.send_command(f'srp client service remove {instance_name} {service_name}')
+ self._expect_done()
+
+ def srp_client_get_services(self):
+ cmd = 'srp client service'
+ self.send_command(cmd)
+ service_lines = self._expect_command_output(cmd)
+ return [self._parse_srp_client_service(line) for line in service_lines]
+
+ def _encode_txt_entry(self, entry):
+ """Encodes the TXT entry to the DNS-SD TXT record format as a HEX string.
+
+ Example usage:
+ self._encode_txt_entries(['abc']) -> '03616263'
+ self._encode_txt_entries(['def=']) -> '046465663d'
+ self._encode_txt_entries(['xyz=XYZ']) -> '0778797a3d58595a'
+ """
+ return '{:02x}'.format(len(entry)) + "".join("{:02x}".format(ord(c)) for c in entry)
+
+ def _parse_srp_client_service(self, line: str):
+ """Parse one line of srp service list into a dictionary which
+ maps string keys to string values.
+
+ Example output for input
+ 'instance:\"%s\", name:\"%s\", state:%s, port:%d, priority:%d, weight:%d"'
+ {
+ 'instance': 'my-service',
+ 'name': '_ipps._udp',
+ 'state': 'ToAdd',
+ 'port': '12345',
+ 'priority': '0',
+ 'weight': '0'
+ }
+
+ Note that value of 'port', 'priority' and 'weight' are represented
+ as strings but not integers.
+ """
+ key_values = [word.strip().split(':') for word in line.split(',')]
+ keys = [key_value[0] for key_value in key_values]
+ values = [key_value[1].strip('"') for key_value in key_values]
+ return dict(zip(keys, values))
def enable_backbone_router(self):
cmd = 'bbr enable'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def disable_backbone_router(self):
cmd = 'bbr disable'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def register_backbone_router(self):
cmd = 'bbr register'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_backbone_router_state(self):
states = [r'Disabled', r'Primary', r'Secondary']
@@ -742,7 +1095,7 @@
cmd += ' timeout %d' % mlr_timeout
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_domain_prefix(self, prefix, flags='prosD'):
self.add_prefix(prefix, flags)
@@ -763,7 +1116,7 @@
if iid is not None:
cmd += ' ' + str(iid)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_dua_iid(self, iid: str):
assert len(iid) == 16
@@ -771,12 +1124,12 @@
cmd = 'dua iid {}'.format(iid)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def clear_dua_iid(self):
cmd = 'dua iid clear'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def multicast_listener_list(self) -> Dict[ipaddress.IPv6Address, int]:
cmd = 'bbr mgmt mlr listener'
@@ -797,7 +1150,7 @@
def multicast_listener_clear(self):
cmd = f'bbr mgmt mlr listener clear'
self.send_command(cmd)
- self._expect("Done")
+ self._expect_done()
def multicast_listener_add(self, ip: Union[ipaddress.IPv6Address, str], timeout: int = 0):
if not isinstance(ip, ipaddress.IPv6Address):
@@ -810,7 +1163,7 @@
def set_next_mlr_response(self, status: int):
cmd = 'bbr mgmt mlr response {}'.format(status)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def register_multicast_listener(self, *ipaddrs: Union[ipaddress.IPv6Address, str], timeout=None):
assert len(ipaddrs) > 0, ipaddrs
@@ -833,17 +1186,17 @@
def set_link_quality(self, addr, lqi):
cmd = 'macfilter rss add-lqi %s %s' % (addr, lqi)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_outbound_link_quality(self, lqi):
cmd = 'macfilter rss add-lqi * %s' % (lqi)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def remove_allowlist(self, addr):
cmd = 'macfilter addr remove %s' % addr
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_addr16(self):
self.send_command('rloc16')
@@ -863,7 +1216,7 @@
assert len(addr64) == 16
int(addr64, 16)
self.send_command('extaddr %s' % addr64)
- self._expect('Done')
+ self._expect_done()
def get_eui64(self):
self.send_command('eui64')
@@ -871,7 +1224,7 @@
def set_extpanid(self, extpanid):
self.send_command('extpanid %s' % extpanid)
- self._expect('Done')
+ self._expect_done()
def get_joiner_id(self):
self.send_command('joiner id')
@@ -884,7 +1237,7 @@
def set_channel(self, channel):
cmd = 'channel %d' % channel
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_masterkey(self):
self.send_command('masterkey')
@@ -893,7 +1246,7 @@
def set_masterkey(self, masterkey):
cmd = 'masterkey %s' % masterkey
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_key_sequence_counter(self):
self.send_command('keysequence counter')
@@ -903,17 +1256,17 @@
def set_key_sequence_counter(self, key_sequence_counter):
cmd = 'keysequence counter %d' % key_sequence_counter
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_key_switch_guardtime(self, key_switch_guardtime):
cmd = 'keysequence guardtime %d' % key_switch_guardtime
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_network_id_timeout(self, network_id_timeout):
cmd = 'networkidtimeout %d' % network_id_timeout
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def _escape_escapable(self, string):
"""Escape CLI escapable characters in the given string.
@@ -936,7 +1289,7 @@
def set_network_name(self, network_name):
cmd = 'networkname %s' % self._escape_escapable(network_name)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_panid(self):
self.send_command('panid')
@@ -946,12 +1299,12 @@
def set_panid(self, panid=config.PANID):
cmd = 'panid %d' % panid
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_parent_priority(self, priority):
cmd = 'parentpriority %d' % priority
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_preferred_partition_id(self):
self.send_command('partitionid preferred')
@@ -960,7 +1313,7 @@
def set_preferred_partition_id(self, partition_id):
cmd = 'partitionid preferred %d' % partition_id
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_pollperiod(self):
self.send_command('pollperiod')
@@ -968,41 +1321,41 @@
def set_pollperiod(self, pollperiod):
self.send_command('pollperiod %d' % pollperiod)
- self._expect('Done')
+ self._expect_done()
def get_csl_info(self):
self.send_command('csl')
- self._expect('Done')
+ self._expect_done()
def set_csl_channel(self, csl_channel):
self.send_command('csl channel %d' % csl_channel)
- self._expect('Done')
+ self._expect_done()
def set_csl_period(self, csl_period):
self.send_command('csl period %d' % csl_period)
- self._expect('Done')
+ self._expect_done()
def set_csl_timeout(self, csl_timeout):
self.send_command('csl timeout %d' % csl_timeout)
- self._expect('Done')
+ self._expect_done()
def send_mac_emptydata(self):
self.send_command('mac send emptydata')
- self._expect('Done')
+ self._expect_done()
def send_mac_datarequest(self):
self.send_command('mac send datarequest')
- self._expect('Done')
+ self._expect_done()
def set_router_upgrade_threshold(self, threshold):
cmd = 'routerupgradethreshold %d' % threshold
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_router_downgrade_threshold(self, threshold):
cmd = 'routerdowngradethreshold %d' % threshold
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_router_downgrade_threshold(self) -> int:
self.send_command('routerdowngradethreshold')
@@ -1011,7 +1364,7 @@
def set_router_eligible(self, enable: bool):
cmd = f'routereligible {"enable" if enable else "disable"}'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_router_eligible(self) -> bool:
states = [r'Disabled', r'Enabled']
@@ -1021,12 +1374,12 @@
def prefer_router_id(self, router_id):
cmd = 'preferrouterid %d' % router_id
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def release_router_id(self, router_id):
cmd = 'releaserouterid %d' % router_id
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_state(self):
states = [r'detached', r'child', r'router', r'leader', r'disabled']
@@ -1036,7 +1389,7 @@
def set_state(self, state):
cmd = 'state %s' % state
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_timeout(self):
self.send_command('childtimeout')
@@ -1045,12 +1398,12 @@
def set_timeout(self, timeout):
cmd = 'childtimeout %d' % timeout
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_max_children(self, number):
cmd = 'childmax %d' % number
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_weight(self):
self.send_command('leaderweight')
@@ -1059,27 +1412,27 @@
def set_weight(self, weight):
cmd = 'leaderweight %d' % weight
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def add_ipaddr(self, ipaddr):
cmd = 'ipaddr add %s' % ipaddr
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def del_ipaddr(self, ipaddr):
cmd = 'ipaddr del %s' % ipaddr
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def add_ipmaddr(self, ipmaddr):
cmd = 'ipmaddr add %s' % ipmaddr
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def del_ipmaddr(self, ipmaddr):
cmd = 'ipmaddr del %s' % ipmaddr
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def get_addrs(self):
self.send_command('ipaddr')
@@ -1162,12 +1515,23 @@
serverData,
)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def remove_service(self, enterpriseNumber, serviceData):
cmd = 'service remove %s %s' % (enterpriseNumber, serviceData)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
+
+ def __getOmrAddress(self):
+ prefixes = [prefix.split('::')[0] for prefix in self.get_prefixes()]
+ omr_addrs = []
+ for addr in self.get_addrs():
+ for prefix in prefixes:
+ if (addr.startswith(prefix)):
+ omr_addrs.append(addr)
+ break
+
+ return omr_addrs
def __getLinkLocalAddress(self):
for ip6Addr in self.get_addrs():
@@ -1242,6 +1606,8 @@
return self.__getDua()
elif address_type == config.ADDRESS_TYPE.BACKBONE_GUA:
return self._getBackboneGua()
+ elif address_type == config.ADDRESS_TYPE.OMR:
+ return self.__getOmrAddress()
else:
return None
@@ -1252,17 +1618,62 @@
def set_context_reuse_delay(self, delay):
cmd = 'contextreusedelay %d' % delay
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def add_prefix(self, prefix, flags='paosr', prf='med'):
cmd = 'prefix add %s %s %s' % (prefix, flags, prf)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def remove_prefix(self, prefix):
cmd = 'prefix remove %s' % prefix
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
+
+ def enable_br(self):
+ self.send_command('br enable')
+ self._expect_done()
+
+ def disable_br(self):
+ self.send_command('br disable')
+ self._expect_done()
+
+ def get_prefixes(self):
+ return self.get_netdata()['Prefixes']
+
+ def get_routes(self):
+ return self.get_netdata()['Routes']
+
+ def get_services(self):
+ netdata = self.netdata_show()
+ services = []
+ services_section = False
+
+ for line in netdata:
+ if line.startswith('Services:'):
+ services_section = True
+ elif services_section:
+ services.append(line.strip().split(' '))
+ return services
+
+ def netdata_show(self):
+ self.send_command('netdata show')
+ return self._expect_command_output('netdata show')
+
+ def get_netdata(self):
+ raw_netdata = self.netdata_show()
+ netdata = {'Prefixes': [], 'Routes': [], 'Services': []}
+ key_list = ['Prefixes', 'Routes', 'Services']
+ key = None
+
+ for i in range(0, len(raw_netdata)):
+ keys = list(filter(raw_netdata[i].startswith, key_list))
+ if keys != []:
+ key = keys[0]
+ elif key is not None:
+ netdata[key].append(raw_netdata[i])
+
+ return netdata
def add_route(self, prefix, stable=False, prf='med'):
cmd = 'route add %s ' % prefix
@@ -1270,16 +1681,16 @@
cmd += 's'
cmd += ' %s' % prf
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def remove_route(self, prefix):
cmd = 'route remove %s' % prefix
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def register_netdata(self):
self.send_command('netdata register')
- self._expect('Done')
+ self._expect_done()
def send_network_diag_get(self, addr, tlv_types):
self.send_command('networkdiagnostic get %s %s' % (addr, ' '.join([str(t.value) for t in tlv_types])))
@@ -1290,7 +1701,7 @@
else:
timeout = 8
- self._expect('Done', timeout=timeout)
+ self._expect_done(timeout=timeout)
def send_network_diag_reset(self, addr, tlv_types):
self.send_command('networkdiagnostic reset %s %s' % (addr, ' '.join([str(t.value) for t in tlv_types])))
@@ -1301,7 +1712,7 @@
else:
timeout = 8
- self._expect('Done', timeout=timeout)
+ self._expect_done(timeout=timeout)
def energy_scan(self, mask, count, period, scan_duration, ipaddr):
cmd = 'commissioner energy %d %d %d %d %s' % (
@@ -1375,12 +1786,12 @@
def reset(self):
self.send_command('reset')
- time.sleep(0.1)
+ time.sleep(self.RESET_DELAY)
def set_router_selection_jitter(self, jitter):
cmd = 'routerselectionjitter %d' % jitter
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def set_active_dataset(
self,
@@ -1392,31 +1803,31 @@
security_policy=[],
):
self.send_command('dataset clear')
- self._expect('Done')
+ self._expect_done()
cmd = 'dataset activetimestamp %d' % timestamp
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if panid is not None:
cmd = 'dataset panid %d' % panid
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if channel is not None:
cmd = 'dataset channel %d' % channel
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if channel_mask is not None:
cmd = 'dataset channelmask %d' % channel_mask
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if master_key is not None:
cmd = 'dataset masterkey %s' % master_key
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if security_policy and len(security_policy) == 2:
cmd = 'dataset securitypolicy %s %s' % (
@@ -1424,48 +1835,65 @@
security_policy[1],
)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
# Set the meshlocal prefix in config.py
self.send_command('dataset meshlocalprefix %s' % config.MESH_LOCAL_PREFIX.split('/')[0])
- self._expect('Done')
+ self._expect_done()
self.send_command('dataset commit active')
- self._expect('Done')
+ self._expect_done()
def set_pending_dataset(self, pendingtimestamp, activetimestamp, panid=None, channel=None, delay=None):
self.send_command('dataset clear')
- self._expect('Done')
+ self._expect_done()
cmd = 'dataset pendingtimestamp %d' % pendingtimestamp
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
cmd = 'dataset activetimestamp %d' % activetimestamp
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if panid is not None:
cmd = 'dataset panid %d' % panid
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if channel is not None:
cmd = 'dataset channel %d' % channel
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
if delay is not None:
cmd = 'dataset delay %d' % delay
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
# Set the meshlocal prefix in config.py
self.send_command('dataset meshlocalprefix %s' % config.MESH_LOCAL_PREFIX.split('/')[0])
- self._expect('Done')
+ self._expect_done()
self.send_command('dataset commit pending')
- self._expect('Done')
+ self._expect_done()
+
+ def start_dataset_updater(self, panid=None, channel=None):
+ self.send_command('dataset clear')
+ self._expect_done()
+
+ if panid is not None:
+ cmd = 'dataset panid %d' % panid
+ self.send_command(cmd)
+ self._expect_done()
+
+ if channel is not None:
+ cmd = 'dataset channel %d' % channel
+ self.send_command(cmd)
+ self._expect_done()
+
+ self.send_command('dataset updater start')
+ self._expect_done()
def announce_begin(self, mask, count, period, ipaddr):
cmd = 'commissioner announce %d %d %d %s' % (
@@ -1475,7 +1903,7 @@
ipaddr,
)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def send_mgmt_active_set(
self,
@@ -1519,7 +1947,7 @@
cmd += '-x %s ' % binary
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def send_mgmt_active_get(self, addr='', tlvs=[]):
cmd = 'dataset mgmtgetcommand active'
@@ -1534,7 +1962,7 @@
cmd += tlv_str
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def send_mgmt_pending_get(self, addr='', tlvs=[]):
cmd = 'dataset mgmtgetcommand pending'
@@ -1549,7 +1977,7 @@
cmd += tlv_str
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def send_mgmt_pending_set(
self,
@@ -1588,7 +2016,7 @@
cmd += 'networkname %s ' % self._escape_escapable(network_name)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coap_cancel(self):
"""
@@ -1596,7 +2024,7 @@
"""
cmd = 'coap cancel'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coap_delete(self, ipaddr, uri, con=False, payload=None):
"""
@@ -1610,6 +2038,12 @@
"""
return self._coap_rq('get', ipaddr, uri, con, payload)
+ def coap_get_block(self, ipaddr, uri, size=16, count=0):
+ """
+ Send a GET request via CoAP.
+ """
+ return self._coap_rq_block('get', ipaddr, uri, size, count)
+
def coap_observe(self, ipaddr, uri, con=False, payload=None):
"""
Send a GET request via CoAP with Observe set.
@@ -1622,12 +2056,24 @@
"""
return self._coap_rq('post', ipaddr, uri, con, payload)
+ def coap_post_block(self, ipaddr, uri, size=16, count=0):
+ """
+ Send a POST request via CoAP.
+ """
+ return self._coap_rq_block('post', ipaddr, uri, size, count)
+
def coap_put(self, ipaddr, uri, con=False, payload=None):
"""
Send a PUT request via CoAP.
"""
return self._coap_rq('put', ipaddr, uri, con, payload)
+ def coap_put_block(self, ipaddr, uri, size=16, count=0):
+ """
+ Send a PUT request via CoAP.
+ """
+ return self._coap_rq_block('put', ipaddr, uri, size, count)
+
def _coap_rq(self, method, ipaddr, uri, con=False, payload=None):
"""
Issue a GET/POST/PUT/DELETE/GET OBSERVE request.
@@ -1644,6 +2090,20 @@
self.send_command(cmd)
return self.coap_wait_response()
+ def _coap_rq_block(self, method, ipaddr, uri, size=16, count=0):
+ """
+ Issue a GET/POST/PUT/DELETE/GET OBSERVE BLOCK request.
+ """
+ cmd = 'coap %s %s %s' % (method, ipaddr, uri)
+
+ cmd += ' block-%d' % size
+
+ if count != 0:
+ cmd += ' %d' % count
+
+ self.send_command(cmd)
+ return self.coap_wait_response()
+
def coap_wait_response(self):
"""
Wait for a CoAP response, and return it.
@@ -1664,7 +2124,10 @@
observe = int(observe, base=10)
if payload is not None:
- payload = binascii.a2b_hex(payload).decode('UTF-8')
+ try:
+ payload = binascii.a2b_hex(payload).decode('UTF-8')
+ except UnicodeDecodeError:
+ pass
# Return the values received
return dict(source=source, observe=observe, payload=payload)
@@ -1728,6 +2191,14 @@
"""
cmd = 'coap resource %s' % path
self.send_command(cmd)
+ self._expect_done()
+
+ def coap_set_resource_path_block(self, path, count=0):
+ """
+ Set the path for the CoAP resource and how many blocks can be received from this resource.
+ """
+ cmd = 'coap resource %s %d' % (path, count)
+ self.send_command(cmd)
self._expect('Done')
def coap_set_content(self, content):
@@ -1736,7 +2207,7 @@
"""
cmd = 'coap set %s' % content
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coap_start(self):
"""
@@ -1744,7 +2215,7 @@
"""
cmd = 'coap start'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coap_stop(self):
"""
@@ -1759,30 +2230,30 @@
else:
timeout = 5
- self._expect('Done', timeout=timeout)
+ self._expect_done(timeout=timeout)
def coaps_start_psk(self, psk, pskIdentity):
cmd = 'coaps psk %s %s' % (psk, pskIdentity)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
cmd = 'coaps start'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coaps_start_x509(self):
cmd = 'coaps x509'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
cmd = 'coaps start'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coaps_set_resource_path(self, path):
cmd = 'coaps resource %s' % path
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def coaps_stop(self):
cmd = 'coaps stop'
@@ -1794,7 +2265,7 @@
else:
timeout = 5
- self._expect('Done', timeout=timeout)
+ self._expect_done(timeout=timeout)
def coaps_connect(self, ipaddr):
cmd = 'coaps connect %s' % ipaddr
@@ -1811,7 +2282,7 @@
def coaps_disconnect(self):
cmd = 'coaps disconnect'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
self.simulator.go(5)
def coaps_get(self):
@@ -1831,12 +2302,12 @@
if tlvs_binary is not None:
cmd += ' -x %s' % tlvs_binary
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def commissioner_mgmtset(self, tlvs_binary):
cmd = 'commissioner mgmtset -x %s' % tlvs_binary
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def bytes_to_hex_str(self, src):
return ''.join(format(x, '02x') for x in src)
@@ -1850,22 +2321,22 @@
def udp_start(self, local_ipaddr, local_port):
cmd = 'udp open'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
cmd = 'udp bind %s %s' % (local_ipaddr, local_port)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def udp_stop(self):
cmd = 'udp close'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def udp_send(self, bytes, ipaddr, port, success=True):
cmd = 'udp send %s %d -s %d ' % (ipaddr, port, bytes)
self.send_command(cmd)
if success:
- self._expect('Done')
+ self._expect_done()
else:
self._expect('Error')
@@ -1875,7 +2346,7 @@
def set_routereligible(self, enable: bool):
cmd = f'routereligible {"enable" if enable else "disable"}'
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def router_list(self):
cmd = 'router list'
@@ -1885,7 +2356,7 @@
g = self.pexpect.match.groups()
router_list = g[0].decode('utf8') + ' ' + g[1].decode('utf8')
router_list = [int(x) for x in router_list.split()]
- self._expect('Done')
+ self._expect_done()
return router_list
def router_table(self):
@@ -1908,7 +2379,7 @@
line = line[1:][:-1]
line = [x.strip() for x in line.split('|')]
- if len(line) != 8:
+ if len(line) < 9:
print("unexpected line %d: %s" % (i, line))
continue
@@ -1927,6 +2398,7 @@
lqout = int(line[5])
age = int(line[6])
emac = str(line[7])
+ link = int(line[8])
router_table[id] = {
'rloc16': rloc16,
@@ -1936,6 +2408,7 @@
'lqout': lqout,
'age': age,
'emac': emac,
+ 'link': link,
}
return router_table
@@ -1943,12 +2416,12 @@
def link_metrics_query_single_probe(self, dst_addr: str, linkmetrics_flags: str):
cmd = 'linkmetrics query %s single %s' % (dst_addr, linkmetrics_flags)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def link_metrics_query_forward_tracking_series(self, dst_addr: str, series_id: int):
cmd = 'linkmetrics query %s forward %d' % (dst_addr, series_id)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def link_metrics_mgmt_req_enhanced_ack_based_probing(self,
dst_addr: str,
@@ -1961,28 +2434,171 @@
else:
cmd = cmd + " clear"
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def link_metrics_mgmt_req_forward_tracking_series(self, dst_addr: str, series_id: int, series_flags: str,
metrics_flags: str):
cmd = "linkmetrics mgmt %s forward %d %s %s" % (dst_addr, series_id, series_flags, metrics_flags)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def link_metrics_send_link_probe(self, dst_addr: str, series_id: int, length: int):
cmd = "linkmetrics probe %s %d %d" % (dst_addr, series_id, length)
self.send_command(cmd)
- self._expect('Done')
+ self._expect_done()
def send_address_notification(self, dst: str, target: str, mliid: str):
cmd = f'fake /a/an {dst} {target} {mliid}'
self.send_command(cmd)
- self._expect("Done")
+ self._expect_done()
def send_proactive_backbone_notification(self, target: str, mliid: str, ltt: int):
cmd = f'fake /b/ba {target} {mliid} {ltt}'
self.send_command(cmd)
- self._expect("Done")
+ self._expect_done()
+
+ def dns_resolve(self, hostname, server=None, port=53):
+ cmd = f'dns resolve {hostname}'
+ if server is not None:
+ cmd += f' {server} {port}'
+
+ self.send_command(cmd)
+ self.simulator.go(10)
+ output = self._expect_command_output(cmd)
+ dns_resp = output[0]
+ # example output: "DNS response for host1.default.service.arpa. - fd00:db8:0:0:fd3d:d471:1e8c:b60 TTL:7190 "
+ # " fd00:db8:0:0:0:ff:fe00:9000 TTL:7190"
+ addrs = dns_resp.strip().split(' - ')[1].split(' ')
+ ip = [item.strip() for item in addrs[::2]]
+ ttl = [int(item.split('TTL:')[1]) for item in addrs[1::2]]
+
+ return list(zip(ip, ttl))
+
+ def dns_resolve_service(self, instance, service, server=None, port=53):
+ """
+ Resolves the service instance and returns the instance information as a dict.
+
+ Example return value:
+ {
+ 'port': 12345,
+ 'priority': 0,
+ 'weight': 0,
+ 'host': 'ins1._ipps._tcp.default.service.arpa.',
+ 'address': '2001::1',
+ 'txt_data': 'a=00, b=02bb',
+ 'srv_ttl': 7100,
+ 'txt_ttl': 7100,
+ 'aaaa_ttl': 7100,
+ }
+ """
+ cmd = f'dns service {instance} {service}'
+ if server is not None:
+ cmd += f' {server} {port}'
+
+ self.send_command(cmd)
+ self.simulator.go(10)
+ output = self._expect_command_output(cmd)
+
+ # Example output:
+ # DNS service resolution response for ins2 for service _ipps._tcp.default.service.arpa.
+ # Port:22222, Priority:2, Weight:2, TTL:7155
+ # Host:host2.default.service.arpa.
+ # HostAddress:0:0:0:0:0:0:0:0 TTL:0
+ # TXT:[a=00, b=02bb] TTL:7155
+ # Done
+
+ m = re.match(
+ r'.*Port:(\d+), Priority:(\d+), Weight:(\d+), TTL:(\d+)\s+Host:(.*?)\s+HostAddress:(\S+) TTL:(\d+)\s+TXT:\[(.*?)\] TTL:(\d+)',
+ '\r'.join(output))
+ if m:
+ port, priority, weight, srv_ttl, hostname, address, aaaa_ttl, txt_data, txt_ttl = m.groups()
+ return {
+ 'port': int(port),
+ 'priority': int(priority),
+ 'weight': int(weight),
+ 'host': hostname,
+ 'address': address,
+ 'txt_data': txt_data,
+ 'srv_ttl': int(srv_ttl),
+ 'txt_ttl': int(txt_ttl),
+ 'aaaa_ttl': int(aaaa_ttl),
+ }
+ else:
+ raise Exception('dns resolve service failed: %s.%s' % (instance, service))
+
+ @staticmethod
+ def __parse_hex_string(hexstr: str) -> bytes:
+ assert (len(hexstr) % 2 == 0)
+ return bytes(int(hexstr[i:i + 2], 16) for i in range(0, len(hexstr), 2))
+
+ def dns_browse(self, service_name, server=None, port=53):
+ """
+ Browse the service and returns the instances.
+
+ Example return value:
+ {
+ 'ins1': {
+ 'port': 12345,
+ 'priority': 1,
+ 'weight': 1,
+ 'host': 'ins1._ipps._tcp.default.service.arpa.',
+ 'address': '2001::1',
+ 'txt_data': 'a=00, b=11cf',
+ 'srv_ttl': 7100,
+ 'txt_ttl': 7100,
+ 'aaaa_ttl': 7100,
+ },
+ 'ins2': {
+ 'port': 12345,
+ 'priority': 2,
+ 'weight': 2,
+ 'host': 'ins2._ipps._tcp.default.service.arpa.',
+ 'address': '2001::2',
+ 'txt_data': 'a=01, b=23dd',
+ 'srv_ttl': 7100,
+ 'txt_ttl': 7100,
+ 'aaaa_ttl': 7100,
+ }
+ }
+ """
+ cmd = f'dns browse {service_name}'
+ if server is not None:
+ cmd += f' {server} {port}'
+
+ self.send_command(cmd)
+ self.simulator.go(10)
+ output = '\n'.join(self._expect_command_output(cmd))
+
+ # Example output:
+ # ins2
+ # Port:22222, Priority:2, Weight:2, TTL:7175
+ # Host:host2.default.service.arpa.
+ # HostAddress:fd00:db8:0:0:3205:28dd:5b87:6a63 TTL:7175
+ # TXT:[a=00, b=11cf] TTL:7175
+ # ins1
+ # Port:11111, Priority:1, Weight:1, TTL:7170
+ # Host:host1.default.service.arpa.
+ # HostAddress:fd00:db8:0:0:39f4:d9:eb4f:778 TTL:7170
+ # TXT:[a=01, b=23dd] TTL:7170
+ # Done
+
+ result = {}
+ for ins, port, priority, weight, srv_ttl, hostname, address, aaaa_ttl, txt_data, txt_ttl in re.findall(
+ r'(.*?)\s+Port:(\d+), Priority:(\d+), Weight:(\d+), TTL:(\d+)\s*Host:(\S+)\s+HostAddress:(\S+) TTL:(\d+)\s+TXT:\[(.*?)\] TTL:(\d+)',
+ output):
+ result[ins] = {
+ 'port': int(port),
+ 'priority': int(priority),
+ 'weight': int(weight),
+ 'host': hostname,
+ 'address': address,
+ 'txt_data': txt_data,
+ 'srv_ttl': int(srv_ttl),
+ 'txt_ttl': int(txt_ttl),
+ 'aaaa_ttl': int(aaaa_ttl),
+ }
+
+ return result
class Node(NodeImpl, OtCli):
@@ -1993,6 +2609,18 @@
PING_RESPONSE_PATTERN = re.compile(r'\d+ bytes from .*:.*')
ETH_DEV = config.BACKBONE_IFNAME
+ def enable_ether(self):
+ """Enable the ethernet interface.
+ """
+
+ self.bash(f'ifconfig {self.ETH_DEV} up')
+
+ def disable_ether(self):
+ """Disable the ethernet interface.
+ """
+
+ self.bash(f'ifconfig {self.ETH_DEV} down')
+
def get_ether_addrs(self):
output = self.bash(f'ip -6 addr list dev {self.ETH_DEV}')
@@ -2044,12 +2672,22 @@
return resp_count
def _getBackboneGua(self) -> Optional[str]:
- for ip6Addr in self.get_addrs():
- if re.match(config.BACKBONE_PREFIX_REGEX_PATTERN, ip6Addr, re.I):
- return ip6Addr
+ for addr in self.get_addrs():
+ if re.match(config.BACKBONE_PREFIX_REGEX_PATTERN, addr, re.I):
+ return addr
return None
+ def _getInfraUla(self) -> Optional[str]:
+ """ Returns the ULA addresses autoconfigured on the infra link.
+ """
+ addrs = []
+ for addr in self.get_addrs():
+ if re.match(config.ONLINK_PREFIX_REGEX_PATTERN, addr, re.I):
+ addrs.append(addr)
+
+ return addrs
+
def ping(self, *args, **kwargs):
backbone = kwargs.pop('backbone', False)
if backbone:
@@ -2072,6 +2710,66 @@
(self.ETH_DEV, self.ETH_DEV))
self.bash(f'ip -6 neigh list dev {self.ETH_DEV}')
+ def discover_mdns_service(self, instance, name, host_name, timeout=2):
+ """ Discover/resolve the mDNS service on ethernet.
+
+ :param instance: the service instance name.
+ :param name: the service name in format of '<service-name>.<protocol>'.
+ :param host_name: the host name this service points to. The domain
+ should not be included.
+ :param timeout: timeout value in seconds before returning.
+ :return: a dict of service properties or None.
+
+ The return value is a dict with the same key/values of srp_server_get_service
+ except that we don't have a `deleted` field here.
+ """
+
+ self.bash(f'dns-sd -Z {name} local. > /tmp/{name} 2>&1 &')
+ self.bash(f'dns-sd -G v6 {host_name}.local. > /tmp/{host_name} 2>&1 &')
+ time.sleep(timeout)
+
+ self.bash('pkill dns-sd')
+ addresses = []
+ service = {}
+
+ logging.debug(self.bash(f'cat /tmp/{host_name}'))
+ logging.debug(self.bash(f'cat /tmp/{name}'))
+
+ # example output in the host file:
+ # Timestamp A/R Flags if Hostname Address TTL
+ # 9:38:09.274 Add 23 48 my-host.local. 2001:0000:0000:0000:0000:0000:0000:0002%<0> 120
+ #
+ for line in self.bash(f'cat /tmp/{host_name}'):
+ elements = line.split()
+ fullname = f'{host_name}.local.'
+ if fullname not in elements:
+ continue
+ addresses.append(elements[elements.index(fullname) + 1].split('%')[0])
+
+ logging.debug(f'addresses of {host_name}: {addresses}')
+
+ # example output of in the service file:
+ # _ipps._tcp PTR my-service._ipps._tcp
+ # my-service._ipps._tcp SRV 0 0 12345 my-host.local. ; Replace with unicast FQDN of target host
+ # my-service._ipps._tcp TXT ""
+ #
+ for line in self.bash(f'cat /tmp/{name}'):
+ elements = line.split()
+ if not elements or elements[0] != f'{instance}.{name}':
+ continue
+ if elements[1] == 'SRV':
+ service['fullname'] = elements[0]
+ service['instance'] = instance
+ service['name'] = name
+ service['priority'] = int(elements[2])
+ service['weight'] = int(elements[3])
+ service['port'] = int(elements[4])
+ service['host_fullname'] = elements[5]
+ assert (service['host_fullname'] == f'{host_name}.local.')
+ service['host'] = host_name
+ service['addresses'] = addresses
+ return service if service['addresses'] else None
+
class OtbrNode(LinuxHost, NodeImpl, OtbrDocker):
is_otbr = True
@@ -2097,9 +2795,12 @@
self.name = name or ('Host%d' % nodeid)
super().__init__(nodeid, **kwargs)
- def start(self):
+ def start(self, start_radvd=True, prefix=config.DOMAIN_PREFIX, slaac=False):
self._setup_sysctl()
- self._service_radvd_start()
+ if start_radvd:
+ self._service_radvd_start(prefix, slaac)
+ else:
+ self._service_radvd_stop()
def stop(self):
self._service_radvd_stop()
@@ -2110,6 +2811,17 @@
def __repr__(self):
return f'Host<{self.nodeid}>'
+ def get_matched_ula_addresses(self, prefix):
+ """Get the IPv6 addresses that matches given prefix.
+ """
+
+ addrs = []
+ for addr in self.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA):
+ if addr.startswith(prefix.split('::')[0]):
+ addrs.append(addr)
+
+ return addrs
+
def get_ip6_address(self, address_type: config.ADDRESS_TYPE):
"""Get specific type of IPv6 address configured on thread device.
@@ -2119,14 +2831,16 @@
Returns:
IPv6 address string.
"""
- assert address_type == config.ADDRESS_TYPE.BACKBONE_GUA
+ assert address_type in [config.ADDRESS_TYPE.BACKBONE_GUA, config.ADDRESS_TYPE.ONLINK_ULA]
if address_type == config.ADDRESS_TYPE.BACKBONE_GUA:
return self._getBackboneGua()
+ if address_type == config.ADDRESS_TYPE.ONLINK_ULA:
+ return self._getInfraUla()
else:
return None
- def _service_radvd_start(self):
+ def _service_radvd_start(self, prefix, slaac):
self.bash("""cat >/etc/radvd.conf <<EOF
interface eth0
{
@@ -2139,12 +2853,12 @@
prefix %s
{
AdvOnLink on;
- AdvAutonomous off;
+ AdvAutonomous %s;
AdvRouterAddr off;
};
};
EOF
-""" % config.DOMAIN_PREFIX)
+""" % (prefix, 'on' if slaac else 'off'))
self.bash('service radvd start')
self.bash('service radvd status') # Make sure radvd service is running
diff --git a/tests/scripts/thread-cert/pcap.py b/tests/scripts/thread-cert/pcap.py
index 905a5dd..267f147 100644
--- a/tests/scripts/thread-cert/pcap.py
+++ b/tests/scripts/thread-cert/pcap.py
@@ -28,19 +28,25 @@
#
""" Module to provide codec utilities for .pcap formatters. """
+import os
import struct
import time
-DLT_IEEE802_15_4 = 195
+# https://www.tcpdump.org/linktypes.html
+DLT_IEEE802_15_4_WITHFCS = 195
+DLT_IEEE802_15_4_TAP = 283
PCAP_MAGIC_NUMBER = 0xA1B2C3D4
PCAP_VERSION_MAJOR = 2
PCAP_VERSION_MINOR = 4
+PACKET_VERIFICATION = int(os.getenv('PACKET_VERIFICATION', 0))
+
class PcapCodec(object):
""" Utility class for .pcap formatters. """
def __init__(self, filename):
+ self._dlt = DLT_IEEE802_15_4_WITHFCS if PACKET_VERIFICATION else DLT_IEEE802_15_4_TAP
self._pcap_file = open('%s.pcap' % filename, 'wb')
self._pcap_file.write(self.encode_header())
@@ -54,14 +60,28 @@
0,
0,
256,
- DLT_IEEE802_15_4,
+ self._dlt,
)
def encode_frame(self, frame, sec, usec):
""" Returns a pcap encapsulation of the given frame. """
+ length = 0
+
+ if self._dlt == DLT_IEEE802_15_4_TAP:
+ # Append TLVs according to 802.15.4 TAP specification:
+ # https://github.com/jkcko/ieee802.15.4-tap
+ pcap_tap_fcs_tlv = struct.pack("<HHL", 0, 1, 1)
+ pcap_tap_channel_tlv = struct.pack("<HHHH", 3, 3, frame[0], 0)
+ length = 4 + len(pcap_tap_fcs_tlv) + len(pcap_tap_channel_tlv)
+ pcap_tap_header = struct.pack("<HH", 0, length)
+
frame = frame[1:]
- length = len(frame)
+ length += len(frame)
pcap_frame = struct.pack("<LLLL", sec, usec, length, length)
+
+ if self._dlt == DLT_IEEE802_15_4_TAP:
+ pcap_frame += pcap_tap_header + pcap_tap_fcs_tlv + pcap_tap_channel_tlv
+
pcap_frame += frame
return pcap_frame
diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py
index 31f142c..114440a 100644
--- a/tests/scripts/thread-cert/pktverify/consts.py
+++ b/tests/scripts/thread-cert/pktverify/consts.py
@@ -352,6 +352,8 @@
CSL_DEFAULT_PERIOD_IN_SECOND = 0.5
US_PER_TEN_SYMBOLS = 160
CSL_IE_ID = 0x1a
+CSL_DEFAULT_TIMEOUT = 30
+CSL_DEFAULT_CHANNEL = 12
# Thread Version TLV value
THREAD_VERSION_1_2 = 3
diff --git a/tests/scripts/thread-cert/simulator.py b/tests/scripts/thread-cert/simulator.py
index 4dbe37e..2505010 100644
--- a/tests/scripts/thread-cert/simulator.py
+++ b/tests/scripts/thread-cert/simulator.py
@@ -144,12 +144,15 @@
BLOCK_TIMEOUT = 10
- RADIO_ONLY = os.getenv('RADIO_DEVICE') is not None
NCP_SIM = os.getenv('NODE_TYPE', 'sim') == 'ncp-sim'
+ _message_factory = None
+
def __init__(self, use_message_factory=True):
super(VirtualTime, self).__init__()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2 * 1024 * 1024)
+ self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2 * 1024 * 1024)
ip = '127.0.0.1'
self.port = self.BASE_PORT + (self.PORT_OFFSET * (self.MAX_NODES + 1))
@@ -242,7 +245,7 @@
return (addr[0], addr[1] - self.BASE_PORT)
def _core_addr_from(self, nodeid):
- if self.RADIO_ONLY:
+ if self._nodes[nodeid].is_posix:
return ('127.0.0.1', self.BASE_PORT + self.port + nodeid)
else:
return ('127.0.0.1', self.port + nodeid)
@@ -497,7 +500,7 @@
def go(self, duration, nodeid=None):
assert self.current_time == self._pause_time
- duration = int(duration) * 1000000
+ duration = int(duration * 1000000)
dbg_print('running for %d us' % duration)
self._pause_time += duration
if nodeid:
diff --git a/tests/scripts/thread-cert/sniffer_transport.py b/tests/scripts/thread-cert/sniffer_transport.py
index 756c5a4..a45731a 100644
--- a/tests/scripts/thread-cert/sniffer_transport.py
+++ b/tests/scripts/thread-cert/sniffer_transport.py
@@ -128,6 +128,8 @@
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
+ self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2 * 1024 * 1024)
+ self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2 * 1024 * 1024)
self._socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(self.RADIO_GROUP) + socket.inet_aton('127.0.0.1'))
self._socket.bind(self._nodeid_to_address(0))
diff --git a/tests/scripts/thread-cert/test_coap_block.py b/tests/scripts/thread-cert/test_coap_block.py
new file mode 100755
index 0000000..27c98bf
--- /dev/null
+++ b/tests/scripts/thread-cert/test_coap_block.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import unittest
+
+import pexpect
+import config
+import thread_cert
+
+LEADER = 1
+ROUTER = 2
+
+
+class TestCoapBlockTransfer(thread_cert.TestCase):
+ """
+ Test suite for CoAP Block-Wise Transfers (RFC7959).
+ """
+
+ SUPPORT_NCP = False
+
+ TOPOLOGY = {
+ LEADER: {
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'whitelist': [ROUTER]
+ },
+ ROUTER: {
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1,
+ 'whitelist': [LEADER]
+ },
+ }
+
+ def _do_transfer_test(self, method):
+ self.nodes[LEADER].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
+
+ self.nodes[ROUTER].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
+
+ mleid = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
+
+ self.nodes[LEADER].coap_start()
+ self.nodes[LEADER].coap_set_resource_path_block('test', 10)
+
+ self.nodes[ROUTER].coap_start()
+
+ if method == 'GET':
+ response = self.nodes[ROUTER].coap_get_block(mleid, 'test', size=32)
+ response_payload = response['payload']
+ self.assertIsNotNone(response_payload)
+
+ if method == 'PUT':
+ self.nodes[ROUTER].coap_put_block(mleid, 'test', size=256, count=2)
+ request = self.nodes[ROUTER].coap_wait_request()
+ request_payload = request['payload']
+ self.assertIsNotNone(request_payload)
+
+ if method == 'POST':
+ self.nodes[ROUTER].coap_post_block(mleid, 'test', size=1024, count=2)
+ request = self.nodes[ROUTER].coap_wait_request()
+ request_payload = request['payload']
+ self.assertIsNotNone(request_payload)
+
+ self.simulator.go(10)
+
+ self.nodes[ROUTER].coap_stop()
+ self.nodes[LEADER].coap_stop()
+
+ def test_get(self):
+ """
+ Test block-wise transfer using GET method.
+ """
+ for trial in range(0, 3):
+ try:
+ self._do_transfer_test(method='GET')
+ break
+ except (AssertionError, pexpect.exceptions.TIMEOUT):
+ continue
+
+ def test_put(self):
+ """
+ Test block-wise transfer using PUT method.
+ """
+ for trial in range(0, 3):
+ try:
+ self._do_transfer_test(method='PUT')
+ break
+ except (AssertionError, pexpect.exceptions.TIMEOUT):
+ continue
+
+ def test_post(self):
+ """
+ Test block-wise transfer using POST method.
+ """
+ for trial in range(0, 3):
+ try:
+ self._do_transfer_test(method='POST')
+ break
+ except (AssertionError, pexpect.exceptions.TIMEOUT):
+ continue
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_dataset_updater.py b/tests/scripts/thread-cert/test_dataset_updater.py
new file mode 100755
index 0000000..10a8527
--- /dev/null
+++ b/tests/scripts/thread-cert/test_dataset_updater.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+
+import unittest
+
+import config
+import thread_cert
+
+LEADER = 1
+ROUTER = 2
+MED = 3
+SED = 4
+
+
+class TestDatasetUpdater(thread_cert.TestCase):
+ SUPPORT_NCP = False
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ LEADER: {
+ 'mode': 'rdn',
+ 'channel': 11,
+ 'panid': 0xface,
+ },
+ ROUTER: {
+ 'mode': 'rdn',
+ 'channel': 11,
+ 'panid': 0xface,
+ 'router_selection_jitter': 1,
+ },
+ MED: {
+ 'mode': 'rn',
+ 'channel': 11,
+ 'panid': 0xface,
+ 'allowlist': [ROUTER],
+ },
+ SED: {
+ 'mode': '-',
+ 'channel': 11,
+ 'panid': 0xface,
+ 'timeout': config.DEFAULT_CHILD_TIMEOUT,
+ 'allowlist': [ROUTER],
+ },
+ }
+
+ def test(self):
+ self.nodes[LEADER].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
+
+ self.nodes[ROUTER].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
+
+ self.nodes[MED].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[MED].get_state(), 'child')
+
+ self.nodes[SED].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[SED].get_state(), 'child')
+
+ self.verify_state(11)
+
+ # update initiated by LEADER
+ self.nodes[LEADER].start_dataset_updater(channel=12)
+ self.simulator.go(120)
+ self.verify_state(12)
+
+ # update initiated by ROUTER
+ self.nodes[ROUTER].start_dataset_updater(channel=13)
+ self.simulator.go(120)
+ self.verify_state(13)
+
+ # update initiated by LEADER overridden by ROUTER
+ self.nodes[LEADER].start_dataset_updater(channel=14)
+ self.simulator.go(20)
+ self.nodes[ROUTER].start_dataset_updater(channel=15)
+ self.simulator.go(120)
+ self.verify_state(15)
+
+ # update initiated by ROUTER overridden by LEADER
+ self.nodes[ROUTER].start_dataset_updater(channel=16)
+ self.simulator.go(10)
+ self.nodes[LEADER].start_dataset_updater(channel=17)
+ self.simulator.go(120)
+ self.verify_state(17)
+
+ def verify_state(self, channel):
+ self.assertEqual(self.nodes[LEADER].get_channel(), channel)
+ self.assertEqual(self.nodes[ROUTER].get_channel(), channel)
+ self.assertEqual(self.nodes[MED].get_channel(), channel)
+ self.assertEqual(self.nodes[SED].get_channel(), channel)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_dnssd.py b/tests/scripts/thread-cert/test_dnssd.py
new file mode 100755
index 0000000..d4b80d6
--- /dev/null
+++ b/tests/scripts/thread-cert/test_dnssd.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+import ipaddress
+import typing
+import unittest
+
+import thread_cert
+
+SERVER = 1
+CLIENT1 = 2
+CLIENT2 = 3
+
+DOMAIN = 'default.service.arpa.'
+SERVICE = '_ipps._tcp'
+
+#
+# Topology:
+# LEADER -- CLIENT1
+# |
+# CLIENT2
+#
+
+
+class TestDnssd(thread_cert.TestCase):
+ SUPPORT_NCP = False
+ USE_MESSAGE_FACTORY = False
+
+ TOPOLOGY = {
+ SERVER: {
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ },
+ CLIENT1: {
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1,
+ },
+ CLIENT2: {
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1,
+ },
+ }
+
+ def test(self):
+ self.nodes[SERVER].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[SERVER].get_state(), 'leader')
+ self.nodes[SERVER].srp_server_set_enabled(True)
+
+ self.nodes[CLIENT1].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[CLIENT1].get_state(), 'router')
+
+ self.nodes[CLIENT2].start()
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[CLIENT1].get_state(), 'router')
+
+ client1_addrs = [self.nodes[CLIENT1].get_mleid(), self.nodes[CLIENT1].get_rloc()]
+ self._config_srp_client_services(CLIENT1, 'ins1', 'host1', 11111, 1, 1, client1_addrs)
+
+ client2_addrs = [self.nodes[CLIENT2].get_mleid(), self.nodes[CLIENT2].get_rloc()]
+ self._config_srp_client_services(CLIENT2, 'ins2', 'host2', 22222, 2, 2, client2_addrs)
+
+ # Test AAAA query using DNS client
+ answers = self.nodes[CLIENT1].dns_resolve(f"host1.{DOMAIN}", self.nodes[SERVER].get_mleid(), 53)
+ self.assertEqual(set(ipaddress.IPv6Address(ip) for ip, _ in answers),
+ set(map(ipaddress.IPv6Address, client1_addrs)))
+
+ answers = self.nodes[CLIENT1].dns_resolve(f"host2.{DOMAIN}", self.nodes[SERVER].get_mleid(), 53)
+ self.assertEqual(set(ipaddress.IPv6Address(ip) for ip, _ in answers),
+ set(map(ipaddress.IPv6Address, client2_addrs)))
+
+ service_instances = self.nodes[CLIENT1].dns_browse(f'{SERVICE}.{DOMAIN}', self.nodes[SERVER].get_mleid(), 53)
+ self.assertEqual({'ins1', 'ins2'}, set(service_instances.keys()), service_instances)
+
+ instance1_verify_info = {
+ 'port': 11111,
+ 'priority': 1,
+ 'weight': 1,
+ 'host': 'host1.default.service.arpa.',
+ 'address': client1_addrs,
+ 'txt_data': '',
+ 'srv_ttl': lambda x: x > 0,
+ 'txt_ttl': lambda x: x > 0,
+ 'aaaa_ttl': lambda x: x > 0,
+ }
+
+ instance2_verify_info = {
+ 'port': 22222,
+ 'priority': 2,
+ 'weight': 2,
+ 'host': 'host2.default.service.arpa.',
+ 'address': client2_addrs,
+ 'txt_data': '',
+ 'srv_ttl': lambda x: x > 0,
+ 'txt_ttl': lambda x: x > 0,
+ 'aaaa_ttl': lambda x: x > 0,
+ }
+
+ self._assert_service_instance_equal(service_instances['ins1'], instance1_verify_info)
+ self._assert_service_instance_equal(service_instances['ins2'], instance2_verify_info)
+
+ service_instance = self.nodes[CLIENT1].dns_resolve_service('ins1', f'{SERVICE}.{DOMAIN}',
+ self.nodes[SERVER].get_mleid(), 53)
+ self._assert_service_instance_equal(service_instance, instance1_verify_info)
+
+ service_instance = self.nodes[CLIENT1].dns_resolve_service('ins2', f'{SERVICE}.{DOMAIN}',
+ self.nodes[SERVER].get_mleid(), 53)
+ self._assert_service_instance_equal(service_instance, instance2_verify_info)
+
+ def _assert_service_instance_equal(self, instance, info):
+ for f in ('port', 'priority', 'weight', 'host', 'txt_data'):
+ self.assertEqual(instance[f], info[f], instance)
+
+ verify_addresses = info['address']
+ if not isinstance(verify_addresses, typing.Collection):
+ verify_addresses = [verify_addresses]
+ self.assertIn(ipaddress.IPv6Address(instance['address']), map(ipaddress.IPv6Address, verify_addresses),
+ instance)
+
+ for ttl_f in ('srv_ttl', 'txt_ttl', 'aaaa_ttl'):
+ check_ttl = info[ttl_f]
+ if not callable(check_ttl):
+ check_ttl = lambda x: x == check_ttl
+
+ self.assertTrue(check_ttl(instance[ttl_f]), instance)
+
+ def _config_srp_client_services(self, client, instancename, hostname, port, priority, weight, addrs):
+ self.nodes[client].netdata_show()
+ srp_server_port = self.nodes[client].get_srp_server_port()
+
+ self.nodes[client].srp_client_start(self.nodes[SERVER].get_mleid(), srp_server_port)
+ self.nodes[client].srp_client_set_host_name(hostname)
+ self.nodes[client].srp_client_set_host_address(*addrs)
+ self.nodes[client].srp_client_add_service(instancename, SERVICE, port, priority, weight)
+
+ self.simulator.go(5)
+ self.assertEqual(self.nodes[client].srp_client_get_host_state(), 'Registered')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_reset.py b/tests/scripts/thread-cert/test_reset.py
index 2265279..155c97a 100755
--- a/tests/scripts/thread-cert/test_reset.py
+++ b/tests/scripts/thread-cert/test_reset.py
@@ -27,6 +27,7 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+import config
import unittest
import thread_cert
@@ -70,39 +71,27 @@
self.simulator.go(7)
self.assertEqual(self.nodes[ED].get_state(), 'child')
- leader_addrs = self.nodes[LEADER].get_addrs()
- router_addrs = self.nodes[ROUTER].get_addrs()
-
for i in range(0, 1010):
- self.assertTrue(self.nodes[ED].ping(leader_addrs[0]))
+ self.assertTrue(self.nodes[ED].ping(self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC)))
self.simulator.go(1)
- # 1 - Leader
self.nodes[LEADER].reset()
self.nodes[LEADER].start()
self.simulator.go(7)
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
- for addr in router_addrs:
- self.assertTrue(self.nodes[LEADER].ping(addr))
-
- # 2 - Router
self.nodes[ROUTER].reset()
self.nodes[ROUTER].start()
self.simulator.go(7)
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
- for addr in leader_addrs:
- self.assertTrue(self.nodes[ROUTER].ping(addr))
-
- # 3 - Child
self.nodes[ED].reset()
+ self.nodes[LEADER].add_allowlist(self.nodes[ROUTER].get_addr64())
+ self.nodes[LEADER].enable_allowlist()
self.nodes[ED].start()
self.simulator.go(7)
self.assertEqual(self.nodes[ED].get_state(), 'child')
-
- for addr in router_addrs:
- self.assertTrue(self.nodes[ED].ping(addr))
+ self.assertTrue(self.nodes[ED].ping(self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC)))
if __name__ == '__main__':
diff --git a/tests/scripts/thread-cert/test_srp_auto_start_mode.py b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
new file mode 100755
index 0000000..1a28397
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_auto_start_mode.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import thread_cert
+
+# Test description:
+# This test verifies SRP client auto-start functionality that SRP client can
+# correctly discover and connect to SRP server.
+#
+# Topology:
+#
+# CLIENT (leader) -- SERVER1 (router)
+# |
+# |
+# SERVER2 (router)
+#
+
+CLIENT = 1
+SERVER1 = 2
+SERVER2 = 3
+
+
+class SrpAutoStartMode(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+ SUPPORT_NCP = False
+
+ TOPOLOGY = {
+ CLIENT: {
+ 'name': 'SRP_CLIENT',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface
+ },
+ SERVER1: {
+ 'name': 'SRP_SERVER1',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ SERVER2: {
+ 'name': 'SRP_SERVER2',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ }
+
+ def test(self):
+ client = self.nodes[CLIENT]
+ server1 = self.nodes[SERVER1]
+ server2 = self.nodes[SERVER2]
+
+ #
+ # 0. Start the server & client devices.
+ #
+
+ client.srp_server_set_enabled(False)
+ client.start()
+ self.simulator.go(5)
+ self.assertEqual(client.get_state(), 'leader')
+
+ server1.srp_server_set_enabled(True)
+ server2.srp_server_set_enabled(False)
+ server1.start()
+ server2.start()
+ self.simulator.go(5)
+ self.assertEqual(server1.get_state(), 'router')
+ self.assertEqual(server2.get_state(), 'router')
+
+ #
+ # 1. Enable auto start mode on client and check that server1 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')
+ self.assertTrue(server1.has_ipaddr(client.srp_client_get_server_address()))
+
+ #
+ # 2. Disable server1 and check client is stopped/disabled.
+ #
+
+ server1.srp_server_set_enabled(False)
+ self.simulator.go(5)
+ self.assertEqual(client.srp_client_get_state(), 'Disabled')
+
+ #
+ # 3. Enable server2 and check client starts again.
+ #
+
+ server2.srp_server_set_enabled(True)
+ self.simulator.go(5)
+ self.assertEqual(client.srp_client_get_state(), 'Enabled')
+ server2_address = client.srp_client_get_server_address()
+
+ #
+ # 4. Enable both servers and check client stays with server2.
+ #
+
+ server1.srp_server_set_enabled(True)
+ self.simulator.go(2)
+ self.assertEqual(client.srp_client_get_state(), 'Enabled')
+ self.assertEqual(client.srp_client_get_server_address(), server2_address)
+
+ #
+ # 5. Disable server2 and check client switches to server1.
+ #
+
+ server2.srp_server_set_enabled(False)
+ self.simulator.go(5)
+ self.assertEqual(client.srp_client_get_state(), 'Enabled')
+ self.assertNotEqual(client.srp_client_get_server_address(), server2_address)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_lease.py b/tests/scripts/thread-cert/test_srp_lease.py
new file mode 100755
index 0000000..baf45af
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_lease.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import thread_cert
+
+# Test description:
+# This test verifies the SRP server and client properly handle SRP host
+# and service instance lease.
+#
+# Topology:
+# LEADER (SRP server)
+# |
+# |
+# ROUTER (SRP client)
+#
+
+SERVER = 1
+CLIENT = 2
+LEASE = 10 # Seconds
+KEY_LEASE = 20 # Seconds
+
+
+class SrpRegisterSingleService(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+ SUPPORT_NCP = False
+
+ TOPOLOGY = {
+ SERVER: {
+ 'name': 'SRP_SERVER',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface
+ },
+ CLIENT: {
+ 'name': 'SRP_CLIENT',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ }
+
+ def test(self):
+ server = self.nodes[SERVER]
+ client = self.nodes[CLIENT]
+
+ #
+ # 0. Start the server and client devices.
+ #
+
+ server.srp_server_set_enabled(True)
+ server.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE)
+ server.start()
+ self.simulator.go(5)
+ self.assertEqual(server.get_state(), 'leader')
+ self.simulator.go(5)
+
+ client.srp_server_set_enabled(False)
+ client.start()
+ self.simulator.go(5)
+ self.assertEqual(client.get_state(), 'router')
+
+ #
+ # 1. Register a single service and verify that it works.
+ #
+
+ 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)
+
+ self.check_host_and_service(server, client)
+
+ #
+ # 2. Stop the client and wait for the service instance LEASE to expire.
+ #
+
+ client.srp_client_stop()
+ self.simulator.go(LEASE + 1)
+
+ # The SRP server should remove the host and service but retain their names
+ # since the the KEY LEASE hasn't expired yet.
+ self.assertEqual(server.srp_server_get_host('my-host')['deleted'], 'true')
+ 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())
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client)
+
+ #
+ # 3. Stop the client and wait for the KEY LEASE to expire.
+ # The host and service instance should be fully removed by the SRP server.
+ #
+
+ client.srp_client_stop()
+ self.simulator.go(KEY_LEASE + 1)
+
+ # The host and service are expected to be fully removed.
+ self.assertEqual(len(server.srp_server_get_hosts()), 0)
+ 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())
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client)
+
+ def check_host_and_service(self, server, client):
+ """Check that we have properly registered host and service instance.
+ """
+
+ client_services = client.srp_client_get_services()
+ print(client_services)
+ self.assertEqual(len(client_services), 1)
+ client_service = client_services[0]
+
+ # Verify that the client possesses correct service resources.
+ self.assertEqual(client_service['instance'], 'my-service')
+ self.assertEqual(client_service['name'], '_ipps._tcp')
+ self.assertEqual(int(client_service['port']), 12345)
+ self.assertEqual(int(client_service['priority']), 0)
+ self.assertEqual(int(client_service['weight']), 0)
+
+ # Verify that the client received a SUCCESS response for the server.
+ self.assertEqual(client_service['state'], 'Registered')
+
+ # Wait for a KEY LEASE period to make sure that the client has refreshed
+ # the host and service instance.
+ self.simulator.go(KEY_LEASE + 1)
+
+ server_services = server.srp_server_get_services()
+ print(server_services)
+ self.assertEqual(len(server_services), 1)
+ server_service = server_services[0]
+
+ # Verify that the server accepted the SRP registration and stored
+ # the same service resources.
+ self.assertEqual(server_service['deleted'], 'false')
+ self.assertEqual(server_service['instance'], client_service['instance'])
+ self.assertEqual(server_service['name'], client_service['name'])
+ self.assertEqual(int(server_service['port']), int(client_service['port']))
+ self.assertEqual(int(server_service['priority']), int(client_service['priority']))
+ self.assertEqual(int(server_service['weight']), int(client_service['weight']))
+ self.assertEqual(server_service['host'], 'my-host')
+
+ server_hosts = server.srp_server_get_hosts()
+ print(server_hosts)
+ self.assertEqual(len(server_hosts), 1)
+ server_host = server_hosts[0]
+
+ self.assertEqual(server_host['deleted'], 'false')
+ self.assertEqual(server_host['fullname'], server_service['host_fullname'])
+ self.assertEqual(len(server_host['addresses']), 1)
+ self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address('2001::1'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_name_conflicts.py b/tests/scripts/thread-cert/test_srp_name_conflicts.py
new file mode 100755
index 0000000..1e28518
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_name_conflicts.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import thread_cert
+
+# Test description:
+# This test verifies if the SRP server can handle name conflicts correctly.
+#
+# Topology:
+# LEADER (SRP server)
+# / \
+# / \
+# / \
+# ROUTER1 ROUTER2
+#
+
+SERVER = 1
+CLIENT1 = 2
+CLIENT2 = 3
+
+
+class SrpNameConflicts(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+ SUPPORT_NCP = False
+
+ TOPOLOGY = {
+ SERVER: {
+ 'name': 'SRP_SERVER',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface
+ },
+ CLIENT1: {
+ 'name': 'SRP_CLIENT1',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ CLIENT2: {
+ 'name': 'SRP_CLIENT2',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ }
+
+ def test(self):
+ server = self.nodes[SERVER]
+ client_1 = self.nodes[CLIENT1]
+ client_2 = self.nodes[CLIENT2]
+
+ #
+ # 0. Start the server & client devices.
+ #
+
+ server.srp_server_set_enabled(True)
+ server.start()
+ self.simulator.go(5)
+ self.assertEqual(server.get_state(), 'leader')
+ self.simulator.go(5)
+
+ client_1.srp_server_set_enabled(False)
+ client_1.start()
+ self.simulator.go(5)
+ self.assertEqual(client_1.get_state(), 'router')
+
+ client_2.srp_server_set_enabled(False)
+ client_2.start()
+ self.simulator.go(5)
+ self.assertEqual(client_2.get_state(), 'router')
+
+ #
+ # 1. Register a single service and verify that it works.
+ #
+
+ 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)
+
+ # Verify that the client possesses correct service resources.
+ client_1_service = client_1.srp_client_get_services()[0]
+ self.assertEqual(client_1_service['instance'], 'my-service-1')
+ self.assertEqual(client_1_service['name'], '_ipps._tcp')
+ self.assertEqual(int(client_1_service['port']), 12345)
+ self.assertEqual(int(client_1_service['priority']), 0)
+ self.assertEqual(int(client_1_service['weight']), 0)
+
+ # Verify that the client receives a SUCCESS response for the server.
+ self.assertEqual(client_1_service['state'], 'Registered')
+
+ # Verify that the server accepts the SRP registration and stored
+ # the same service resources.
+ server_service = server.srp_server_get_services()[0]
+ self.assertEqual(server_service['deleted'], 'false')
+ self.assertEqual(server_service['instance'], client_1_service['instance'])
+ self.assertEqual(server_service['name'], client_1_service['name'])
+ self.assertEqual(int(server_service['port']), int(client_1_service['port']))
+ self.assertEqual(int(server_service['priority']), int(client_1_service['priority']))
+ self.assertEqual(int(server_service['weight']), int(client_1_service['weight']))
+ self.assertEqual(server_service['host'], 'my-host-1')
+
+ server_host = server.srp_server_get_hosts()[0]
+ self.assertEqual(server_host['deleted'], 'false')
+ self.assertEqual(server_host['fullname'], server_service['host_fullname'])
+ self.assertEqual(len(server_host['addresses']), 1)
+ self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address('2001::1'))
+
+ #
+ # 2. Register with the same host name from the second client and it should fail.
+ #
+
+ 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)
+
+ # It is expected that the registration will be rejected.
+ client_2_service = client_2.srp_client_get_services()[0]
+ self.assertNotEqual(client_2_service['state'], 'Registered')
+ self.assertNotEqual(client_2.srp_client_get_host_state(), 'Registered')
+
+ self.assertEqual(len(server.srp_server_get_services()), 1)
+ self.assertEqual(len(server.srp_server_get_hosts()), 1)
+
+ client_2.srp_client_clear_host()
+ client_2.srp_client_stop()
+
+ #
+ # 3. Register with the same service name from the second client and it should fail.
+ #
+
+ 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)
+
+ # It is expected that the registration will be rejected.
+ client_2_service = client_2.srp_client_get_services()[0]
+ self.assertNotEqual(client_2_service['state'], 'Registered')
+ self.assertNotEqual(client_2.srp_client_get_host_state(), 'Registered')
+
+ self.assertEqual(len(server.srp_server_get_services()), 1)
+ self.assertEqual(len(server.srp_server_get_hosts()), 1)
+
+ client_2.srp_client_clear_host()
+ client_2.srp_client_stop()
+
+ #
+ # 4. Register with different host & service instance name, it should succeed.
+ #
+
+ 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)
+
+ # It is expected that the registration will be accepted.
+ client_2_service = client_2.srp_client_get_services()[0]
+ self.assertEqual(client_2_service['state'], 'Registered')
+ self.assertEqual(client_2.srp_client_get_host_state(), 'Registered')
+
+ self.assertEqual(len(server.srp_server_get_services()), 2)
+ self.assertEqual(len(server.srp_server_get_hosts()), 2)
+ self.assertEqual(server.srp_server_get_host('my-host-2')['deleted'], 'false')
+ self.assertEqual(server.srp_server_get_service('my-service-2', '_ipps._tcp')['deleted'], 'false')
+
+ # Remove the host and all services registered on the SRP server.
+ client_2.srp_client_remove_host(remove_key=True)
+ self.simulator.go(2)
+
+ client_2.srp_client_clear_host()
+ client_2.srp_client_stop()
+
+ #
+ # 5. Register with the same service instance name before its KEY LEASE expires,
+ # it is expected to fail.
+ #
+
+ # Remove the service instance from SRP server but retains its name.
+ client_1.srp_client_remove_service('my-service-1', '_ipps._tcp')
+ self.simulator.go(2)
+
+ 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)
+
+ # It is expected that the registration will be rejected.
+ client_2_service = client_2.srp_client_get_services()[0]
+ self.assertNotEqual(client_2_service['state'], 'Registered')
+ self.assertNotEqual(client_2.srp_client_get_host_state(), 'Registered')
+
+ # The service 'my-service-1' is removed but its name is retained.
+ # This is why we can see the service record on the SRP server.
+ self.assertEqual(len(server.srp_server_get_services()), 1)
+ self.assertEqual(len(server.srp_server_get_hosts()), 1)
+ self.assertEqual(server.srp_server_get_host('my-host-1')['deleted'], 'false')
+ self.assertEqual(server.srp_server_get_service('my-service-1', '_ipps._tcp')['deleted'], 'true')
+
+ client_2.srp_client_clear_host()
+ client_2.srp_client_stop()
+
+ #
+ # 6. The service instance name can be re-used by another client when
+ # the service has been permanently removed (the KEY resource is
+ # removed) from the host.
+ #
+
+ # Client 1 adds back the service, it should success.
+ client_1.srp_client_add_service('my-service-1', '_ipps._tcp', 12345)
+ self.simulator.go(2)
+ self.assertEqual(len(server.srp_server_get_services()), 1)
+ self.assertEqual(len(server.srp_server_get_hosts()), 1)
+ self.assertEqual(server.srp_server_get_host('my-host-1')['deleted'], 'false')
+ self.assertEqual(server.srp_server_get_service('my-service-1', '_ipps._tcp')['deleted'], 'false')
+
+ # Permanently removes the service instance.
+ client_1.srp_client_remove_host(remove_key=True)
+ self.simulator.go(2)
+ self.assertEqual(len(server.srp_server_get_services()), 0)
+ self.assertEqual(len(server.srp_server_get_hosts()), 0)
+
+ # Client 2 registers the same host & service instance name with Client 1.
+ client_2.srp_client_stop()
+ 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)
+
+ # It is expected that client 2 will success because those names has been
+ # released by client 1.
+ self.assertEqual(len(server.srp_server_get_services()), 1)
+ self.assertEqual(len(server.srp_server_get_hosts()), 1)
+ self.assertEqual(server.srp_server_get_host('my-host-1')['deleted'], 'false')
+ self.assertEqual(server.srp_server_get_service('my-service-1', '_ipps._tcp')['deleted'], 'false')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/test_srp_register_single_service.py b/tests/scripts/thread-cert/test_srp_register_single_service.py
new file mode 100755
index 0000000..6241cac
--- /dev/null
+++ b/tests/scripts/thread-cert/test_srp_register_single_service.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2021, 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.
+#
+
+import ipaddress
+import unittest
+
+import command
+import thread_cert
+
+# Test description:
+# This test verifies basic SRP function that a service can be registered to
+# and unregistered from the SRP server.
+#
+# Topology:
+# LEADER (SRP server)
+# |
+# |
+# ROUTER (SRP client)
+#
+
+SERVER = 1
+CLIENT = 2
+
+
+class SrpRegisterSingleService(thread_cert.TestCase):
+ USE_MESSAGE_FACTORY = False
+ SUPPORT_NCP = False
+
+ TOPOLOGY = {
+ SERVER: {
+ 'name': 'SRP_SERVER',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface
+ },
+ CLIENT: {
+ 'name': 'SRP_CLIENT',
+ 'masterkey': '00112233445566778899aabbccddeeff',
+ 'mode': 'rdn',
+ 'panid': 0xface,
+ 'router_selection_jitter': 1
+ },
+ }
+
+ def test(self):
+ server = self.nodes[SERVER]
+ client = self.nodes[CLIENT]
+
+ #
+ # 0. Start the server & client devices.
+ #
+
+ server.srp_server_set_enabled(True)
+ server.start()
+ self.simulator.go(5)
+ self.assertEqual(server.get_state(), 'leader')
+ self.simulator.go(5)
+
+ client.srp_server_set_enabled(False)
+ client.start()
+ self.simulator.go(5)
+ self.assertEqual(client.get_state(), 'router')
+
+ #
+ # 1. Register a single service and verify that it works.
+ #
+
+ 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)
+
+ self.check_host_and_service(server, client, '2001::1')
+
+ #
+ # 2. Unregister a service but retain the name. The service name should be
+ # retained on the server.
+ #
+
+ client.srp_client_remove_service('my-service', '_ipps._tcp')
+ self.simulator.go(2)
+
+ client_services = client.srp_client_get_services()
+ print(client_services)
+ self.assertEqual(len(client_services), 0)
+
+ server_services = server.srp_server_get_services()
+ print(server_services)
+ self.assertEqual(len(server_services), 1)
+ server_service = server_services[0]
+
+ # Verify that the service has been successfully removed on the server side.
+ self.assertEqual(server_service['deleted'], 'true')
+
+ server_hosts = server.srp_server_get_hosts()
+ print(server_hosts)
+ self.assertEqual(len(server_hosts), 1)
+ server_host = server_hosts[0]
+
+ # The registered host should not be touched.
+ self.assertEqual(server_host['deleted'], 'false')
+ self.assertEqual(server_host['name'], 'my-host')
+ self.assertEqual(len(server_host['addresses']), 1)
+ self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address('2001::1'))
+
+ #
+ # 3. Register the same service again. It should succeed and the name should be
+ # reused.
+ #
+
+ client.srp_client_add_service('my-service', '_ipps._tcp', 12345, 0, 0, ['abc', 'def=', 'xyz=XYZ'])
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client, '2001::1')
+
+ #
+ # 4. Update the SRP host address and make sure it will succeed.
+ #
+
+ client.srp_client_set_host_address('2001::2')
+ self.simulator.go(2)
+
+ self.check_host_and_service(server, client, '2001::2')
+
+ #
+ # 5. Fully remove the host and all its service instances.
+ #
+
+ client.srp_client_remove_host(remove_key=True)
+ self.simulator.go(2)
+
+ client_services = client.srp_client_get_services()
+ print(client_services)
+ self.assertEqual(len(client_services), 0)
+
+ print(client.srp_client_get_host_state())
+
+ server_services = server.srp_server_get_services()
+ print(server_services)
+ self.assertEqual(len(server_services), 0)
+
+ server_hosts = server.srp_server_get_hosts()
+ print(server_hosts)
+ self.assertEqual(len(server_hosts), 0)
+
+ def check_host_and_service(self, server, client, host_addr):
+ """Check that we have properly registered host and service instance.
+ """
+
+ client_services = client.srp_client_get_services()
+ print(client_services)
+ self.assertEqual(len(client_services), 1)
+ client_service = client_services[0]
+
+ # Verify that the client possesses correct service resources.
+ self.assertEqual(client_service['instance'], 'my-service')
+ self.assertEqual(client_service['name'], '_ipps._tcp')
+ self.assertEqual(int(client_service['port']), 12345)
+ self.assertEqual(int(client_service['priority']), 0)
+ self.assertEqual(int(client_service['weight']), 0)
+
+ # Verify that the client received a SUCCESS response for the server.
+ self.assertEqual(client_service['state'], 'Registered')
+
+ server_services = server.srp_server_get_services()
+ self.assertEqual(len(server_services), 1)
+ server_service = server_services[0]
+
+ # Verify that the server accepted the SRP registration and stores
+ # the same service resources.
+ self.assertEqual(server_service['deleted'], 'false')
+ self.assertEqual(server_service['instance'], client_service['instance'])
+ self.assertEqual(server_service['name'], client_service['name'])
+ self.assertEqual(int(server_service['port']), int(client_service['port']))
+ self.assertEqual(int(server_service['priority']), int(client_service['priority']))
+ self.assertEqual(int(server_service['weight']), int(client_service['weight']))
+ # We output value of TXT entry as HEX string.
+ print(server_service['TXT'])
+ self.assertEqual(server_service['TXT'], ['abc', 'def=', 'xyz=58595a'])
+ self.assertEqual(server_service['host'], 'my-host')
+
+ server_hosts = server.srp_server_get_hosts()
+ print(server_hosts)
+ self.assertEqual(len(server_hosts), 1)
+ server_host = server_hosts[0]
+
+ self.assertEqual(server_host['deleted'], 'false')
+ self.assertEqual(server_host['fullname'], server_service['host_fullname'])
+ self.assertEqual(len(server_host['addresses']), 1)
+ self.assertEqual(ipaddress.ip_address(server_host['addresses'][0]), ipaddress.ip_address(host_addr))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/scripts/thread-cert/thread_cert.py b/tests/scripts/thread-cert/thread_cert.py
index ed2393d..23f7775 100644
--- a/tests/scripts/thread-cert/thread_cert.py
+++ b/tests/scripts/thread-cert/thread_cert.py
@@ -27,6 +27,7 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+import binascii
import json
import logging
import os
@@ -157,6 +158,7 @@
if node.is_host:
continue
+ self.nodes[i].set_masterkey(binascii.hexlify(config.DEFAULT_MASTER_KEY).decode())
self.nodes[i].set_panid(params['panid'])
self.nodes[i].set_mode(params['mode'])
@@ -184,6 +186,8 @@
self.nodes[i].set_timeout(params['timeout'])
if 'active_dataset' in params:
+ if 'master_key' not in params['active_dataset']:
+ params['active_dataset']['master_key'] = binascii.hexlify(config.DEFAULT_MASTER_KEY).decode()
self.nodes[i].set_active_dataset(params['active_dataset']['timestamp'],
panid=params['active_dataset'].get('panid'),
channel=params['active_dataset'].get('channel'),
diff --git a/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py b/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
index 623cc5d..15bafe9 100755
--- a/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
+++ b/tests/scripts/thread-cert/v1_2_LowPower_5_3_01_SSEDAttachment.py
@@ -61,6 +61,7 @@
SSED_1: {
'version': '1.2',
'name': 'SSED_1',
+ 'is_mtd': True,
'mode': '-',
'panid': 0xface,
'allowlist': [LEADER],
@@ -97,6 +98,8 @@
size=128,
timeout=timeout * 2))
+ self.simulator.go(5)
+
def verify(self, pv):
pkts = pv.pkts
pv.summary.show()
diff --git a/tests/scripts/thread-cert/v1_2_test_csl_transmission.py b/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
index 352ad47..f0c46e4 100755
--- a/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
+++ b/tests/scripts/thread-cert/v1_2_test_csl_transmission.py
@@ -31,14 +31,11 @@
import mle
import thread_cert
+from pktverify import consts
LEADER = 1
SSED_1 = 2
-CSL_PERIOD = 500 * 6.25 # 500ms
-CSL_TIMEOUT = 30 # 30s
-CSL_CHANNEL = 12
-
class SSED_CslTransmission(thread_cert.TestCase):
TOPOLOGY = {
@@ -47,6 +44,7 @@
},
SSED_1: {
'version': '1.2',
+ 'is_mtd': True,
'mode': '-',
},
}
@@ -54,8 +52,8 @@
def test(self):
- self.nodes[SSED_1].set_csl_period(CSL_PERIOD)
- self.nodes[SSED_1].set_csl_timeout(CSL_TIMEOUT)
+ self.nodes[SSED_1].set_csl_period(consts.CSL_DEFAULT_PERIOD)
+ self.nodes[SSED_1].set_csl_timeout(consts.CSL_DEFAULT_TIMEOUT)
self.nodes[SSED_1].get_csl_info()
@@ -68,24 +66,26 @@
self.assertEqual(self.nodes[SSED_1].get_state(), 'child')
print('SSED rloc:%s' % self.nodes[SSED_1].get_rloc())
- self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc()))
+ # Set ping timeout as two CSL periods.
+ timeout = 2 * consts.CSL_DEFAULT_PERIOD_IN_SECOND
+ self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc(), timeout=timeout))
self.simulator.go(5)
ssed_messages = self.simulator.get_messages_sent_by(SSED_1)
msg = ssed_messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST)
msg.assertMleMessageDoesNotContainTlv(mle.CslChannel)
- self.nodes[SSED_1].set_csl_channel(CSL_CHANNEL)
+ self.nodes[SSED_1].set_csl_channel(consts.CSL_DEFAULT_CHANNEL)
self.simulator.go(1)
ssed_messages = self.simulator.get_messages_sent_by(SSED_1)
msg = ssed_messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST)
msg.assertMleMessageContainsTlv(mle.CslChannel)
- self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc()))
+ self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc(), timeout=timeout))
self.simulator.go(5)
self.nodes[SSED_1].set_csl_channel(0)
self.simulator.go(1)
- self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc()))
+ self.assertTrue(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc(), timeout=timeout))
self.simulator.go(5)
ssed_messages = self.simulator.get_messages_sent_by(SSED_1)
@@ -93,7 +93,7 @@
msg.assertMleMessageDoesNotContainTlv(mle.CslChannel)
self.nodes[SSED_1].set_csl_period(0)
- self.assertFalse(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc()))
+ self.assertFalse(self.nodes[LEADER].ping(self.nodes[SSED_1].get_rloc(), timeout=timeout))
self.simulator.go(2)
self.nodes[SSED_1].set_pollperiod(1000)
diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h
index fae2095..fb41137 100644
--- a/tests/toranj/openthread-core-toranj-config-posix.h
+++ b/tests/toranj/openthread-core-toranj-config-posix.h
@@ -62,6 +62,21 @@
#define OPENTHREAD_CONFIG_POSIX_APP_TREL_INTERFACE_NAME "trel"
/**
+ * @def OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET
+ *
+ * Defines whether the TREL UDP6 platform uses netlink socket to add/remove addresses on the TREL netif or `ioctl()`
+ * command.
+ *
+ * When netlink is used Duplicate Address Detection (DAD) is disabled when a new address is added on the netif.
+ *
+ */
+#ifdef __linux__
+#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 1
+#else
+#define OPENTHREAD_CONFIG_POSIX_TREL_USE_NETLINK_SOCKET 0
+#endif
+
+/**
* @def OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
*
* Define as 1 to enable PTY device support in POSIX app.
diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h
index 0d0c328..2dc25c9 100644
--- a/tests/toranj/openthread-core-toranj-config.h
+++ b/tests/toranj/openthread-core-toranj-config.h
@@ -313,12 +313,12 @@
#define OPENTHREAD_CONFIG_LOG_PLATFORM 1
/**
- * @def OPENTHREAD_CONFIG_NCP_UART_ENABLE
+ * @def OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
*
- * Define to 1 to enable NCP UART support.
+ * Define to 1 to enable NCP HDLC support.
*
*/
-#define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
/**
* @def OPENTHREAD_CONFIG_NCP_TX_BUFFER_SIZE
@@ -470,6 +470,30 @@
*/
#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
+ *
+ * Define to 1 to enable SRP Client support.
+ *
+ */
+#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
+ *
+ * Define to 1 to enable SRP Server support.
+ *
+ */
+#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 1
+
+/**
+ * @def OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_CHANGE_ENABLE
+ *
+ * Define to 1 for the SRP client implementation to provides APIs to allow domain name to be set/changed.
+ *
+ */
+#define OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE 1
+
#if OPENTHREAD_RADIO
/**
* @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
diff --git a/tests/toranj/test-002-form.py b/tests/toranj/test-002-form.py
index 969d9ae..34841af 100644
--- a/tests/toranj/test-002-form.py
+++ b/tests/toranj/test-002-form.py
@@ -53,13 +53,11 @@
# Test implementation
# default values after reset
-DEFAULT_KEY = '[00112233445566778899AABBCCDDEEFF]'
DEFAULT_NAME = '"OpenThread"'
DEFAULT_PANID = '0xFFFF'
DEFAULT_XPANID = '0xDEAD00BEEF00CAFE'
verify(node.get(wpan.WPAN_STATE) == wpan.STATE_OFFLINE)
-verify(node.get(wpan.WPAN_KEY) == DEFAULT_KEY)
verify(node.get(wpan.WPAN_NAME) == DEFAULT_NAME)
verify(node.get(wpan.WPAN_PANID) == DEFAULT_PANID)
verify(node.get(wpan.WPAN_XPANID) == DEFAULT_XPANID)
@@ -70,7 +68,6 @@
verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
verify(node.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_LEADER)
verify(node.get(wpan.WPAN_NAME) == '"asha"')
-verify(node.get(wpan.WPAN_KEY) != DEFAULT_KEY)
verify(node.get(wpan.WPAN_PANID) != DEFAULT_PANID)
verify(node.get(wpan.WPAN_XPANID) != DEFAULT_XPANID)
@@ -83,7 +80,6 @@
verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
verify(node.get(wpan.WPAN_NAME) == '"ahura"')
verify(node.get(wpan.WPAN_CHANNEL) == '20')
-verify(node.get(wpan.WPAN_KEY) != DEFAULT_KEY)
verify(node.get(wpan.WPAN_PANID) != DEFAULT_PANID)
verify(node.get(wpan.WPAN_XPANID) != DEFAULT_XPANID)
diff --git a/tests/toranj/wpan.py b/tests/toranj/wpan.py
index 0780a97..1153405 100644
--- a/tests/toranj/wpan.py
+++ b/tests/toranj/wpan.py
@@ -1185,7 +1185,7 @@
m = re.match(
r'\t"([0-9a-fA-F:]+)\s*prefix_len:(\d+)\s+origin:(\w*)\s+stable:(\w*).* \[' +
- r'on-mesh:(\d)\s+def-route:(\d)\s+config:(\d)\s+dhcp:(\d)\s+slaac:(\d)\s+pref:(\d)\s+prio:(\w*)\]' +
+ r'on-mesh:(\d)\s+def-route:(\d)\s+config:(\d)\s+dhcp:(\d)\s+slaac:(\d)\s+pref:(\d)\s+.*prio:(\w*)\]' +
r'\s+rloc:(0x[0-9a-fA-F]+)', text)
verify(m is not None)
data = m.groups()
diff --git a/tests/unit/test_checksum.cpp b/tests/unit/test_checksum.cpp
index 0398e7d..b823281 100644
--- a/tests/unit/test_checksum.cpp
+++ b/tests/unit/test_checksum.cpp
@@ -197,7 +197,7 @@
CorruptMessage(*message);
- VerifyOrQuit(Checksum::VerifyMessageChecksum(*message, messageInfo, Ip6::kProtoUdp) != OT_ERROR_NONE,
+ VerifyOrQuit(Checksum::VerifyMessageChecksum(*message, messageInfo, Ip6::kProtoUdp) != kErrorNone,
"Checksum passed on corrupted message");
message->Free();
@@ -271,7 +271,7 @@
CorruptMessage(*message);
- VerifyOrQuit(Checksum::VerifyMessageChecksum(*message, messageInfo, Ip6::kProtoIcmp6) != OT_ERROR_NONE,
+ VerifyOrQuit(Checksum::VerifyMessageChecksum(*message, messageInfo, Ip6::kProtoIcmp6) != kErrorNone,
"Checksum passed on corrupted message");
message->Free();
diff --git a/tests/unit/test_child.cpp b/tests/unit/test_child.cpp
index 7f23363..40ee48b 100644
--- a/tests/unit/test_child.cpp
+++ b/tests/unit/test_child.cpp
@@ -92,7 +92,7 @@
{
Ip6::Address address;
- VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == kErrorNotFound,
"Child::GetMeshLocalIp6Address() returned an address not in the expected list");
}
@@ -263,7 +263,7 @@
for (uint8_t index = 0; index < numAddresses; index++)
{
- VerifyOrQuit(child.AddIp6Address(addresses[index]) == OT_ERROR_ALREADY,
+ VerifyOrQuit(child.AddIp6Address(addresses[index]) == kErrorAlready,
"AddIp6Address() did not fail when adding same address");
VerifyChildIp6Addresses(child, numAddresses, addresses);
}
@@ -278,7 +278,7 @@
SuccessOrQuit(child.RemoveIp6Address(addresses[index]), "RemoveIp6Address() failed");
VerifyChildIp6Addresses(child, numAddresses - 1 - index, &addresses[index + 1]);
- VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
"RemoveIp6Address() did not fail when removing an address not on the list");
}
@@ -298,7 +298,7 @@
SuccessOrQuit(child.RemoveIp6Address(addresses[index]), "RemoveIp6Address() failed");
VerifyChildIp6Addresses(child, index, &addresses[0]);
- VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
"RemoveIp6Address() did not fail when removing an address not on the list");
}
@@ -318,7 +318,7 @@
SuccessOrQuit(child.RemoveIp6Address(addresses[indexToRemove]), "RemoveIp6Address() failed");
- VerifyOrQuit(child.RemoveIp6Address(addresses[indexToRemove]) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(child.RemoveIp6Address(addresses[indexToRemove]) == kErrorNotFound,
"RemoveIp6Address() did not fail when removing an address not on the list");
{
diff --git a/tests/unit/test_child_table.cpp b/tests/unit/test_child_table.cpp
index fd66c65..664f46a 100644
--- a/tests/unit/test_child_table.cpp
+++ b/tests/unit/test_child_table.cpp
@@ -295,7 +295,7 @@
uint16_t testNumAllowedChildren = 2;
ChildTable *table;
- otError error;
+ Error error;
sInstance = testInitInstance();
VerifyOrQuit(sInstance != nullptr, "Null instance");
@@ -364,17 +364,17 @@
printf("Test Get/SetMaxChildrenAllowed");
error = table->SetMaxChildrenAllowed(kMaxChildren - 1);
- VerifyOrQuit(error == OT_ERROR_INVALID_STATE, "SetMaxChildrenAllowed() should fail when table is not empty");
+ VerifyOrQuit(error == kErrorInvalidState, "SetMaxChildrenAllowed() should fail when table is not empty");
table->Clear();
error = table->SetMaxChildrenAllowed(kMaxChildren + 1);
- VerifyOrQuit(error == OT_ERROR_INVALID_ARGS, "SetMaxChildrenAllowed() did not fail with an invalid arg");
+ VerifyOrQuit(error == kErrorInvalidArgs, "SetMaxChildrenAllowed() did not fail with an invalid arg");
error = table->SetMaxChildrenAllowed(0);
- VerifyOrQuit(error == OT_ERROR_INVALID_ARGS, "SetMaxChildrenAllowed() did not fail with an invalid arg");
+ VerifyOrQuit(error == kErrorInvalidArgs, "SetMaxChildrenAllowed() did not fail with an invalid arg");
error = table->SetMaxChildrenAllowed(testNumAllowedChildren);
- VerifyOrQuit(error == OT_ERROR_NONE, "SetMaxChildrenAllowed() failed");
+ VerifyOrQuit(error == kErrorNone, "SetMaxChildrenAllowed() failed");
VerifyOrQuit(table->GetMaxChildrenAllowed() == testNumAllowedChildren, "GetMaxChildrenAllowed() failed");
for (uint16_t num = 0; num < testNumAllowedChildren; num++)
diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp
index 2450149..64011e5 100644
--- a/tests/unit/test_dns.cpp
+++ b/tests/unit/test_dns.cpp
@@ -34,7 +34,7 @@
#include "test_util.hpp"
#include "common/instance.hpp"
-#include "net/dns_headers.hpp"
+#include "net/dns_types.hpp"
namespace ot {
@@ -42,9 +42,8 @@
{
enum
{
- kMaxSize = 300,
- kLabelSize = 64,
- kNameSize = 256,
+ kMaxSize = 300,
+ kMaxNameLength = Dns::Name::kMaxNameSize - 1,
};
struct TestName
@@ -62,9 +61,9 @@
uint8_t buffer[kMaxSize];
uint16_t len;
uint16_t offset;
- char label[kLabelSize];
+ char label[Dns::Name::kMaxLabelSize];
uint8_t labelLength;
- char name[kNameSize];
+ char name[Dns::Name::kMaxNameSize];
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};
@@ -88,6 +87,18 @@
{nullptr, sizeof(kEncodedName4), kEncodedName4, kLabels4, "."},
};
+ static const char *kMaxLengthNames[] = {
+ "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
+ "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
+ "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
+ "SorcererAndMagicia.",
+
+ "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
+ "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
+ "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
+ "SorcererAndMagicia",
+ };
+
static const char *kInvalidNames[] = {
"foo..bar",
"..",
@@ -104,8 +115,24 @@
"SorcererAndMagician.NoEyesCanEverSee.AnArtfulConjurer.MySenseFromMeTaken."
"MyEyesWillNeverSee.BeautiesOfTheWholeWorld.BeholdWhoseVisionFine.MySightFromMeTaken"
"PoemByRumiMolana",
+
+ // Long name of 255 characters which ends with a dot
+ "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
+ "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
+ "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
+ "SorcererAndMagician.",
+
+ // Long name of 254 characters which does not end with a dot
+ "HereIsSomeoneHidden.MyHoldFromMeTaken.FromSelfHasMeDriven.MyLeadFromMeTaken."
+ "HereIsSomeoneHidden.AsLifeSweeterThanLife.TakesMeToGardenOfSoul.MyFortFromMeTaken."
+ "HereIsSomeoneHidden.LikeSugarInSugarCane.ASweetSugarTrader.MyShopFromMeTaken."
+ "SorcererAndMagician",
+
};
+ static const char kBadLabel[] = "badlabel";
+ static const char kBadName[] = "bad.name";
+
printf("================================================================\n");
printf("TestDnsName()\n");
@@ -115,6 +142,45 @@
messagePool = &instance->Get<MessagePool>();
VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+ message->SetOffset(0);
+
+ printf("----------------------------------------------------------------\n");
+ printf("Verify domain name match:\n");
+
+ {
+ const char *subDomain;
+ const char *domain;
+
+ subDomain = "my-service._ipps._tcp.local.";
+ domain = "local.";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ subDomain = "my-service._ipps._tcp.local";
+ domain = "local.";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ subDomain = "my-service._ipps._tcp.local.";
+ domain = "local";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ subDomain = "my-service._ipps._tcp.local";
+ domain = "local";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ subDomain = "my-service._ipps._tcp.default.service.arpa.";
+ domain = "default.service.arpa.";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ subDomain = "my-service._ipps._tcp.default.service.arpa.";
+ domain = "service.arpa.";
+ VerifyOrQuit(Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() failed");
+
+ // Verify it doesn't match a portion of a label.
+ subDomain = "my-service._ipps._tcp.default.service.arpa.";
+ domain = "vice.arpa.";
+ VerifyOrQuit(!Dns::Name::IsSubDomainOf(subDomain, domain), "Name::IsSubDomainOf() succeed");
+ }
+
printf("----------------------------------------------------------------\n");
printf("Append names, check encoded bytes, parse name and read labels:\n");
@@ -143,7 +209,7 @@
for (uint8_t index = 0; test.mLabels[index] != nullptr; index++)
{
labelLength = sizeof(label);
- SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, 0, label, labelLength), "Name::ReadLabel() failed");
+ SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength), "Name::ReadLabel() failed");
printf("Label[%d] = \"%s\"\n", index, label);
@@ -152,12 +218,12 @@
}
labelLength = sizeof(label);
- VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, 0, label, labelLength) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
"Name::ReadLabel() failed at end of the name");
// Read entire name
offset = 0;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, 0, name, sizeof(name)), "Name::ReadName() failed");
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)), "Name::ReadName() failed");
printf("Read name =\"%s\"\n", name);
@@ -167,12 +233,82 @@
// Read entire name with different name buffer sizes (just right and one byte off the expected size)
offset = 0;
SuccessOrQuit(
- Dns::Name::ReadName(*message, offset, 0, name, static_cast<uint16_t>(strlen(test.mExpectedReadName) + 1)),
+ Dns::Name::ReadName(*message, offset, name, static_cast<uint16_t>(strlen(test.mExpectedReadName) + 1)),
"Name::ReadName() failed with exact name buffer size");
offset = 0;
- VerifyOrQuit(Dns::Name::ReadName(*message, offset, 0, name,
- static_cast<uint16_t>(strlen(test.mExpectedReadName))) == OT_ERROR_NO_BUFS,
+ VerifyOrQuit(Dns::Name::ReadName(*message, offset, name,
+ static_cast<uint16_t>(strlen(test.mExpectedReadName))) == kErrorNoBufs,
"Name::ReadName() did not fail with too small name buffer size");
+
+ // Compare labels one by one.
+ offset = 0;
+
+ for (uint8_t index = 0; test.mLabels[index] != nullptr; index++)
+ {
+ uint16_t startOffset = offset;
+
+ SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, test.mLabels[index]),
+ "Name::CompareLabel() failed");
+ VerifyOrQuit(offset != startOffset, "Name::CompareLabel() did not change offset");
+
+ VerifyOrQuit(Dns::Name::CompareLabel(*message, startOffset, kBadLabel) == kErrorNotFound,
+ "Name::CompareLabel() did not fail with incorrect label");
+ }
+
+ // Compare the whole name.
+ offset = 0;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, test.mExpectedReadName), "Name::CompareName() failed");
+ VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
+
+ offset = 0;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
+ "Name::CompareName() did not fail with incorrect name");
+ VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
+
+ // Remove the terminating '.' in expected name and verify
+ // that it can still be used by `CompareName()`.
+ offset = 0;
+ strcpy(name, test.mExpectedReadName);
+ name[strlen(name) - 1] = '\0';
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, name), "Name::CompareName() failed with root");
+ VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
+
+ if (strlen(name) >= 1)
+ {
+ name[strlen(name) - 1] = '\0';
+ offset = 0;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, name) == kErrorNotFound,
+ "Name::CompareName() did not fail with invalid name");
+ VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
+ }
+
+ // Compare the name with itself read from message.
+ offset = 0;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset),
+ "Name::CompareName() with itself failed");
+ VerifyOrQuit(offset == len, "Name::CompareName() returned incorrect offset");
+ }
+
+ printf("----------------------------------------------------------------\n");
+ printf("Max length names:\n");
+
+ for (const char *&maxLengthName : kMaxLengthNames)
+ {
+ if (maxLengthName[strlen(maxLengthName) - 1] == '.')
+ {
+ VerifyOrQuit(strlen(maxLengthName) == kMaxNameLength, "invalid max length string");
+ }
+ else
+ {
+ VerifyOrQuit(strlen(maxLengthName) == kMaxNameLength - 1, "invalid max length string");
+ }
+
+ IgnoreError(message->SetLength(0));
+
+ printf("\"%s\"\n", maxLengthName);
+
+ VerifyOrQuit(Dns::Name::AppendName(maxLengthName, *message) == kErrorNone,
+ "Name::AppendName() failed with max length name");
}
printf("----------------------------------------------------------------\n");
@@ -184,7 +320,7 @@
printf("\"%s\"\n", invalidName);
- VerifyOrQuit(Dns::Name::AppendName(invalidName, *message) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(Dns::Name::AppendName(invalidName, *message) == kErrorInvalidArgs,
"Name::AppendName() did not fail with an invalid name");
}
@@ -266,6 +402,8 @@
static const char kExpectedReadName2[] = "FOO.F.ISI.ARPA.";
static const char kExpectedReadName3[] = "ISI.ARPA.";
+ static const char kBadName[] = "bad.name";
+
Instance * instance;
MessagePool *messagePool;
Message * message;
@@ -295,6 +433,8 @@
SuccessOrQuit(message->Append(index), "Message::Append() failed");
}
+ message->SetOffset(kHeaderOffset);
+
name1Offset = message->GetLength();
SuccessOrQuit(Dns::Name::AppendName(kName, *message), "Name::AppendName() failed");
@@ -348,8 +488,7 @@
for (const char *nameLabel : kName1Labels)
{
labelLength = sizeof(label);
- SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength),
- "Name::ReadLabel() failed");
+ SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength), "Name::ReadLabel() failed");
printf("label: \"%s\"\n", label);
VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
@@ -357,15 +496,40 @@
}
labelLength = sizeof(label);
- VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
"Name::ReadLabel() failed at end of the name");
offset = name1Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, kHeaderOffset, name, sizeof(name)), "Name::ReadName() failed");
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)), "Name::ReadName() failed");
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), "Name::ComapreLabel() failed");
+ }
+
+ offset = name1Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName1), "Name::CompareName() failed");
+ VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
+
+ offset = name1Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
+ "Name::CompareName() did not fail with incorrect name");
+ VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
+
+ offset = name1Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
+ VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
+
+ offset = name1Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name2Offset) == kErrorNotFound,
+ "Name::CompareName() did not fail with mismatching name");
+ VerifyOrQuit(offset == name1Offset + sizeof(kEncodedName), "Name::CompareName() returned incorrect offset");
+
printf("----------------------------------------------------------------\n");
printf("Read and parse compressed name-2 \"FOO.F.ISI.ARPA\"\n");
@@ -381,8 +545,7 @@
for (const char *nameLabel : kName2Labels)
{
labelLength = sizeof(label);
- SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength),
- "Name::ReadLabel() failed");
+ SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength), "Name::ReadLabel() failed");
printf("label: \"%s\"\n", label);
VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
@@ -390,15 +553,40 @@
}
labelLength = sizeof(label);
- VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
"Name::ReadLabel() failed at end of the name");
offset = name2Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, kHeaderOffset, name, sizeof(name)), "Name::ReadName() failed");
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)), "Name::ReadName() failed");
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), "Name::ComapreLabel() failed");
+ }
+
+ offset = name2Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName2), "Name::CompareName() failed");
+ VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name2Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
+ "Name::CompareName() did not fail with incorrect name");
+ VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name2Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
+ VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name2Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name3Offset) == kErrorNotFound,
+ "Name::CompareName() did not fail with mismatching name");
+ VerifyOrQuit(offset == name2Offset + kName2EncodedSize, "Name::CompareName() returned incorrect offset");
+
printf("----------------------------------------------------------------\n");
printf("Read and parse compressed name-3 \"ISI.ARPA\"\n");
@@ -414,8 +602,7 @@
for (const char *nameLabel : kName3Labels)
{
labelLength = sizeof(label);
- SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength),
- "Name::ReadLabel() failed");
+ SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength), "Name::ReadLabel() failed");
printf("label: \"%s\"\n", label);
VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
@@ -423,15 +610,40 @@
}
labelLength = sizeof(label);
- VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength) == OT_ERROR_NOT_FOUND,
+ VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorNotFound,
"Name::ReadLabel() failed at end of the name");
offset = name3Offset;
- SuccessOrQuit(Dns::Name::ReadName(*message, offset, kHeaderOffset, name, sizeof(name)), "Name::ReadName() failed");
+ SuccessOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)), "Name::ReadName() failed");
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), "Name::ComapreLabel() failed");
+ }
+
+ offset = name3Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kExpectedReadName3), "Name::CompareName() failed");
+ VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name3Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, kBadName) == kErrorNotFound,
+ "Name::CompareName() did not fail with incorrect name");
+ VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name3Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
+ VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
+
+ offset = name3Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name4Offset) == kErrorNotFound,
+ "Name::CompareName() did not fail with mismatching name");
+ VerifyOrQuit(offset == name3Offset + kName3EncodedSize, "Name::CompareName() returned incorrect offset");
+
printf("----------------------------------------------------------------\n");
printf("Read and parse the uncompressed name-4 \"Human\\.Readable.F.ISI.ARPA\"\n");
@@ -447,8 +659,7 @@
for (const char *nameLabel : kName4Labels)
{
labelLength = sizeof(label);
- SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, kHeaderOffset, label, labelLength),
- "Name::ReadLabel() failed");
+ SuccessOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength), "Name::ReadLabel() failed");
printf("label: \"%s\"\n", label);
VerifyOrQuit(strcmp(label, nameLabel) == 0, "Name::ReadLabel() did not get expected label");
@@ -457,9 +668,636 @@
// `ReadName()` for name-4 should fails due to first label containing dot char.
offset = name4Offset;
- VerifyOrQuit(Dns::Name::ReadName(*message, offset, kHeaderOffset, name, sizeof(name)) == OT_ERROR_PARSE,
+ VerifyOrQuit(Dns::Name::ReadName(*message, offset, name, sizeof(name)) == kErrorParse,
"Name::ReadName() did not fail with invalid label");
+ offset = name4Offset;
+
+ for (const char *nameLabel : kName4Labels)
+ {
+ SuccessOrQuit(Dns::Name::CompareLabel(*message, offset, nameLabel), "Name::ComapreLabel() failed");
+ }
+
+ offset = name4Offset;
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, *message, offset), "Name::CompareName() with itself failed");
+
+ offset = name4Offset;
+ VerifyOrQuit(Dns::Name::CompareName(*message, offset, *message, name1Offset) == kErrorNotFound,
+ "Name::CompareName() did not fail with mismatching name");
+
+ message->Free();
+ testFreeInstance(instance);
+}
+
+void TestHeaderAndResourceRecords(void)
+{
+ enum
+ {
+ kHeaderOffset = 0,
+ kQuestionCount = 1,
+ kAnswerCount = 2,
+ kAdditionalCount = 5,
+ kTtl = 7200,
+ kTxtTtl = 7300,
+ kSrvPort = 1234,
+ kSrvPriority = 1,
+ kSrvWeight = 2,
+ kMaxSize = 600,
+ };
+
+ const char kMessageString[] = "DnsMessage";
+ const char kDomainName[] = "example.com.";
+ const char kServiceLabels[] = "_service._udp";
+ const char kServiceName[] = "_service._udp.example.com.";
+ const char kInstance1Label[] = "inst1";
+ const char kInstance2Label[] = "instance2";
+ const char kInstance1Name[] = "inst1._service._udp.example.com.";
+ const char kInstance2Name[] = "instance2._service._udp.example.com.";
+ const char kHostName[] = "host.example.com.";
+ const uint8_t kTxtData[] = {9, 'k', 'e', 'y', '=', 'v', 'a', 'l', 'u', 'e', 0};
+ const char kHostAddress[] = "fd00::abcd:";
+
+ const char *kInstanceLabels[] = {kInstance1Label, kInstance2Label};
+ const char *kInstanceNames[] = {kInstance1Name, kInstance2Name};
+
+ Instance * instance;
+ MessagePool * messagePool;
+ Message * message;
+ Dns::Header header;
+ uint16_t messageId;
+ uint16_t headerOffset;
+ uint16_t offset;
+ uint16_t numRecords;
+ uint16_t len;
+ uint16_t serviceNameOffset;
+ uint16_t hostNameOffset;
+ uint16_t answerSectionOffset;
+ uint16_t additionalSectionOffset;
+ uint16_t index;
+ Dns::PtrRecord ptrRecord;
+ Dns::SrvRecord srvRecord;
+ Dns::TxtRecord txtRecord;
+ Dns::AaaaRecord aaaaRecord;
+ Dns::ResourceRecord record;
+ Ip6::Address hostAddress;
+
+ char label[Dns::Name::kMaxLabelSize];
+ char name[Dns::Name::kMaxNameSize];
+ uint8_t buffer[kMaxSize];
+
+ printf("================================================================\n");
+ printf("TestHeaderAndResourceRecords()\n");
+
+ instance = static_cast<Instance *>(testInitInstance());
+ VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+ messagePool = &instance->Get<MessagePool>();
+ VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+
+ printf("----------------------------------------------------------------\n");
+ printf("Preparing the message\n");
+
+ SuccessOrQuit(message->Append(kMessageString), "Message::Append() failed");
+
+ // Header
+
+ headerOffset = message->GetLength();
+ SuccessOrQuit(header.SetRandomMessageId(), "Header::SetRandomMessageId() failed");
+ messageId = header.GetMessageId();
+ header.SetType(Dns::Header::kTypeResponse);
+ header.SetQuestionCount(kQuestionCount);
+ header.SetAnswerCount(kAnswerCount);
+ header.SetAdditionalRecordCount(kAdditionalCount);
+ SuccessOrQuit(message->Append(header), "Message::Append() failed");
+ message->SetOffset(headerOffset);
+
+ // Question section
+
+ serviceNameOffset = message->GetLength() - headerOffset;
+ SuccessOrQuit(Dns::Name::AppendMultipleLabels(kServiceLabels, *message), "AppendMultipleLabels() failed");
+ SuccessOrQuit(Dns::Name::AppendName(kDomainName, *message), "AppendName() failed");
+ SuccessOrQuit(message->Append(Dns::Question(Dns::ResourceRecord::kTypePtr)), "Message::Append() failed");
+
+ // Answer section
+
+ answerSectionOffset = message->GetLength();
+
+ for (const char *instanceLabel : kInstanceLabels)
+ {
+ SuccessOrQuit(Dns::Name::AppendPointerLabel(serviceNameOffset, *message), "AppendPointerLabel() failed");
+ ptrRecord.Init();
+ ptrRecord.SetTtl(kTtl);
+ offset = message->GetLength();
+ SuccessOrQuit(message->Append(ptrRecord), "Message::Append() failed");
+ SuccessOrQuit(Dns::Name::AppendLabel(instanceLabel, *message), "AppendLabel failed");
+ SuccessOrQuit(Dns::Name::AppendPointerLabel(serviceNameOffset, *message), "AppendPointerLabel() failed");
+ ptrRecord.SetLength(message->GetLength() - offset - sizeof(Dns::ResourceRecord));
+ message->Write(offset, ptrRecord);
+ }
+
+ // Additional section
+
+ additionalSectionOffset = message->GetLength();
+
+ for (const char *instanceName : kInstanceNames)
+ {
+ uint16_t instanceNameOffset = message->GetLength() - headerOffset;
+
+ // SRV record
+ SuccessOrQuit(Dns::Name::AppendName(instanceName, *message), "AppendName() failed");
+ srvRecord.Init();
+ srvRecord.SetTtl(kTtl);
+ srvRecord.SetPort(kSrvPort);
+ srvRecord.SetWeight(kSrvWeight);
+ srvRecord.SetPriority(kSrvPriority);
+ offset = message->GetLength();
+ SuccessOrQuit(message->Append(srvRecord), "Message::Append() failed");
+ hostNameOffset = message->GetLength() - headerOffset;
+ SuccessOrQuit(Dns::Name::AppendName(kHostName, *message), "AppendName() failed");
+ srvRecord.SetLength(message->GetLength() - offset - sizeof(Dns::ResourceRecord));
+ message->Write(offset, srvRecord);
+
+ // TXT record
+ SuccessOrQuit(Dns::Name::AppendPointerLabel(instanceNameOffset, *message), "AppendPointerLabel() failed");
+ txtRecord.Init();
+ txtRecord.SetTtl(kTxtTtl);
+ txtRecord.SetLength(sizeof(kTxtData));
+ SuccessOrQuit(message->Append(txtRecord), "Message::Append() failed");
+ SuccessOrQuit(message->Append(kTxtData), "Message::Append() failed");
+ }
+
+ SuccessOrQuit(hostAddress.FromString(kHostAddress), "Address::FromString() failed");
+ SuccessOrQuit(Dns::Name::AppendPointerLabel(hostNameOffset, *message), "AppendPointerLabel() failed");
+ aaaaRecord.Init();
+ aaaaRecord.SetTtl(kTtl);
+ aaaaRecord.SetAddress(hostAddress);
+ SuccessOrQuit(message->Append(aaaaRecord), "Message::Append()");
+
+ // Dump the entire message
+
+ VerifyOrQuit(message->GetLength() < kMaxSize, "Message is too long");
+ SuccessOrQuit(message->Read(0, buffer, message->GetLength()), "Message::Read() failed");
+ DumpBuffer("message", buffer, message->GetLength());
+
+ printf("----------------------------------------------------------------\n");
+ printf("Parse and verify the message\n");
+
+ offset = 0;
+ VerifyOrQuit(message->Compare(offset, kMessageString), "Message header does not match");
+ offset += sizeof(kMessageString);
+
+ // Header
+
+ VerifyOrQuit(offset == headerOffset, "headerOffset is incorrect");
+ SuccessOrQuit(message->Read(offset, header), "Message::Read() failed");
+ offset += sizeof(header);
+
+ VerifyOrQuit(header.GetMessageId() == messageId, "Header::GetMessageId() failed");
+ VerifyOrQuit(header.GetType() == Dns::Header::kTypeResponse, "Header::GetType() failed");
+ VerifyOrQuit(header.GetQuestionCount() == kQuestionCount, "Header::GetQuestionCount() failed");
+ VerifyOrQuit(header.GetAnswerCount() == kAnswerCount, "Header::GetAnswerCount() failed");
+ VerifyOrQuit(header.GetAdditionalRecordCount() == kAdditionalCount, "Header::GetAdditionalRecordCount() failed");
+
+ printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
+ printf("Question Section\n");
+
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kServiceName), "Question name does not match");
+ VerifyOrQuit(message->Compare(offset, Dns::Question(Dns::ResourceRecord::kTypePtr)), "Question does not match");
+ offset += sizeof(Dns::Question);
+
+ printf("PTR for \"%s\"\n", kServiceName);
+
+ printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
+ printf("Answer Section\n");
+
+ VerifyOrQuit(offset == answerSectionOffset, "answer section offset is incorrect");
+
+ for (const char *instanceName : kInstanceNames)
+ {
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kServiceName), "ServiceName is incorrect");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord), "ReadRecord() failed");
+ VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
+
+ SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, name, sizeof(name)), "ReadName() failed");
+ VerifyOrQuit(strcmp(name, instanceName) == 0, "Inst1 name is incorrect");
+
+ printf(" \"%s\" PTR %u %d \"%s\"\n", kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength(), name);
+ }
+
+ VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
+
+ offset = answerSectionOffset;
+ SuccessOrQuit(Dns::ResourceRecord::ParseRecords(*message, offset, kAnswerCount), "ParseRecords() failed");
+ VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
+
+ printf("Use FindRecord() to find and iterate through all the records:\n");
+
+ offset = answerSectionOffset;
+ numRecords = kAnswerCount;
+
+ while (numRecords > 0)
+ {
+ uint16_t prevNumRecords = numRecords;
+
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)),
+ "FindRecord failed");
+ VerifyOrQuit(numRecords == prevNumRecords - 1, "Incorrect num records");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, ptrRecord), "ReadRecord() failed");
+ VerifyOrQuit(ptrRecord.GetTtl() == kTtl, "Read PTR is incorrect");
+ SuccessOrQuit(ptrRecord.ReadPtrName(*message, offset, label, sizeof(label), name, sizeof(name)),
+ "ReadName() failed");
+ printf(" \"%s\" PTR %u %d inst:\"%s\" at \"%s\"\n", kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength(),
+ label, name);
+ }
+
+ VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)) ==
+ kErrorNotFound,
+ "FindRecord did not fail with no records");
+
+ // Use `ReadRecord()` with a non-matching record type. Verify that it correct skips over the record.
+
+ offset = answerSectionOffset;
+ numRecords = kAnswerCount;
+
+ while (numRecords > 0)
+ {
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kServiceName)),
+ "FindRecord failed");
+ VerifyOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord) == kErrorNotFound,
+ "ReadRecord() did not fail with non-matching type");
+ }
+
+ VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
+
+ // Use `FindRecord` with a non-matching name. Verify that it correctly skips over all records.
+
+ offset = answerSectionOffset;
+ numRecords = kAnswerCount;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kInstance1Name)) ==
+ kErrorNotFound,
+ "FindRecord did not fail with non-matching name");
+ VerifyOrQuit(numRecords == 0, "Incorrect num records");
+ VerifyOrQuit(offset == additionalSectionOffset, "offset is incorrect after answer section parse");
+
+ printf("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n");
+ printf("Additional Section\n");
+
+ for (const char *instanceName : kInstanceNames)
+ {
+ // SRV record
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, instanceName), "Instance is incorrect");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord), "ReadRecord() failed");
+ VerifyOrQuit(srvRecord.GetTtl() == kTtl, "Read SRV is incorrect");
+ VerifyOrQuit(srvRecord.GetPort() == kSrvPort, "Read SRV port is incorrect");
+ VerifyOrQuit(srvRecord.GetWeight() == kSrvWeight, "Read SRV weight is incorrect");
+ VerifyOrQuit(srvRecord.GetPriority() == kSrvPriority, "Read SRV priority is incorrect");
+ SuccessOrQuit(srvRecord.ReadTargetHostName(*message, offset, name, sizeof(name)),
+ "ReadTargetHostName() failed");
+ VerifyOrQuit(strcmp(name, kHostName) == 0, "Inst1 name is incorrect");
+ printf(" \"%s\" SRV %u %d %d %d %d \"%s\"\n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
+ srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority(), name);
+
+ // TXT record
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, instanceName), "Instance is incorrect");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, txtRecord), "ReadRecord() failed");
+ VerifyOrQuit(txtRecord.GetTtl() == kTxtTtl, "Read TXT is incorrect");
+ len = sizeof(buffer);
+ SuccessOrQuit(txtRecord.ReadTxtData(*message, offset, buffer, len), "ReadTxtData() failed");
+ VerifyOrQuit(len == sizeof(kTxtData), "TXT data length is not valid");
+ VerifyOrQuit(memcmp(buffer, kTxtData, len) == 0, "TXT data is not valid");
+ printf(" \"%s\" TXT %u %d \"%s\"\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength(),
+ reinterpret_cast<const char *>(buffer));
+ }
+
+ SuccessOrQuit(Dns::Name::CompareName(*message, offset, kHostName), "HostName is incorrect");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, aaaaRecord), "ReadRecord() failed");
+ VerifyOrQuit(aaaaRecord.GetTtl() == kTtl, "Read AAAA is incorrect");
+ VerifyOrQuit(aaaaRecord.GetAddress() == hostAddress, "Read host address is incorrect");
+ printf(" \"%s\" AAAA %u %d \"%s\"\n", kHostName, aaaaRecord.GetTtl(), aaaaRecord.GetLength(),
+ aaaaRecord.GetAddress().ToString().AsCString());
+
+ VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
+
+ // Use `ParseRecords()` to parse all records
+ offset = additionalSectionOffset;
+ SuccessOrQuit(Dns::ResourceRecord::ParseRecords(*message, offset, kAdditionalCount), "ParseRecords() failed");
+ VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
+
+ printf("Use FindRecord() to search for specific name:\n");
+
+ for (const char *instanceName : kInstanceNames)
+ {
+ offset = additionalSectionOffset;
+ numRecords = kAdditionalCount;
+
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)),
+ "FindRecord failed");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, srvRecord), "ReadRecord() failed");
+ SuccessOrQuit(Dns::Name::ParseName(*message, offset), "ParseName() failed");
+ printf(" \"%s\" SRV %u %d %d %d %d\n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
+ srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority());
+
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)),
+ "FindRecord failed");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, txtRecord), "ReadRecord() failed");
+ offset += txtRecord.GetLength();
+ printf(" \"%s\" TXT %u %d\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength());
+
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(instanceName)) ==
+ kErrorNotFound,
+ "FindRecord() did not fail with no more records");
+
+ VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
+ }
+
+ offset = additionalSectionOffset;
+ numRecords = kAdditionalCount;
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, numRecords, Dns::Name(kHostName)),
+ "FindRecord() failed");
+ SuccessOrQuit(Dns::ResourceRecord::ReadRecord(*message, offset, record), "ReadRecord() failed");
+ VerifyOrQuit(record.GetType() == Dns::ResourceRecord::kTypeAaaa, "Read record has incorrect type");
+ offset += record.GetLength();
+ VerifyOrQuit(offset == message->GetLength(), "offset is incorrect after additional section parse");
+
+ printf("Use FindRecord() to search for specific records:\n");
+ printf(" Answer Section\n");
+
+ for (index = 0; index < OT_ARRAY_LENGTH(kInstanceNames); index++)
+ {
+ offset = answerSectionOffset;
+ SuccessOrQuit(
+ Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName), ptrRecord),
+ "FindRecord() failed");
+
+ printf(" index:%d -> \"%s\" PTR %u %d\n", index, kServiceName, ptrRecord.GetTtl(), ptrRecord.GetLength());
+ }
+
+ // Check `FindRecord()` failure with non-matching name, record type, or bad index.
+
+ offset = answerSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName),
+ ptrRecord) == kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+ VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
+
+ offset = answerSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kInstance1Name),
+ ptrRecord) == kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+ VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
+
+ offset = answerSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAnswerCount, index, Dns::Name(kServiceName),
+ txtRecord) == kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+ VerifyOrQuit(offset == answerSectionOffset, "FindRecord() changed offset on failure");
+
+ printf(" Additional Section\n");
+
+ for (const char *instanceName : kInstanceNames)
+ {
+ // There is a single SRV and TXT entry for each instance
+ offset = additionalSectionOffset;
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 0,
+ Dns::Name(instanceName), srvRecord),
+ "FindRecord() failed");
+ printf(" \"%s\" SRV %u %d %d %d %d \n", instanceName, srvRecord.GetTtl(), srvRecord.GetLength(),
+ srvRecord.GetPort(), srvRecord.GetWeight(), srvRecord.GetPriority());
+
+ offset = additionalSectionOffset;
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 0,
+ Dns::Name(instanceName), txtRecord),
+ "FindRecord() failed");
+ printf(" \"%s\" TXT %u %d\n", instanceName, txtRecord.GetTtl(), txtRecord.GetLength());
+
+ offset = additionalSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 1,
+ Dns::Name(instanceName), srvRecord) == kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+
+ offset = additionalSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, /* aIndex */ 1,
+ Dns::Name(instanceName), txtRecord) == kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+ }
+
+ for (index = 0; index < kAdditionalCount; index++)
+ {
+ offset = additionalSectionOffset;
+ // Find record with empty name (matching any) and any type.
+ SuccessOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, index, Dns::Name(), record),
+ "FindRecord() failed");
+ }
+
+ offset = additionalSectionOffset;
+ VerifyOrQuit(Dns::ResourceRecord::FindRecord(*message, offset, kAdditionalCount, index, Dns::Name(), record) ==
+ kErrorNotFound,
+ "FindRecord() did not fail with bad index");
+
+ message->Free();
+ testFreeInstance(instance);
+}
+
+void TestDnsTxtEntry(void)
+{
+ enum
+ {
+ kMaxTxtDataSize = 255,
+ };
+
+ struct EncodedTxtData
+ {
+ const uint8_t *mData;
+ uint8_t mLength;
+ };
+
+ const char kKey1[] = "key";
+ const uint8_t kValue1[] = {'v', 'a', 'l', 'u', 'e'};
+
+ const char kKey2[] = "E";
+ const uint8_t kValue2[] = {'m', 'c', '^', '2'};
+
+ const char kKey3[] = "space key";
+ const uint8_t kValue3[] = {'=', 0, '='};
+
+ const char kKey4[] = "123456789"; // Max recommended length key
+ const uint8_t kValue4[] = {0};
+
+ const char kKey5[] = "1234567890"; // Longer than recommended key
+ const uint8_t kValue5[] = {'a'};
+
+ const char kKey6[] = "boolKey"; // Should be encoded as "boolKey" (without `=`).
+ const char kKey7[] = "emptyKey"; // Should be encoded as "emptyKey=".
+
+ // Invalid key
+ const char kShortKey[] = "";
+
+ const uint8_t kEncodedTxt1[] = {9, 'k', 'e', 'y', '=', 'v', 'a', 'l', 'u', 'e'};
+ const uint8_t kEncodedTxt2[] = {6, 'E', '=', 'm', 'c', '^', '2'};
+ const uint8_t kEncodedTxt3[] = {13, 's', 'p', 'a', 'c', 'e', ' ', 'k', 'e', 'y', '=', '=', 0, '='};
+ const uint8_t kEncodedTxt4[] = {11, '1', '2', '3', '4', '5', '6', '7', '8', '9', '=', 0};
+ const uint8_t kEncodedTxt5[] = {12, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '=', 'a'};
+ const uint8_t kEncodedTxt6[] = {7, 'b', 'o', 'o', 'l', 'K', 'e', 'y'};
+ const uint8_t kEncodedTxt7[] = {9, 'e', 'm', 'p', 't', 'y', 'K', 'e', 'y', '='};
+
+ const uint8_t kInvalidEncodedTxt1[] = {4, 'a', '=', 'b'}; // Incorrect length
+
+ // Special encoded txt data with zero strings and string starting
+ // with '=' (missing key) whcih should be skipped over silently.
+ const uint8_t kSpecialEncodedTxt[] = {0, 0, 3, 'A', '=', 'B', 2, '=', 'C', 3, 'D', '=', 'E', 3, '=', '1', '2'};
+
+ const Dns::TxtEntry kTxtEntries[] = {
+ Dns::TxtEntry(kKey1, kValue1, sizeof(kValue1)),
+ Dns::TxtEntry(kKey2, kValue2, sizeof(kValue2)),
+ Dns::TxtEntry(kKey3, kValue3, sizeof(kValue3)),
+ Dns::TxtEntry(kKey4, kValue4, sizeof(kValue4)),
+ Dns::TxtEntry(kKey5, kValue5, sizeof(kValue5)),
+ Dns::TxtEntry(kKey6, nullptr, 0),
+ Dns::TxtEntry(kKey7, kValue1, 0),
+ };
+
+ const EncodedTxtData kEncodedTxtData[] = {
+ {kEncodedTxt1, sizeof(kEncodedTxt1)}, {kEncodedTxt2, sizeof(kEncodedTxt2)},
+ {kEncodedTxt3, sizeof(kEncodedTxt3)}, {kEncodedTxt4, sizeof(kEncodedTxt4)},
+ {kEncodedTxt5, sizeof(kEncodedTxt5)}, {kEncodedTxt6, sizeof(kEncodedTxt6)},
+ {kEncodedTxt7, sizeof(kEncodedTxt7)}};
+
+ Instance * instance;
+ MessagePool * messagePool;
+ Message * message;
+ uint8_t txtData[kMaxTxtDataSize];
+ uint16_t txtDataLength;
+ uint8_t index;
+ Dns::TxtEntry txtEntry;
+ Dns::TxtEntry::Iterator iterator;
+
+ printf("================================================================\n");
+ printf("TestDnsTxtEntry()\n");
+
+ instance = static_cast<Instance *>(testInitInstance());
+ VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+ messagePool = &instance->Get<MessagePool>();
+ VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+
+ SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, OT_ARRAY_LENGTH(kTxtEntries), *message),
+ "TxtEntry::AppendEntries() failed");
+
+ txtDataLength = message->GetLength();
+ VerifyOrQuit(txtDataLength < kMaxTxtDataSize, "TXT data is too long");
+
+ SuccessOrQuit(message->Read(0, txtData, txtDataLength), "Failed to read txt data from message");
+ DumpBuffer("txt data", txtData, txtDataLength);
+
+ index = 0;
+ for (const EncodedTxtData &encodedData : kEncodedTxtData)
+ {
+ VerifyOrQuit(memcmp(&txtData[index], encodedData.mData, encodedData.mLength) == 0,
+ "TxtData is incorrectly encoded");
+ index += encodedData.mLength;
+ }
+
+ iterator.Init(txtData, txtDataLength);
+
+ for (const Dns::TxtEntry &expectedTxtEntry : kTxtEntries)
+ {
+ uint8_t expectedKeyLength = static_cast<uint8_t>(strlen(expectedTxtEntry.mKey));
+
+ SuccessOrQuit(iterator.GetNextEntry(txtEntry), "TxtEntry::GetNextEntry() failed");
+ printf("key:\"%s\" valueLen:%d\n", txtEntry.mKey != nullptr ? txtEntry.mKey : "(null)", txtEntry.mValueLength);
+
+ if (expectedKeyLength > Dns::TxtEntry::kMaxKeyLength)
+ {
+ // When the key is longer than recommended max key length,
+ // the full encoded string is returned in `mValue` and
+ // `mValueLength` and `mKey` should be set to `nullptr`.
+
+ VerifyOrQuit(txtEntry.mKey == nullptr, "TxtEntry key does not match expected value for long key");
+ VerifyOrQuit(txtEntry.mValueLength == expectedKeyLength + expectedTxtEntry.mValueLength + sizeof(char),
+ "TxtEntry value length is incorrect for long key");
+ VerifyOrQuit(memcmp(txtEntry.mValue, expectedTxtEntry.mKey, expectedKeyLength) == 0,
+ "txtEntry value does match expected content");
+ VerifyOrQuit(txtEntry.mValue[expectedKeyLength] == static_cast<uint8_t>('='),
+ "txtEntry value does match expected content");
+ VerifyOrQuit(memcmp(&txtEntry.mValue[expectedKeyLength + sizeof(uint8_t)], expectedTxtEntry.mValue,
+ expectedTxtEntry.mValueLength) == 0,
+ "txtEntry value does match expected content");
+ continue;
+ }
+
+ VerifyOrQuit(strcmp(txtEntry.mKey, expectedTxtEntry.mKey) == 0, "TxtEntry key does not match expected value");
+ VerifyOrQuit(txtEntry.mValueLength == expectedTxtEntry.mValueLength,
+ "TxtEntry value length does not match expected value");
+
+ if (txtEntry.mValueLength != 0)
+ {
+ VerifyOrQuit(memcmp(txtEntry.mValue, expectedTxtEntry.mValue, txtEntry.mValueLength) == 0,
+ "TxtEntry value does not match expected content");
+ }
+ else
+ {
+ // Ensure both `txtEntry.mKey` and `expectedTxtEntry.mKey` are
+ // null or both are non-null (for boolean or empty keys).
+ VerifyOrQuit((txtEntry.mKey == nullptr) == (expectedTxtEntry.mKey == nullptr),
+ "TxtEntry value does not match expected value for bool or empty key");
+ }
+ }
+
+ VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() returned unexpected entry");
+ VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() succeeded after done");
+
+ // Verify `AppendEntries()` correctly rejecting invalid key
+ txtEntry.mValue = kValue1;
+ txtEntry.mValueLength = sizeof(kValue1);
+ txtEntry.mKey = kShortKey;
+ VerifyOrQuit(Dns::TxtEntry::AppendEntries(&txtEntry, 1, *message) == kErrorInvalidArgs,
+ "AppendEntries() did not fail with invalid key");
+
+ // Verify appending empty txt data
+
+ SuccessOrQuit(message->SetLength(0), "Message::SetLength() failed");
+ SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
+ txtDataLength = message->GetLength();
+ VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty array");
+ SuccessOrQuit(message->Read(0, txtData, txtDataLength), "Failed to read txt data from message");
+ VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty array");
+
+ SuccessOrQuit(message->SetLength(0), "Message::SetLength() failed");
+ txtEntry.mKey = nullptr;
+ txtEntry.mValue = nullptr;
+ txtEntry.mValueLength = 0;
+ SuccessOrQuit(Dns::TxtEntry::AppendEntries(&txtEntry, 1, *message), "AppendEntries() failed with empty entry");
+ txtDataLength = message->GetLength();
+ VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty entry");
+ SuccessOrQuit(message->Read(0, txtData, txtDataLength), "Failed to read txt data from message");
+ VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty entry");
+
+ // Verify `Iterator` behavior with invalid txt data.
+
+ iterator.Init(kInvalidEncodedTxt1, sizeof(kInvalidEncodedTxt1));
+ VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorParse, "GetNextEntry() did not fail with invalid data");
+
+ // Verify `GetNextEntry()` correctly skipping over empty strings and
+ // strings starting with '=' (missing key) in encoded txt.
+ //
+ // kSpecialEncodedTxt:
+ // { 0, 3, 'A', '=', 'B', 2, '=', 'C', 3, 'D', '=', 'E', 3, '=', '1', '2' }
+
+ iterator.Init(kSpecialEncodedTxt, sizeof(kSpecialEncodedTxt));
+
+ // We should get "A=B` (or key="A", and value="B")
+ SuccessOrQuit(iterator.GetNextEntry(txtEntry), "GetNextEntry() failed");
+ VerifyOrQuit((txtEntry.mKey[0] == 'A') && (txtEntry.mKey[1] == '\0'), "GetNextEntry() got incorrect key");
+ VerifyOrQuit((txtEntry.mValueLength == 1) && (txtEntry.mValue[0] == 'B'), "GetNextEntry() got incorrect value");
+
+ // We should get "D=E` (or key="D", and value="E")
+ SuccessOrQuit(iterator.GetNextEntry(txtEntry), "GetNextEntry() failed");
+ VerifyOrQuit((txtEntry.mKey[0] == 'D') && (txtEntry.mKey[1] == '\0'), "GetNextEntry() got incorrect key");
+ VerifyOrQuit((txtEntry.mValueLength == 1) && (txtEntry.mValue[0] == 'E'), "GetNextEntry() got incorrect value");
+
+ VerifyOrQuit(iterator.GetNextEntry(txtEntry) == kErrorNotFound, "GetNextEntry() returned extra entry");
+
message->Free();
testFreeInstance(instance);
}
@@ -470,6 +1308,8 @@
{
ot::TestDnsName();
ot::TestDnsCompressedName();
+ ot::TestHeaderAndResourceRecords();
+ ot::TestDnsTxtEntry();
printf("All tests passed\n");
return 0;
diff --git a/tests/unit/test_ecdsa.cpp b/tests/unit/test_ecdsa.cpp
index b52bb04..7148f19 100644
--- a/tests/unit/test_ecdsa.cpp
+++ b/tests/unit/test_ecdsa.cpp
@@ -101,7 +101,7 @@
printf("\nHash the message ----------------------------------------------------------\n");
sha256.Start();
- sha256.Update(kMessage, sizeof(kMessage));
+ sha256.Update(kMessage);
sha256.Finish(hash);
DumpBuffer("Hash", hash.GetBytes(), sizeof(hash));
@@ -153,7 +153,7 @@
printf("\nHash the message ----------------------------------------------------------\n");
sha256.Start();
- sha256.Update(reinterpret_cast<const uint8_t *>(kMessage), sizeof(kMessage) - 1);
+ sha256.Update(kMessage, sizeof(kMessage) - 1);
sha256.Finish(hash);
DumpBuffer("Hash", hash.GetBytes(), sizeof(hash));
@@ -167,10 +167,9 @@
printf("\nSignature was verified successfully.");
sha256.Start();
- sha256.Update(reinterpret_cast<const uint8_t *>(kMessage), sizeof(kMessage)); // include null char
+ sha256.Update(kMessage, sizeof(kMessage)); // include null char
sha256.Finish(hash);
- VerifyOrQuit(publicKey.Verify(hash, signature) != OT_ERROR_NONE,
- "PublicKey::Verify() passed for invalid signature");
+ VerifyOrQuit(publicKey.Verify(hash, signature) != kErrorNone, "PublicKey::Verify() passed for invalid signature");
printf("\nSignature verification correctly failed with incorrect hash/signature.\n\n");
testFreeInstance(instance);
diff --git a/tests/unit/test_flash.cpp b/tests/unit/test_flash.cpp
index 4710a30..6304da9 100644
--- a/tests/unit/test_flash.cpp
+++ b/tests/unit/test_flash.cpp
@@ -57,8 +57,8 @@
// No records in settings
- VerifyOrQuit(flash.Delete(0, 0) == OT_ERROR_NOT_FOUND, "Delete() failed");
- VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND, "Get() failed");
+ VerifyOrQuit(flash.Delete(0, 0) == kErrorNotFound, "Delete() failed");
+ VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == kErrorNotFound, "Get() failed");
// Multiple records with different keys
@@ -85,8 +85,8 @@
for (uint16_t key = 0; key < 16; key++)
{
- VerifyOrQuit(flash.Delete(key, 0) == OT_ERROR_NOT_FOUND, "Delete() failed");
- VerifyOrQuit(flash.Get(key, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND, "Get() failed");
+ VerifyOrQuit(flash.Delete(key, 0) == kErrorNotFound, "Delete() failed");
+ VerifyOrQuit(flash.Get(key, 0, nullptr, nullptr) == kErrorNotFound, "Get() failed");
}
// Multiple records with the same key
@@ -112,8 +112,8 @@
SuccessOrQuit(flash.Delete(0, 0), "Delete() failed");
}
- VerifyOrQuit(flash.Delete(0, 0) == OT_ERROR_NOT_FOUND, "Delete() failed");
- VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND, "Get() failed");
+ VerifyOrQuit(flash.Delete(0, 0) == kErrorNotFound, "Delete() failed");
+ VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == kErrorNotFound, "Get() failed");
// Multiple records with the same key
@@ -145,8 +145,8 @@
SuccessOrQuit(flash.Delete(0, 0), "Delete() failed");
}
- VerifyOrQuit(flash.Delete(0, 0) == OT_ERROR_NOT_FOUND, "Delete() failed");
- VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND, "Get() failed");
+ VerifyOrQuit(flash.Delete(0, 0) == kErrorNotFound, "Delete() failed");
+ VerifyOrQuit(flash.Get(0, 0, nullptr, nullptr) == kErrorNotFound, "Get() failed");
// Wipe()
@@ -161,8 +161,8 @@
for (uint16_t key = 0; key < 16; key++)
{
- VerifyOrQuit(flash.Delete(key, 0) == OT_ERROR_NOT_FOUND, "Delete() failed");
- VerifyOrQuit(flash.Get(key, 0, nullptr, nullptr) == OT_ERROR_NOT_FOUND, "Get() failed");
+ VerifyOrQuit(flash.Delete(key, 0) == kErrorNotFound, "Delete() failed");
+ VerifyOrQuit(flash.Get(key, 0, nullptr, nullptr) == kErrorNotFound, "Get() failed");
}
// Test swap
diff --git a/tests/unit/test_heap.cpp b/tests/unit/test_heap.cpp
index 651d60a..813d200 100644
--- a/tests/unit/test_heap.cpp
+++ b/tests/unit/test_heap.cpp
@@ -38,6 +38,8 @@
#include "test_platform.h"
#include "test_util.h"
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
/**
* Verifies single variable allocating and freeing.
*
@@ -171,9 +173,13 @@
TestAllocateMultiple();
}
+#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+
int main(void)
{
+#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
RunTimerTests();
printf("All tests passed\n");
+#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
return 0;
}
diff --git a/tests/unit/test_hmac_sha256.cpp b/tests/unit/test_hmac_sha256.cpp
index 676f966..1623b70 100644
--- a/tests/unit/test_hmac_sha256.cpp
+++ b/tests/unit/test_hmac_sha256.cpp
@@ -29,60 +29,266 @@
#include <openthread/config.h>
#include "common/debug.hpp"
+#include "common/message.hpp"
#include "crypto/hmac_sha256.hpp"
+#include "crypto/sha256.hpp"
#include "test_platform.h"
#include "test_util.h"
-void TestHmacSha256(void)
+namespace ot {
+
+void TestSha256(void)
{
- static const struct
+ const char kData1[] = "abc";
+
+ const otCryptoSha256Hash kHash1 = {{
+ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
+ }};
+
+ const char kData2[] = "";
+
+ const otCryptoSha256Hash kHash2 = {{
+ 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+ 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
+ }};
+
+ const char kData3[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+
+ const otCryptoSha256Hash kHash3 = {{
+ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
+ }};
+
+ const char kData4[] = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmno"
+ "pqrsmnopqrstnopqrstu";
+
+ const otCryptoSha256Hash kHash4 = {{
+ 0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80, 0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37,
+ 0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51, 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1,
+ }};
+
+ struct TestCase
{
- const char * key;
- const char * data;
- otCryptoSha256Hash hash;
- } tests[] = {
- {
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
- "Hi There",
- {{
- 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
- 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
- }},
- },
- {
- nullptr,
- nullptr,
- {},
- },
+ const char * mData; // (null-terminated string).
+ otCryptoSha256Hash mHash;
};
- otInstance *instance = testInitInstance();
+ static const TestCase kTestCases[] = {
+ {kData1, kHash1},
+ {kData2, kHash2},
+ {kData3, kHash3},
+ {kData4, kHash4},
+ };
- // Make sure hmac is destructed before freeing instance.
+ printf("TestSha256\n");
+
+ Instance * instance = testInitInstance();
+ MessagePool *messagePool;
+ Message * message;
+ uint16_t offsets[OT_ARRAY_LENGTH(kTestCases)];
+ uint8_t index;
+
+ VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+ messagePool = &instance->Get<MessagePool>();
+ VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+
+ for (const TestCase &testCase : kTestCases)
{
- ot::Crypto::HmacSha256 hmac;
- ot::Crypto::HmacSha256::Hash hash;
+ Crypto::Sha256 sha256;
+ Crypto::Sha256::Hash hash;
- VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+ sha256.Start();
+ sha256.Update(testCase.mData, static_cast<uint16_t>(strlen(testCase.mData)));
+ sha256.Finish(hash);
- for (int i = 0; tests[i].key != nullptr; i++)
- {
- hmac.Start(reinterpret_cast<const uint8_t *>(tests[i].key), static_cast<uint16_t>(strlen(tests[i].key)));
- hmac.Update(reinterpret_cast<const uint8_t *>(tests[i].data), static_cast<uint16_t>(strlen(tests[i].data)));
- hmac.Finish(hash);
+ VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash), "HMAC-SHA-256 failed");
+ }
- VerifyOrQuit(hash == static_cast<const ot::Crypto::HmacSha256::Hash &>(tests[i].hash),
- "HMAC-SHA-256 failed");
- }
+ // Append all test case `mData` in the message.
+
+ index = 0;
+
+ for (const TestCase &testCase : kTestCases)
+ {
+ SuccessOrQuit(message->Append("Hello"), "Message::Append() failed");
+ offsets[index++] = message->GetLength();
+ SuccessOrQuit(message->AppendBytes(testCase.mData, static_cast<uint16_t>(strlen(testCase.mData))),
+ "Message::AppendBytes() failed");
+ SuccessOrQuit(message->Append("There!"), "Message::Append() failed");
+ }
+
+ index = 0;
+
+ for (const TestCase &testCase : kTestCases)
+ {
+ Crypto::Sha256 sha256;
+ Crypto::Sha256::Hash hash;
+
+ sha256.Start();
+ sha256.Update(*message, offsets[index++], static_cast<uint16_t>(strlen(testCase.mData)));
+ sha256.Finish(hash);
+
+ VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash), "HMAC-SHA-256 failed");
}
testFreeInstance(instance);
}
+void TestHmacSha256(void)
+{
+ struct TestCase
+ {
+ const void * mKey;
+ uint16_t mKeyLength;
+ const void * mData;
+ uint16_t mDataLength;
+ otCryptoSha256Hash mHash;
+ };
+
+ // Test-cases from RFC 4231.
+
+ const uint8_t kKey1[] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ };
+
+ const char kData1[] = "Hi There";
+
+ const otCryptoSha256Hash kHash1 = {{
+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+ 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7,
+ }};
+
+ const char kKey2[] = "Jefe";
+ const char kData2[] = "what do ya want for nothing?";
+
+ const otCryptoSha256Hash kHash2 = {{
+ 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+ 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
+ }};
+
+ const uint8_t kKey3[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
+
+ const uint8_t kData3[] = {
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ };
+
+ const otCryptoSha256Hash kHash3 = {{
+ 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
+ 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
+ }};
+
+ const uint8_t kKey4[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+ };
+
+ const uint8_t kData4[] = {
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ };
+
+ const otCryptoSha256Hash kHash4 = {{
+ 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
+ 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b,
+ }};
+
+ const uint8_t kKey5[] = {
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ };
+
+ const char kData5[] = "This is a test using a larger than block-size key and a larger than block-size data. The "
+ "key needs to be hashed before being used by the HMAC algorithm.";
+
+ const otCryptoSha256Hash kHash5 = {{
+ 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
+ 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
+ }};
+
+ static const TestCase kTestCases[] = {
+ {kKey1, sizeof(kKey1), kData1, sizeof(kData1) - 1, kHash1},
+ {kKey2, sizeof(kKey2) - 1, kData2, sizeof(kData2) - 1, kHash2},
+ {kKey3, sizeof(kKey3), kData3, sizeof(kData3), kHash3},
+ {kKey4, sizeof(kKey4), kData4, sizeof(kData4), kHash4},
+ {kKey5, sizeof(kKey5), kData5, sizeof(kData5) - 1, kHash5},
+ };
+
+ Instance * instance = testInitInstance();
+ MessagePool *messagePool;
+ Message * message;
+ uint16_t offsets[OT_ARRAY_LENGTH(kTestCases)];
+ uint8_t index;
+
+ printf("TestHmacSha256\n");
+
+ VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
+
+ messagePool = &instance->Get<MessagePool>();
+ VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr, "Message::New failed");
+
+ for (const TestCase &testCase : kTestCases)
+ {
+ Crypto::HmacSha256 hmac;
+ Crypto::HmacSha256::Hash hash;
+
+ hmac.Start(reinterpret_cast<const uint8_t *>(testCase.mKey), testCase.mKeyLength);
+ hmac.Update(testCase.mData, testCase.mDataLength);
+ hmac.Finish(hash);
+
+ VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash), "HMAC-SHA-256 failed");
+ }
+
+ // Append all test case `mData` in the message.
+
+ index = 0;
+
+ for (const TestCase &testCase : kTestCases)
+ {
+ SuccessOrQuit(message->Append("Hello"), "Message::Append() failed");
+ offsets[index++] = message->GetLength();
+ SuccessOrQuit(message->AppendBytes(testCase.mData, testCase.mDataLength), "Message::AppendBytes() failed");
+ SuccessOrQuit(message->Append("There"), "Message::Append() failed");
+ }
+
+ index = 0;
+
+ for (const TestCase &testCase : kTestCases)
+ {
+ Crypto::HmacSha256 hmac;
+ Crypto::HmacSha256::Hash hash;
+
+ hmac.Start(reinterpret_cast<const uint8_t *>(testCase.mKey), testCase.mKeyLength);
+ hmac.Update(*message, offsets[index++], testCase.mDataLength);
+ hmac.Finish(hash);
+
+ VerifyOrQuit(hash == static_cast<const Crypto::HmacSha256::Hash &>(testCase.mHash), "HMAC-SHA-256 failed");
+ }
+
+ message->Free();
+
+ testFreeInstance(instance);
+}
+
+} // namespace ot
+
int main(void)
{
- TestHmacSha256();
+ ot::TestSha256();
+ ot::TestHmacSha256();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_ip6_address.cpp b/tests/unit/test_ip6_address.cpp
index e4a3615..0e0b1ec 100644
--- a/tests/unit/test_ip6_address.cpp
+++ b/tests/unit/test_ip6_address.cpp
@@ -40,19 +40,19 @@
{
const char * mString;
const uint8_t mAddr[OT_IP6_ADDRESS_SIZE];
- otError mError;
+ ot::Error mError;
};
static void checkAddressFromString(Ip6AddressStringTestVector *aTestVector)
{
- otError error;
+ ot::Error error;
ot::Ip6::Address address;
error = address.FromString(aTestVector->mString);
VerifyOrQuit(error == aTestVector->mError, "Ip6::Address::FromString returned unexpected error code");
- if (error == OT_ERROR_NONE)
+ if (error == ot::kErrorNone)
{
VerifyOrQuit(0 == memcmp(address.mFields.m8, aTestVector->mAddr, OT_IP6_ADDRESS_SIZE),
"Ip6::Address::FromString parsing failed");
@@ -65,73 +65,73 @@
// Valid full IPv6 address.
{"0102:0304:0506:0708:090a:0b0c:0d0e:0f00",
{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Valid full IPv6 address with mixed capital and small letters.
{"0102:0304:0506:0708:090a:0B0C:0d0E:0F00",
{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Short prefix and full IID.
{"fd11::abcd:e0e0:d10e:0001",
{0xfd, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xcd, 0xe0, 0xe0, 0xd1, 0x0e, 0x00, 0x01},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Valid IPv6 address with unnecessary :: symbol.
{"fd11:1234:5678:abcd::abcd:e0e0:d10e:1000",
{0xfd, 0x11, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0xab, 0xcd, 0xe0, 0xe0, 0xd1, 0x0e, 0x10, 0x00},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Short multicast address.
{"ff03::0b",
{0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Unspecified address.
- {"::", {0}, OT_ERROR_NONE},
+ {"::", {0}, ot::kErrorNone},
// Valid embedded IPv4 address.
{"64:ff9b::100.200.15.4",
{0x00, 0x64, 0xff, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xc8, 0x0f, 0x04},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Valid embedded IPv4 address.
{"2001:db8::abc:def1:127.0.0.1",
{0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xbc, 0xde, 0xf1, 0x7f, 0x00, 0x00, 0x01},
- OT_ERROR_NONE},
+ ot::kErrorNone},
// Two :: should cause a parse error.
- {"2001:db8::a::b", {0}, OT_ERROR_PARSE},
+ {"2001:db8::a::b", {0}, ot::kErrorParse},
// The "g" and "h" are not the hex characters.
- {"2001:db8::abcd:efgh", {0}, OT_ERROR_PARSE},
+ {"2001:db8::abcd:efgh", {0}, ot::kErrorParse},
// Too many colons.
- {"1:2:3:4:5:6:7:8:9", {0}, OT_ERROR_PARSE},
+ {"1:2:3:4:5:6:7:8:9", {0}, ot::kErrorParse},
// Too many characters in a single part.
- {"2001:db8::abc:def12:1:2", {0}, OT_ERROR_PARSE},
+ {"2001:db8::abc:def12:1:2", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::123.231.0.257", {0}, OT_ERROR_PARSE},
+ {"64:ff9b::123.231.0.257", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::1.22.33", {0}, OT_ERROR_PARSE},
+ {"64:ff9b::1.22.33", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::1.22.33.44.5", {0}, OT_ERROR_PARSE},
+ {"64:ff9b::1.22.33.44.5", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {".", {0}, OT_ERROR_PARSE},
+ {".", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {":.", {0}, OT_ERROR_PARSE},
+ {":.", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {"::.", {0}, OT_ERROR_PARSE},
+ {"::.", {0}, ot::kErrorParse},
// Invalid embedded IPv4 address.
- {":f:0:0:c:0:f:f:.", {0}, OT_ERROR_PARSE},
+ {":f:0:0:c:0:f:f:.", {0}, ot::kErrorParse},
};
for (Ip6AddressStringTestVector &testVector : testVectors)
@@ -252,6 +252,7 @@
VerifyOrQuit(!address2.MatchesPrefix(prefix), "Address::MatchedPrefix() failed");
VerifyOrQuit(prefix == prefix, "Prefix::operator==() failed");
+ VerifyOrQuit(!(prefix < prefix), "Prefix::operator<() failed");
for (uint8_t subPrefixLength = 1; subPrefixLength <= prefixLength; subPrefixLength++)
{
@@ -266,14 +267,37 @@
VerifyOrQuit(prefix == subPrefix, "Prefix::operator==() failed");
VerifyOrQuit(prefix.IsEqual(subPrefix.GetBytes(), subPrefix.GetLength()),
"Prefix::IsEqual() failed");
+ VerifyOrQuit(!(subPrefix < prefix), "Prefix::operator<() failed");
}
else
{
VerifyOrQuit(prefix != subPrefix, "Prefix::operator!= failed");
VerifyOrQuit(!prefix.IsEqual(subPrefix.GetBytes(), subPrefix.GetLength()),
"Prefix::IsEqual() failed");
+ VerifyOrQuit(subPrefix < prefix, "Prefix::operator<() failed");
}
}
+
+ for (uint8_t bitNumber = 0; bitNumber < prefixLength; bitNumber++)
+ {
+ ot::Ip6::Prefix prefix2;
+ uint8_t mask = static_cast<uint8_t>(1U << (7 - (bitNumber & 7)));
+ uint8_t index = (bitNumber / 8);
+ bool isPrefixSmaller;
+
+ prefix2 = prefix;
+ VerifyOrQuit(prefix == prefix2, "Prefix::operator==() failed");
+
+ // Flip the `bitNumber` bit between `prefix` and `prefix2`
+
+ prefix2.mPrefix.mFields.m8[index] ^= mask;
+ VerifyOrQuit(prefix != prefix2, "Prefix::operator==() failed");
+
+ isPrefixSmaller = ((prefix.GetBytes()[index] & mask) == 0);
+
+ VerifyOrQuit((prefix < prefix2) == isPrefixSmaller, "Prefix::operator<() failed");
+ VerifyOrQuit((prefix2 < prefix) == !isPrefixSmaller, "Prefix::operator<() failed");
+ }
}
}
}
diff --git a/tests/unit/test_linked_list.cpp b/tests/unit/test_linked_list.cpp
index 5664a00..dbb948b 100644
--- a/tests/unit/test_linked_list.cpp
+++ b/tests/unit/test_linked_list.cpp
@@ -118,18 +118,18 @@
VerifyOrQuit(list.IsEmpty(), "LinkedList::IsEmpty() failed after init");
VerifyOrQuit(list.GetHead() == nullptr, "LinkedList::GetHead() failed after init");
VerifyOrQuit(list.Pop() == nullptr, "LinkedList::Pop() failed when empty");
- VerifyOrQuit(list.Find(a, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
VerifyLinkedListContent(&list, nullptr);
list.Push(a);
VerifyOrQuit(!list.IsEmpty(), "LinkedList::IsEmpty() failed");
VerifyLinkedListContent(&list, &a, nullptr);
- VerifyOrQuit(list.Find(b, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(b, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
SuccessOrQuit(list.Add(b), "LinkedList::Add() failed");
VerifyLinkedListContent(&list, &b, &a, nullptr);
- VerifyOrQuit(list.Find(c, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(c, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
list.Push(c);
VerifyLinkedListContent(&list, &c, &b, &a, nullptr);
@@ -140,14 +140,14 @@
SuccessOrQuit(list.Add(e), "LinkedList::Add() failed");
VerifyLinkedListContent(&list, &e, &d, &c, &b, &a, nullptr);
- VerifyOrQuit(list.Add(a) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
- VerifyOrQuit(list.Add(b) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
- VerifyOrQuit(list.Add(d) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
- VerifyOrQuit(list.Add(e) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
+ VerifyOrQuit(list.Add(a) == ot::kErrorAlready, "LinkedList::Add() did not detect duplicate");
+ VerifyOrQuit(list.Add(b) == ot::kErrorAlready, "LinkedList::Add() did not detect duplicate");
+ VerifyOrQuit(list.Add(d) == ot::kErrorAlready, "LinkedList::Add() did not detect duplicate");
+ VerifyOrQuit(list.Add(e) == ot::kErrorAlready, "LinkedList::Add() did not detect duplicate");
VerifyOrQuit(list.Pop() == &e, "LinkedList::Pop() failed");
VerifyLinkedListContent(&list, &d, &c, &b, &a, nullptr);
- VerifyOrQuit(list.Find(e, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(e, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
VerifyOrQuit(list.FindMatching(d.GetName(), prev) == &d, "List::FindMatching() failed");
VerifyOrQuit(prev == nullptr, "List::FindMatching() failed");
@@ -166,17 +166,17 @@
SuccessOrQuit(list.Remove(c), "LinkedList::Remove() failed");
VerifyLinkedListContent(&list, &e, &d, &b, &a, nullptr);
- VerifyOrQuit(list.Remove(c) == OT_ERROR_NOT_FOUND, "LinkedList::Remove() failed");
+ VerifyOrQuit(list.Remove(c) == ot::kErrorNotFound, "LinkedList::Remove() failed");
VerifyLinkedListContent(&list, &e, &d, &b, &a, nullptr);
- VerifyOrQuit(list.Find(c, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(c, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
SuccessOrQuit(list.Remove(e), "LinkedList::Remove() failed");
VerifyLinkedListContent(&list, &d, &b, &a, nullptr);
- VerifyOrQuit(list.Find(e, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(e, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
SuccessOrQuit(list.Remove(a), "LinkedList::Remove() failed");
VerifyLinkedListContent(&list, &d, &b, nullptr);
- VerifyOrQuit(list.Find(a, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
list.Push(a);
list.Push(c);
@@ -225,11 +225,11 @@
VerifyOrQuit(list.IsEmpty(), "LinkedList::IsEmpty() failed after Clear()");
VerifyOrQuit(list.PopAfter(nullptr) == nullptr, "LinkedList::PopAfter() failed");
VerifyLinkedListContent(&list, nullptr);
- VerifyOrQuit(list.Find(a, prev) == OT_ERROR_NOT_FOUND, "LinkedList::Find() succeeded for a missing entry");
+ VerifyOrQuit(list.Find(a, prev) == ot::kErrorNotFound, "LinkedList::Find() succeeded for a missing entry");
VerifyOrQuit(list.FindMatching(b.GetName(), prev) == nullptr, "LinkedList::FindMatching() succeeded when empty");
VerifyOrQuit(list.FindMatching(c.GetId(), prev) == nullptr, "LinkedList::FindMatching() succeeded when empty");
VerifyOrQuit(list.RemoveMatching(a.GetName()) == nullptr, "LinkedList::RemoveMatching() succeeded when empty");
- VerifyOrQuit(list.Remove(a) == OT_ERROR_NOT_FOUND, "LinkedList::Remove() succeeded when empty");
+ VerifyOrQuit(list.Remove(a) == ot::kErrorNotFound, "LinkedList::Remove() succeeded when empty");
}
int main(void)
diff --git a/tests/unit/test_lowpan.cpp b/tests/unit/test_lowpan.cpp
index 540ac0f..b5a5700 100644
--- a/tests/unit/test_lowpan.cpp
+++ b/tests/unit/test_lowpan.cpp
@@ -179,7 +179,7 @@
VerifyOrQuit(sLowpan->Compress(*message, aVector.mMacSource, aVector.mMacDestination, buffer) == aVector.mError,
"6lo: Lowpan:Compress failed");
- if (aVector.mError == OT_ERROR_NONE)
+ if (aVector.mError == kErrorNone)
{
uint8_t compressBytes = static_cast<uint8_t>(buffer.GetWritePointer() - result);
@@ -209,7 +209,7 @@
message->ReadBytes(0, result, message->GetLength());
- if (aVector.mError == OT_ERROR_NONE)
+ if (aVector.mError == kErrorNone)
{
// Append payload to the IPv6 Packet.
memcpy(result + message->GetLength(), iphc + decompressedBytes,
@@ -270,7 +270,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -295,7 +295,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -320,7 +320,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -345,7 +345,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -369,7 +369,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -396,7 +396,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -422,7 +422,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -448,7 +448,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -473,7 +473,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -498,7 +498,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -524,7 +524,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -550,7 +550,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -575,7 +575,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -600,7 +600,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -625,7 +625,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -651,7 +651,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -677,7 +677,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform decompression test only.
Test(testVector, false, true);
@@ -702,7 +702,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -727,7 +727,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -752,7 +752,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -777,7 +777,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -803,7 +803,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -829,7 +829,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -856,7 +856,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression test only.
Test(testVector, true, false);
@@ -881,7 +881,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform decompression tests.
Test(testVector, true, true);
@@ -906,7 +906,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -931,7 +931,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -956,7 +956,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -981,7 +981,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1006,7 +1006,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1031,7 +1031,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1056,7 +1056,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1084,7 +1084,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1112,7 +1112,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1140,7 +1140,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1168,7 +1168,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1196,7 +1196,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1221,7 +1221,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(40);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform only decompression test.
Test(testVector, false, true);
@@ -1250,7 +1250,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1279,7 +1279,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1308,7 +1308,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1337,7 +1337,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1366,7 +1366,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(48);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1397,7 +1397,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(56);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1428,7 +1428,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(64);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1459,7 +1459,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(64);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1491,7 +1491,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(56);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1528,7 +1528,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(96);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1557,7 +1557,7 @@
// Set payload and error.
testVector.SetPayload(sTestPayloadDefault, sizeof(sTestPayloadDefault));
testVector.SetPayloadOffset(80);
- testVector.SetError(OT_ERROR_NONE);
+ testVector.SetError(kErrorNone);
// Perform compression and decompression tests.
Test(testVector, true, true);
@@ -1576,7 +1576,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1595,7 +1595,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1614,7 +1614,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1633,7 +1633,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1652,7 +1652,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1671,7 +1671,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1690,7 +1690,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1709,7 +1709,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1728,7 +1728,7 @@
testVector.SetIphcHeader(iphc, sizeof(iphc));
// Set payload and error.
- testVector.SetError(OT_ERROR_PARSE);
+ testVector.SetError(kErrorParse);
// Perform decompression test.
Test(testVector, false, true);
@@ -1866,7 +1866,7 @@
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "MeshHeader::GetDestination() failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "MeshHeader::GetHopsLeft() failed after ParseFrom()");
- VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1889,7 +1889,7 @@
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "MeshHeader::GetDestination() failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetHopsLeft() == 0x20, "MeshHeader::GetHopsLeft() failed after ParseFrom()");
- VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1903,7 +1903,7 @@
VerifyOrQuit(meshHeader.WriteTo(frame) == sizeof(kMeshHeader1), "MeshHeader::WriteTo() failed");
- VerifyOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3) - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3) - 1, headerLength) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
}
@@ -1949,7 +1949,7 @@
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "FragmentHeader::GetDatagramTag() failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "FragmentHeader::GetDatagramOffset() failed after ParseFrom()");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1980,7 +1980,7 @@
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset,
"FragmentHeader::GetDatagramOffset() failed after ParseFrom()");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1993,7 +1993,7 @@
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "FragmentHeader::GetDatagramTag() failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "FragmentHeader::GetDatagramOffset() failed after ParseFrom()");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == OT_ERROR_PARSE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2002,21 +2002,21 @@
memcpy(frame, kInvalidFragHeader1, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
"IsFragmentHeader() did not detect invalid header");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != OT_ERROR_NONE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
length = sizeof(kInvalidFragHeader2);
memcpy(frame, kInvalidFragHeader2, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
"IsFragmentHeader() did not detect invalid header");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != OT_ERROR_NONE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
length = sizeof(kInvalidFragHeader3);
memcpy(frame, kInvalidFragHeader3, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
"IsFragmentHeader() did not detect invalid header");
- VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != OT_ERROR_NONE,
+ VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
}
diff --git a/tests/unit/test_lowpan.hpp b/tests/unit/test_lowpan.hpp
index e069c9c..64c52d7 100644
--- a/tests/unit/test_lowpan.hpp
+++ b/tests/unit/test_lowpan.hpp
@@ -200,7 +200,7 @@
* @param aError Expected result.
*
*/
- void SetError(otError aError) { mError = aError; }
+ void SetError(Error aError) { mError = aError; }
/**
* This method initializes IPv6 Payload (uncompressed data).
@@ -274,7 +274,7 @@
*
*/
Payload mPayload;
- otError mError;
+ Error mError;
const char *mTestName;
};
diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp
index ef6102b..abb9372 100644
--- a/tests/unit/test_mac_frame.cpp
+++ b/tests/unit/test_mac_frame.cpp
@@ -182,12 +182,12 @@
SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))), "NetworkName::Set() failed");
CompareNetworkName(networkName, kName1);
- VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))) == OT_ERROR_ALREADY,
- "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY");
+ VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))) == kErrorAlready,
+ "NetworkName::Set() accepted same name without returning kErrorAlready");
CompareNetworkName(networkName, kName1);
- VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1) - 1)) == OT_ERROR_ALREADY,
- "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY");
+ VerifyOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1) - 1)) == kErrorAlready,
+ "NetworkName::Set() accepted same name without returning kErrorAlready");
SuccessOrQuit(networkName.Set(Mac::NameData(kName2, sizeof(kName2))), "NetworkName::Set() failed");
CompareNetworkName(networkName, kName2);
@@ -198,15 +198,15 @@
SuccessOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName))), "NetworkName::Set() failed");
CompareNetworkName(networkName, kLongName);
- VerifyOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName) - 1)) == OT_ERROR_ALREADY,
- "NetworkName::Set() accepted same name without returning OT_ERROR_ALREADY");
+ VerifyOrQuit(networkName.Set(Mac::NameData(kLongName, sizeof(kLongName) - 1)) == kErrorAlready,
+ "NetworkName::Set() accepted same name without returning kErrorAlready");
SuccessOrQuit(networkName.Set(Mac::NameData(nullptr, 0)), "NetworkName::Set() failed");
CompareNetworkName(networkName, kEmptyName);
SuccessOrQuit(networkName.Set(Mac::NameData(kName1, sizeof(kName1))), "NetworkName::Set() failed");
- VerifyOrQuit(networkName.Set(Mac::NameData(kTooLongName, sizeof(kTooLongName))) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(networkName.Set(Mac::NameData(kTooLongName, sizeof(kTooLongName))) == kErrorInvalidArgs,
"NetworkName::Set() accepted an invalid (too long) name");
CompareNetworkName(networkName, kName1);
@@ -310,7 +310,7 @@
index = 0;
channel = Mac::ChannelMask::kChannelIteratorFirst;
- while (aMask.GetNextChannel(channel) == OT_ERROR_NONE)
+ while (aMask.GetNextChannel(channel) == kErrorNone)
{
VerifyOrQuit(channel == aChannels[index++], "ChannelMask.GetNextChannel() failed");
}
@@ -424,7 +424,7 @@
uint8_t mac_cmd_psdu2[] = {0x6b, 0xaa, 0x8d, 0xce, 0xfa, 0x00, 0x68, 0x01, 0x68, 0x0d,
0x08, 0x00, 0x00, 0x00, 0x01, 0x04, 0x0d, 0xed, 0x0b, 0x35,
0x0c, 0x80, 0x3f, 0x04, 0x4b, 0x88, 0x89, 0xd6, 0x59, 0xe1};
- otError error;
+ Error error;
uint8_t scf; // SecurityControlField
#endif
@@ -469,11 +469,11 @@
VerifyOrQuit(frame.IsDstPanIdPresent() == true, "Mac::Frame::IsDstPanIdPresent failed\n");
VerifyOrQuit(frame.IsDstAddrPresent() == true, "Mac::Frame::IsDstAddrPresent failed\n");
VerifyOrQuit(frame.IsSrcAddrPresent() == true, "Mac::Frame::IsSrcAddrPresent failed\n");
- VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE,
+ VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == kErrorNone,
"Mac::Frame::GetSecurityControlField failed\n");
VerifyOrQuit(scf == 0x0d, "Mac::Frame::GetSecurityControlField value failed\n");
frame.SetSecurityControlField(0xff);
- VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == OT_ERROR_NONE,
+ VerifyOrQuit((error = frame.GetSecurityControlField(scf)) == kErrorNone,
"Mac::Frame::GetSecurityControlField failed\n");
VerifyOrQuit(scf == 0xff, "Mac::Frame::SetSecurityControlField value failed\n");
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
@@ -487,11 +487,11 @@
VerifyOrQuit(frame.GetSequence() == 133, "Mac::Frame::GetSequence failed\n");
VerifyOrQuit(frame.GetVersion() == Mac::Frame::kFcfFrameVersion2006, "Mac::Frame::GetVersion failed\n");
VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd, "Mac::Frame::GetType failed\n");
- VerifyOrQuit(frame.GetCommandId(commandId) == OT_ERROR_NONE, "Mac::Frame::GetCommandId failed\n");
+ VerifyOrQuit(frame.GetCommandId(commandId) == kErrorNone, "Mac::Frame::GetCommandId failed\n");
VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest, "Mac::Frame::GetCommandId value not correct\n");
- VerifyOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest) == OT_ERROR_NONE,
+ VerifyOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdBeaconRequest) == kErrorNone,
"Mac::Frame::SetCommandId failed\n");
- VerifyOrQuit(frame.GetCommandId(commandId) == OT_ERROR_NONE, "Mac::Frame::GetCommandId failed\n");
+ VerifyOrQuit(frame.GetCommandId(commandId) == kErrorNone, "Mac::Frame::GetCommandId failed\n");
VerifyOrQuit(commandId == Mac::Frame::kMacCmdBeaconRequest, "Mac::Frame::SetCommandId value not correct\n");
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
@@ -506,12 +506,12 @@
VerifyOrQuit(frame.GetSequence() == 141, "Mac::Frame::GetSequence failed\n");
VerifyOrQuit(frame.IsVersion2015() == true, "Mac::Frame::IsVersion2015 failed\n");
VerifyOrQuit(frame.GetType() == Mac::Frame::kFcfFrameMacCmd, "Mac::Frame::GetVersion failed\n");
- VerifyOrQuit(frame.GetCommandId(commandId) == OT_ERROR_NONE, "Mac::Frame::GetCommandId failed\n");
+ VerifyOrQuit(frame.GetCommandId(commandId) == kErrorNone, "Mac::Frame::GetCommandId failed\n");
VerifyOrQuit(commandId == Mac::Frame::kMacCmdDataRequest, "Mac::Frame::GetCommandId value not correct\n");
printf("commandId:%d\n", commandId);
- VerifyOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdOrphanNotification) == OT_ERROR_NONE,
+ VerifyOrQuit(frame.SetCommandId(Mac::Frame::kMacCmdOrphanNotification) == kErrorNone,
"Mac::Frame::SetCommandId failed\n");
- VerifyOrQuit(frame.GetCommandId(commandId) == OT_ERROR_NONE, "Mac::Frame::GetCommandId failed\n");
+ VerifyOrQuit(frame.GetCommandId(commandId) == kErrorNone, "Mac::Frame::GetCommandId failed\n");
VerifyOrQuit(commandId == Mac::Frame::kMacCmdOrphanNotification, "Mac::Frame::SetCommandId value not correct\n");
#endif
@@ -620,7 +620,7 @@
Mac::CslIe *csl;
IgnoreError(ackFrame.GenerateEnhAck(receivedFrame, false, ie_data, sizeof(ie_data)));
- csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe));
+ csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
VerifyOrQuit(ackFrame.mLength == 23,
"Mac::Frame::GenerateEnhAck() failed, length incorrect\n"); // 23 is the length of the correct ack
VerifyOrQuit(ackFrame.GetType() == Mac::Frame::kFcfFrameAck,
@@ -642,7 +642,7 @@
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
ackFrame.SetCslIe(123, 456);
- csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::Frame::kHeaderIeCsl) + sizeof(Mac::HeaderIe));
+ csl = reinterpret_cast<Mac::CslIe *>(ackFrame.GetHeaderIe(Mac::CslIe::kHeaderIeId) + sizeof(Mac::HeaderIe));
VerifyOrQuit(csl->GetPeriod() == 123 && csl->GetPhase() == 456, "Mac::Frame::SetCslIe failed, CslIe incorrect\n");
#endif
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
diff --git a/tests/unit/test_message.cpp b/tests/unit/test_message.cpp
index 9a2e50e..dace851 100644
--- a/tests/unit/test_message.cpp
+++ b/tests/unit/test_message.cpp
@@ -67,6 +67,8 @@
message->WriteBytes(0, writeBuffer, kMaxSize);
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize), "Message::Read failed");
VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0, "Message compare failed");
+ VerifyOrQuit(message->CompareBytes(0, readBuffer, kMaxSize), "Message::CompareBytes failed");
+ VerifyOrQuit(message->Compare(0, readBuffer), "Message::Compare failed");
VerifyOrQuit(message->GetLength() == kMaxSize, "Message::GetLength failed");
for (uint16_t offset = 0; offset < kMaxSize; offset++)
@@ -82,11 +84,30 @@
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize), "Message::Read failed");
VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0, "Message compare failed");
+ VerifyOrQuit(message->Compare(0, writeBuffer), "Message::Compare() failed");
memset(readBuffer, 0, sizeof(readBuffer));
SuccessOrQuit(message->Read(offset, readBuffer, length), "Message::Read failed");
VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], length) == 0, "Message compare failed");
VerifyOrQuit(memcmp(&readBuffer[length], zeroBuffer, kMaxSize - length) == 0, "Message read after length");
+
+ VerifyOrQuit(message->CompareBytes(offset, &writeBuffer[offset], length), "Message::CompareBytes() failed");
+
+ if (length == 0)
+ {
+ continue;
+ }
+
+ // Change the first byte, and then last byte, and verify that
+ // `CompareBytes()` correctly fails.
+
+ writeBuffer[offset]++;
+ VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length), "CompareBytes() failed");
+ writeBuffer[offset]--;
+
+ writeBuffer[offset + length - 1]++;
+ VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length), "CompareBytes() failed");
+ writeBuffer[offset + length - 1]--;
}
// Verify `ReadBytes()` behavior when requested read length goes beyond available bytes in the message.
@@ -97,10 +118,14 @@
memset(readBuffer, 0, sizeof(readBuffer));
readLength = message->ReadBytes(offset, readBuffer, length);
- VerifyOrQuit(readLength <= length, "Message::ReadBytes() returned longer length");
+
+ VerifyOrQuit(readLength < length, "Message::ReadBytes() returned longer length");
VerifyOrQuit(readLength == kMaxSize - offset, "Message::Read failed");
VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], readLength) == 0, "Message compare failed");
VerifyOrQuit(memcmp(&readBuffer[readLength], zeroBuffer, kMaxSize - readLength) == 0, "read after length");
+
+ VerifyOrQuit(!message->CompareBytes(offset, readBuffer, length), "Message::CompareBytes failed");
+ VerifyOrQuit(message->CompareBytes(offset, readBuffer, readLength), "Message::CompareBytes failed");
}
}
@@ -140,6 +165,11 @@
VerifyOrQuit(
memcmp(&readBuffer[dstOffset + bytesCopied], zeroBuffer, kMaxSize - bytesCopied - dstOffset) == 0,
"read after length");
+
+ VerifyOrQuit(message->CompareBytes(srcOffset, *message2, dstOffset, bytesCopied),
+ "Message::CompareBytes with two messages failed");
+ VerifyOrQuit(message2->CompareBytes(dstOffset, *message, srcOffset, bytesCopied),
+ "Message::CompareBytes with two messages failed");
}
}
}
diff --git a/tests/unit/test_multicast_listeners_table.cpp b/tests/unit/test_multicast_listeners_table.cpp
index 70efcde..8c1922c 100644
--- a/tests/unit/test_multicast_listeners_table.cpp
+++ b/tests/unit/test_multicast_listeners_table.cpp
@@ -92,10 +92,10 @@
SuccessOrQuit(table.Add(static_cast<const Ip6::Address &>(MA501), TimerMilli::GetNow()), "Add failed");
VerifyOrQuit(table.Count() == 2, "Table count is wrong");
- // Add invalid MAs should fail with OT_ERROR_INVALID_ARGS
- VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA201), TimerMilli::GetNow()) == OT_ERROR_INVALID_ARGS,
+ // Add invalid MAs should fail with kErrorInvalidArgs
+ VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA201), TimerMilli::GetNow()) == kErrorInvalidArgs,
"Add should fail");
- VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA301), TimerMilli::GetNow()) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA301), TimerMilli::GetNow()) == kErrorInvalidArgs,
"Add should fail");
// Expire should expire outdated Listeners
@@ -117,7 +117,7 @@
}
// Now the table is full, we can't add more addresses
- VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA501), TimerMilli::GetNow()) == OT_ERROR_NO_BUFS,
+ VerifyOrQuit(table.Add(static_cast<const Ip6::Address &>(MA501), TimerMilli::GetNow()) == kErrorNoBufs,
"Add should fail");
// Expire one Listener at a time
@@ -169,7 +169,7 @@
otBackboneRouterMulticastListenerInfo info;
size_t table_size = 0;
- while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == OT_ERROR_NONE)
+ while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == kErrorNone)
{
VerifyOrQuit(false, "Table should be empty");
}
@@ -177,7 +177,7 @@
SuccessOrQuit(otBackboneRouterMulticastListenerAdd(aInstance, &MA401, 30), "Add failed");
table_size = 0, iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
- while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == OT_ERROR_NONE)
+ while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == kErrorNone)
{
table_size++;
@@ -189,7 +189,7 @@
otBackboneRouterMulticastListenerClear(aInstance);
iter = OT_BACKBONE_ROUTER_MULTICAST_LISTENER_ITERATOR_INIT;
- while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == OT_ERROR_NONE)
+ while (otBackboneRouterMulticastListenerGetNext(aInstance, &iter, &info) == kErrorNone)
{
VerifyOrQuit(false, "Table should be empty");
}
diff --git a/tests/unit/test_ndproxy_table.cpp b/tests/unit/test_ndproxy_table.cpp
index 73db965..8bbdf89 100644
--- a/tests/unit/test_ndproxy_table.cpp
+++ b/tests/unit/test_ndproxy_table.cpp
@@ -58,7 +58,7 @@
void TestNdProxyTable(void)
{
- otError error;
+ Error error;
sInstance = testInitInstance();
VerifyOrQuit(sInstance != nullptr, "Null OpenThread instance");
@@ -72,7 +72,7 @@
// Reregister address IID when there are enough room should succeed.
error = table.Register(existedAddressIid, existedMeshLocalIid, 0, nullptr);
- VerifyOrQuit(error == OT_ERROR_NONE, "Register failed");
+ VerifyOrQuit(error == kErrorNone, "Register failed");
VerifyOrQuit(table.IsRegistered(existedAddressIid), "should be registered");
VerifyOrQuit(!table.IsRegistered(notExistAddressIid), "should not be registered");
@@ -83,17 +83,17 @@
// Reregister address IID when there are enough room should succeed.
error = table.Register(addressIid, meshLocalIid, i, nullptr);
- VerifyOrQuit(error == OT_ERROR_NONE, "Register failed");
+ VerifyOrQuit(error == kErrorNone, "Register failed");
VerifyOrQuit(table.IsRegistered(addressIid), "should be registered");
// Reregister the same address IID should always succeed.
error = table.Register(addressIid, meshLocalIid, i, nullptr);
- VerifyOrQuit(error == OT_ERROR_NONE, "Register again failed");
+ VerifyOrQuit(error == kErrorNone, "Register again failed");
// Register the same address IID with a different ML-IID should fail.
error = table.Register(addressIid, notExistMeshLocalIid, i, nullptr);
- VerifyOrQuit(error == OT_ERROR_DUPLICATED, "Register duplicate should fail");
+ VerifyOrQuit(error == kErrorDuplicated, "Register duplicate should fail");
VerifyOrQuit(table.IsRegistered(addressIid), "should be registered");
}
@@ -101,7 +101,7 @@
// Now the table is full, registering another IID should fail.
error =
table.Register(notExistAddressIid, notExistMeshLocalIid, OPENTHREAD_CONFIG_NDPROXY_TABLE_ENTRY_NUM, nullptr);
- VerifyOrQuit(error == OT_ERROR_NO_BUFS, "should fail with no bufs");
+ VerifyOrQuit(error == kErrorNoBufs, "should fail with no bufs");
VerifyOrQuit(!table.IsRegistered(notExistAddressIid), "should not be registered");
}
diff --git a/tests/unit/test_netif.cpp b/tests/unit/test_netif.cpp
index ca1ace0..be33e80 100644
--- a/tests/unit/test_netif.cpp
+++ b/tests/unit/test_netif.cpp
@@ -168,11 +168,11 @@
VerifyMulticastAddressList(netif, &addresses[0], 8);
IgnoreError(address.FromString(kTestAddress1)); // same as netifAddress (internal)
- VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorInvalidArgs,
"UnsubscribeExternalMulticast() did not fail when address was not external");
IgnoreError(address.FromString(kRealmLocalAllMpl));
- VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(netif.UnsubscribeExternalMulticast(address) == kErrorInvalidArgs,
"UnsubscribeExternalMulticast() did not fail when address was fixed address");
netif.UnsubscribeAllRoutersMulticast();
@@ -200,7 +200,7 @@
for (uint8_t i = 0; i < 5; i++)
{
- VerifyOrQuit(netif.SubscribeExternalMulticast(addresses[i]) == OT_ERROR_INVALID_ARGS,
+ VerifyOrQuit(netif.SubscribeExternalMulticast(addresses[i]) == kErrorInvalidArgs,
"SubscribeExternalMulticast() did not fail when address was a default/fixed address");
}
}
diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp
index 99f156b..bb2e7cc 100644
--- a/tests/unit/test_platform.cpp
+++ b/tests/unit/test_platform.cpp
@@ -94,7 +94,7 @@
extern "C" {
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
return calloc(aNum, aSize);
@@ -691,6 +691,27 @@
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aShortAddress);
+
+ otLinkMetrics metrics;
+
+ memset(&metrics, 0, sizeof(metrics));
+
+ return metrics;
+}
+#endif
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
+ const otIp6Address *aDestAddress,
+ const uint8_t * aBuffer,
+ uint16_t aBufferLength)
+{
+ OT_UNUSED_VARIABLE(aInfraIfIndex);
+ OT_UNUSED_VARIABLE(aDestAddress);
+ OT_UNUSED_VARIABLE(aBuffer);
+ OT_UNUSED_VARIABLE(aBufferLength);
+
+ return OT_ERROR_FAILED;
}
#endif
diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.cpp
index 9ff02ab..d3b8e69 100644
--- a/tests/unit/test_timer.cpp
+++ b/tests/unit/test_timer.cpp
@@ -87,7 +87,7 @@
{
public:
explicit TestTimer(ot::Instance &aInstance)
- : TimerType(aInstance, TestTimer::HandleTimerFired, nullptr)
+ : TimerType(aInstance, TestTimer::HandleTimerFired)
, mFiredCounter(0)
{
}
diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt
index f777749..96ab34a 100644
--- a/third_party/CMakeLists.txt
+++ b/third_party/CMakeLists.txt
@@ -34,8 +34,16 @@
add_subdirectory(nxp)
elseif(OT_PLATFORM MATCHES "cc*")
add_subdirectory(ti)
-elseif(OT_PLATFORM STREQUAL "qpg6095")
+elseif(OT_PLATFORM MATCHES "^qpg*")
+ add_subdirectory(Qorvo)
+elseif(OT_PLATFORM STREQUAL "gp712")
add_subdirectory(Qorvo)
elseif(OT_PLATFORM STREQUAL "samr21")
add_subdirectory(microchip)
+elseif(OT_PLATFORM MATCHES "^nrf*")
+ add_subdirectory(jlink)
+ add_subdirectory(NordicSemiconductor)
+elseif(OT_PLATFORM MATCHES "^efr*")
+ add_subdirectory(jlink)
+ add_subdirectory(silabs)
endif()
diff --git a/third_party/mbedtls/mbedtls-config.h b/third_party/mbedtls/mbedtls-config.h
index e318e8f..579328b 100644
--- a/third_party/mbedtls/mbedtls-config.h
+++ b/third_party/mbedtls/mbedtls-config.h
@@ -117,7 +117,7 @@
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */
#define MBEDTLS_ENTROPY_MAX_SOURCES 1 /**< Maximum number of sources supported */
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
#define MBEDTLS_PLATFORM_STD_CALLOC otPlatCAlloc /**< Default allocator to use, can be undefined */
#define MBEDTLS_PLATFORM_STD_FREE otPlatFree /**< Default free to use, can be undefined */
#else
diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py
index c5c4ed5..db354e0 100644
--- a/tools/harness-thci/OpenThread.py
+++ b/tools/harness-thci/OpenThread.py
@@ -148,14 +148,12 @@
"""
Connect to the device.
"""
- pass
@abstractmethod
def _disconnect(self):
"""
Disconnect from the device
"""
- pass
@abstractmethod
def _cliReadLine(self):
@@ -164,7 +162,6 @@
Returns:
None if no data
"""
- pass
@abstractmethod
def _cliWriteLine(self, line):
@@ -173,17 +170,14 @@
Args:
line str: data send to device
"""
- pass
@abstractmethod
def _onCommissionStart(self):
"""Called when commissioning starts."""
- pass
@abstractmethod
def _onCommissionStop(self):
"""Called when commissioning stops."""
- pass
def __sendCommand(self, cmd, expectEcho=True):
self.log("command: %s", cmd)
@@ -436,9 +430,7 @@
print('call setAddressFilterMode() ' + mode)
try:
cmd = 'macfilter addr ' + mode
- if self.__executeCommand(cmd)[-1] == 'Done':
- return True
- return False
+ return self.__executeCommand(cmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('__setAddressFilterMode() Error: ' + str(e))
@@ -575,6 +567,7 @@
strIp6Prefix = prefix[:19]
return strIp6Prefix + '::'
+ # pylint: disable=no-self-use
def __convertLongToHex(self, iValue, fillZeros=None):
"""convert a long hex integer to string
remove '0x' and 'L' return string
@@ -640,6 +633,7 @@
self.logThreadStatus = self.logStatus['stop']
return logs
+ # pylint: disable=no-self-use
def __convertChannelMask(self, channelsArray):
"""convert channelsArray to bitmask format
@@ -705,6 +699,7 @@
print('%s call getCommissionerSessionId' % self)
return self.__executeCommand('commissioner sessionid')[0]
+ # pylint: disable=no-self-use
def __escapeEscapable(self, string):
"""Escape CLI escapable characters in the given string.
@@ -737,7 +732,7 @@
cmd = 'networkname %s' % networkName
datasetCmd = 'dataset networkname %s' % networkName
self.hasActiveDatasetToCommit = True
- return (self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done')
+ return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('setNetworkName() Error: ' + str(e))
@@ -761,7 +756,7 @@
cmd = 'channel %s' % channel
datasetCmd = 'dataset channel %s' % channel
self.hasActiveDatasetToCommit = True
- return (self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done')
+ return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('setChannel() Error: ' + str(e))
@@ -907,7 +902,7 @@
self.networkKey = masterKey
self.hasActiveDatasetToCommit = True
- return (self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done')
+ return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('setNetworkkey() Error: ' + str(e))
@@ -1266,7 +1261,7 @@
cmd = 'panid %s' % panid
datasetCmd = 'dataset panid %s' % panid
self.hasActiveDatasetToCommit = True
- return (self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done')
+ return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('setPANID() Error: ' + str(e))
@@ -1880,7 +1875,7 @@
self.xpanId = xpanid
self.hasActiveDatasetToCommit = True
- return (self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done')
+ return self.__executeCommand(cmd)[-1] == 'Done' and self.__executeCommand(datasetCmd)[-1] == 'Done'
except Exception as e:
ModuleHelper.WriteIntoDebugLogger('setXpanId() Error: ' + str(e))
@@ -2045,7 +2040,7 @@
if not listTLV_ids:
return
- if not len(listTLV_ids):
+ if len(listTLV_ids) == 0:
return
cmd = 'networkdiagnostic get %s %s' % (
@@ -2061,7 +2056,7 @@
if not listTLV_ids:
return
- if not len(listTLV_ids):
+ if len(listTLV_ids) == 0:
return
cmd = 'networkdiagnostic reset %s %s' % (
@@ -2085,10 +2080,7 @@
self.__executeCommand('ifconfig up')
cmd = 'joiner start %s' % (strPSKc)
print(cmd)
- if self.__executeCommand(cmd)[-1] == 'Done':
- return True
- else:
- return False
+ return self.__executeCommand(cmd)[-1] == 'Done'
@API
def startCollapsedCommissioner(self):
@@ -2835,10 +2827,7 @@
@API
def ValidateDeviceFirmware(self):
print('%s call ValidateDeviceFirmware' % self)
- if 'OPENTHREAD' in self.UIStatusMsg:
- return True
- else:
- return False
+ return 'OPENTHREAD' in self.UIStatusMsg
# Low power THCI
@API
@@ -2870,7 +2859,8 @@
print(cmd)
return self.__executeCommand(cmd)[-1] == 'Done'
- def getForwardSeriesFlagsFromHexStr(self, flags):
+ @staticmethod
+ def getForwardSeriesFlagsFromHexStr(flags):
hexFlags = int(flags, 16)
strFlags = ''
if hexFlags == 0:
@@ -2887,7 +2877,8 @@
return strFlags
- def mapMetricsHexToChar(self, metrics):
+ @staticmethod
+ def mapMetricsHexToChar(metrics):
metricsFlagMap = {
0x40: 'p',
0x09: 'q',
@@ -2896,21 +2887,22 @@
}
return metricsFlagMap.get(metrics, '?')
- def getMetricsFlagsFromHexStr(self, metrics):
+ @staticmethod
+ def getMetricsFlagsFromHexStr(metrics):
if metrics.startswith('0x'):
metrics = metrics[2:]
hexMetricsArray = bytearray.fromhex(metrics)
strMetrics = ''
for metric in hexMetricsArray:
- strMetrics += mapMetricsHexToChar(metric)
+ strMetrics += OpenThreadTHCI.mapMetricsHexToChar(metric)
return strMetrics
@API
def LinkMetricsSingleReq(self, dst_addr, metrics):
self.log('call LinkMetricsSingleReq')
- cmd = 'linkmetrics query %s single %s' % (dst_addr, getMetricsFlagsFromHexStr(metrics))
+ cmd = 'linkmetrics query %s single %s' % (dst_addr, self.getMetricsFlagsFromHexStr(metrics))
print(cmd)
return self.__executeCommand(cmd)[-1] == 'Done'
@@ -2919,14 +2911,14 @@
self.log('call LinkMetricsMgmtReq')
cmd = 'linkmetrics mgmt %s ' % dst_addr
if type_ == 'FWD':
- cmd += 'forward %d %s' % (series_id, getForwardSeriesFlagsFromHexStr(flags))
+ cmd += 'forward %d %s' % (series_id, self.getForwardSeriesFlagsFromHexStr(flags))
if flags != 0:
- cmd += ' %s' % (getMetricsFlagsFromHexStr(metrics))
+ cmd += ' %s' % (self.getMetricsFlagsFromHexStr(metrics))
elif type_ == 'ENH':
cmd += 'enhanced-ack'
if flags != 0:
cmd += ' register'
- metricsFlags = getMetricsFlagsFromHexStr(metrics)
+ metricsFlags = self.getMetricsFlagsFromHexStr(metrics)
if '?' in metricsFlags:
cmd += ' %s r' % metricsFlags.replace('?', '')
else:
@@ -2974,7 +2966,7 @@
print(cmd1)
cmd2 = 'udp send %s %d %s' % (destination, port, payload)
print(cmd2)
- return (self.__executeCommand(cmd1)[-1] == 'Done' and self.__executeCommand(cmd2)[-1] == 'Done')
+ return self.__executeCommand(cmd1)[-1] == 'Done' and self.__executeCommand(cmd2)[-1] == 'Done'
@API
def send_udp(self, interface, destination, port, payload='12ABcd'):
@@ -2986,7 +2978,7 @@
print(cmd1)
cmd2 = 'udp send %s %s -x %s' % (destination, port, payload)
print(cmd2)
- return (self.__executeCommand(cmd1)[-1] == 'Done' and self.__executeCommand(cmd2)[-1] == 'Done')
+ return self.__executeCommand(cmd1)[-1] == 'Done' and self.__executeCommand(cmd2)[-1] == 'Done'
@API
def sendMACcmd(self, enh=False):
@@ -3071,7 +3063,7 @@
return self.__lines.pop(0)
tail = ''
- if len(self.__lines):
+ if len(self.__lines) != 0:
tail = self.__lines.pop()
try:
diff --git a/tools/otci/LICENSE b/tools/otci/LICENSE
new file mode 100644
index 0000000..d63767e
--- /dev/null
+++ b/tools/otci/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2020, The OpenThread Authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/tools/otci/README.md b/tools/otci/README.md
new file mode 100644
index 0000000..788f937
--- /dev/null
+++ b/tools/otci/README.md
@@ -0,0 +1,53 @@
+# OpenThread Control Interface
+
+The OpenThread Control Interface (OTCI) is a library which provides uniform python interfaces to connect and control various kinds of devices running OpenThread.
+
+## Supported device types
+
+- OpenThread CLI
+ - SOC device via Serial
+- OpenThread NCP (limited support via [pyspinel](https://pypi.org/project/pyspinel/))
+ - SOC device via Serial
+- [OpenThread Border Router](https://github.com/openthread/ot-br-posix)
+ - OTBR device via SSH
+
+## Example
+
+```python
+import otci
+
+# Connect to an OTBR device via SSH
+node1 = otci.connect_otbr_ssh("192.168.1.101")
+
+# Connect to an OpenThread CLI device via Serial
+node2 = otci.connect_cli_serial("/dev/ttyACM0"))
+
+# Start node1 to become Leader
+node1.dataset_init_buffer()
+node1.dataset_set_buffer(network_name='test', master_key='00112233445566778899aabbccddeeff', panid=0xface, channel=11)
+node1.dataset_commit_buffer('active')
+
+node1.ifconfig_up()
+node1.thread_start()
+node1.wait(5)
+assert node1.get_state() == "leader"
+
+# Start Commissioner on node1
+node1.commissioner_start()
+node1.wait(3)
+
+node1.commissioner_add_joiner("TEST123",eui64='*')
+
+# Start node2
+node2.ifconfig_up()
+node2.set_router_selection_jitter(1)
+
+# Start Joiner on node2 to join the network
+node2.joiner_start("TEST123")
+node2.wait(10, expect_line="Join success")
+
+# Wait for node 2 to become Router
+node2.thread_start()
+node2.wait(5)
+assert node2.get_state() == "router"
+```
diff --git a/tests/scripts/expect/cli-anycast.exp b/tools/otci/otci/__init__.py
similarity index 73%
copy from tests/scripts/expect/cli-anycast.exp
copy to tools/otci/otci/__init__.py
index 3081a6b..8c3a1e5 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/tools/otci/otci/__init__.py
@@ -1,4 +1,4 @@
-#!/usr/bin/expect -f
+#!/usr/bin/env python3
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
@@ -27,30 +27,23 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
+from . import errors
+from .constants import THREAD_VERSION_1_1, THREAD_VERSION_1_2
+from .otci import OTCI
+from .otci import \
+ connect_cli_sim, \
+ connect_cli_serial, \
+ connect_ncp_sim, \
+ connect_cmd_handler, \
+ connect_otbr_ssh
+from .types import Rloc16, ChildId
+_connectors = [
+ 'connect_cli_sim',
+ 'connect_cli_serial',
+ 'connect_ncp_sim',
+ 'connect_otbr_ssh',
+ 'connect_cmd_handler',
+]
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+__all__ = ['OTCI', 'errors', 'Rloc16', 'ChildId', 'THREAD_VERSION_1_1', 'THREAD_VERSION_1_2'] + _connectors
diff --git a/tools/otci/otci/command_handlers.py b/tools/otci/otci/command_handlers.py
new file mode 100644
index 0000000..c3b6484
--- /dev/null
+++ b/tools/otci/otci/command_handlers.py
@@ -0,0 +1,211 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import logging
+import queue
+import re
+import threading
+import time
+from abc import abstractmethod
+from typing import Union, List, Pattern
+
+from .connectors import OtCliHandler
+from .errors import ExpectLineTimeoutError, CommandError
+from .utils import match_line
+
+
+class OTCommandHandler:
+ """This abstract class defines interfaces of a OT Command Handler."""
+
+ @abstractmethod
+ def execute_command(self, cmd: str, timeout: float) -> List[str]:
+ """Method execute_command should execute the OT CLI command within a timeout (in seconds) and return the
+ command output as a list of lines.
+
+ Note: each line SHOULD NOT contain '\r\n' at the end. The last line of output should be 'Done' or
+ 'Error <code>: <msg>' following OT CLI conventions.
+ """
+ pass
+
+ @abstractmethod
+ def close(self):
+ """Method close should close the OT Command Handler."""
+ pass
+
+ @abstractmethod
+ def wait(self, duration: float) -> List[str]:
+ """Method wait should wait for a given duration and return the OT CLI output during this period.
+
+ Normally, OT CLI does not output when it's not executing any command. But OT CLI can also output
+ asynchronously in some cases (e.g. `Join Success` when Joiner joins successfully).
+ """
+ pass
+
+
+class OtCliCommandRunner(OTCommandHandler):
+ __PATTERN_COMMAND_DONE_OR_ERROR = re.compile(
+ r'(Done|Error|Error \d+:.*|.*: command not found)$') # "Error" for spinel-cli.py
+
+ __PATTERN_LOG_LINE = re.compile(r'((\[(NONE|CRIT|WARN|NOTE|INFO|DEBG)\])'
+ r'|(-.*-+: )' # e.g. -CLI-----:
+ r')')
+ """regex used to filter logs"""
+
+ __ASYNC_COMMANDS = {
+ 'scan',
+ }
+
+ def __init__(self, otcli: OtCliHandler, is_spinel_cli=False):
+ self.__otcli: OtCliHandler = otcli
+ self.__is_spinel_cli = is_spinel_cli
+ self.__expect_command_echoback = not self.__is_spinel_cli
+
+ self.__pending_lines = queue.Queue()
+ self.__should_close = threading.Event()
+ self.__otcli_reader = threading.Thread(target=self.__otcli_read_routine)
+ self.__otcli_reader.setDaemon(True)
+ self.__otcli_reader.start()
+
+ def __repr__(self):
+ return repr(self.__otcli)
+
+ def execute_command(self, cmd, timeout=10) -> None:
+ self.__otcli.writeline(cmd)
+
+ if cmd in {'reset', 'factoryreset'}:
+ return []
+
+ if self.__expect_command_echoback:
+ self.__expect_line(timeout, cmd)
+
+ output = self.__expect_line(timeout,
+ OtCliCommandRunner.__PATTERN_COMMAND_DONE_OR_ERROR,
+ asynchronous=cmd.split()[0] in OtCliCommandRunner.__ASYNC_COMMANDS)
+ return output
+
+ def wait(self, duration: float) -> List[str]:
+ self.__otcli.wait(duration)
+
+ output = []
+ try:
+ while True:
+ line = self.__pending_lines.get_nowait()
+ output.append(line)
+
+ except queue.Empty:
+ pass
+
+ return output
+
+ def close(self):
+ self.__should_close.set()
+ self.__otcli.close()
+
+ #
+ # Private methods
+ #
+
+ def __expect_line(self, timeout: float, expect_line: Union[str, Pattern], asynchronous=False) -> List[str]:
+ output = []
+
+ if not asynchronous:
+ while True:
+ try:
+ line = self.__pending_lines.get(timeout=timeout)
+ except queue.Empty:
+ raise ExpectLineTimeoutError(expect_line)
+
+ output.append(line)
+
+ if match_line(line, expect_line):
+ break
+ else:
+ done = False
+ while not done and timeout > 0:
+ lines = self.wait(1)
+ timeout -= 1
+
+ for line in lines:
+ output.append(line)
+
+ if match_line(line, expect_line):
+ done = True
+ break
+
+ if not done:
+ raise ExpectLineTimeoutError(expect_line)
+
+ return output
+
+ def __otcli_read_routine(self):
+ while not self.__should_close.isSet():
+ line = self.__otcli.readline()
+ if line.startswith('> '):
+ line = line[2:]
+
+ logging.debug('%s: %s', self.__otcli, line)
+
+ if not OtCliCommandRunner.__PATTERN_LOG_LINE.match(line):
+ self.__pending_lines.put(line)
+
+
+class OtbrSshCommandRunner(OTCommandHandler):
+
+ def __init__(self, host, port, username, password):
+ import paramiko
+
+ self.__host = host
+ self.__port = port
+ self.__ssh = paramiko.SSHClient()
+ self.__ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ self.__ssh.connect(host,
+ port=port,
+ username=username,
+ password=password,
+ allow_agent=False,
+ look_for_keys=False)
+
+ def __repr__(self):
+ return f'{self.__host}:{self.__port}'
+
+ def execute_command(self, cmd: str, timeout: float) -> List[str]:
+ sh_cmd = f'sudo ot-ctl "{cmd}"'
+ cmd_in, cmd_out, cmd_err = self.__ssh.exec_command(sh_cmd, timeout=int(timeout), bufsize=1024)
+ err = cmd_err.read().decode('utf-8')
+ if err:
+ raise CommandError(cmd, [err])
+
+ output = [l.rstrip('\r\n') for l in cmd_out.readlines()]
+ return output
+
+ def close(self):
+ self.__ssh.close()
+
+ def wait(self, duration: float) -> List[str]:
+ time.sleep(duration)
+ return []
diff --git a/tools/otci/otci/connectors.py b/tools/otci/otci/connectors.py
new file mode 100644
index 0000000..1785f11
--- /dev/null
+++ b/tools/otci/otci/connectors.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import logging
+import subprocess
+import time
+from abc import abstractmethod
+
+
+class OtCliHandler:
+ """This abstract class defines interfaces for a OT CLI Handler."""
+
+ @abstractmethod
+ def readline(self) -> str:
+ """Method readline should return the next line read from OT CLI."""
+ pass
+
+ @abstractmethod
+ def writeline(self, s: str) -> None:
+ """Method writeline should write a line to the OT CLI.
+
+ It should block until all characters are written to OT CLI.
+ """
+ pass
+
+ @abstractmethod
+ def wait(self, duration: float) -> None:
+ """Method wait should wait for a given duration.
+
+ A normal implementation should just call `time.sleep(duration)`. This is intended for proceeding Virtual Time
+ Simulation instances.
+ """
+ pass
+
+ @abstractmethod
+ def close(self) -> None:
+ """Method close should close the OT CLI Handler."""
+ pass
+
+
+class Simulator:
+ """This abstract class defines interfaces for a Virtual Time Simulator."""
+
+ @abstractmethod
+ def go(self, duration: float):
+ """Proceed the simulator for a given duration (in seconds)."""
+ pass
+
+
+class OtCliPopen(OtCliHandler):
+ """Connector for OT CLI process (a Popen instance)."""
+
+ def __init__(self, proc: subprocess.Popen, nodeid: int, simulator: Simulator):
+ self.__otcli_proc = proc
+ self.__nodeid = nodeid
+ self.__simulator = simulator
+
+ def __repr__(self):
+ return 'OTCli<%d>' % self.__nodeid
+
+ def readline(self) -> str:
+ return self.__otcli_proc.stdout.readline().rstrip('\r\n')
+
+ def writeline(self, s: str):
+ self.__otcli_proc.stdin.write(s + '\n')
+ self.__otcli_proc.stdin.flush()
+
+ def wait(self, duration: float):
+ if self.__simulator is not None:
+ # Virtual time simulation
+ self.__simulator.go(duration)
+ else:
+ # Real time simulation
+ time.sleep(duration)
+
+ def close(self):
+ self.__otcli_proc.stdin.close()
+ self.__otcli_proc.stdout.close()
+ self.__otcli_proc.wait()
+
+
+class OtCliSim(OtCliPopen):
+ """Connector for OT CLI Simulation instances."""
+
+ def __init__(self, executable: str, nodeid: int, simulator: Simulator):
+ logging.info('%s: executable=%s', self.__class__.__name__, executable)
+
+ proc = subprocess.Popen(args=[executable, str(nodeid)],
+ executable=executable,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ encoding='utf-8',
+ bufsize=1024)
+ super().__init__(proc, nodeid, simulator)
+
+
+class OtNcpSim(OtCliHandler):
+ """Connector for OT NCP Simulation instances."""
+
+ def __init__(self, executable: str, nodeid: int, simulator: Simulator):
+ logging.info('%s: executable=%s', self.__class__.__name__, executable)
+
+ proc = subprocess.Popen(args=f'spinel-cli.py -p "{executable}" -n {nodeid} 2>&1',
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ encoding='utf-8',
+ bufsize=1024,
+ shell=True)
+ super().__init__(proc, nodeid, simulator)
+
+
+class OtCliSerial(OtCliHandler):
+ """Connector for OT CLI SOC devices via Serial."""
+
+ def __init__(self, dev: str, baudrate: int):
+ self.__dev = dev
+ self.__baudrate = baudrate
+
+ import serial
+ self.__serial = serial.Serial(self.__dev, self.__baudrate, timeout=None, exclusive=True)
+
+ def __repr__(self):
+ return self.__dev
+
+ def readline(self) -> str:
+ line = self.__serial.readline().decode('utf-8').rstrip('\r\n')
+ return line
+
+ def writeline(self, s: str):
+ self.__serial.write((s + '\n').encode('utf-8'))
+
+ def wait(self, duration: float):
+ time.sleep(duration)
+
+ def close(self):
+ self.__serial.close()
diff --git a/tests/scripts/expect/cli-anycast.exp b/tools/otci/otci/constants.py
similarity index 76%
copy from tests/scripts/expect/cli-anycast.exp
copy to tools/otci/otci/constants.py
index 3081a6b..4bf13c4 100644
--- a/tests/scripts/expect/cli-anycast.exp
+++ b/tools/otci/otci/constants.py
@@ -1,4 +1,4 @@
-#!/usr/bin/expect -f
+#!/usr/bin/env python3
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
@@ -27,30 +27,6 @@
# POSSIBILITY OF SUCH DAMAGE.
#
-source "tests/scripts/expect/_common.exp"
-
-
-set spawn_id [spawn_node 1]
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-
-wait_for "state" "leader"
-expect "Done"
-
-send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
-expect "Done"
-expect "16 bytes from "
-expect {
- "fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-
- -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
-
- timeout abort
-}
-
-dispose
+# Thread versions
+THREAD_VERSION_1_1 = 2
+THREAD_VERSION_1_2 = 3
diff --git a/tests/scripts/expect/v1_2-rcp.exp b/tools/otci/otci/errors.py
old mode 100755
new mode 100644
similarity index 60%
copy from tests/scripts/expect/v1_2-rcp.exp
copy to tools/otci/otci/errors.py
index 776d880..dc8fd59
--- a/tests/scripts/expect/v1_2-rcp.exp
+++ b/tools/otci/otci/errors.py
@@ -1,4 +1,4 @@
-#!/usr/bin/expect -f
+#!/usr/bin/env python3
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
@@ -26,40 +26,39 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
+from typing import List
-source "tests/scripts/expect/_common.exp"
-spawn_node 1
+class OTCIError(Exception):
+ """Base class for OTCI Errors."""
+ pass
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "leader"
-expect "Done"
-send "ipaddr mleid\n"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
+class ExpectLineTimeoutError(OTCIError):
+ """OTCI failed to find an expected line before timeout."""
-spawn_node 2 mtd
+ def __init__(self, line):
+ super(ExpectLineTimeoutError, self).__init__("Expected line %r, but timed out" % line)
-send "panid 0xface\n"
-expect "Done"
-send "mode -\n"
-expect "Done"
-send "csl period 5000\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "child"
-expect "Done"
-send "ping $addr\n"
-expect "16 bytes from $addr: icmp_seq=1"
-dispose_all
+class CommandError(OTCIError):
+ """OTCI failed to execute a command."""
+
+ def __init__(self, cmd: str, output: List[str]):
+ self.__output = output
+ super(CommandError, self).__init__("Command error while executing %r:\n%s\n" % (cmd, '\n'.join(output)))
+
+ def error(self) -> str:
+ return self.__output[-1]
+
+
+class UnexpectedCommandOutput(OTCIError):
+ """OTCI got unexpected command output."""
+
+ def __init__(self, output: List[str]):
+ super(UnexpectedCommandOutput, self).__init__("Unexpected command output:\n%s\n" % '\n'.join(output))
+
+
+class InvalidArgumentsError(OTCIError):
+ """Invalid arguments."""
+ pass
diff --git a/tools/otci/otci/otci.py b/tools/otci/otci/otci.py
new file mode 100644
index 0000000..361162b
--- /dev/null
+++ b/tools/otci/otci/otci.py
@@ -0,0 +1,1938 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import ipaddress
+import logging
+import re
+import time
+from collections import Counter
+from typing import List, Collection, Union, Tuple, Optional, Dict, Pattern, Any
+
+from . import connectors
+from .command_handlers import OTCommandHandler, OtCliCommandRunner, OtbrSshCommandRunner
+from .connectors import Simulator
+from .errors import UnexpectedCommandOutput, ExpectLineTimeoutError, CommandError, InvalidArgumentsError
+from .types import ChildId, Rloc16, Ip6Addr, ThreadState, PartitionId, DeviceMode, RouterId, SecurityPolicy, Ip6Prefix, \
+ RouterTableEntry
+from .utils import match_line, constant_property
+
+
+class OTCI(object):
+ """
+ This class represents an OpenThread Controller Interface instance that provides versatile interfaces to
+ manipulate an OpenThread device.
+ """
+
+ def __init__(self, otcmd: OTCommandHandler):
+ """
+ This method initializes an OTCI instance.
+
+ :param otcmd: An OpenThread Command Handler instance to execute OpenThread CLI commands.
+ """
+ self.__otcmd: OTCommandHandler = otcmd
+ self.__logger = logging.getLogger(name=str(self))
+
+ def __repr__(self):
+ """Gets the string representation of the OTCI instance."""
+ return repr(self.__otcmd)
+
+ def wait(self, duration: float, expect_line: Union[str, Pattern, Collection[Any]] = None):
+ """Wait for a given duration.
+
+ :param duration: The duration (in seconds) wait for.
+ :param expect_line: The line expected to output if given.
+ Raise ExpectLineTimeoutError if expect_line is not found within the given duration.
+ """
+ self.__logger and self.__logger.info("wait for %.3f seconds", duration)
+ if expect_line is None:
+ self.__otcmd.wait(duration)
+ else:
+ success = False
+
+ while duration > 0:
+ output = self.__otcmd.wait(1)
+ if match_line(expect_line, output):
+ success = True
+ break
+
+ if not success:
+ raise ExpectLineTimeoutError(expect_line)
+
+ def close(self):
+ """Close the OTCI instance."""
+ self.__otcmd.close()
+
+ def execute_command(self, cmd: str, timeout: float = 10, silent: bool = False) -> List[str]:
+ """Execute the OpenThread CLI command.
+
+ :param cmd: The command to execute.
+ :param timeout: The command timeout.
+ :param silent: Whether to run the command silent without logging.
+ :returns: The command output as a list of lines.
+ """
+ if not silent:
+ self.__logger and self.__logger.info('> %s', cmd)
+
+ output = self.__otcmd.execute_command(cmd, timeout)
+
+ if not silent:
+ for line in output:
+ self.__logger and self.__logger.info('%s', line)
+
+ if cmd in ('reset', 'factoryreset'):
+ self.__wait_reset()
+ return output
+
+ if output[-1] == 'Done':
+ output = output[:-1]
+ return output
+ else:
+ raise CommandError(cmd, output)
+
+ def set_logger(self, logger: logging.Logger):
+ """Set the logger for the OTCI instance, or None to disable logging."""
+ self.__logger = logger
+
+ #
+ # Constant properties
+ #
+ @constant_property
+ def version(self):
+ """Returns the firmware version. (e.g. "OPENTHREAD/20191113-01411-gb2d66e424-dirty; SIMULATION; Nov 14 2020 14:24:38")"""
+ return self.__parse_str(self.execute_command('version'))
+
+ @constant_property
+ def thread_version(self):
+ """Get the Thread Version number."""
+ return self.__parse_int(self.execute_command('thread version'))
+
+ @constant_property
+ def api_version(self):
+ """Get API version number."""
+ try:
+ return self.__parse_int(self.execute_command('version api'))
+ except ValueError:
+ # If the device does not have `version api` command, it will print the firmware version, which would lead to ValueError.
+ return 0
+
+ #
+ # Basic device operations
+ #
+ def ifconfig_up(self):
+ """Bring up the IPv6 interface."""
+ self.execute_command('ifconfig up')
+
+ def ifconfig_down(self):
+ """Bring down the IPv6 interface."""
+ self.execute_command('ifconfig down')
+
+ def get_ifconfig_state(self) -> bool:
+ """Get the status of the IPv6 interface."""
+ return self.__parse_values(self.execute_command('ifconfig'), up=True, down=False)
+
+ def thread_start(self):
+ """Enable Thread protocol operation and attach to a Thread network."""
+ self.execute_command('thread start')
+
+ def thread_stop(self):
+ """Disable Thread protocol operation and detach from a Thread network."""
+ self.execute_command('thread stop')
+
+ def reset(self):
+ """Signal a platform reset."""
+ self.execute_command('reset')
+
+ def factory_reset(self):
+ """Delete all stored settings, and signal a platform reset."""
+ self.execute_command('factoryreset')
+
+ #
+ # Network Operations
+ #
+
+ def ping(self, ip: str, size: int = None, count: int = None, interval: int = None, hoplimit: int = None):
+ """Send an ICMPv6 Echo Request.
+
+ :param ip: The target IPv6 address to ping.
+ :param size: The number of data bytes in the payload.
+ :param count: The number of ICMPv6 Echo Requests to be sent.
+ :param interval: The interval between two consecutive ICMPv6 Echo Requests in seconds. The value may have fractional form, for example 0.5.
+ :param hoplimit: The hoplimit of ICMPv6 Echo Request to be sent.
+ """
+ cmd = f'ping {ip}'
+
+ if size is not None:
+ cmd += f' {size}'
+
+ if count is not None:
+ cmd += f' {count}'
+
+ if interval is not None:
+ cmd += f' {interval}'
+
+ if hoplimit is not None:
+ cmd += f' {hoplimit}'
+
+ self.execute_command(cmd)
+
+ def ping_stop(self):
+ """Stop sending ICMPv6 Echo Requests."""
+ self.execute_command('ping stop')
+
+ def scan(self, channel: int = None) -> List[Dict[str, Any]]:
+ """Perform an IEEE 802.15.4 Active Scan."""
+ cmd = 'scan'
+ if channel is not None:
+ cmd += f' {channel}'
+
+ output = self.execute_command(cmd, timeout=10)
+ if len(output) < 2:
+ raise UnexpectedCommandOutput(output)
+
+ networks = []
+ for line in output[2:]:
+ fields = line.strip().split('|')
+
+ _, J, netname, extpanid, panid, extaddr, ch, dbm, lqi, _ = fields
+ networks.append({
+ 'joinable': bool(int(J)),
+ 'network_name': netname.strip(),
+ 'extpanid': extpanid,
+ 'panid': int(panid, 16),
+ 'extaddr': extaddr,
+ 'channel': int(ch),
+ 'dbm': int(dbm),
+ 'lqi': int(lqi),
+ })
+
+ return networks
+
+ def scan_energy(self, duration: float = None, channel: int = None) -> Dict[int, int]:
+ """Perform an IEEE 802.15.4 Energy Scan."""
+ cmd = 'scan energy'
+ if duration is not None:
+ cmd += f' {duration * 1000:d}'
+
+ if channel is not None:
+ cmd += f' {channel}'
+
+ output = self.execute_command(cmd, timeout=10)
+ if len(output) < 2:
+ raise UnexpectedCommandOutput(output)
+
+ channels = {}
+ for line in output[2:]:
+ fields = line.strip().split('|')
+
+ _, Ch, RSSI, _ = fields
+ channels[int(Ch)] = int(RSSI)
+
+ return channels
+
+ def mac_send_data_request(self):
+ """Instruct an Rx-Off-When-Idle device to send a Data Request mac frame to its parent."""
+ self.execute_command('mac send datarequest')
+
+ def mac_send_empty_data(self):
+ """Instruct an Rx-Off-When-Idle device to send a Empty Data mac frame to its parent."""
+ self.execute_command('mac send emptydata')
+
+ # TODO: discover
+ # TODO: dns resolve <hostname> [DNS server IP] [DNS server port]
+ # TODO: fake /a/an <dst-ipaddr> <target> <meshLocalIid>
+ # TODO: sntp query
+
+ #
+ # Set or get device/network parameters
+ #
+
+ def get_mode(self) -> str:
+ """Get the Thread Device Mode value.
+
+ -: 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
+ """
+ return self.__parse_str(self.execute_command('mode'))
+
+ def set_mode(self, mode: str):
+ """Set the Thread Device Mode value.
+
+ -: 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
+ """
+ self.execute_command(f'mode {DeviceMode(mode)}')
+
+ def get_extaddr(self) -> str:
+ """Get the IEEE 802.15.4 Extended Address."""
+ return self.__parse_extaddr(self.execute_command('extaddr'))
+
+ def set_extaddr(self, extaddr: str):
+ """Set the IEEE 802.15.4 Extended Address."""
+ self.__validate_hex64b(extaddr)
+ self.execute_command(f'extaddr {extaddr}')
+
+ def get_eui64(self) -> str:
+ """Get the factory-assigned IEEE EUI-64."""
+ return self.__parse_eui64(self.execute_command('eui64'))
+
+ def set_extpanid(self, extpanid: str):
+ """Set the Thread Extended PAN ID value."""
+ self.__validate_extpanid(extpanid)
+ self.execute_command(f'extpanid {extpanid}')
+
+ def get_extpanid(self) -> str:
+ """Get the Thread Extended PAN ID value."""
+ return self.__parse_extpanid(self.execute_command('extpanid'))
+
+ def set_channel(self, ch):
+ """Set the IEEE 802.15.4 Channel value."""
+ self.execute_command('channel %d' % ch)
+
+ def get_channel(self):
+ """Get the IEEE 802.15.4 Channel value."""
+ return self.__parse_int(self.execute_command('channel'))
+
+ def get_preferred_channel_mask(self) -> int:
+ """Get preferred channel mask."""
+ return self.__parse_int(self.execute_command('channel preferred'))
+
+ def get_supported_channel_mask(self):
+ """Get supported channel mask."""
+ return self.__parse_int(self.execute_command('channel supported'))
+
+ def get_panid(self):
+ """Get the IEEE 802.15.4 PAN ID value."""
+ return self.__parse_int(self.execute_command('panid'), 16)
+
+ def set_panid(self, panid):
+ """Get the IEEE 802.15.4 PAN ID value."""
+ self.execute_command('panid %d' % panid)
+
+ def set_network_name(self, name):
+ """Set network name."""
+ self.execute_command('networkname %s' % self.__escape_escapable(name))
+
+ def get_network_name(self):
+ """Get network name."""
+ return self.__parse_str(self.execute_command('networkname'))
+
+ def get_master_key(self) -> str:
+ """Get the network master key."""
+ return self.__parse_master_key(self.execute_command('masterkey'))
+
+ def set_master_key(self, masterkey: str):
+ """Set the network master key."""
+ self.__validate_master_key(masterkey)
+ self.execute_command(f'masterkey {masterkey}')
+
+ def get_key_sequence_counter(self) -> int:
+ """Get the Thread Key Sequence Counter."""
+ return self.__parse_int(self.execute_command('keysequence counter'))
+
+ def set_key_sequence_counter(self, counter: int):
+ """Set the Thread Key Sequence Counter."""
+ self.execute_command(f'keysequence counter {counter}')
+
+ def get_key_sequence_guard_time(self) -> int:
+ """Get Thread Key Switch Guard Time (in hours)."""
+ return self.__parse_int(self.execute_command('keysequence guardtime'))
+
+ def set_key_sequence_guard_time(self, hours: int):
+ """Set Thread Key Switch Guard Time (in hours) 0 means Thread Key Switch immediately if key index match."""
+ self.execute_command(f'keysequence guardtime {hours}')
+
+ def get_cca_threshold(self) -> int:
+ """Get the CCA threshold in dBm measured at antenna connector per IEEE 802.15.4 - 2015 section 10.1.4."""
+ output = self.execute_command(f'ccathreshold')
+ val = self.__parse_str(output)
+ if not val.endswith(' dBm'):
+ raise UnexpectedCommandOutput(output)
+
+ return int(val[:-4])
+
+ def set_cca_threshold(self, val: int):
+ """Set the CCA threshold measured at antenna connector per IEEE 802.15.4 - 2015 section 10.1.4."""
+ self.execute_command(f'ccathreshold {val}')
+
+ def get_promiscuous(self) -> bool:
+ """Get radio promiscuous property."""
+ return self.__parse_Enabled_or_Disabled(self.execute_command('promiscuous'))
+
+ def enable_promiscuous(self):
+ """Enable radio promiscuous operation and print raw packet content."""
+ self.execute_command('promiscuous enable')
+
+ def disable_promiscuous(self):
+ """Disable radio promiscuous operation."""
+ self.execute_command('promiscuous disable')
+
+ def get_txpower(self) -> int:
+ """Get the transmit power in dBm."""
+ line = self.__parse_str(self.execute_command('txpower'))
+ if not line.endswith(' dBm'):
+ raise UnexpectedCommandOutput([line])
+
+ return int(line.split()[0])
+
+ def set_txpower(self, val: int):
+ """Set the transmit power in dBm."""
+ self.execute_command(f'txpower {val}')
+
+ # TODO: fem
+ # TODO: fem lnagain
+ # TODO: fem lnagain <LNA gain>
+ # TODO: mac retries direct
+ # TODO: mac retries direct
+ # TODO: mac retries indirect
+ # TODO: mac retries indirect <number>
+
+ #
+ # Basic Node states and properties
+ #
+
+ def get_state(self) -> ThreadState:
+ """Get the current Thread state."""
+ return ThreadState(self.__parse_str(self.execute_command('state')))
+
+ def set_state(self, state: str):
+ """Try to switch to state detached, child, router or leader."""
+ self.execute_command(f'state {state}')
+
+ def get_rloc16(self) -> int:
+ """Get the Thread RLOC16 value."""
+ return self.__parse_int(self.execute_command('rloc16'), 16)
+
+ def get_router_id(self) -> int:
+ """Get the Thread Router ID value."""
+ return self.get_rloc16() >> 10
+
+ def prefer_router_id(self, routerid: int):
+ """Prefer a Router ID when solicit router id from Leader."""
+ self.execute_command(f'preferrouterid {routerid}')
+
+ def is_singleton(self) -> bool:
+ return self.__parse_values(self.execute_command('singleton'), true=True, false=False)
+
+ #
+ # RCP related utilities
+ #
+
+ def get_rcp_version(self):
+ return self.__parse_str(self.execute_command('rcp version'))
+
+ #
+ # Unsecure port utilities
+ #
+
+ def get_unsecure_ports(self) -> List[int]:
+ """all ports from the allowed unsecured port list."""
+ return self.__parse_int_list(self.execute_command('unsecureport get'))
+
+ def add_unsecure_port(self, port: int):
+ """Add a port to the allowed unsecured port list."""
+ self.execute_command(f'unsecureport add {port}')
+
+ def remove_unsecure_port(self, port: int):
+ """Remove a port from the allowed unsecured port list."""
+ self.execute_command(f'unsecureport remove {port}')
+
+ def clear_unsecure_ports(self):
+ """Remove all ports from the allowed unsecured port list."""
+ self.execute_command('unsecureport remove all')
+
+ #
+ # Leader configurations
+ #
+
+ def get_preferred_partition_id(self) -> PartitionId:
+ """Get the preferred Thread Leader Partition ID."""
+ return PartitionId(self.__parse_int(self.execute_command(self.__get_partition_preferred_cmd())))
+
+ def set_preferred_partition_id(self, parid: int):
+ """Set the preferred Thread Leader Partition ID."""
+ self.execute_command(f'{self.__get_partition_preferred_cmd()} {parid}')
+
+ def __get_partition_preferred_cmd(self) -> str:
+ """"""
+ return 'partitionid preferred' if self.api_version >= 51 else 'leaderpartitionid'
+
+ def get_leader_weight(self) -> int:
+ """Get the Thread Leader Weight."""
+ return self.__parse_int(self.execute_command('leaderweight'))
+
+ def set_leader_weight(self, weight: int):
+ """Set the Thread Leader Weight."""
+ self.execute_command(f'leaderweight {weight}')
+
+ __LEADER_DATA_KEY_MAP = {
+ 'Partition ID': 'partition_id',
+ 'Weighting': 'weight',
+ 'Data Version': 'data_ver',
+ 'Stable Data Version': 'stable_data_ver',
+ 'Leader Router ID': 'leader_id',
+ }
+
+ def get_leader_data(self) -> Dict[str, int]:
+ """Get the Thread Leader Data."""
+ data = {}
+ output = self.execute_command('leaderdata')
+
+ try:
+ for line in output:
+ k, v = line.split(': ')
+ data[OTCI.__LEADER_DATA_KEY_MAP[k]] = int(v)
+ except KeyError:
+ raise UnexpectedCommandOutput(output)
+
+ return data
+
+ #
+ # Router configurations
+ #
+
+ def get_router_selection_jitter(self):
+ """Get the ROUTER_SELECTION_JITTER value."""
+ return self.__parse_int(self.execute_command('routerselectionjitter'))
+
+ def set_router_selection_jitter(self, jitter):
+ """Set the ROUTER_SELECTION_JITTER value."""
+ self.execute_command(f'routerselectionjitter {jitter}')
+
+ def get_network_id_timeout(self) -> int:
+ """Get the NETWORK_ID_TIMEOUT parameter used in the Router role."""
+ return self.__parse_int(self.execute_command('networkidtimeout'))
+
+ def set_network_id_timeout(self, timeout: int):
+ """Set the NETWORK_ID_TIMEOUT parameter used in the Router role."""
+ self.execute_command(f'networkidtimeout {timeout}')
+
+ def get_parent_priority(self) -> int:
+ """Get the assigned parent priority value, -2 means not assigned."""
+ return self.__parse_int(self.execute_command('parentpriority'))
+
+ def set_parent_priority(self, priority: int):
+ """Set the assigned parent priority value: 1, 0, -1 or -2."""
+ self.execute_command(f'parentpriority {priority}')
+
+ def get_router_upgrade_threshold(self) -> int:
+ """Get the ROUTER_UPGRADE_THRESHOLD value."""
+ return self.__parse_int(self.execute_command('routerupgradethreshold'))
+
+ def set_router_upgrade_threshold(self, threshold: int):
+ """Set the ROUTER_UPGRADE_THRESHOLD value."""
+ self.execute_command(f'routerupgradethreshold {threshold}')
+
+ def get_router_downgrade_threshold(self):
+ """Set the ROUTER_DOWNGRADE_THRESHOLD value."""
+ return self.__parse_int(self.execute_command('routerdowngradethreshold'))
+
+ def set_router_downgrade_threshold(self, threshold: int):
+ """Get the ROUTER_DOWNGRADE_THRESHOLD value."""
+ self.execute_command(f'routerdowngradethreshold {threshold}')
+
+ def get_router_eligible(self) -> bool:
+ """Indicates whether the router role is enabled or disabled."""
+ return self.__parse_Enabled_or_Disabled(self.execute_command('routereligible'))
+
+ def enable_router_eligible(self):
+ """Disable the router role."""
+ self.execute_command('routereligible enable')
+
+ def disable_router_eligible(self):
+ """Disable the router role."""
+ self.execute_command('routereligible disable')
+
+ def get_router_list(self) -> List[RouterId]:
+ """Get allocated Router IDs."""
+ line = self.__parse_str(self.execute_command('router list'))
+ return list(map(RouterId, line.strip().split()))
+
+ def get_router_table(self) -> Dict[RouterId, RouterTableEntry]:
+ """table of routers."""
+ output = self.execute_command('router table')
+ if len(output) < 2:
+ raise UnexpectedCommandOutput(output)
+
+ #
+ # Example output:
+ #
+ # | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC |
+ # +----+--------+----------+-----------+-------+--------+-----+------------------+
+ # | 21 | 0x5400 | 21 | 0 | 3 | 3 | 5 | d28d7f875888fccb |
+ # | 56 | 0xe000 | 56 | 0 | 0 | 0 | 182 | f2d92a82c8d8fe43 |
+ # Done
+ #
+
+ headers = self.__split_table_row(output[0])
+
+ table = {}
+ for line in output[2:]:
+ line = line.strip()
+ if not line:
+ continue
+
+ fields = self.__split_table_row(line)
+ if len(fields) != len(headers):
+ raise UnexpectedCommandOutput(output)
+
+ col = lambda colname: self.__get_table_col(colname, headers, fields)
+ id = col('ID')
+
+ table[RouterId(id)] = router = RouterTableEntry({
+ 'id': RouterId(id),
+ 'rloc16': Rloc16(col('RLOC16'), 16),
+ 'next_hop': int(col('Next Hop')),
+ 'path_cost': int(col('Path Cost')),
+ 'lq_in': int(col('LQ In')),
+ 'lq_out': int(col('LQ Out')),
+ 'age': int(col('Age')),
+ 'extaddr': col('Extended MAC'),
+ })
+
+ if 'Link' in headers:
+ router['link'] = int(col('Link'))
+ else:
+ # support older version of OT which does not output `Link` field
+ router['link'] = self.get_router_info(router['id'], silent=True)['link']
+
+ return table
+
+ def get_router_info(self, id: int, silent: bool = False) -> RouterTableEntry:
+ cmd = f'router {id}'
+ info = {}
+ output = self.execute_command(cmd, silent=silent)
+ items = [line.strip().split(': ') for line in output]
+
+ headers = [h for h, _ in items]
+ fields = [f for _, f in items]
+ col = lambda colname: self.__get_table_col(colname, headers, fields)
+
+ return RouterTableEntry({
+ 'id': RouterId(id),
+ 'rloc16': Rloc16(col('Rloc'), 16),
+ 'alloc': int(col('Alloc')),
+ 'next_hop': int(col('Next Hop'), 16) >> 10, # convert RLOC16 to Router ID
+ 'link': int(col('Link')),
+ })
+
+ #
+ # Router utilities: Child management
+ #
+
+ def get_child_table(self) -> Dict[ChildId, Dict[str, Any]]:
+ """Get the table of attached children."""
+ output = self.execute_command('child table')
+ if len(output) < 2:
+ raise UnexpectedCommandOutput(output)
+
+ #
+ # Example output:
+ # | ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt| Extended MAC |
+ # +-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+------------------+
+ # | 1 | 0xc801 | 240 | 24 | 3 | 131 |1|0|0| 3| 0 | 0 | 4ecede68435358ac |
+ # | 2 | 0xc802 | 240 | 2 | 3 | 131 |0|0|0| 3| 1 | 0 | a672a601d2ce37d8 |
+ # Done
+ #
+
+ headers = self.__split_table_row(output[0])
+
+ table = {}
+ for line in output[2:]:
+ line = line.strip()
+ if not line:
+ continue
+
+ fields = self.__split_table_row(line)
+ col = lambda colname: self.__get_table_col(colname, headers, fields)
+
+ id = int(col("ID"))
+ r, d, n = int(col("R")), int(col("D")), int(col("N"))
+ mode = DeviceMode(f'{"r" if r else ""}{"d" if d else ""}{"n" if n else ""}')
+
+ child = {
+ 'id': ChildId(id),
+ 'rloc16': Rloc16(col('RLOC16'), 16),
+ 'timeout': int(col('Timeout')),
+ 'age': int(col('Age')),
+ 'lq_in': int(col('LQ In')),
+ 'c_vn': int(col('C_VN')),
+ 'mode': mode,
+ 'extaddr': col('Extended MAC')
+ }
+
+ if 'Ver' in headers:
+ child['ver'] = int(col('Ver'))
+
+ if 'CSL' in headers:
+ child['csl'] = bool(int(col('CSL')))
+
+ if 'QMsgCnt' in headers:
+ child['qmsgcnt'] = int(col('QMsgCnt'))
+
+ table[ChildId(id)] = child
+
+ return table
+
+ def __split_table_row(self, row: str) -> List[str]:
+ if not (row.startswith('|') and row.endswith('|')):
+ raise ValueError(row)
+
+ fields = row.split('|')
+ fields = [x.strip() for x in fields[1:-1]]
+ return fields
+
+ def __get_table_col(self, colname: str, headers: List[str], fields: List[str]) -> str:
+ return fields[headers.index(colname)]
+
+ def get_child_list(self) -> List[ChildId]:
+ """Get attached Child IDs."""
+ line = self.__parse_str(self.execute_command(f'child list'))
+ return [ChildId(id) for id in line.strip().split()]
+
+ def get_child_info(self, child: Union[ChildId, Rloc16]) -> Dict[str, Any]:
+ output = self.execute_command(f'child {child}')
+
+ info = {}
+
+ for line in output:
+ k, v = line.split(': ')
+ if k == 'Child ID':
+ info['id'] = int(v)
+ elif k == 'Rloc':
+ info['rloc16'] = int(v, 16)
+ elif k == 'Ext Addr':
+ info['extaddr'] = v
+ elif k == 'Mode':
+ info['mode'] = DeviceMode(v)
+ elif k == 'Net Data':
+ info['c_vn'] = int(v)
+ elif k == 'Timeout':
+ info['timeout'] = int(v)
+ elif k == 'Age':
+ info['age'] = int(v)
+ elif k == 'Link Quality In':
+ info['lq_in'] = int(v)
+ elif k == 'RSSI':
+ info['rssi'] = int(v)
+ else:
+ self.__logger and self.__logger.warning("Child info %s: %s ignored", k, v)
+
+ return info
+
+ def get_child_ipaddrs(self) -> Dict[Rloc16, List[Ip6Addr]]:
+ """Get the list of IP addresses stored for MTD children.
+
+ Note: Each MTD child might has multiple IP addresses.
+ """
+ output = self.execute_command('childip')
+
+ ipaddrs = {}
+
+ for line in output:
+ rloc16, ip = line.split(': ')
+ rloc16 = Rloc16(rloc16, 16)
+ ipaddrs.setdefault(rloc16, []).append(Ip6Addr(ip.strip()))
+
+ return ipaddrs
+
+ #
+ # Child configurations
+ #
+
+ def get_max_children(self) -> int:
+ """Get the Thread maximum number of allowed children."""
+ return self.__parse_int(self.execute_command('childmax'))
+
+ def set_max_children(self, val: int):
+ """Set the Thread maximum number of allowed children."""
+ self.execute_command(f'childmax {val}')
+
+ def get_child_ip_max(self) -> int:
+ """Get the maximum number of IP addresses that each MTD child may register with this device as parent."""
+ return self.__parse_int(self.execute_command('childip max'))
+
+ def set_child_ip_max(self, val: int):
+ """Get the maximum number of IP addresses that each MTD child may register with this device as parent."""
+ self.execute_command(f'childip max {val}')
+
+ def get_child_timeout(self):
+ """Get the Thread Child Timeout value."""
+ return self.__parse_int(self.execute_command('childtimeout'))
+
+ def set_child_timeout(self, timeout):
+ """Set the Thread Child Timeout value."""
+ self.execute_command('childtimeout %d' % timeout)
+
+ def get_child_supervision_interval(self) -> int:
+ """Get the Child Supervision Check Timeout value."""
+ return self.__parse_int(self.execute_command('childsupervision interval'))
+
+ def set_child_supervision_interval(self, val: int):
+ """Set the Child Supervision Interval value.
+ This command can only be used with FTD devices.
+ """
+ self.execute_command(f'childsupervision interval {val}')
+
+ def get_child_supervision_check_timeout(self) -> int:
+ """Get the Child Supervision Check Timeout value."""
+ return self.__parse_int(self.execute_command('childsupervision checktimeout'))
+
+ def set_child_supervision_check_timeout(self, val: int):
+ """Set the Child Supervision Check Timeout value."""
+ self.execute_command(f'childsupervision checktimeout {val}')
+
+ #
+ # Neighbor management
+ #
+
+ def get_neighbor_list(self) -> List[Rloc16]:
+ """Get a list of RLOC16 of neighbors"""
+ line = self.__parse_str(self.execute_command('neighbor list')).strip()
+ return [Rloc16(id, 16) for id in line.split()]
+
+ def get_neighbor_table(self) -> Dict[Rloc16, Dict[str, Any]]:
+ output = self.execute_command('neighbor table')
+ if len(output) < 2:
+ raise UnexpectedCommandOutput(output)
+
+ #
+ # Example output:
+ #
+ # | Role | RLOC16 | Age | Avg RSSI | Last RSSI |R|D|N| Extended MAC |
+ # +------+--------+-----+----------+-----------+-+-+-+------------------+
+ # | C | 0xcc01 | 96 | -46 | -46 |1|1|1| 1eb9ba8a6522636b |
+ # | R | 0xc800 | 2 | -29 | -29 |1|1|1| 9a91556102c39ddb |
+ # | R | 0xf000 | 3 | -28 | -28 |1|1|1| 0ad7ed6beaa6016d |
+ # Done
+ #
+
+ headers = self.__split_table_row(output[0])
+
+ table = {}
+ for line in output[2:]:
+ line = line.strip()
+ if not line:
+ continue
+
+ fields = self.__split_table_row(line)
+ col = lambda colname: self.__get_table_col(colname, headers, fields)
+
+ role = col('Role')
+ is_router = role == 'R'
+ r, d, n = int(col('R')), int(col('D')), int(col('N'))
+ mode = DeviceMode(f'{"r" if r else ""}{"d" if d else ""}{"n" if n else ""}')
+
+ rloc16 = Rloc16(col('RLOC16'), 16)
+
+ table[rloc16] = {
+ 'is_router': is_router,
+ 'rloc16': rloc16,
+ 'age': int(col('Age')),
+ 'avg_rssi': int(col('Avg RSSI')),
+ 'last_rssi': int(col('Last RSSI')),
+ 'mode': mode,
+ 'extaddr': col('Extended MAC'),
+ }
+
+ return table
+
+ #
+ # SED/SSED configuration
+ #
+
+ def get_poll_period(self) -> int:
+ """Get the customized data poll period of sleepy end device (milliseconds).
+ Only for Reference Device."""
+ return self.__parse_int(self.execute_command('pollperiod'))
+
+ def set_poll_period(self, poll_period: int):
+ """Set the customized data poll period (in milliseconds) for sleepy end device.
+
+ Only for Reference Device."""
+ self.execute_command(f'pollperiod {poll_period}')
+
+ # TODO: csl
+ # TODO: csl channel <channel>
+ # TODO: csl period <period>
+ # TODO: csl timeout <timeout>
+
+ _CSL_PERIOD_PATTERN = re.compile(r'(\d+)\(in units of 10 symbols\), \d+ms')
+ _CSL_TIMEOUT_PATTERN = re.compile(r'(\d+)s')
+
+ def get_csl_config(self) -> Dict[str, int]:
+ """Get the CSL configuration."""
+ output = self.execute_command('csl')
+
+ cfg = {}
+ for line in output:
+ k, v = line.split(': ')
+ if k == 'Channel':
+ cfg['channel'] = int(v)
+ elif k == 'Timeout':
+ cfg['timeout'] = int(OTCI._CSL_TIMEOUT_PATTERN.match(v).group(1))
+ elif k == 'Period':
+ cfg['period'] = int(OTCI._CSL_PERIOD_PATTERN.match(v).group(1))
+ else:
+ logging.warning("Ignore unknown CSL parameter: %s: %s", k, v)
+
+ return cfg
+
+ def config_csl(self, channel: int = None, period: int = None, timeout: int = None):
+ """Configure CSL parameters.
+
+ :param channel: Set CSL channel.
+ :param period: Set CSL period in units of 10 symbols. Disable CSL by setting this parameter to 0.
+ :param timeout: Set the CSL timeout in seconds.
+ """
+
+ if channel is None and period is None and timeout is None:
+ raise InvalidArgumentsError("Please specify at least 1 parameter to configure.")
+
+ if channel is not None:
+ self.execute_command(f'csl channel {channel}')
+
+ if period is not None:
+ self.execute_command(f'csl period {period}')
+
+ if timeout is not None:
+ self.execute_command(f'csl timeout {timeout}')
+
+ #
+ # Leader utilities
+ #
+
+ def get_context_id_reuse_delay(self) -> int:
+ """Get the CONTEXT_ID_REUSE_DELAY value."""
+ return self.__parse_int(self.execute_command('contextreusedelay'))
+
+ def set_context_id_reuse_delay(self, val: int):
+ """Set the CONTEXT_ID_REUSE_DELAY value."""
+ self.execute_command(f'contextreusedelay {val}')
+
+ def release_router_id(self, routerid: int):
+ """Release a Router ID that has been allocated by the device in the Leader role."""
+ self.execute_command(f'releaserouterid {routerid}')
+
+ # Time Sync utilities
+ # TODO: networktime
+ # TODO: networktime <timesyncperiod> <xtalthreshold>
+ # TODO: delaytimermin
+ # TODO: delaytimermin <delaytimermin>
+
+ #
+ # Commissioniner operations
+ #
+
+ def commissioner_start(self):
+ """Start the Commissioner role."""
+ self.execute_command('commissioner start')
+
+ def commissioner_stop(self):
+ """Stop the Commissioner role."""
+ self.execute_command('commissioner stop')
+
+ def get_commissioiner_state(self) -> str:
+ """Get current Commissioner state (active or petitioning or disabled)."""
+ return self.__parse_str(self.execute_command('commissioner state'))
+
+ def get_commissioner_session_id(self) -> int:
+ """Get current commissioner session id."""
+ return self.__parse_int(self.execute_command('commissioner sessionid'))
+
+ def commissioner_add_joiner(self, pskd, eui64=None, discerner=None, timeout=None):
+ """Add a Joiner entry.
+
+ :param pskd: Pre-Shared Key for the Joiner.
+ :param eui64: The IEEE EUI-64 of the Joiner or '*' to match any Joiner
+ :param discerner: The Joiner discerner in format number/length.
+ :param timeout: Joiner timeout in seconds.
+ """
+ if (eui64 is not None) == (discerner is not None):
+ raise InvalidArgumentsError("Please specify eui64 or discerner, but not both.")
+
+ if eui64 is not None and eui64 != '*':
+ self.__validate_extaddr(eui64)
+
+ cmd = f'commissioner joiner add {eui64 or discerner} {pskd}'
+
+ if timeout is not None:
+ cmd += f' {timeout}'
+
+ self.execute_command(cmd)
+
+ def commissioner_remove_jointer(self, eui64=None, discerner=None):
+ if (eui64 is not None) == (discerner is not None):
+ raise InvalidArgumentsError("Please specify eui64 or discerner, but not both.")
+
+ if eui64 is not None and eui64 != '*':
+ self.__validate_extaddr(eui64)
+
+ self.execute_command(f'commissioner joiner remove {eui64 or discerner}')
+
+ def set_commissioner_provisioning_url(self, url: str):
+ self.execute_command(f'commissioner provisioningurl {url}')
+
+ # TODO: commissioner announce
+ # TODO: commissioner energy
+ # TODO: commissioner mgmtget
+ # TODO: commissioner mgmtset
+ # TODO: commissioner panid
+
+ #
+ # Joiner operations
+ #
+ def joiner_start(self, psk: str, provisioning_url: str = None):
+ """Start the Joiner."""
+ cmd = f'joiner start {psk}'
+ if provisioning_url is not None:
+ cmd += f' {provisioning_url}'
+
+ self.execute_command(cmd)
+
+ def joiner_stop(self):
+ """Stop the Joiner role."""
+ self.execute_command('joiner stop')
+
+ def get_joiner_id(self) -> str:
+ """Get the Joiner ID."""
+ return self.__parse_joiner_id(self.execute_command('joiner id'))
+
+ def get_joiner_port(self) -> int:
+ """Get the Joiner port."""
+ return self.__parse_int(self.execute_command(f'joinerport'))
+
+ def set_joiner_port(self, port: int):
+ """Set the Joiner port."""
+ self.execute_command(f'joinerport {port}')
+
+ # TODO: joiner discerner
+
+ #
+ # Network Data utilities
+ #
+ def get_local_prefixes(self) -> List[Tuple[Ip6Prefix, str, str, Rloc16]]:
+ """Get prefixes from local Network Data."""
+ output = self.execute_command('prefix')
+ return self.__parse_prefixes(output)
+
+ def __parse_prefixes(self, output: List[str]) -> List[Tuple[Ip6Prefix, str, str, Rloc16]]:
+ prefixes = []
+
+ for line in output:
+ if line.startswith('- '):
+ line = line[2:]
+
+ prefix, flags, prf, rloc16 = line.split()[:4]
+ prefixes.append((Ip6Prefix(prefix), flags, prf, Rloc16(rloc16, 16)))
+
+ return prefixes
+
+ def add_prefix(self, prefix: str, flags='paosr', prf='med'):
+ """Add a valid prefix to the Network Data."""
+ self.execute_command(f'prefix add {prefix} {flags} {prf}')
+
+ def remove_prefix(self, prefix: str):
+ """Invalidate a prefix in the Network Data."""
+ self.execute_command(f'prefix remove {prefix}')
+
+ def register_network_data(self):
+ self.execute_command('netdata register')
+
+ def get_network_data(self) -> Dict[str, List]:
+ output = self.execute_command('netdata show')
+
+ netdata = {}
+ if output.pop(0) != 'Prefixes:':
+ raise UnexpectedCommandOutput(output)
+
+ prefixes_output = []
+ while True:
+ line = output.pop(0)
+ if line == 'Routes:':
+ break
+ else:
+ prefixes_output.append(line)
+
+ netdata['prefixes'] = self.__parse_prefixes(prefixes_output)
+
+ print(prefixes_output, output)
+ routes_output = []
+ while True:
+ line = output.pop(0)
+ if line == 'Services:':
+ break
+ else:
+ routes_output.append(line)
+
+ netdata['routes'] = self.__parse_routes(routes_output)
+ netdata['services'] = self.__parse_services(output)
+
+ return netdata
+
+ def get_prefixes(self) -> List[Tuple[Ip6Prefix, str, str, Rloc16]]:
+ """Get network prefixes from Thread Network Data."""
+ network_data = self.get_network_data()
+ return network_data['prefixes']
+
+ def get_routes(self) -> List[Tuple[str, bool, str, Rloc16]]:
+ """Get routes from Thread Network Data."""
+ network_data = self.get_network_data()
+ return network_data['routes']
+
+ def get_services(self) -> List[Tuple[int, bytes, bytes, bool, Rloc16]]:
+ """Get services from Thread Network Data"""
+ network_data = self.get_network_data()
+ return network_data['services']
+
+ def __parse_services(self, output: List[str]) -> List[Tuple[int, bytes, bytes, bool, Rloc16]]:
+ services = []
+ for line in output:
+ line = line.split()
+
+ enterprise_number, service_data, server_data = line[:3]
+ if line[3] == 's':
+ stable, rloc16 = True, line[4]
+ else:
+ stable, rloc16 = False, line[3]
+
+ enterprise_number = int(enterprise_number)
+ service_data = self.__hex_to_bytes(service_data)
+ server_data = self.__hex_to_bytes(server_data)
+ rloc16 = Rloc16(rloc16, 16)
+
+ services.append((enterprise_number, service_data, server_data, stable, rloc16))
+
+ return services
+
+ def get_network_data_bytes(self) -> bytes:
+ """Get the raw Network Data."""
+ hexstr = self.__parse_str(self.execute_command('netdata show -x'))
+ return bytes(int(hexstr[i:i + 2], 16) for i in range(0, len(hexstr), 2))
+
+ def get_local_routes(self) -> List[Tuple[str, bool, str, Rloc16]]:
+ """Get routes from local Network Data."""
+ return self.__parse_routes(self.execute_command('route'))
+
+ def __parse_routes(self, output: List[str]) -> List[Tuple[str, bool, str, Rloc16]]:
+ routes = []
+ for line in output:
+ line = line.split()
+ print(line)
+ if line[1] == 's':
+ prefix, _, prf, rloc16 = line
+ stable = True
+ else:
+ prefix, prf, rloc16 = line
+ stable = False
+
+ rloc16 = Rloc16(rloc16, 16)
+ routes.append((prefix, stable, prf, rloc16))
+
+ return routes
+
+ def add_route(self, prefix: str, stable=True, prf='med'):
+ """Add a valid external route to the Network Data."""
+ cmd = f'route add {prefix}'
+ if stable:
+ cmd += ' s'
+
+ cmd += f' {prf}'
+ self.execute_command(cmd)
+
+ def remove_route(self, prefix: str):
+ """Invalidate a external route in the Network Data."""
+ self.execute_command(f'route remove {prefix}')
+
+ def add_service(self, enterprise_number: int, service_data: Union[str, bytes], server_data: Union[str, bytes]):
+ """Add service to the Network Data.
+
+ enterpriseNumber: IANA enterprise number
+ serviceData: hex-encoded binary service data
+ serverData: hex-encoded binary server data
+ """
+ service_data = self.__validate_hex_or_bytes(service_data)
+ server_data = self.__validate_hex_or_bytes(server_data)
+ self.execute_command(f'service add {enterprise_number} {service_data} {server_data}')
+
+ def remove_service(self, enterprise_number, service_data):
+ """Remove service from Network Data.
+
+ enterpriseNumber: IANA enterprise number
+ serviceData: hext-encoded binary service data
+ """
+ service_data = self.__validate_hex_or_bytes(service_data)
+ self.execute_command(f'service remove {enterprise_number} {service_data}')
+
+ #
+ # Dataset management
+ #
+
+ def dataset_init_buffer(self, get_active_dataset=False, get_pending_dataset=False):
+ """Initialize operational dataset buffer."""
+ if get_active_dataset and get_pending_dataset:
+ raise InvalidArgumentsError("Can not specify both `get_active_dataset` and `get_pending_dataset`.")
+
+ if get_active_dataset:
+ self.execute_command(f'dataset init active')
+ elif get_pending_dataset:
+ self.execute_command(f'dataset init pending')
+ else:
+ self.execute_command(f'dataset init new')
+
+ def dataset_commit_buffer(self, dataset: str):
+ if dataset in ('active', 'pending'):
+ cmd = f'dataset commit {dataset}'
+ else:
+ raise InvalidArgumentsError(f'Unkonwn dataset: {dataset}')
+
+ self.execute_command(cmd)
+
+ def dataset_clear_buffer(self):
+ """Reset operational dataset buffer."""
+ self.execute_command('dataset clear')
+
+ def get_dataset(self, dataset: str = 'buffer'):
+ if dataset in ('active', 'pending'):
+ cmd = f'dataset {dataset}'
+ elif dataset == 'buffer':
+ cmd = 'dataset'
+ else:
+ raise InvalidArgumentsError(f'Unkonwn dataset: {dataset}')
+
+ output = self.execute_command(cmd)
+ return self.__parse_dataset(output)
+
+ def __parse_dataset(self, output: List[str]) -> Dict[str, Any]:
+ # Example output:
+ #
+ # Active Timestamp: 1
+ # Channel: 22
+ # Channel Mask: 0x07fff800
+ # Ext PAN ID: 5c93ae980ff22d35
+ # Mesh Local Prefix: fdc7:55fe:6363:bd01::/64
+ # Master Key: d1a8348d59fb1fac1d6c4f95007d487a
+ # Network Name: OpenThread-7caa
+ # PAN ID: 0x7caa
+ # PSKc: 167d89fd169e439ca0b8266de248090f
+ # Security Policy: 0, onrcb
+
+ dataset = {}
+
+ for line in output:
+ line = line.split(': ')
+ key, val = line[0], ': '.join(line[1:])
+
+ if key == 'Active Timestamp':
+ dataset['active_timestamp'] = int(val)
+ elif key == 'Channel':
+ dataset['channel'] = int(val)
+ elif key == 'Channel Mask':
+ dataset['channel_mask'] = int(val, 16)
+ elif key == 'Ext PAN ID':
+ dataset['extpanid'] = val
+ elif key == 'Mesh Local Prefix':
+ dataset['mesh_local_prefix'] = val
+ elif key == 'Master Key':
+ dataset['masterkey'] = val
+ elif key == 'Network Name':
+ dataset['network_name'] = val
+ elif key == 'PAN ID':
+ dataset['panid'] = int(val, 16)
+ elif key == 'PSKc':
+ dataset['pskc'] = val
+ elif key == 'Security Policy':
+ rotation_time, flags = val.split(', ')
+ rotation_time = int(rotation_time)
+ dataset['security_policy'] = SecurityPolicy(rotation_time, flags)
+ else:
+ raise UnexpectedCommandOutput(output)
+
+ return dataset
+
+ def get_dataset_bytes(self, dataset: str) -> bytes:
+ if dataset in ('active', 'pending'):
+ cmd = f'dataset {dataset} -x'
+ else:
+ raise InvalidArgumentsError(f'Unkonwn dataset: {dataset}')
+
+ hexstr = self.__parse_str(self.execute_command(cmd))
+ return self.__hex_to_bytes(hexstr)
+
+ def dataset_set_buffer(self,
+ active_timestamp: int = None,
+ channel: int = None,
+ channel_mask: int = None,
+ extpanid: str = None,
+ mesh_local_prefix: str = None,
+ master_key: str = None,
+ network_name: str = None,
+ panid: int = None,
+ pskc: str = None,
+ security_policy: tuple = None,
+ pending_timestamp: int = None):
+ if active_timestamp is not None:
+ self.execute_command(f'dataset activetimestamp {active_timestamp}')
+
+ if channel is not None:
+ self.execute_command(f'dataset channel {channel}')
+
+ if channel_mask is not None:
+ self.execute_command(f'dataset channelmask {channel_mask}')
+
+ if extpanid is not None:
+ self.execute_command(f'dataset extpanid {extpanid}')
+
+ if mesh_local_prefix is not None:
+ self.execute_command(f'dataset meshlocalprefix {mesh_local_prefix}')
+
+ if master_key is not None:
+ self.execute_command(f'dataset masterkey {master_key}')
+
+ if network_name is not None:
+ self.execute_command(f'dataset networkname {self.__escape_escapable(network_name)}')
+
+ if panid is not None:
+ self.execute_command(f'dataset panid {panid}')
+
+ if pskc is not None:
+ self.execute_command(f'dataset pskc {pskc}')
+
+ if security_policy is not None:
+ rotation_time, flags = security_policy
+ self.execute_command(f'dataset securitypolicy {rotation_time} {flags}')
+
+ if pending_timestamp is not None:
+ self.execute_command(f'dataset pendingtimestamp {pending_timestamp}')
+
+ # TODO: dataset mgmtgetcommand
+ # TODO: dataset mgmtsetcommand
+ # TODO: dataset set <active|pending> <dataset>
+
+ #
+ # Allowlist management
+ #
+
+ def enable_allowlist(self):
+ self.execute_command(f'macfilter addr {self.__detect_allowlist_cmd()}')
+
+ def disable_allowlist(self):
+ self.execute_command('macfilter addr disable')
+
+ def add_allowlist(self, addr: str, rssi: int = None):
+ cmd = f'macfilter addr add {addr}'
+
+ if rssi is not None:
+ cmd += f' {rssi}'
+
+ self.execute_command(cmd)
+
+ def remove_allowlist(self, addr: str):
+ self.execute_command(f'macfilter addr remove {addr}')
+
+ def clear_allowlist(self):
+ self.execute_command('macfilter addr clear')
+
+ def set_allowlist(self, allowlist: Collection[Union[str, Tuple[str, int]]]):
+ self.clear_allowlist()
+
+ if allowlist is None:
+ self.disable_allowlist()
+ else:
+ self.enable_allowlist()
+ for item in allowlist:
+ if isinstance(item, str):
+ self.add_allowlist(item)
+ else:
+ addr, rssi = item[0], item[1]
+ self.add_allowlist(addr, rssi)
+
+ # TODO: denylist
+ # TODO: macfilter rss
+ # TODO: macfilter rss add <extaddr> <rss>
+ # TODO: macfilter rss add-lqi <extaddr> <lqi>
+ # TODO: macfilter rss remove <extaddr>
+ # TODO: macfilter rss clear
+
+ def __detect_allowlist_cmd(self):
+ if self.api_version >= 28:
+ return 'allowlist'
+ else:
+ return '\x77\x68\x69\x74\x65\x6c\x69\x73\x74'
+
+ #
+ # Unicast Addresses management
+ #
+ def add_ipaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Add an IPv6 address to the Thread interface."""
+ self.execute_command(f'ipaddr add {ip}')
+
+ def del_ipaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Delete an IPv6 address from the Thread interface."""
+ self.execute_command(f'ipaddr del {ip}')
+
+ def get_ipaddrs(self) -> Tuple[Ip6Addr]:
+ """Get all IPv6 addresses assigned to the Thread interface."""
+ return tuple(map(Ip6Addr, self.execute_command('ipaddr')))
+
+ def has_ipaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Check if a Ip6 address was added to the Thread interface."""
+ return ip in self.get_ipaddrs()
+
+ def get_ipaddr_mleid(self) -> Ip6Addr:
+ """Get Thread Mesh Local EID address."""
+ return self.__parse_ip6addr(self.execute_command('ipaddr mleid'))
+
+ def get_ipaddr_linklocal(self) -> Ip6Addr:
+ """Get Thread link-local IPv6 address."""
+ return self.__parse_ip6addr(self.execute_command('ipaddr linklocal'))
+
+ def get_ipaddr_rloc(self) -> Ip6Addr:
+ """Get Thread Routing Locator (RLOC) address."""
+ return self.__parse_ip6addr(self.execute_command('ipaddr rloc'))
+
+ #
+ # Multicast Addresses management
+ #
+
+ def add_ipmaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Subscribe the Thread interface to the IPv6 multicast address."""
+ self.execute_command(f'ipmaddr add {ip}')
+
+ def del_ipmaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Unsubscribe the Thread interface to the IPv6 multicast address."""
+ self.execute_command(f'ipmaddr del {ip}')
+
+ def get_ipmaddrs(self) -> Tuple[Ip6Addr]:
+ """Get all IPv6 multicast addresses subscribed to the Thread interface."""
+ return tuple(map(Ip6Addr, self.execute_command('ipmaddr')))
+
+ def has_ipmaddr(self, ip: Union[str, ipaddress.IPv6Address]):
+ """Check if a Ip6 multicast address was subscribed by the Thread interface."""
+ return ip in self.get_ipmaddrs()
+
+ def get_ipmaddr_promiscuous(self) -> bool:
+ """Get multicast promiscuous mode."""
+ return self.__parse_Enabled_or_Disabled(self.execute_command("ipmaddr promiscuous"))
+
+ def enable_ipmaddr_promiscuous(self):
+ """Enable multicast promiscuous mode."""
+ self.execute_command('ipmaddr promiscuous enable')
+
+ def disable_ipmaddr_promiscuous(self):
+ """Disable multicast promiscuous mode."""
+ self.execute_command('ipmaddr promiscuous disable')
+
+ #
+ # Backbone Router Utilities
+ #
+
+ # TODO: bbr mgmt ...
+
+ def enable_backbone_router(self):
+ """Enable Backbone Router Service for Thread 1.2 FTD.
+
+ SRV_DATA.ntf would be triggerred for attached device if there is no Backbone Router Service in Thread Network Data.
+ """
+ self.execute_command('bbr enable')
+
+ def disable_backbone_router(self):
+ """Disable Backbone Router Service for Thread 1.2 FTD.
+
+ SRV_DATA.ntf would be triggerred if Backbone Router is Primary state.
+ """
+ self.execute_command('bbr disable')
+
+ def get_backbone_router_state(self) -> str:
+ """Get local Backbone state (Disabled or Primary or Secondary) for Thread 1.2 FTD."""
+ self.__parse_str(self.execute_command('bbr state'))
+
+ def get_primary_backbone_router_info(self) -> Optional[dict]:
+ """Show current Primary Backbone Router information for Thread 1.2 device."""
+ output = self.execute_command('bbr')
+
+ if len(output) < 1:
+ raise UnexpectedCommandOutput(output)
+
+ line = output[0]
+ if line == 'BBR Primary: None':
+ return None
+
+ if line != 'BBR Primary:':
+ raise UnexpectedCommandOutput(output)
+
+ # Example output:
+ # BBR Primary:
+ # server16: 0xE400
+ # seqno: 10
+ # delay: 120 secs
+ # timeout: 300 secs
+
+ dataset = {}
+
+ for line in output[1:]:
+ key, val = line.split(':')
+ key, val = key.strip(), val.strip()
+ if key == 'server16':
+ dataset[key] = int(val, 16)
+ elif key == 'seqno':
+ dataset[key] = int(val)
+ elif key == 'delay':
+ if not val.endswith(' secs'):
+ raise UnexpectedCommandOutput(output)
+ dataset[key] = int(val.split()[0])
+ elif key == 'timeout':
+ if not val.endswith(' secs'):
+ raise UnexpectedCommandOutput(output)
+ dataset[key] = int(val.split()[0])
+ else:
+ raise UnexpectedCommandOutput(output)
+
+ return dataset
+
+ def register_backbone_router_dataset(self):
+ """Register Backbone Router Service for Thread 1.2 FTD.
+
+ SRV_DATA.ntf would be triggerred for attached device.
+ """
+ self.execute_command('bbr register')
+
+ def get_backbone_router_config(self) -> dict:
+ """Show local Backbone Router configuration for Thread 1.2 FTD."""
+ output = self.execute_command('bbr config')
+ # Example output:
+ # seqno: 10
+ # delay: 120 secs
+ # timeout: 300 secs
+
+ config = {}
+
+ for line in output:
+ key, val = line.split(':')
+ key, val = key.strip(), val.strip()
+ if key == 'seqno':
+ config[key] = int(val)
+ elif key in ('delay', 'timeout'):
+ if not line.endswith(' secs'):
+ raise UnexpectedCommandOutput(output)
+ config[key] = int(val.split()[0])
+ else:
+ raise UnexpectedCommandOutput(output)
+
+ return config
+
+ def set_backbone_router_config(self, seqno: int = None, delay: int = None, timeout: int = None):
+ """Configure local Backbone Router configuration for Thread 1.2 FTD.
+
+ Call register_backbone_router_dataset() to explicitly register Backbone Router service to Leader for Secondary Backbone Router.
+ """
+ if seqno is None and delay is None and timeout is None:
+ raise InvalidArgumentsError("Please specify seqno or delay or timeout")
+
+ cmd = 'bbr config'
+ if seqno is not None:
+ cmd += f' seqno {seqno}'
+
+ if delay is not None:
+ cmd += f' delay {delay}'
+
+ if timeout is not None:
+ cmd += f' timeout {timeout}'
+
+ self.execute_command(cmd)
+
+ def get_backbone_router_jitter(self) -> int:
+ """Get jitter (in seconds) for Backbone Router registration for Thread 1.2 FTD."""
+ return self.__parse_int(self.execute_command('bbr jitter'))
+
+ def set_backbone_router_jitter(self, val: int):
+ """Set jitter (in seconds) for Backbone Router registration for Thread 1.2 FTD."""
+ self.execute_command(f'bbr jitter {val}')
+
+ #
+ # Thread 1.2 and DUA/MLR utilities
+ #
+
+ def get_domain_name(self) -> str:
+ """Get the Thread Domain Name for Thread 1.2 device."""
+ return self.__parse_str(self.execute_command('domainname'))
+
+ def set_domain_name(self, name: str):
+ """Set the Thread Domain Name for Thread 1.2 device."""
+ self.execute_command('domainname %s' % self.__escape_escapable(name))
+
+ # TODO: dua iid
+ # TODO: dua iid <iid>
+ # TODO: dua iid clear
+ # TODO: mlr reg <ipaddr> ... [timeout]
+
+ #
+ # Link metrics management
+ #
+ # TODO: linkmetrics mgmt <ipaddr> forward <seriesid> [ldraX][pqmr]
+ # TODO: linkmetrics probe <ipaddr> <seriesid> <length>
+ # TODO: linkmetrics query <ipaddr> single [pqmr]
+ # TODO: linkmetrics query <ipaddr> forward <seriesid>
+ # TODO: linkquality <extaddr>
+ # TODO: linkquality <extaddr> <linkquality>
+ #
+
+ #
+ # Logging
+ #
+
+ def get_log_level(self) -> int:
+ """Get the log level."""
+ return self.__parse_int(self.execute_command('log level'))
+
+ def set_log_level(self, level: int):
+ """Set the log level."""
+ self.execute_command(f'log level {level}')
+
+ #
+ # Device performance related information
+ #
+
+ def get_message_buffer_info(self) -> dict:
+ """Get the current message buffer information."""
+ output = self.execute_command('bufferinfo')
+
+ info = {}
+
+ def _parse_val(val):
+ vals = val.split()
+ return int(vals[0]) if len(vals) == 1 else tuple(map(int, vals))
+
+ for line in output:
+ key, val = line.split(':')
+ key, val = key.strip(), val.strip()
+ info[key.replace(' ', '_')] = _parse_val(val)
+
+ return info
+
+ @constant_property
+ def counter_names(self):
+ """Get the supported counter names."""
+ return tuple(self.execute_command('counters'))
+
+ def get_counter(self, name: str) -> Counter:
+ """Reset the counter value."""
+ output = self.execute_command(f'counters {name}')
+
+ counter = Counter()
+ for line in output:
+ k, v = line.strip().split(': ')
+ counter[k] = int(v)
+
+ return counter
+
+ def reset_counter(self, name: str):
+ """Reset the counter value."""
+ self.execute_command(f'counters {name} reset')
+
+ def get_eidcache(self) -> Dict[Ip6Addr, Rloc16]:
+ """Get the EID-to-RLOC cache entries."""
+ output = self.execute_command('eidcache')
+ cache = {}
+
+ for line in output:
+ ip, rloc16 = line.split()
+
+ cache[Ip6Addr(ip)] = Rloc16(rloc16, 16)
+
+ return cache
+
+ #
+ # UDP utilities
+ #
+
+ def udp_open(self):
+ """Opens the example socket."""
+ self.execute_command('udp open')
+
+ def udp_close(self):
+ """Opens the example socket."""
+ self.execute_command('udp close')
+
+ def udp_bind(self, ip: str, port: int):
+ """Assigns a name (i.e. IPv6 address and port) to the example socket.
+
+ :param ip: the IPv6 address or the unspecified IPv6 address (::).
+ :param port: the UDP port
+ """
+ self.execute_command(f'udp bind {ip} {port}')
+
+ def udp_connect(self, ip: str, port: int):
+ """Specifies the peer with which the socket is to be associated.
+
+ ip: the peer's IPv6 address.
+ port: the peer's UDP port.
+ """
+ self.execute_command(f'udp connect {ip} {port}')
+
+ def udp_send(self, ip: str = None, port: int = None, text: str = None, random_bytes: int = None, hex: str = None):
+ """Send a few bytes over UDP.
+
+ ip: the IPv6 destination address.
+ port: the UDP destination port.
+ type: the type of the message: _ -t: text payload in the value, same as without specifying the type. _ -s: autogenerated payload with specified length indicated in the value.
+ * -x: binary data in hexadecimal representation in the value.
+ """
+ if (ip is None) != (port is None):
+ raise InvalidArgumentsError("Please specify both `ip` and `port`.")
+
+ if (text is not None) + (random_bytes is not None) + (hex is not None) != 1:
+ raise InvalidArgumentsError("Please specify `text` or `random_bytes` or `hex`.")
+
+ cmd = 'udp send'
+
+ if ip is not None:
+ cmd += f' {ip} {port}'
+
+ if text is not None:
+ cmd += f' -t {text}'
+ elif random_bytes is not None:
+ cmd += f' -s {random_bytes}'
+ elif hex is not None:
+ self.__validate_hex(hex)
+ cmd += f' -x {hex}'
+
+ self.execute_command(cmd)
+
+ def udp_get_link_security(self) -> bool:
+ """Gets whether the link security is enabled or disabled."""
+ return self.__parse_Enabled_or_Disabled(self.execute_command('udp linksecurity'))
+
+ def udp_enable_link_security(self):
+ """Enable link security."""
+ self.execute_command('udp linksecurity enable')
+
+ def udp_disable_link_security(self):
+ """Disable link security."""
+ self.execute_command('udp linksecurity disable')
+
+ #
+ # CoAP CLI (test) utilities
+ #
+ def coap_start(self):
+ """Starts the application coap service."""
+ self.execute_command('coap start')
+
+ def coap_stop(self):
+ """Stops the application coap service."""
+ self.execute_command('coap stop')
+
+ def coap_get(self, addr: str, uri_path: str, type: str = "con"):
+ cmd = f'coap get {addr} {uri_path} {type}'
+ self.execute_command(cmd)
+
+ def coap_put(self, addr: str, uri_path: str, type: str = "con", payload: str = None):
+ cmd = f'coap put {addr} {uri_path} {type}'
+
+ if payload is not None:
+ cmd += f' {payload}'
+
+ self.execute_command(cmd)
+
+ def coap_post(self, addr: str, uri_path: str, type: str = "con", payload: str = None):
+ cmd = f'coap post {addr} {uri_path} {type}'
+
+ if payload is not None:
+ cmd += f' {payload}'
+
+ self.execute_command(cmd)
+
+ def coap_delete(self, addr: str, uri_path: str, type: str = "con", payload: str = None):
+ cmd = f'coap delete {addr} {uri_path} {type}'
+
+ if payload is not None:
+ cmd += f' {payload}'
+
+ self.execute_command(cmd)
+
+ def coap_get_test_resource_path(self) -> str:
+ """Gets the URI path for the test resource."""
+ return self.__parse_str(self.execute_command('coap resource'))
+
+ def coap_set_test_resource_path(self, path: str):
+ """Sets the URI path for the test resource."""
+ self.execute_command(f'coap resource {path}')
+
+ def coap_test_set_resource_content(self, content: str):
+ """Sets the content sent by the test resource. If a CoAP client is observing the resource, a notification is sent to that client."""
+ self.execute_command(f'coap set {content}')
+
+ # TODO: coap observe <address> <uri-path> [type]
+ # TODO: coap cancel
+ # TODO: coap parameters <type> ["default"|<ack_timeout> <ack_random_factor_numerator> <ack_random_factor_denominator> <max_retransmit>]
+ # TODO: CoAP Secure utilities
+
+ #
+ # Other TODOs
+ #
+ # TODO: netstat
+ # TODO: networkdiagnostic get <addr> <type> ..
+ # TODO: networkdiagnostic reset <addr> <type> ..
+ # TODO: parent
+ # TODO: pskc [-p] <key>|<passphrase>
+ #
+
+ #
+ # Private methods
+ #
+
+ def __parse_str(self, output: List[str]) -> str:
+ if len(output) != 1:
+ raise UnexpectedCommandOutput(output)
+
+ return output[0]
+
+ def __parse_int_list(self, output: List[str]) -> List[int]:
+ line = self.__parse_str(output)
+ return list(map(int, line.strip().split()))
+
+ def __parse_ip6addr(self, output: List[str]) -> Ip6Addr:
+ return Ip6Addr(self.__parse_str(output))
+
+ def __parse_int(self, output: List[str], base=10) -> int:
+ if len(output) != 1:
+ raise UnexpectedCommandOutput(output)
+
+ return int(output[0], base)
+
+ def __parse_master_key(self, output: List[str]) -> str:
+ masterkey = self.__parse_str(output)
+
+ try:
+ self.__validate_master_key(masterkey)
+ except ValueError:
+ raise UnexpectedCommandOutput(output)
+
+ return masterkey
+
+ def __validate_master_key(self, masterkey: str):
+ if len(masterkey) != 32:
+ raise ValueError(masterkey)
+
+ int(masterkey, 16)
+
+ def __parse_hex64b(self, output: List[str]) -> str:
+ extaddr = self.__parse_str(output)
+
+ try:
+ self.__validate_hex64b(extaddr)
+ except ValueError:
+ raise UnexpectedCommandOutput(output)
+
+ return extaddr
+
+ __parse_extaddr = __parse_hex64b
+ __parse_extpanid = __parse_hex64b
+ __parse_eui64 = __parse_hex64b
+ __parse_joiner_id = __parse_hex64b
+
+ def __validate_hex64b(self, extaddr: str):
+ if len(extaddr) != 16:
+ raise ValueError(extaddr)
+
+ self.__validate_hex(extaddr)
+
+ def __validate_hex(self, hexstr: str):
+ if len(hexstr) % 2 != 0:
+ raise ValueError(hexstr)
+
+ for i in range(0, len(hexstr), 2):
+ int(hexstr[i:i + 2], 16)
+
+ __validate_extaddr = __validate_hex64b
+ __validate_extpanid = __validate_hex64b
+
+ def __parse_Enabled_or_Disabled(self, output: List[str]) -> bool:
+ return self.__parse_values(output, Enabled=True, Disabled=False)
+
+ def __parse_values(self, output: List[str], **vals) -> Any:
+ val = self.__parse_str(output)
+ if val not in vals:
+ raise UnexpectedCommandOutput(output)
+
+ return vals[val]
+
+ def __validate_hex_or_bytes(self, data: Union[str, bytes]) -> str:
+ if isinstance(data, bytes):
+ return ''.join('%02x' % c for c in data)
+ else:
+ self.__validate_hex(data)
+ return data
+
+ def __hex_to_bytes(self, hexstr: str) -> bytes:
+ self.__validate_hex(hexstr)
+ return bytes(int(hexstr[i:i + 2], 16) for i in range(0, len(hexstr), 2))
+
+ def __escape_escapable(self, s: str) -> str:
+ """Escape CLI escapable characters in the given string.
+ """
+ escapable_chars = '\\ \t\r\n'
+ for char in escapable_chars:
+ s = s.replace(char, '\\%s' % char)
+ return s
+
+ def __wait_reset(self):
+ # reset would restart the otbr-agent executable. It's risky to send commands after reset too quickly because
+ # it might cause ot-ctl to quit abnormally.
+ # So we sleep for a while after reset.
+ time.sleep(3)
+
+
+def connect_cli_sim(executable: str, nodeid: int, simulator: Optional[Simulator] = None) -> OTCI:
+ cli_handler = connectors.OtCliSim(executable, nodeid, simulator=simulator)
+ cmd_handler = OtCliCommandRunner(cli_handler)
+ return OTCI(cmd_handler)
+
+
+def connect_cli_serial(dev: str, baudrate=115200) -> OTCI:
+ cli_handler = connectors.OtCliSerial(dev, baudrate)
+ cmd_handler = OtCliCommandRunner(cli_handler)
+ return OTCI(cmd_handler)
+
+
+def connect_ncp_sim(executable: str, nodeid: int, simulator: Optional[Simulator] = None) -> OTCI:
+ ncp_handler = connectors.OtNcpSim(executable, nodeid, simulator=simulator)
+ cmd_handler = OtCliCommandRunner(ncp_handler, is_spinel_cli=True)
+ return OTCI(cmd_handler)
+
+
+def connect_otbr_ssh(host: str, port: int = 22, username='pi', password='raspberry'):
+ cmd_handler = OtbrSshCommandRunner(host, port, username, password)
+ return OTCI(cmd_handler)
+
+
+def connect_cmd_handler(cmd_handler: OTCommandHandler) -> OTCI:
+ return OTCI(cmd_handler)
diff --git a/tools/otci/otci/types.py b/tools/otci/otci/types.py
new file mode 100644
index 0000000..f5d39a1
--- /dev/null
+++ b/tools/otci/otci/types.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import ipaddress
+from collections import namedtuple
+
+
+class ChildId(int):
+ """Represents a Child ID."""
+ pass
+
+
+class RouterId(int):
+ """Represents a Router ID."""
+ pass
+
+
+class Rloc16(int):
+ """Represents a RLOC16."""
+
+ def __repr__(self):
+ return '0x%04x' % self
+
+
+class PartitionId(int):
+ """Represents a Thread Network Partition ID."""
+ pass
+
+
+class DeviceMode(str):
+ """Represents a device mode."""
+
+ def __new__(cls, o: str):
+ ins = str.__new__(cls, o)
+
+ if ins != '-':
+ for c in ins:
+ if c not in 'rdn':
+ raise ValueError(o)
+
+ # check for empty mode (SED should use "-")
+ if not ins:
+ raise ValueError(o)
+
+ # check for duplicate chars
+ if len(ins) != len(set(ins)):
+ raise ValueError(o)
+
+ return ins
+
+
+class ThreadState(str):
+ """Represents a Thread state."""
+ _VALID_VALUES = {'disabled', 'detached', 'child', 'router', 'leader'}
+
+ def __new__(cls, o: str):
+ ins = str.__new__(cls, o)
+
+ if ins not in ThreadState._VALID_VALUES:
+ raise ValueError(o)
+
+ return ins
+
+
+class Ip6Addr(ipaddress.IPv6Address):
+ """Represents an IPv6 address."""
+
+ def __eq__(self, other):
+ if isinstance(other, str):
+ other = ipaddress.IPv6Address(other)
+
+ return super().__eq__(other)
+
+ def __repr__(self):
+ return self.compressed
+
+ def __hash__(self):
+ return super().__hash__()
+
+
+class Ip6Prefix(ipaddress.IPv6Network):
+ """Represents an IPv6 prefix."""
+
+ def __eq__(self, other):
+ if isinstance(other, str):
+ other = ipaddress.IPv6Network(other)
+
+ return super().__eq__(other)
+
+ def __repr__(self):
+ return self.compressed
+
+ def __hash__(self):
+ return super().__hash__()
+
+
+SecurityPolicy = namedtuple('SecurityPolicy', ['rotation_time', 'flags'])
+"""Represents a Security Policy configuration."""
+
+
+class RouterTableEntry(dict):
+
+ @property
+ def is_link_established(self):
+ return bool(self['link'])
+
+
+if __name__ == '__main__':
+ assert Ip6Addr('2001:0:0:0:0:0:0:1') == '2001::1'
+ assert repr(Ip6Addr('2001:0:0:0:0:0:0:1')) == '2001::1'
+ assert str(Ip6Addr('2001:0:0:0:0:0:0:1')) == '2001::1'
+ assert Ip6Prefix('2001:0:0:0::/64') == '2001::/64'
+ assert repr(Ip6Prefix('2001:0:0:0::/64')) == '2001::/64'
+ assert str(Ip6Prefix('2001:0:0:0::/64')) == '2001::/64'
diff --git a/tools/otci/otci/utils.py b/tools/otci/otci/utils.py
new file mode 100644
index 0000000..3a52a82
--- /dev/null
+++ b/tools/otci/otci/utils.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import functools
+from typing import Union, Collection, Any, Pattern
+
+
+def match_line(line: str, expect_line: Union[str, Pattern, Collection[Any]]) -> bool:
+ """Checks if a line is expected (matched by one of the given patterns)."""
+ if isinstance(expect_line, Pattern):
+ match = expect_line.match(line)
+ elif isinstance(expect_line, str):
+ match = (line == expect_line)
+ else:
+ match = any(match_line(line, x) for x in expect_line)
+
+ return match
+
+
+def cached(func):
+ """Decorator cached makes the function to cache its result and return it in duplicate calls."""
+ prop_name = '__cached_' + func.__name__
+
+ @functools.wraps(func)
+ def _cached_func(self):
+ try:
+ return getattr(self, prop_name)
+ except AttributeError:
+ val = func(self)
+ setattr(self, prop_name, val)
+ return val
+
+ return _cached_func
+
+
+def constant_property(func):
+ """A constant property is a property that only evaluated once."""
+ return property(cached(func))
diff --git a/tests/scripts/expect/v1_2-rcp.exp b/tools/otci/setup.py
old mode 100755
new mode 100644
similarity index 68%
rename from tests/scripts/expect/v1_2-rcp.exp
rename to tools/otci/setup.py
index 776d880..f3d6868
--- a/tests/scripts/expect/v1_2-rcp.exp
+++ b/tools/otci/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/expect -f
+#!/usr/bin/env python3
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
@@ -26,40 +26,25 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
+import setuptools
-source "tests/scripts/expect/_common.exp"
+with open("README.md", "r") as fh:
+ long_description = fh.read()
-spawn_node 1
-
-send "panid 0xface\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "leader"
-expect "Done"
-
-send "ipaddr mleid\n"
-expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
-set addr $expect_out(1,string)
-expect "Done"
-
-spawn_node 2 mtd
-
-send "panid 0xface\n"
-expect "Done"
-send "mode -\n"
-expect "Done"
-send "csl period 5000\n"
-expect "Done"
-send "ifconfig up\n"
-expect "Done"
-send "thread start\n"
-expect "Done"
-wait_for "state" "child"
-expect "Done"
-send "ping $addr\n"
-expect "16 bytes from $addr: icmp_seq=1"
-
-dispose_all
+setuptools.setup(
+ name="otci-openthread",
+ version="0.0.1",
+ author="The OpenThread Authors",
+ description="OpenThread Controller Interface",
+ long_description=long_description,
+ long_description_content_type="text/markdown",
+ url="https://github.com/openthread/openthread",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: BSD 3-Clause License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+ install_requires=['pySerial', 'paramiko', 'pyspinel'],
+)
diff --git a/tools/otci/tests/test_otci.py b/tools/otci/tests/test_otci.py
new file mode 100644
index 0000000..0a15835
--- /dev/null
+++ b/tools/otci/tests/test_otci.py
@@ -0,0 +1,525 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2020, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+import json
+import logging
+import os
+import subprocess
+import unittest
+
+import otci
+from otci.errors import CommandError
+
+logging.basicConfig(level=logging.INFO)
+
+TEST_CHANNEL = 22
+TEST_NETWORK_NAME = 'OT CI'
+TEST_PANID = 0xeeee
+TEST_MASTERKEY = 'ffeeddccbbaa99887766554433221100'
+
+REAL_DEVICE = int(os.getenv('REAL_DEVICE', '0'))
+
+
+class TestOTCI(unittest.TestCase):
+
+ def testCliRealDevice(self):
+ if not REAL_DEVICE:
+ self.skipTest('not for virtual device')
+
+ if os.getenv('OTBR_SSH'):
+ node = otci.connect_otbr_ssh(os.getenv('OTBR_SSH'))
+ elif os.getenv('OT_CLI_SERIAL'):
+ node = otci.connect_cli_serial(os.getenv('OT_CLI_SERIAL'))
+ else:
+ self.fail("Please set OT_CLI_SERIAL or OTBR_SSH to test the real device.")
+
+ node.factory_reset()
+
+ self._test_otci_single_node(node)
+
+ def testCliSimRealTime(self):
+ if REAL_DEVICE:
+ self.skipTest('not for real device')
+
+ subprocess.check_call('rm -rf tmp/', shell=True)
+ VIRTUAL_TIME = int(os.getenv('VIRTUAL_TIME', "1"))
+
+ import simulator
+
+ if VIRTUAL_TIME:
+ sim = simulator.VirtualTime(use_message_factory=False)
+ else:
+ sim = None
+
+ if os.getenv('OT_CLI'):
+ executable = os.getenv('OT_CLI')
+ connector = otci.connect_cli_sim
+ elif os.getenv('OT_NCP'):
+ executable = os.getenv('OT_NCP')
+ connector = otci.connect_ncp_sim
+ else:
+ self.fail("Please set OT_CLI to test virtual device")
+
+ node1 = connector(executable, 1, simulator=sim)
+ self._test_otci_single_node(node1)
+
+ node1.factory_reset()
+
+ node2 = connector(executable, 2, simulator=sim)
+ node3 = connector(executable, 3, simulator=sim)
+ node4 = connector(executable, 4, simulator=sim)
+
+ self._test_otci_example(node1, node2)
+
+ node1.factory_reset()
+ node2.factory_reset()
+
+ self._test_otci_multi_nodes(node1, node2, node3, node4)
+
+ def _test_otci_single_node(self, leader):
+ logging.info('leader version: %r', leader.version)
+ logging.info('leader thread version: %r', leader.thread_version)
+ logging.info('API version: %r', leader.api_version)
+ logging.info('log level: %r', leader.get_log_level())
+
+ leader.enable_promiscuous()
+ self.assertTrue(leader.get_promiscuous())
+ leader.disable_promiscuous()
+ self.assertFalse(leader.get_promiscuous())
+ try:
+ logging.info("RCP version: %r", leader.get_rcp_version())
+ except CommandError:
+ pass
+
+ self.assertTrue(leader.get_router_eligible())
+ leader.disable_router_eligible()
+ self.assertFalse(leader.get_router_eligible())
+ leader.enable_router_eligible()
+
+ self.assertFalse(leader.get_ifconfig_state())
+ # ifconfig up
+ leader.ifconfig_up()
+ self.assertTrue(leader.get_ifconfig_state())
+
+ logging.info('leader eui64 = %r', leader.get_eui64())
+ logging.info('leader extpanid = %r', leader.get_extpanid())
+ logging.info('leader masterkey = %r', leader.get_master_key())
+
+ extaddr = leader.get_extaddr()
+ self.assertEqual(16, len(extaddr))
+ int(extaddr, 16)
+ new_extaddr = 'aabbccddeeff0011'
+ leader.set_extaddr(new_extaddr)
+ self.assertEqual(new_extaddr, leader.get_extaddr())
+
+ leader.set_network_name(TEST_NETWORK_NAME)
+
+ leader.set_master_key(TEST_MASTERKEY)
+ self.assertEqual(TEST_MASTERKEY, leader.get_master_key())
+
+ leader.set_panid(TEST_PANID)
+ self.assertEqual(TEST_PANID, leader.get_panid())
+
+ leader.set_channel(TEST_CHANNEL)
+ self.assertEqual(TEST_CHANNEL, leader.get_channel())
+
+ leader.set_network_name(TEST_NETWORK_NAME)
+ self.assertEqual(TEST_NETWORK_NAME, leader.get_network_name())
+
+ self.assertEqual('rdn', leader.get_mode())
+ leader.set_mode('-')
+ self.assertEqual('-', leader.get_mode())
+ leader.set_mode('rdn')
+ self.assertEqual('rdn', leader.get_mode())
+
+ logging.info('leader weight: %d', leader.get_leader_weight())
+ leader.set_leader_weight(72)
+
+ logging.info('domain name: %r', leader.get_domain_name())
+ leader.set_domain_name("DefaultDomain2")
+ self.assertEqual("DefaultDomain2", leader.get_domain_name())
+
+ self.assertEqual(leader.get_preferred_partition_id(), 0)
+ leader.set_preferred_partition_id(0xabcddead)
+ self.assertEqual(leader.get_preferred_partition_id(), 0xabcddead)
+
+ leader.thread_start()
+ leader.wait(5)
+ self.assertEqual('leader', leader.get_state())
+ self.assertEqual(0xabcddead, leader.get_leader_data()['partition_id'])
+ logging.info('leader key sequence counter = %d', leader.get_key_sequence_counter())
+
+ rloc16 = leader.get_rloc16()
+ leader_id = leader.get_router_id()
+ self.assertEqual(rloc16, leader_id << 10)
+
+ self.assertFalse(leader.get_child_list())
+ self.assertEqual({}, leader.get_child_table())
+
+ leader.enable_allowlist()
+ leader.add_allowlist(leader.get_extaddr())
+ leader.remove_allowlist(leader.get_extaddr())
+ leader.set_allowlist([leader.get_extaddr()])
+ leader.disable_allowlist()
+
+ leader.add_ipmaddr('ff04::1')
+ leader.del_ipmaddr('ff04::1')
+ leader.add_ipmaddr('ff04::2')
+ logging.info('leader ipmaddrs: %r', leader.get_ipmaddrs())
+ self.assertFalse(leader.has_ipmaddr('ff04::1'))
+ self.assertTrue(leader.has_ipmaddr('ff04::2'))
+ self.assertTrue(leader.get_ipaddr_rloc())
+ self.assertTrue(leader.get_ipaddr_linklocal())
+ self.assertTrue(leader.get_ipaddr_mleid())
+
+ leader.add_ipaddr('2001::1')
+ leader.del_ipaddr('2001::1')
+ leader.add_ipaddr('2001::2')
+ logging.info('leader ipaddrs: %r', leader.get_ipaddrs())
+ self.assertFalse(leader.has_ipaddr('2001::1'))
+ self.assertTrue(leader.has_ipaddr('2001::2'))
+
+ logging.info('leader bbr state: %r', leader.get_backbone_router_state())
+ bbr_config = leader.get_backbone_router_config()
+ logging.info('leader bbr config: %r', bbr_config)
+ logging.info('leader PBBR: %r', leader.get_primary_backbone_router_info())
+
+ leader.set_backbone_router_config(seqno=bbr_config['seqno'] + 1, delay=10, timeout=301)
+ self.assertEqual({
+ 'seqno': bbr_config['seqno'] + 1,
+ 'delay': 10,
+ 'timeout': 301
+ }, leader.get_backbone_router_config())
+
+ leader.enable_backbone_router()
+ leader.wait(3)
+
+ logging.info('leader bbr state: %r', leader.get_backbone_router_state())
+ logging.info('leader bbr config: %r', leader.get_backbone_router_config())
+ logging.info('leader PBBR: %r', leader.get_primary_backbone_router_info())
+
+ logging.info('leader bufferinfo: %r', leader.get_message_buffer_info())
+
+ logging.info('child ipaddrs: %r', leader.get_child_ipaddrs())
+ logging.info('child ipmax: %r', leader.get_child_ip_max())
+ leader.set_child_ip_max(2)
+ self.assertEqual(2, leader.get_child_ip_max())
+ logging.info('childmax: %r', leader.get_max_children())
+
+ logging.info('counter names: %r', leader.counter_names)
+ for counter_name in leader.counter_names:
+ logging.info('counter %s: %r', counter_name, leader.get_counter(counter_name))
+ leader.reset_counter(counter_name)
+ self.assertTrue(all(x == 0 for x in leader.get_counter(counter_name).values()))
+
+ logging.info("CSL config: %r", leader.get_csl_config())
+ leader.config_csl(channel=13, period=100, timeout=200)
+ logging.info("CSL config: %r", leader.get_csl_config())
+
+ logging.info("EID-to-RLOC cache: %r", leader.get_eidcache())
+
+ logging.info("ipmaddr promiscuous: %r", leader.get_ipmaddr_promiscuous())
+ leader.enable_ipmaddr_promiscuous()
+ self.assertTrue(leader.get_ipmaddr_promiscuous())
+ leader.disable_ipmaddr_promiscuous()
+ self.assertFalse(leader.get_ipmaddr_promiscuous())
+
+ logging.info("leader data: %r", leader.get_leader_data())
+ logging.info("leader neighbor list: %r", leader.get_neighbor_list())
+ logging.info("leader neighbor table: %r", leader.get_neighbor_table())
+ logging.info("Leader external routes: %r", leader.get_local_routes())
+ leader.add_route('2002::/64')
+ leader.register_network_data()
+ logging.info("Leader external routes: %r", leader.get_local_routes())
+
+ self.assertEqual(1, len(leader.get_router_list()))
+ self.assertEqual(1, len(leader.get_router_table()))
+ logging.info("Leader router table: %r", leader.get_router_table())
+ self.assertFalse(list(leader.get_router_table().values())[0].is_link_established)
+
+ logging.info('scan: %r', leader.scan())
+ logging.info('scan energy: %r', leader.scan_energy())
+
+ leader.add_service(44970, '112233', 'aabbcc')
+ leader.register_network_data()
+ leader.add_service(44971, b'\x11\x22\x33', b'\xaa\xbb\xcc\xdd')
+
+ leader.add_prefix("2001::/64")
+
+ logging.info("network data: %r", leader.get_network_data())
+ logging.info("network data raw: %r", leader.get_network_data_bytes())
+ self.assertEqual(leader.get_network_data()['prefixes'], leader.get_prefixes())
+ self.assertEqual(leader.get_network_data()['routes'], leader.get_routes())
+ self.assertEqual(leader.get_network_data()['services'], leader.get_services())
+
+ logging.info("local prefixes: %r", leader.get_local_prefixes())
+ logging.info("local routes: %r", leader.get_local_routes())
+
+ logging.info('txpower %r', leader.get_txpower())
+ leader.set_txpower(-10)
+ self.assertEqual(-10, leader.get_txpower())
+
+ self.assertTrue(leader.is_singleton())
+
+ leader.coap_start()
+ leader.coap_set_test_resource_path('test')
+ leader.coap_test_set_resource_content('helloworld')
+ leader.coap_get(leader.get_ipaddr_rloc(), 'test')
+ leader.coap_put(leader.get_ipaddr_rloc(), 'test', 'con', 'xxx')
+ leader.coap_post(leader.get_ipaddr_rloc(), 'test', 'con', 'xxx')
+ leader.coap_delete(leader.get_ipaddr_rloc(), 'test', 'con', 'xxx')
+ leader.wait(1)
+ leader.coap_stop()
+
+ leader.udp_open()
+ leader.udp_bind("::", 1234)
+ leader.udp_send(leader.get_ipaddr_rloc(), 1234, text='hello')
+ leader.udp_send(leader.get_ipaddr_rloc(), 1234, random_bytes=3)
+ leader.udp_send(leader.get_ipaddr_rloc(), 1234, hex='112233')
+ leader.wait(1)
+ leader.udp_close()
+
+ logging.info('dataset: %r', leader.get_dataset())
+ logging.info('dataset active: %r', leader.get_dataset('active'))
+
+ leader.dataset_init_buffer()
+ leader.dataset_commit_buffer('pending')
+ leader.dataset_init_buffer(get_active_dataset=True)
+ leader.dataset_init_buffer(get_pending_dataset=True)
+
+ logging.info('dataset: %r', leader.get_dataset())
+ logging.info('dataset active: %r', leader.get_dataset('active'))
+ logging.info('dataset pending: %r', leader.get_dataset('pending'))
+
+ logging.info('dataset active -x: %r', leader.get_dataset_bytes('active'))
+ logging.info('dataset pending -x: %r', leader.get_dataset_bytes('pending'))
+
+ def _test_otci_example(self, node1, node2):
+ node1.dataset_init_buffer()
+ node1.dataset_set_buffer(network_name='test',
+ master_key='00112233445566778899aabbccddeeff',
+ panid=0xface,
+ channel=11)
+ node1.dataset_commit_buffer('active')
+
+ node1.ifconfig_up()
+ node1.thread_start()
+ node1.wait(5)
+ assert node1.get_state() == "leader"
+
+ node1.commissioner_start()
+ node1.wait(3)
+
+ node1.commissioner_add_joiner("TEST123", eui64='*')
+
+ node2.ifconfig_up()
+ node2.set_router_selection_jitter(1)
+
+ node2.joiner_start("TEST123")
+ node2.wait(10, expect_line="Join success")
+ node2.thread_start()
+ node2.wait(5)
+ assert node2.get_state() == "router"
+
+ def _test_otci_multi_nodes(self, leader, commissioner, child1, child2):
+ self.assertFalse(leader.get_ifconfig_state())
+
+ # ifconfig up
+ leader.ifconfig_up()
+ self.assertTrue(leader.get_ifconfig_state())
+
+ logging.info('leader eui64 = %r', leader.get_eui64())
+ logging.info('leader extpanid = %r', leader.get_extpanid())
+ logging.info('leader masterkey = %r', leader.get_master_key())
+
+ extaddr = leader.get_extaddr()
+ self.assertEqual(16, len(extaddr))
+ int(extaddr, 16)
+ new_extaddr = 'aabbccddeeff0011'
+ leader.set_extaddr(new_extaddr)
+ self.assertEqual(new_extaddr, leader.get_extaddr())
+
+ leader.set_network_name(TEST_NETWORK_NAME)
+
+ leader.set_master_key(TEST_MASTERKEY)
+ self.assertEqual(TEST_MASTERKEY, leader.get_master_key())
+
+ leader.set_panid(TEST_PANID)
+ self.assertEqual(TEST_PANID, leader.get_panid())
+
+ leader.set_channel(TEST_CHANNEL)
+ self.assertEqual(TEST_CHANNEL, leader.get_channel())
+
+ leader.set_network_name(TEST_NETWORK_NAME)
+ self.assertEqual(TEST_NETWORK_NAME, leader.get_network_name())
+
+ self.assertEqual('rdn', leader.get_mode())
+
+ leader.thread_start()
+ leader.wait(5)
+ self.assertEqual('leader', leader.get_state())
+ logging.info('leader key sequence counter = %d', leader.get_key_sequence_counter())
+
+ rloc16 = leader.get_rloc16()
+ leader_id = leader.get_router_id()
+ self.assertEqual(rloc16, leader_id << 10)
+
+ commissioner.ifconfig_up()
+ commissioner.set_channel(TEST_CHANNEL)
+ commissioner.set_panid(TEST_PANID)
+ commissioner.set_network_name(TEST_NETWORK_NAME)
+ commissioner.set_router_selection_jitter(1)
+ commissioner.set_master_key(TEST_MASTERKEY)
+ commissioner.thread_start()
+
+ commissioner.wait(5)
+
+ self.assertEqual('router', commissioner.get_state())
+
+ for dst_ip in leader.get_ipaddrs():
+ commissioner.ping(dst_ip, size=10, count=1, interval=2, hoplimit=3)
+
+ self.assertEqual('disabled', commissioner.get_commissioiner_state())
+ commissioner.commissioner_start()
+ commissioner.wait(5)
+ self.assertEqual('active', commissioner.get_commissioiner_state())
+
+ logging.info('commissioner.get_network_id_timeout() = %d', commissioner.get_network_id_timeout())
+ commissioner.set_network_id_timeout(60)
+ self.assertEqual(60, commissioner.get_network_id_timeout())
+
+ commissioner.commissioner_add_joiner('TEST123', eui64='*')
+ commissioner.wait(3)
+
+ child1.ifconfig_up()
+
+ logging.info("child1 scan: %r", child1.scan())
+ logging.info("child1 scan energy: %r", child1.scan_energy())
+
+ child1.set_mode('rn')
+ child1.set_router_selection_jitter(1)
+
+ child1.joiner_start('TEST123')
+ logging.info('joiner id = %r', child1.get_joiner_id())
+ child1.wait(10, expect_line="Join success")
+
+ child1.enable_allowlist()
+ child1.disable_allowlist()
+ child1.add_allowlist(commissioner.get_extaddr())
+ child1.remove_allowlist(commissioner.get_extaddr())
+ child1.set_allowlist([commissioner.get_extaddr()])
+
+ child1.thread_start()
+ child1.wait(3)
+ self.assertEqual('child', child1.get_state())
+
+ child1.thread_stop()
+
+ child1.set_mode('n')
+ child1.set_poll_period(1000)
+ self.assertEqual(1000, child1.get_poll_period())
+
+ child1.thread_start()
+ child1.wait(3)
+ self.assertEqual('child', child1.get_state())
+
+ child2.ifconfig_up()
+ child2.set_mode('rn')
+ child2.set_router_selection_jitter(1)
+
+ child2.joiner_start('TEST123')
+ logging.info('joiner id = %r', child2.get_joiner_id())
+ child2.wait(10, expect_line="Join success")
+
+ child2.enable_allowlist()
+ child2.disable_allowlist()
+ child2.add_allowlist(commissioner.get_extaddr())
+ child2.remove_allowlist(commissioner.get_extaddr())
+ child2.set_allowlist([commissioner.get_extaddr()])
+
+ child2.thread_start()
+ child2.wait(3)
+ self.assertEqual('child', child2.get_state())
+
+ child_table = commissioner.get_child_table()
+ logging.info('commissioiner child table: \n%s\n', json.dumps(child_table, indent=True))
+ child_list = commissioner.get_child_list()
+ logging.info('commissioiner child list: %r', child_list)
+ for child_id in child_list:
+ logging.info('child %s info: %r', child_id, commissioner.get_child_info(child_id))
+
+ logging.info('child1 info: %r', commissioner.get_child_info(child1.get_rloc16()))
+ logging.info('child2 info: %r', commissioner.get_child_info(child2.get_rloc16()))
+
+ self.assertEqual(set(commissioner.get_child_list()), set(commissioner.get_child_table().keys()))
+
+ child1.add_ipmaddr('ff04::1')
+ child1.del_ipmaddr('ff04::1')
+ child1.add_ipmaddr('ff04::2')
+ logging.info('child1 ipmaddrs: %r', child1.get_ipmaddrs())
+ self.assertFalse(child1.has_ipmaddr('ff04::1'))
+ self.assertTrue(child1.has_ipmaddr('ff04::2'))
+
+ child1.add_ipaddr('2001::1')
+ child1.del_ipaddr('2001::1')
+ child1.add_ipaddr('2001::2')
+ logging.info('child1 ipaddrs: %r', child1.get_ipaddrs())
+ self.assertFalse(child1.has_ipaddr('2001::1'))
+ self.assertTrue(child1.has_ipaddr('2001::2'))
+
+ logging.info('child ipaddrs: %r', commissioner.get_child_ipaddrs())
+
+ logging.info("EID-to-RLOC cache: %r", leader.get_eidcache())
+
+ logging.info("leader neighbor list: %r", leader.get_neighbor_list())
+ logging.info("leader neighbor table: %r", leader.get_neighbor_table())
+ logging.info("prefixes: %r", commissioner.get_local_prefixes())
+ commissioner.add_prefix('2001::/64')
+ commissioner.register_network_data()
+ commissioner.wait(1)
+ logging.info("prefixes: %r", commissioner.get_local_prefixes())
+
+ self.assertEqual(2, len(leader.get_router_list()))
+ self.assertEqual(2, len(leader.get_router_table()))
+ logging.info('leader router table: %r', leader.get_router_table())
+ self.assertEqual({False, True},
+ set(router.is_link_established for router in leader.get_router_table().values()))
+
+ self.assertFalse(leader.is_singleton())
+
+ # Shutdown
+ leader.thread_stop()
+ logging.info("node state: %s", leader.get_state())
+ leader.ifconfig_down()
+ self.assertFalse(leader.get_ifconfig_state())
+
+ leader.close()
+
+
+if __name__ == '__main__':
+ unittest.main()