aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanda Wang <handaw@google.com>2023-12-01 16:00:52 +0800
committerHanda Wang <handaw@google.com>2023-12-04 09:52:52 +0800
commitb0ea20342e7a9e8c1638381e9c469e130852051c (patch)
tree6ccdacf83bd106f31c40415ccf8f2849e07aad97
parent4b88c3154ce26bff2a9d9bf459214fbedebe38b5 (diff)
downloadopenthread-b0ea20342e7a9e8c1638381e9c469e130852051c.tar.gz
[Github Sync] Merge github/main to aosp/main
* github/main: [meshcop-tlvs] update name style in `DiscoveryResponseTlv` (#9671) [dataset] introduce `WriteTlv()` methods (#9664) [posix] fix a few compiler warnings around nat64 (#9666) [test] update `channel-announce-recovery` test to check router recovery (#9670) [link-metrics] add Subject status check when getting link metrics data (#9665) [github-actions] cover NCP build with `OT_OPERATIONAL_DATASET_AUTO_INIT` (#9663) [dataset] introduce `ContainsTlv()` method (#9663) [srp-client] exclude non-preferred addresses in `AutoAddress` mode (#9642) [tlvs] add `ReadValueAs()` & `WriteValueAs()` to simplify `MeshCop::Tlv` (#9661) [bbr-local] smaller enhancements (#9657) [spinel] fix multipan rcp enable config (#9659) [cli] add Doxygen for SRP server (#9653) [posix] unify the infra netif and backbone netif (#9638) [border-router] add missing `otBorderRoutingDhcp6PdGetState()` declaration (#9654) [dataset-updater] fix possible use of uninitialized `Timestamp` (#9658) [spinel] add support for multiple spinel interfaces (#9360) [spinel] fix compiling issue of enum multiplication (#9649) [dataset] simplify saving/reading of TLVs in/from secure storage (#9626) [dhcp6-pd] stop `PrefixManager` when `RoutingManager` is stopped (#9608) [tests] fix the check of external routes in `test_multi_thread_networks.py` (#9648) [csl] fix `TimerMicro::GetNow()` call in `sub_mac.cpp` (#9639) [posix] fix unused private variables (#9644) github-actions: bump step-security/harden-runner from 2.6.0 to 2.6.1 (#9650) [mlr] use shorter variable/method names (#9635) [config] define `OPENTHREAD_CONFIG_TLS_UPDATE` in all cases (#9630) [ip6] update Ip6::SelectSourceAddress() to prefer non-deprecated addresses (#9634) [mlr-manager] define `AddressArray` which uses `Array<Ip6::Address>` (#9633) [typo] fix error message of link metrics option dependency (#9646) [platform] fix compiling issue when use `SuccessOrDie` (#9640) [continuous-integration] fix bootstrap issue for ot-commissioner (#9643) [docs] update Code of Conduct to Contributor Covenant v2.1 (#9627) [spinel] expose RestoreProperties as a public method within RadioSpinel (#9501) [cli] make linkmetrics cli as a separate module (#9619) [message] add API functions to enable multicast looping of a message (#9524) [simulation] SIGHUP when parent dies (#9624) [routing-manager] learn and copy `M` & `O` flags from discovered routers (#9607) [cli] add Doxygen tags to SRP commands (#9615) [lint] explicitly initialize failedAddresses (#9622) [routing-manager] new API to get list of discovered routers (#9601) [posix] clear SPI tx buffer after usage (#9567) github-actions: bump actions/upload-artifact from 3.1.2 to 3.1.3 (#9625) [encoding] avoid the use of `using` for `Big/LittleEndian` functions (#9621) [num-limits] add `kBitsPerByte`, `BitSizeOf()`, and `BytesForBitSize()` (#9618) [core] add missing platform function for `OT_PLATFORM_KEY_REF` (#9620) [dns] support longer key length in `otDnsTxtEntryIterator` (#9616) [test] define all unit tests in `ot` namespace (#9617) [joiner-router] enhance & fix appending TLVs to Joiner Entrust msg (#9614) [posix] more robust netlink message handler (#9613) [mle] add `ChannelTlvValue` to use in `ChannelTlv` & `CslChannelTlv` (#9612) [cli] remove extra line in `trel peers` docs in `README.md` (#9611) [mle] remove `MleRouter` class definition under `MTD` build (#9610) [mle] fix responding to "Child Update Request" from non-parent device (#9609) [cli] adding set ipv4 CIDR for NAT64 in README (#9511) [test] ensure to `FinalizeTest()` in `TestProcessPlatfromGeneratedNd()` (#9606) [radio] add `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` capability (#9554) (#9554) [mle] define `IsRouterIdValid()` helper in `mle_types.hpp` (#9598) github-actions: bump docker/setup-buildx-action from 2.9.1 to 3.0.0 (#9600) [test] address occasional failure of `test_routing_manager` (#9603) [toranj] update config header to use `OT_LOG_LEVEL_INFO` (#9595) [routing-manager] check `mIsRunning` in `ScheduleRoutingPolicyEvaluation()` (#9594) [multi-radio] perform tag duplication check for first fragment (#9590) [routing-manager] use `Heap::Array` for `OnMeshPrefixArray` (#9592) [cli] TCP readme corrections (#9593) [posix] allow OT process to run when infra netif gets lost (#9583) [slaac] simplify adding/removing addresses and other enhancements (#9579) [csl] add `OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC` option (#9568) (#9568) [docs] TCP Commands - add Doxygen tags (#9578) [dataset] returns OT_ERROR_REJECTED when MGMT_SET is rejected by leader (#9582) github-actions: bump ossf/scorecard-action from 2.2.0 to 2.3.1 (#9584) [build] move `radio_spinel.cpp` to new lib `openthread-radio-spinel` (#9530) [netdata] simplify `Leader` class (#9563) [mac] validate received ack frame PSDU in `ProcessEnhAckSecurity()` (#9565) github-actions: bump github/codeql-action from 2.22.3 to 2.22.5 (#9571) [api] add API to reset to bootloader mode (#9523) [core] define `core/instance` folder for `instance` modules (#9561) [posix] fix uninitialized pointer read (#9562) [log] add `otLogGenerateNextHexDumpLine()` to generate hex dump (#9555) [posix] add `otSysSetInfraNetif` API (#9528) [mle] add `TxMessage::AppendSteeringData()` (#9559) [posix] addressing coverity warning: resource leak (#9472) [mac] update the cached supported channel mask when the region code changes (#9418) [docs] added xrefs from UDP CLI to UDP Concepts Guide (#9558) [ip6] log checksum error from `Checksum::VerifyMessageChecksum()` (#9556) [nedata] add API to retrieve Commissioning Dataset (#9551) github-actions: bump actions/checkout from 4.1.0 to 4.1.1 (#9557) [netdata] simplify and update `HandleTmf<kUriCommissionerSet>()` (#9550) [netdata] resign active commissioner on NetData restore on leader (#9549) [tests] fix verification in `test_routing_manager.cpp` (#9548) [udp] remove `aIpProto` from `Ip6::Udp::SendDatagram()` (#9547) ... Change-Id: I4623d2a0bcba3f1880071d9efd91ca6d2bb6ad1b
-rw-r--r--.github/workflows/build.yml58
-rw-r--r--.github/workflows/codeql.yml8
-rw-r--r--.github/workflows/docker.yml6
-rw-r--r--.github/workflows/fuzz.yml4
-rw-r--r--.github/workflows/makefile-check.yml4
-rw-r--r--.github/workflows/otbr.yml18
-rw-r--r--.github/workflows/otci.yml4
-rw-r--r--.github/workflows/otns.yml26
-rw-r--r--.github/workflows/posix.yml44
-rw-r--r--.github/workflows/scorecards.yml8
-rw-r--r--.github/workflows/simulation-1.1.yml61
-rw-r--r--.github/workflows/simulation-1.2.yml58
-rw-r--r--.github/workflows/size.yml5
-rw-r--r--.github/workflows/toranj.yml28
-rw-r--r--.github/workflows/unit.yml20
-rw-r--r--.github/workflows/version.yml4
-rw-r--r--CODE_OF_CONDUCT.md77
-rw-r--r--doc/ot_api_doc.h1
-rw-r--r--etc/cmake/options.cmake5
-rw-r--r--examples/apps/cli/main.c11
-rw-r--r--examples/apps/ncp/main.c43
-rw-r--r--examples/apps/ncp/ncp.c13
-rw-r--r--examples/platforms/simulation/CMakeLists.txt1
-rw-r--r--examples/platforms/simulation/crypto.c37
-rw-r--r--examples/platforms/simulation/misc.c9
-rw-r--r--examples/platforms/simulation/multipan.c66
-rw-r--r--include/openthread/BUILD.gn1
-rw-r--r--include/openthread/border_routing.h58
-rw-r--r--include/openthread/commissioner.h1
-rw-r--r--include/openthread/dns.h10
-rw-r--r--include/openthread/instance.h33
-rw-r--r--include/openthread/ip6.h42
-rw-r--r--include/openthread/logging.h78
-rw-r--r--include/openthread/message.h22
-rw-r--r--include/openthread/ncp.h10
-rw-r--r--include/openthread/netdata.h10
-rw-r--r--include/openthread/ping_sender.h1
-rw-r--r--include/openthread/platform/misc.h14
-rw-r--r--include/openthread/platform/multipan.h145
-rw-r--r--include/openthread/platform/radio.h35
-rw-r--r--include/openthread/platform/toolchain.h1
-rw-r--r--include/openthread/srp_client.h8
-rwxr-xr-xscript/check-simulation-build-cmake4
-rwxr-xr-xscript/test18
-rw-r--r--src/cli/BUILD.gn2
-rw-r--r--src/cli/CMakeLists.txt1
-rw-r--r--src/cli/README.md46
-rw-r--r--src/cli/README_BR.md40
-rw-r--r--src/cli/README_DATASET.md141
-rw-r--r--src/cli/README_NETDATA.md11
-rw-r--r--src/cli/README_SRP_CLIENT.md2
-rw-r--r--src/cli/README_TCP.md6
-rw-r--r--src/cli/README_UDP.md2
-rw-r--r--src/cli/cli.cpp596
-rw-r--r--src/cli/cli.hpp46
-rw-r--r--src/cli/cli_br.cpp71
-rw-r--r--src/cli/cli_br.hpp3
-rw-r--r--src/cli/cli_link_metrics.cpp530
-rw-r--r--src/cli/cli_link_metrics.hpp128
-rw-r--r--src/cli/cli_network_data.cpp38
-rw-r--r--src/cli/cli_network_data.hpp1
-rw-r--r--src/cli/cli_srp_client.cpp375
-rw-r--r--src/cli/cli_srp_server.cpp192
-rw-r--r--src/cli/cli_tcp.cpp185
-rw-r--r--src/cli/cli_udp.cpp154
-rw-r--r--src/core/BUILD.gn9
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/api/border_router_api.cpp2
-rw-r--r--src/core/api/border_routing_api.cpp12
-rw-r--r--src/core/api/coap_api.cpp8
-rw-r--r--src/core/api/dns_api.cpp2
-rw-r--r--src/core/api/dns_server_api.cpp2
-rw-r--r--src/core/api/instance_api.cpp14
-rw-r--r--src/core/api/ip6_api.cpp13
-rw-r--r--src/core/api/logging_api.cpp42
-rw-r--r--src/core/api/message_api.cpp7
-rw-r--r--src/core/api/nat64_api.cpp2
-rw-r--r--src/core/api/netdata_api.cpp5
-rw-r--r--src/core/api/thread_api.cpp13
-rw-r--r--src/core/api/trel_api.cpp2
-rw-r--r--src/core/api/udp_api.cpp7
-rw-r--r--src/core/backbone_router/bbr_leader.cpp2
-rw-r--r--src/core/backbone_router/bbr_leader.hpp9
-rw-r--r--src/core/backbone_router/bbr_local.cpp105
-rw-r--r--src/core/backbone_router/bbr_local.hpp49
-rw-r--r--src/core/backbone_router/bbr_manager.cpp9
-rw-r--r--src/core/backbone_router/multicast_listeners_table.cpp2
-rw-r--r--src/core/border_router/infra_if.cpp2
-rw-r--r--src/core/border_router/routing_manager.cpp260
-rw-r--r--src/core/border_router/routing_manager.hpp71
-rw-r--r--src/core/coap/coap.cpp2
-rw-r--r--src/core/coap/coap_message.cpp10
-rw-r--r--src/core/coap/coap_message.hpp6
-rw-r--r--src/core/coap/coap_secure.cpp2
-rw-r--r--src/core/common/bit_vector.hpp3
-rw-r--r--src/core/common/encoding.hpp72
-rw-r--r--src/core/common/frame_builder.cpp14
-rw-r--r--src/core/common/frame_data.cpp8
-rw-r--r--src/core/common/heap.cpp2
-rw-r--r--src/core/common/locator_getters.hpp2
-rw-r--r--src/core/common/log.cpp156
-rw-r--r--src/core/common/log.hpp30
-rw-r--r--src/core/common/message.cpp2
-rw-r--r--src/core/common/message.hpp27
-rw-r--r--src/core/common/notifier.cpp2
-rw-r--r--src/core/common/numeric_limits.hpp22
-rw-r--r--src/core/common/settings.cpp2
-rw-r--r--src/core/common/settings.hpp48
-rw-r--r--src/core/common/string.cpp39
-rw-r--r--src/core/common/string.hpp56
-rw-r--r--src/core/common/time_ticker.cpp2
-rw-r--r--src/core/common/time_ticker.hpp5
-rw-r--r--src/core/common/timer.cpp2
-rw-r--r--src/core/common/tlvs.cpp34
-rw-r--r--src/core/common/tlvs.hpp142
-rw-r--r--src/core/common/uptime.cpp2
-rw-r--r--src/core/config/ip6.h4
-rw-r--r--src/core/config/mac.h32
-rw-r--r--src/core/config/misc.h30
-rw-r--r--src/core/crypto/aes_ccm.cpp4
-rw-r--r--src/core/crypto/crypto_platform.cpp4
-rw-r--r--src/core/diags/factory_diags.cpp2
-rw-r--r--src/core/instance/extension.hpp (renamed from src/core/common/extension.hpp)0
-rw-r--r--src/core/instance/extension_example.cpp (renamed from src/core/common/extension_example.cpp)2
-rw-r--r--src/core/instance/instance.cpp (renamed from src/core/common/instance.cpp)33
-rw-r--r--src/core/instance/instance.hpp (renamed from src/core/common/instance.hpp)31
-rw-r--r--src/core/mac/channel_mask.hpp8
-rw-r--r--src/core/mac/data_poll_handler.cpp2
-rw-r--r--src/core/mac/data_poll_sender.cpp2
-rw-r--r--src/core/mac/link_raw.cpp2
-rw-r--r--src/core/mac/mac.cpp31
-rw-r--r--src/core/mac/mac_frame.cpp31
-rw-r--r--src/core/mac/mac_frame.hpp41
-rw-r--r--src/core/mac/mac_links.cpp2
-rw-r--r--src/core/mac/mac_links.hpp10
-rw-r--r--src/core/mac/sub_mac.cpp63
-rw-r--r--src/core/mac/sub_mac.hpp10
-rw-r--r--src/core/mac/sub_mac_callbacks.cpp2
-rw-r--r--src/core/meshcop/announce_begin_client.cpp2
-rw-r--r--src/core/meshcop/border_agent.cpp21
-rw-r--r--src/core/meshcop/border_agent.hpp6
-rw-r--r--src/core/meshcop/commissioner.cpp77
-rw-r--r--src/core/meshcop/commissioner.hpp141
-rw-r--r--src/core/meshcop/dataset.cpp183
-rw-r--r--src/core/meshcop/dataset.hpp225
-rw-r--r--src/core/meshcop/dataset_local.cpp132
-rw-r--r--src/core/meshcop/dataset_local.hpp19
-rw-r--r--src/core/meshcop/dataset_manager.cpp41
-rw-r--r--src/core/meshcop/dataset_manager.hpp6
-rw-r--r--src/core/meshcop/dataset_manager_ftd.cpp84
-rw-r--r--src/core/meshcop/dataset_updater.cpp13
-rw-r--r--src/core/meshcop/dtls.cpp2
-rw-r--r--src/core/meshcop/energy_scan_client.cpp2
-rw-r--r--src/core/meshcop/joiner.cpp2
-rw-r--r--src/core/meshcop/joiner_router.cpp89
-rw-r--r--src/core/meshcop/joiner_router.hpp5
-rw-r--r--src/core/meshcop/meshcop.cpp28
-rw-r--r--src/core/meshcop/meshcop.hpp150
-rw-r--r--src/core/meshcop/meshcop_leader.cpp82
-rw-r--r--src/core/meshcop/meshcop_leader.hpp43
-rw-r--r--src/core/meshcop/meshcop_tlvs.cpp67
-rw-r--r--src/core/meshcop/meshcop_tlvs.hpp713
-rw-r--r--src/core/meshcop/panid_query_client.cpp2
-rw-r--r--src/core/meshcop/timestamp.hpp20
-rw-r--r--src/core/net/checksum.cpp15
-rw-r--r--src/core/net/dhcp6.hpp64
-rw-r--r--src/core/net/dhcp6_client.cpp2
-rw-r--r--src/core/net/dhcp6_server.cpp17
-rw-r--r--src/core/net/dhcp6_server.hpp7
-rw-r--r--src/core/net/dns_client.cpp13
-rw-r--r--src/core/net/dns_dso.cpp2
-rw-r--r--src/core/net/dns_dso.hpp23
-rw-r--r--src/core/net/dns_platform.cpp2
-rw-r--r--src/core/net/dns_types.cpp14
-rw-r--r--src/core/net/dns_types.hpp114
-rw-r--r--src/core/net/dnssd_server.cpp2
-rw-r--r--src/core/net/icmp6.cpp2
-rw-r--r--src/core/net/icmp6.hpp14
-rw-r--r--src/core/net/ip4_types.cpp8
-rw-r--r--src/core/net/ip4_types.hpp27
-rw-r--r--src/core/net/ip6.cpp367
-rw-r--r--src/core/net/ip6.hpp41
-rw-r--r--src/core/net/ip6_address.cpp45
-rw-r--r--src/core/net/ip6_address.hpp24
-rw-r--r--src/core/net/ip6_filter.cpp2
-rw-r--r--src/core/net/ip6_headers.hpp42
-rw-r--r--src/core/net/ip6_mpl.cpp120
-rw-r--r--src/core/net/ip6_mpl.hpp15
-rw-r--r--src/core/net/nat64_translator.cpp2
-rw-r--r--src/core/net/nd6.hpp32
-rw-r--r--src/core/net/nd_agent.cpp13
-rw-r--r--src/core/net/nd_agent.hpp6
-rw-r--r--src/core/net/netif.cpp41
-rw-r--r--src/core/net/netif.hpp32
-rw-r--r--src/core/net/sntp_client.cpp2
-rw-r--r--src/core/net/sntp_client.hpp76
-rw-r--r--src/core/net/srp_client.cpp16
-rw-r--r--src/core/net/srp_server.cpp2
-rw-r--r--src/core/net/tcp6.cpp37
-rw-r--r--src/core/net/tcp6.hpp16
-rw-r--r--src/core/net/udp6.cpp8
-rw-r--r--src/core/net/udp6.hpp19
-rw-r--r--src/core/radio/radio.cpp1
-rw-r--r--src/core/radio/radio.hpp12
-rw-r--r--src/core/radio/radio_callbacks.cpp2
-rw-r--r--src/core/radio/radio_platform.cpp8
-rw-r--r--src/core/radio/trel_interface.cpp4
-rw-r--r--src/core/radio/trel_link.cpp4
-rw-r--r--src/core/radio/trel_packet.cpp2
-rw-r--r--src/core/radio/trel_packet.hpp8
-rw-r--r--src/core/thread/address_resolver.cpp2
-rw-r--r--src/core/thread/announce_begin_server.cpp2
-rw-r--r--src/core/thread/announce_sender.cpp2
-rw-r--r--src/core/thread/anycast_locator.cpp2
-rw-r--r--src/core/thread/child.cpp2
-rw-r--r--src/core/thread/child_supervision.cpp17
-rw-r--r--src/core/thread/child_table.cpp2
-rw-r--r--src/core/thread/discover_scanner.cpp2
-rw-r--r--src/core/thread/dua_manager.cpp4
-rw-r--r--src/core/thread/energy_scan_server.cpp6
-rw-r--r--src/core/thread/indirect_sender.cpp2
-rw-r--r--src/core/thread/key_manager.cpp6
-rw-r--r--src/core/thread/link_metrics.cpp2
-rw-r--r--src/core/thread/link_metrics_tlvs.hpp6
-rw-r--r--src/core/thread/link_quality.cpp2
-rw-r--r--src/core/thread/lowpan.cpp28
-rw-r--r--src/core/thread/lowpan.hpp10
-rw-r--r--src/core/thread/mesh_forwarder.cpp46
-rw-r--r--src/core/thread/mesh_forwarder.hpp9
-rw-r--r--src/core/thread/mesh_forwarder_ftd.cpp111
-rw-r--r--src/core/thread/mesh_forwarder_mtd.cpp18
-rw-r--r--src/core/thread/mle.cpp250
-rw-r--r--src/core/thread/mle.hpp58
-rw-r--r--src/core/thread/mle_router.cpp37
-rw-r--r--src/core/thread/mle_router.hpp43
-rw-r--r--src/core/thread/mle_tlvs.hpp135
-rw-r--r--src/core/thread/mle_types.hpp15
-rw-r--r--src/core/thread/mlr_manager.cpp209
-rw-r--r--src/core/thread/mlr_manager.hpp88
-rw-r--r--src/core/thread/neighbor.cpp2
-rw-r--r--src/core/thread/neighbor_table.cpp2
-rw-r--r--src/core/thread/network_data.cpp2
-rw-r--r--src/core/thread/network_data_leader.cpp209
-rw-r--r--src/core/thread/network_data_leader.hpp414
-rw-r--r--src/core/thread/network_data_leader_ftd.cpp281
-rw-r--r--src/core/thread/network_data_leader_ftd.hpp369
-rw-r--r--src/core/thread/network_data_local.cpp2
-rw-r--r--src/core/thread/network_data_notifier.cpp2
-rw-r--r--src/core/thread/network_data_publisher.cpp2
-rw-r--r--src/core/thread/network_data_service.cpp4
-rw-r--r--src/core/thread/network_data_service.hpp19
-rw-r--r--src/core/thread/network_data_tlvs.cpp2
-rw-r--r--src/core/thread/network_data_tlvs.hpp37
-rw-r--r--src/core/thread/network_data_types.cpp2
-rw-r--r--src/core/thread/network_diagnostic.cpp32
-rw-r--r--src/core/thread/network_diagnostic.hpp2
-rw-r--r--src/core/thread/network_diagnostic_tlvs.cpp96
-rw-r--r--src/core/thread/network_diagnostic_tlvs.hpp83
-rw-r--r--src/core/thread/panid_query_server.cpp2
-rw-r--r--src/core/thread/radio_selector.cpp2
-rw-r--r--src/core/thread/router.cpp2
-rw-r--r--src/core/thread/router_table.cpp2
-rw-r--r--src/core/thread/src_match_controller.cpp2
-rw-r--r--src/core/thread/thread_netif.cpp2
-rw-r--r--src/core/thread/thread_tlvs.hpp3
-rw-r--r--src/core/thread/time_sync_service.cpp2
-rw-r--r--src/core/utils/channel_manager.cpp2
-rw-r--r--src/core/utils/flash.cpp2
-rw-r--r--src/core/utils/history_tracker.cpp2
-rw-r--r--src/core/utils/jam_detector.cpp2
-rw-r--r--src/core/utils/link_metrics_manager.cpp1
-rw-r--r--src/core/utils/link_metrics_manager.hpp2
-rw-r--r--src/core/utils/mesh_diag.cpp2
-rw-r--r--src/core/utils/ping_sender.cpp7
-rw-r--r--src/core/utils/slaac_address.cpp240
-rw-r--r--src/core/utils/slaac_address.hpp43
-rw-r--r--src/core/utils/srp_client_buffers.cpp2
-rw-r--r--src/lib/platform/BUILD.gn1
-rw-r--r--src/lib/platform/exit_code.h1
-rw-r--r--src/lib/spinel/CMakeLists.txt23
-rw-r--r--src/lib/spinel/multi_frame_buffer.hpp14
-rw-r--r--src/lib/spinel/openthread-spinel-config.h11
-rw-r--r--src/lib/spinel/radio_spinel.cpp499
-rw-r--r--src/lib/spinel/radio_spinel.hpp262
-rw-r--r--src/lib/spinel/spi_frame.hpp11
-rw-r--r--src/lib/spinel/spinel.c8
-rw-r--r--src/lib/spinel/spinel.h75
-rw-r--r--src/lib/spinel/spinel_interface.hpp24
-rw-r--r--src/ncp/BUILD.gn1
-rw-r--r--src/ncp/CMakeLists.txt10
-rw-r--r--src/ncp/changed_props_set.cpp6
-rw-r--r--src/ncp/example_vendor_hook.cpp29
-rw-r--r--src/ncp/multipan_platform.cpp101
-rw-r--r--src/ncp/ncp_base.cpp186
-rw-r--r--src/ncp/ncp_base.hpp120
-rw-r--r--src/ncp/ncp_base_dispatcher.cpp7
-rw-r--r--src/ncp/ncp_base_ftd.cpp2
-rw-r--r--src/ncp/ncp_base_mtd.cpp4
-rw-r--r--src/ncp/ncp_base_radio.cpp104
-rw-r--r--src/ncp/ncp_hdlc.cpp47
-rw-r--r--src/ncp/ncp_hdlc.hpp13
-rw-r--r--src/ncp/ncp_spi.cpp2
-rw-r--r--src/posix/cli.cmake1
-rw-r--r--src/posix/daemon.cmake1
-rw-r--r--src/posix/main.c1
-rw-r--r--src/posix/platform/CMakeLists.txt9
-rw-r--r--src/posix/platform/backbone.cpp101
-rw-r--r--src/posix/platform/configuration.cpp9
-rw-r--r--src/posix/platform/configuration.hpp26
-rw-r--r--src/posix/platform/include/openthread/openthread-system.h8
-rw-r--r--src/posix/platform/infra_if.cpp113
-rw-r--r--src/posix/platform/infra_if.hpp37
-rw-r--r--src/posix/platform/multicast_routing.cpp4
-rw-r--r--src/posix/platform/multicast_routing.hpp2
-rw-r--r--src/posix/platform/netif.cpp79
-rw-r--r--src/posix/platform/openthread-posix-config.h14
-rw-r--r--src/posix/platform/platform-posix.h57
-rw-r--r--src/posix/platform/radio.cpp79
-rw-r--r--src/posix/platform/radio.hpp1
-rw-r--r--src/posix/platform/radio_url.cpp11
-rw-r--r--src/posix/platform/settings.cpp25
-rw-r--r--src/posix/platform/spi_interface.cpp2
-rw-r--r--src/posix/platform/system.cpp30
-rw-r--r--src/posix/platform/udp.cpp11
-rw-r--r--tests/fuzz/fuzzer_platform.cpp11
-rwxr-xr-xtests/scripts/expect/cli-commissioner.exp4
-rwxr-xr-xtests/scripts/expect/cli-promiscuous.exp5
-rwxr-xr-xtests/scripts/expect/cli-reset.exp3
-rwxr-xr-xtests/scripts/thread-cert/border_router/test_multi_thread_networks.py15
-rwxr-xr-xtests/scripts/thread-cert/node.py8
-rwxr-xr-xtests/scripts/thread-cert/test_srp_auto_host_address.py25
-rwxr-xr-xtests/toranj/build.sh23
-rw-r--r--tests/toranj/cli/cli.py4
-rwxr-xr-xtests/toranj/cli/test-008-multicast-traffic.py94
-rwxr-xr-xtests/toranj/cli/test-025-mesh-local-prefix-change.py125
-rwxr-xr-xtests/toranj/cli/test-603-channel-announce-recovery.py36
-rw-r--r--tests/toranj/openthread-core-toranj-config-posix.h3
-rw-r--r--tests/toranj/openthread-core-toranj-config-simulation.h2
-rw-r--r--tests/toranj/openthread-core-toranj-config.h2
-rwxr-xr-xtests/toranj/start.sh1
-rw-r--r--tests/unit/CMakeLists.txt101
-rw-r--r--tests/unit/test_aes.cpp50
-rw-r--r--tests/unit/test_array.cpp2
-rw-r--r--tests/unit/test_checksum.cpp15
-rw-r--r--tests/unit/test_child.cpp4
-rw-r--r--tests/unit/test_child_table.cpp4
-rw-r--r--tests/unit/test_cmd_line_parser.cpp30
-rw-r--r--tests/unit/test_dns.cpp19
-rw-r--r--tests/unit/test_dns_client.cpp2
-rw-r--r--tests/unit/test_dso.cpp10
-rw-r--r--tests/unit/test_hdlc.cpp2
-rw-r--r--tests/unit/test_heap.cpp6
-rw-r--r--tests/unit/test_hkdf_sha256.cpp14
-rw-r--r--tests/unit/test_ip4_header.cpp8
-rw-r--r--tests/unit/test_ip6_header.cpp4
-rw-r--r--tests/unit/test_ip_address.cpp286
-rw-r--r--tests/unit/test_link_metrics_manager.cpp10
-rw-r--r--tests/unit/test_link_quality.cpp2
-rw-r--r--tests/unit/test_linked_list.cpp2
-rw-r--r--tests/unit/test_lowpan.cpp10
-rw-r--r--tests/unit/test_lowpan.hpp2
-rw-r--r--tests/unit/test_mac_frame.cpp2
-rw-r--r--tests/unit/test_macros.cpp14
-rw-r--r--tests/unit/test_message.cpp2
-rw-r--r--tests/unit/test_message_queue.cpp54
-rw-r--r--tests/unit/test_multicast_listeners_table.cpp6
-rw-r--r--tests/unit/test_multipan_rcp_instances.cpp766
-rw-r--r--tests/unit/test_nat64.cpp2
-rw-r--r--tests/unit/test_ndproxy_table.cpp4
-rw-r--r--tests/unit/test_netif.cpp2
-rw-r--r--tests/unit/test_network_data.cpp12
-rw-r--r--tests/unit/test_platform.cpp65
-rw-r--r--tests/unit/test_platform.h8
-rw-r--r--tests/unit/test_pool.cpp20
-rw-r--r--tests/unit/test_power_calibration.cpp4
-rw-r--r--tests/unit/test_priority_queue.cpp130
-rw-r--r--tests/unit/test_pskc.cpp22
-rw-r--r--tests/unit/test_routing_manager.cpp428
-rw-r--r--tests/unit/test_spinel_buffer.cpp6
-rw-r--r--tests/unit/test_spinel_decoder.cpp2
-rw-r--r--tests/unit/test_spinel_encoder.cpp2
-rw-r--r--tests/unit/test_srp_server.cpp22
-rw-r--r--tests/unit/test_string.cpp31
-rw-r--r--tests/unit/test_timer.cpp52
-rw-r--r--tests/unit/test_tlv.cpp2
-rw-r--r--tests/unit/test_toolchain.cpp12
-rw-r--r--tests/unit/test_trickle_timer.cpp8
-rw-r--r--tests/unit/test_url.cpp40
-rw-r--r--tools/harness-thci/OpenThread.py5
389 files changed, 10649 insertions, 6051 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 19b461933..5f3d85ab2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -49,11 +49,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -71,11 +71,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: gaurav-nelson/github-action-markdown-link-check@5c5dfc0ac2e225883c0e5f03a85311ec2830d368 # v1
with:
use-verbose-mode: 'yes'
@@ -85,11 +85,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -104,11 +104,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -144,11 +144,11 @@ jobs:
CXX: ${{ matrix.compiler_cpp }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -163,11 +163,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -182,18 +182,18 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y ninja-build libreadline-dev libncurses-dev
rm -rf third_party/mbedtls/repo
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: ARMmbed/mbedtls
ref: v3.5.0
@@ -235,11 +235,11 @@ jobs:
gcc_extract_dir: arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -276,11 +276,11 @@ jobs:
CXX: g++-${{ matrix.gcc_ver }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -309,11 +309,11 @@ jobs:
CXX: clang++-${{ matrix.clang_ver }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -347,11 +347,11 @@ jobs:
LDFLAGS: -m32
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -375,11 +375,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -411,11 +411,11 @@ jobs:
CXX: ${{ matrix.CXX }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -435,11 +435,11 @@ jobs:
image: openthread/environment
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Install unzip
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index ca6d852f7..17044aa71 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -54,19 +54,19 @@ jobs:
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Checkout repository
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y ninja-build libreadline-dev libncurses-dev
- name: Initialize CodeQL
- uses: github/codeql-action/init@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8
+ uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -80,6 +80,6 @@ jobs:
./script/test build
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.21.8
+ uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 08cd6124b..8cce3c7f4 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -55,11 +55,11 @@ jobs:
- docker_name: environment
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
@@ -83,7 +83,7 @@ jobs:
${TAGS} --file ${DOCKER_FILE} ." >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1
+ uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Docker Buildx (build)
run: |
diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml
index 486a6afa4..932742765 100644
--- a/.github/workflows/fuzz.yml
+++ b/.github/workflows/fuzz.yml
@@ -45,7 +45,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
@@ -61,7 +61,7 @@ jobs:
fuzz-seconds: 1800
dry-run: false
- name: Upload Crash
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: failure()
with:
name: artifacts
diff --git a/.github/workflows/makefile-check.yml b/.github/workflows/makefile-check.yml
index 431d9972e..2f5044757 100644
--- a/.github/workflows/makefile-check.yml
+++ b/.github/workflows/makefile-check.yml
@@ -48,11 +48,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Check
diff --git a/.github/workflows/otbr.yml b/.github/workflows/otbr.yml
index 59b0f1ae9..62cddbf50 100644
--- a/.github/workflows/otbr.yml
+++ b/.github/workflows/otbr.yml
@@ -62,7 +62,7 @@ jobs:
# of OMR prefix and Domain prefix is not deterministic.
BORDER_ROUTING: 0
steps:
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Build OTBR Docker
@@ -86,11 +86,11 @@ jobs:
export CI_ENV="$(bash <(curl -s https://codecov.io/env)) -e GITHUB_ACTIONS -e COVERAGE"
echo "CI_ENV=${CI_ENV}"
sudo -E ./script/test cert_suite ./tests/scripts/thread-cert/backbone/*.py || (sudo chmod a+r *.log *.json *.pcap && false)
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-1-3-backbone-docker
path: /tmp/coverage/
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: thread-1-3-backbone-results
@@ -103,7 +103,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-1-3-backbone
path: tmp/coverage.info
@@ -179,7 +179,7 @@ jobs:
NAT64: ${{ matrix.nat64 }}
MAX_JOBS: 3
steps:
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set firewall environment variables
if: ${{ matrix.use_core_firewall }}
run: |
@@ -206,11 +206,11 @@ jobs:
export CI_ENV="$(bash <(curl -s https://codecov.io/env)) -e GITHUB_ACTIONS -e COVERAGE"
echo "CI_ENV=${CI_ENV}"
sudo -E ./script/test cert_suite ${{ matrix.cert_scripts }} || (sudo chmod a+r *.log *.json *.pcap && false)
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-border-router-docker
path: /tmp/coverage/
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: thread-border-router-results
@@ -223,7 +223,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-border-router
path: tmp/coverage.info
@@ -234,7 +234,7 @@ jobs:
- thread-border-router
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
diff --git a/.github/workflows/otci.yml b/.github/workflows/otci.yml
index d7386c1f5..ece75a0dd 100644
--- a/.github/workflows/otci.yml
+++ b/.github/workflows/otci.yml
@@ -57,11 +57,11 @@ jobs:
REAL_DEVICE: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
diff --git a/.github/workflows/otns.yml b/.github/workflows/otns.yml
index 887123f24..9f4feaeeb 100644
--- a/.github/workflows/otns.yml
+++ b/.github/workflows/otns.yml
@@ -58,11 +58,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version: "1.20"
@@ -82,7 +82,7 @@ jobs:
cd /tmp/otns
./script/test py-unittests
)
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: unittests-pcaps
@@ -92,7 +92,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-otns-unittests
path: tmp/coverage.info
@@ -101,7 +101,7 @@ jobs:
name: Examples
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version: "1.20"
@@ -121,7 +121,7 @@ jobs:
cd /tmp/otns
./script/test py-examples
)
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: examples-pcaps
@@ -131,7 +131,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-otns-examples
path: tmp/coverage.info
@@ -159,11 +159,11 @@ jobs:
STRESS_LEVEL: ${{ matrix.stress_level }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version: "1.20"
@@ -183,7 +183,7 @@ jobs:
cd /tmp/otns
./script/test stress-tests ${{ matrix.suite }}
)
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: stress-tests-${{ matrix.suite }}-pcaps
@@ -193,7 +193,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-otns-stress-tests-${{ matrix.suite }}
path: tmp/coverage.info
@@ -206,11 +206,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y lcov
diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml
index 09ca9afbb..b019a255a 100644
--- a/.github/workflows/posix.yml
+++ b/.github/workflows/posix.yml
@@ -52,11 +52,11 @@ jobs:
CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov socat
@@ -75,7 +75,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_RCP=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED_RCP == '1' }}
with:
name: core-expect-rcp
@@ -84,7 +84,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-expects-linux-1
path: tmp/coverage.info
@@ -107,13 +107,13 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_TUN=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED_TUN == '1' }}
with:
name: core-expect-linux
path: |
./ot-core-dump/*
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: syslog-expect-linux
@@ -121,7 +121,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-expects-linux-2
path: tmp/coverage.info
@@ -135,11 +135,11 @@ jobs:
VIRTUAL_TIME: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -153,7 +153,7 @@ jobs:
- name: Run
run: |
MAX_JOBS=$(getconf _NPROCESSORS_ONLN) ./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: thread-cert
@@ -161,7 +161,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-cert
path: tmp/coverage.info
@@ -179,11 +179,11 @@ jobs:
OT_READLINE: 'readline'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo rm /etc/apt/sources.list.d/* && sudo apt-get update
@@ -211,7 +211,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-pty-linux-${{ matrix.DAEMON }}
path: tmp/coverage.info
@@ -228,11 +228,11 @@ jobs:
OT_READLINE: 'off'
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
rm -f /usr/local/bin/2to3
@@ -258,11 +258,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
@@ -278,7 +278,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-rcp-stack-reset
path: tmp/coverage.info
@@ -291,11 +291,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -318,7 +318,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 74368132f..76ce1c9d7 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -60,12 +60,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: "Run analysis"
- uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
+ uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
@@ -87,7 +87,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.0
+ uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.0
with:
name: SARIF file
path: results.sarif
@@ -95,6 +95,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@6a28655e3dcb49cb0840ea372fd6d17733edd8a4 # v2.1.27
+ uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.1.27
with:
sarif_file: results.sarif
diff --git a/.github/workflows/simulation-1.1.yml b/.github/workflows/simulation-1.1.yml
index cb238cdc2..3705ceb4d 100644
--- a/.github/workflows/simulation-1.1.yml
+++ b/.github/workflows/simulation-1.1.yml
@@ -55,11 +55,11 @@ jobs:
MULTIPLY: 3
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -76,7 +76,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: packet-verification-pcaps
@@ -86,7 +86,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-packet-verification
path: tmp/coverage.info
@@ -103,11 +103,11 @@ jobs:
VIRTUAL_TIME: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -121,7 +121,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: cli-ftd-thread-cert
@@ -129,7 +129,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-cli-ftd
path: tmp/coverage.info
@@ -153,11 +153,11 @@ jobs:
MESSAGE_USE_HEAP: ${{ matrix.message_use_heap }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -171,7 +171,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: cli-mtd-thread-cert
@@ -179,7 +179,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-cli-mtd-${{ matrix.message_use_heap }}
path: tmp/coverage.info
@@ -196,11 +196,11 @@ jobs:
VIRTUAL_TIME: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -214,7 +214,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: cli-time-sync-thread-cert
@@ -222,7 +222,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-cli-time-sync
path: tmp/coverage.info
@@ -235,11 +235,11 @@ jobs:
THREAD_VERSION: 1.1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Bootstrap
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov socat
@@ -254,7 +254,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED_CLI=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED_CLI == '1' }}
with:
name: core-expect-cli
@@ -263,7 +263,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-expects
path: tmp/coverage.info
@@ -274,11 +274,11 @@ jobs:
THREAD_VERSION: 1.1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -286,6 +286,7 @@ jobs:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
sudo rm /etc/apt/sources.list.d/*
+ sudo apt-get update
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 main
- name: Build
@@ -311,7 +312,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-ot-commissioner
path: tmp/coverage.info
@@ -325,11 +326,11 @@ jobs:
CXXFLAGS: "-DOPENTHREAD_CONFIG_LOG_PREPEND_UPTIME=0"
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -342,7 +343,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: ot_testing
@@ -350,7 +351,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-multiple-instance
path: tmp/coverage.info
@@ -367,11 +368,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -394,7 +395,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
diff --git a/.github/workflows/simulation-1.2.yml b/.github/workflows/simulation-1.2.yml
index 1ffd088f1..d88be6c5c 100644
--- a/.github/workflows/simulation-1.2.yml
+++ b/.github/workflows/simulation-1.2.yml
@@ -66,11 +66,11 @@ jobs:
arch: ["m32", "m64"]
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -95,12 +95,12 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-thread-1-3
@@ -109,7 +109,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage "${{ matrix.compiler.gcov }}"
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-1-3-${{ matrix.compiler.c }}-${{ matrix.arch }}
path: tmp/coverage.info
@@ -127,11 +127,11 @@ jobs:
INTER_OP_BBR: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -142,6 +142,9 @@ jobs:
- name: Build
run: |
./script/test build
+ - name: Build with OT_CSL_RECEIVER_LOCAL_TIME_SYNC
+ run: |
+ OT_BUILDDIR="${PWD}/build_csl_receiver_local_time_sync" OT_OPTIONS="-DOT_CSL_RECEIVER_LOCAL_TIME_SYNC=ON" ./script/test build
- name: Get Thread-Wireshark
run: |
./script/test get_thread_wireshark
@@ -153,20 +156,23 @@ jobs:
do
./script/test cert_suite ./tests/scripts/thread-cert/v1_2_LowPower*.py
done
+ - name: Run with OT_CSL_RECEIVER_LOCAL_TIME_SYNC
+ run: |
+ OT_BUILDDIR="${PWD}/build_csl_receiver_local_time_sync" ./script/test cert_suite ./tests/scripts/thread-cert/v1_2_LowPower*.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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: packet-verification-low-power-pcaps
path: |
*.pcap
*.json
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-packet-verification-low-power
@@ -175,7 +181,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-packet-verification-low-power
path: tmp/coverage.info
@@ -191,11 +197,11 @@ jobs:
MULTIPLY: 3
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -212,7 +218,7 @@ jobs:
- name: Run
run: |
./script/test cert_suite ./tests/scripts/thread-cert/Cert_*.py ./tests/scripts/thread-cert/test_*.py
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: packet-verification-1.1-on-1.3-pcaps
@@ -222,7 +228,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-packet-verification-1-1-on-1-3
path: tmp/coverage.info
@@ -235,11 +241,11 @@ jobs:
VIRTUAL_TIME: 0
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -256,7 +262,7 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-expect-1-3
@@ -265,7 +271,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-expects
path: tmp/coverage.info
@@ -283,11 +289,11 @@ jobs:
INTER_OP: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -314,12 +320,12 @@ jobs:
CRASHED=$(./script/test check_crash | tail -1)
[[ $CRASHED -eq "1" ]] && echo "Crashed!" || echo "Not crashed."
echo "CRASHED=$CRASHED" >> $GITHUB_ENV
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() }}
with:
name: thread-1-3-posix-pcaps
path: "*.pcap"
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ failure() && env.CRASHED == '1' }}
with:
name: core-thread-1-3-posix
@@ -328,7 +334,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-thread-1-3-posix
path: tmp/coverage.info
@@ -343,11 +349,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -370,7 +376,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
index 1b8a916c1..f0a364df3 100644
--- a/.github/workflows/size.yml
+++ b/.github/workflows/size.yml
@@ -49,11 +49,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run
env:
OT_BASE_BRANCH: "${{ github.base_ref }}"
@@ -67,3 +67,4 @@ jobs:
export OT_SIZE_REPORTER=./size-report
fi
./script/check-size
+ cat /tmp/ot-size-report/report_pr >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/toranj.yml b/.github/workflows/toranj.yml
index 2d7df1aa9..16e9e92e8 100644
--- a/.github/workflows/toranj.yml
+++ b/.github/workflows/toranj.yml
@@ -59,11 +59,11 @@ jobs:
TORANJ_EVENT_NAME: ${{ github.event_name }}
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -90,11 +90,11 @@ jobs:
TORANJ_CLI: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -111,7 +111,7 @@ jobs:
if: "matrix.TORANJ_RADIO != 'multi'"
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: "matrix.TORANJ_RADIO != 'multi'"
with:
name: cov-toranj-cli-${{ matrix.TORANJ_RADIO }}
@@ -122,11 +122,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -144,11 +144,19 @@ jobs:
ninja test
# Validate posix builds with different radio configs
git clean -dfx
+ ./tests/toranj/build.sh ncp-15.4
+ git clean -dfx
+ ./tests/toranj/build.sh ncp-trel
+ git clean -dfx
+ ./tests/toranj/build.sh ncp-15.4+trel
+ git clean -dfx
./tests/toranj/build.sh posix-15.4
git clean -dfx
./tests/toranj/build.sh posix-15.4+trel
git clean -dfx
./tests/toranj/build.sh posix-trel
+ git clean -dfx
+ ./tests/toranj/build.sh --enable-plat-key-ref all
upload-coverage:
needs:
@@ -156,11 +164,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -183,7 +191,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml
index b8e50ad14..1df2df537 100644
--- a/.github/workflows/unit.yml
+++ b/.github/workflows/unit.yml
@@ -49,11 +49,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Build
@@ -67,11 +67,11 @@ jobs:
COVERAGE: 1
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -82,6 +82,10 @@ jobs:
run: ./script/cmake-build simulation
- name: Test Simulation
run: cd build/simulation && ninja test
+ - name: Build Multipan Simulation
+ run: ./script/cmake-build simulation -DOT_MULTIPAN_TEST=ON
+ - name: Test Multipan Simulation
+ run: cd build/simulation && ninja test
- name: Build POSIX
run: ./script/cmake-build posix
- name: Test POSIX
@@ -89,7 +93,7 @@ jobs:
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: cov-unit-tests
path: tmp/coverage.info
@@ -100,11 +104,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Bootstrap
@@ -127,7 +131,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml
index 1b70f9fca..41a4e8db9 100644
--- a/.github/workflows/version.yml
+++ b/.github/workflows/version.yml
@@ -45,11 +45,11 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Harden Runner
- uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1
+ uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
submodules: true
- name: Check
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index a8eaeda9f..dc0912d33 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -2,45 +2,82 @@
## Our Pledge
-In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to creating a positive environment include:
+Examples of behavior that contributes to a positive environment for our community include:
-- Using welcoming and inclusive language
-- Being respectful of differing viewpoints and experiences
-- Gracefully accepting constructive criticism
-- Focusing on what is best for the community
-- Showing empathy towards other community members
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall community
-Examples of unacceptable behavior by participants include:
+Examples of unacceptable behavior include:
-- The use of sexualized language or imagery and unwelcome sexual attention or advances
-- Trolling, insulting/derogatory comments, and personal or political attacks
+- The use of sexualized language or imagery, and sexual attention or advances of any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
-- Publishing others' private information, such as a physical or electronic address, without explicit permission
+- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
-## Our Responsibilities
+## Enforcement Responsibilities
-Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
-This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at openthread-conduct@google.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at openthread-conduct@google.com. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of actions.
-Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][mozilla coc].
+
+For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][faq]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
-[homepage]: http://contributor-covenant.org
-[version]: http://contributor-covenant.org/version/1/4/
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[mozilla coc]: https://github.com/mozilla/diversity
+[faq]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h
index d6ce51e47..84e48c800 100644
--- a/doc/ot_api_doc.h
+++ b/doc/ot_api_doc.h
@@ -176,6 +176,7 @@
* @defgroup plat-memory Memory
* @defgroup plat-messagepool Message Pool
* @defgroup plat-misc Miscellaneous
+ * @defgroup plat-multipan Multipan
* @defgroup plat-otns Network Simulator
* @defgroup plat-radio Radio
* @defgroup plat-settings Settings
diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake
index 0c667d0ee..3b5a155d3 100644
--- a/etc/cmake/options.cmake
+++ b/etc/cmake/options.cmake
@@ -188,6 +188,7 @@ ot_option(OT_COMMISSIONER OPENTHREAD_CONFIG_COMMISSIONER_ENABLE "commissioner")
ot_option(OT_CSL_AUTO_SYNC OPENTHREAD_CONFIG_MAC_CSL_AUTO_SYNC_ENABLE "data polling based on csl")
ot_option(OT_CSL_DEBUG OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE "csl debug")
ot_option(OT_CSL_RECEIVER OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE "csl receiver")
+ot_option(OT_CSL_RECEIVER_LOCAL_TIME_SYNC OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC "use local time for csl elapsed sync time")
ot_option(OT_DATASET_UPDATER OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE "dataset updater")
ot_option(OT_DEVICE_PROP_LEADER_WEIGHT OPENTHREAD_CONFIG_MLE_DEVICE_PROPERTY_LEADER_WEIGHT_ENABLE "device prop for leader weight")
ot_option(OT_DHCP6_CLIENT OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE "DHCP6 client")
@@ -225,6 +226,8 @@ ot_option(OT_NETDIAG_CLIENT OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE "Network
ot_option(OT_OPERATIONAL_DATASET_AUTO_INIT OPENTHREAD_CONFIG_OPERATIONAL_DATASET_AUTO_INIT "operational dataset auto init")
ot_option(OT_OTNS OPENTHREAD_CONFIG_OTNS_ENABLE "OTNS")
ot_option(OT_PING_SENDER OPENTHREAD_CONFIG_PING_SENDER_ENABLE "ping sender" ${OT_APP_CLI})
+ot_option(OT_PLATFORM_BOOTLOADER_MODE OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE "platform bootloader mode")
+ot_option(OT_PLATFORM_KEY_REF OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE "platform key reference secure storage")
ot_option(OT_PLATFORM_NETIF OPENTHREAD_CONFIG_PLATFORM_NETIF_ENABLE "platform netif")
ot_option(OT_PLATFORM_UDP OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE "platform UDP")
ot_option(OT_REFERENCE_DEVICE OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE "test harness reference device")
@@ -243,7 +246,7 @@ ot_option(OT_UDP_FORWARD OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE "UDP forward")
ot_option(OT_UPTIME OPENTHREAD_CONFIG_UPTIME_ENABLE "uptime")
option(OT_DOC "build OpenThread documentation")
-
+option(OT_MULTIPAN_RCP "Multi-PAN RCP" OFF)
message(STATUS "- - - - - - - - - - - - - - - - ")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/examples/apps/cli/main.c b/examples/apps/cli/main.c
index 461d987c1..62f7e3f1b 100644
--- a/examples/apps/cli/main.c
+++ b/examples/apps/cli/main.c
@@ -27,6 +27,11 @@
*/
#include <assert.h>
+#ifdef __linux__
+#include <signal.h>
+#include <sys/prctl.h>
+#endif
+
#include <openthread-core-config.h>
#include <openthread/config.h>
@@ -97,6 +102,12 @@ int main(int argc, char *argv[])
{
otInstance *instance;
+#ifdef __linux__
+ // Ensure we terminate this process if the
+ // parent process dies.
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+#endif
+
OT_SETUP_RESET_JUMP(argv);
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
diff --git a/examples/apps/ncp/main.c b/examples/apps/ncp/main.c
index 0f3889511..5f59261e8 100644
--- a/examples/apps/ncp/main.c
+++ b/examples/apps/ncp/main.c
@@ -27,6 +27,11 @@
*/
#include <assert.h>
+#ifdef __linux__
+#include <signal.h>
+#include <sys/prctl.h>
+#endif
+
#include <openthread-core-config.h>
#include <openthread/config.h>
@@ -37,6 +42,16 @@
#include "openthread-system.h"
#include "lib/platform/reset_util.h"
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE == 0
+#error "Support for multiple OpenThread static instance is disabled."
+#endif
+#define ENDPOINT_CT OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM
+#else
+#define ENDPOINT_CT 1
+#endif /* OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE */
+
/**
* Initializes the NCP app.
*
@@ -44,6 +59,7 @@
*
*/
extern void otAppNcpInit(otInstance *aInstance);
+extern void otAppNcpInitMulti(otInstance **aInstances, uint8_t count);
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_TOOL_WEAK void *otPlatCAlloc(size_t aNum, size_t aSize) { return calloc(aNum, aSize); }
@@ -59,7 +75,15 @@ int main(int argc, char *argv[])
OT_SETUP_RESET_JUMP(argv);
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#ifdef __linux__
+ // Ensure we terminate this process if the
+ // parent process dies.
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+#endif
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ otInstance *instances[ENDPOINT_CT] = {NULL};
+#elif OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
size_t otInstanceBufferLength = 0;
uint8_t *otInstanceBuffer = NULL;
#endif
@@ -68,7 +92,16 @@ pseudo_reset:
otSysInit(argc, argv);
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ for (int i = 0; i < ENDPOINT_CT; i++)
+ {
+ instances[i] = otInstanceInitMultiple(i);
+
+ assert(instances[i]);
+ }
+ instance = instances[0];
+#elif OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+
// Call to query the buffer size
(void)otInstanceInit(NULL, &otInstanceBufferLength);
@@ -83,7 +116,11 @@ pseudo_reset:
#endif
assert(instance);
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ otAppNcpInitMulti(instances, ENDPOINT_CT);
+#else
otAppNcpInit(instance);
+#endif
while (!otSysPseudoResetWasRequested())
{
@@ -92,7 +129,7 @@ pseudo_reset:
}
otInstanceFinalize(instance);
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && !OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
free(otInstanceBuffer);
#endif
diff --git a/examples/apps/ncp/ncp.c b/examples/apps/ncp/ncp.c
index df6529a3a..38c95b42d 100644
--- a/examples/apps/ncp/ncp.c
+++ b/examples/apps/ncp/ncp.c
@@ -61,4 +61,17 @@ void otAppNcpInit(otInstance *aInstance)
otNcpHdlcInit(aInstance, NcpSend);
#endif
}
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+void otAppNcpInitMulti(otInstance **aInstances, uint8_t aCount)
+{
+#if OPENTHREAD_CONFIG_NCP_SPI_ENABLE
+#error Multipan support not implemented for SPI
+#else
+ IgnoreError(otPlatUartEnable());
+
+ otNcpHdlcInitMulti(aInstances, aCount, NcpSend);
+#endif
+}
+#endif
#endif // !OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt
index c99597d4a..439fcb9d4 100644
--- a/examples/platforms/simulation/CMakeLists.txt
+++ b/examples/platforms/simulation/CMakeLists.txt
@@ -68,6 +68,7 @@ add_library(openthread-simulation
infra_if.c
logging.c
misc.c
+ multipan.c
radio.c
spi-stubs.c
system.c
diff --git a/examples/platforms/simulation/crypto.c b/examples/platforms/simulation/crypto.c
index b220f7cb5..20c151b46 100644
--- a/examples/platforms/simulation/crypto.c
+++ b/examples/platforms/simulation/crypto.c
@@ -81,4 +81,41 @@ bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
return false;
}
+otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
+{
+ OT_UNUSED_VARIABLE(aKeyRef);
+
+ return OT_ERROR_NONE;
+}
+
+otError otPlatCryptoEcdsaExportPublicKey(otCryptoKeyRef aKeyRef, otPlatCryptoEcdsaPublicKey *aPublicKey)
+{
+ OT_UNUSED_VARIABLE(aKeyRef);
+ OT_UNUSED_VARIABLE(aPublicKey);
+
+ return OT_ERROR_NONE;
+}
+
+otError otPlatCryptoEcdsaSignUsingKeyRef(otCryptoKeyRef aKeyRef,
+ const otPlatCryptoSha256Hash *aHash,
+ otPlatCryptoEcdsaSignature *aSignature)
+{
+ OT_UNUSED_VARIABLE(aKeyRef);
+ OT_UNUSED_VARIABLE(aHash);
+ OT_UNUSED_VARIABLE(aSignature);
+
+ return OT_ERROR_NONE;
+}
+
+otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKeyRef,
+ const otPlatCryptoSha256Hash *aHash,
+ const otPlatCryptoEcdsaSignature *aSignature)
+{
+ OT_UNUSED_VARIABLE(aKeyRef);
+ OT_UNUSED_VARIABLE(aHash);
+ OT_UNUSED_VARIABLE(aSignature);
+
+ return OT_ERROR_NONE;
+}
+
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
diff --git a/examples/platforms/simulation/misc.c b/examples/platforms/simulation/misc.c
index aefbca5de..07739a2fe 100644
--- a/examples/platforms/simulation/misc.c
+++ b/examples/platforms/simulation/misc.c
@@ -60,6 +60,15 @@ void otPlatReset(otInstance *aInstance)
#endif // OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
}
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+otError otPlatResetToBootloader(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ return OT_ERROR_NOT_CAPABLE;
+}
+#endif
+
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
diff --git a/examples/platforms/simulation/multipan.c b/examples/platforms/simulation/multipan.c
new file mode 100644
index 000000000..1c173dfe0
--- /dev/null
+++ b/examples/platforms/simulation/multipan.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "platform-simulation.h"
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include <openthread/platform/multipan.h>
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+static otInstance *sActiveInstance;
+#endif
+
+otError otPlatMultipanGetActiveInstance(otInstance **aInstance)
+{
+ otError error = OT_ERROR_NOT_IMPLEMENTED;
+ OT_UNUSED_VARIABLE(aInstance);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ *aInstance = sActiveInstance;
+ error = OT_ERROR_NONE;
+#endif
+
+ return error;
+}
+
+otError otPlatMultipanSetActiveInstance(otInstance *aInstance, bool aCompletePending)
+{
+ otError error = OT_ERROR_NOT_IMPLEMENTED;
+
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aCompletePending);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ sActiveInstance = aInstance;
+ error = OT_ERROR_NONE;
+#endif
+
+ return error;
+}
diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn
index 5bc1c0967..e4760c29c 100644
--- a/include/openthread/BUILD.gn
+++ b/include/openthread/BUILD.gn
@@ -97,6 +97,7 @@ source_set("openthread") {
"platform/memory.h",
"platform/messagepool.h",
"platform/misc.h",
+ "platform/multipan.h",
"platform/otns.h",
"platform/radio.h",
"platform/settings.h",
diff --git a/include/openthread/border_routing.h b/include/openthread/border_routing.h
index 36e83a6d0..3fd95c6ad 100644
--- a/include/openthread/border_routing.h
+++ b/include/openthread/border_routing.h
@@ -89,21 +89,33 @@ typedef struct otBorderRoutingPrefixTableIterator
} otBorderRoutingPrefixTableIterator;
/**
+ * Represents a discovered router on the infrastructure link.
+ *
+ */
+typedef struct otBorderRoutingRouterEntry
+{
+ otIp6Address mAddress; ///< IPv6 address of the router.
+ bool mManagedAddressConfigFlag : 1; ///< The router's Managed Address Config flag (`M` flag).
+ bool mOtherConfigFlag : 1; ///< The router's Other Config flag (`O` flag).
+ bool mStubRouterFlag : 1; ///< The router's Stub Router flag.
+} otBorderRoutingRouterEntry;
+
+/**
* Represents an entry from the discovered prefix table.
*
* The entries in the discovered table track the Prefix/Route Info Options in the received Router Advertisement messages
- * from other routers on infrastructure link.
+ * from other routers on the infrastructure link.
*
*/
typedef struct otBorderRoutingPrefixTableEntry
{
- otIp6Address mRouterAddress; ///< IPv6 address of the router.
- otIp6Prefix mPrefix; ///< The discovered IPv6 prefix.
- bool mIsOnLink; ///< Indicates whether the prefix is on-link or route prefix.
- uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
- uint32_t mValidLifetime; ///< Valid lifetime of the prefix (in seconds).
- otRoutePreference mRoutePreference; ///< Route preference when `mIsOnlink` is false.
- uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink` is true.
+ otBorderRoutingRouterEntry mRouter; ///< Information about the router advertising this prefix.
+ otIp6Prefix mPrefix; ///< The discovered IPv6 prefix.
+ bool mIsOnLink; ///< Indicates whether the prefix is on-link or route prefix.
+ uint32_t mMsecSinceLastUpdate; ///< Milliseconds since last update of this prefix.
+ uint32_t mValidLifetime; ///< Valid lifetime of the prefix (in seconds).
+ otRoutePreference mRoutePreference; ///< Route preference when `mIsOnlink` is false.
+ uint32_t mPreferredLifetime; ///< Preferred lifetime of the on-link prefix when `mIsOnLink`.
} otBorderRoutingPrefixTableEntry;
/**
@@ -391,6 +403,9 @@ void otBorderRoutingPrefixTableInitIterator(otInstance *aInstance, otBorderRouti
/**
* Iterates over the entries in the Border Router's discovered prefix table.
*
+ * Prefix entries associated with the same discovered router on an infrastructure link are guaranteed to be grouped
+ * together (retrieved back-to-back).
+ *
* @param[in] aInstance The OpenThread instance.
* @param[in,out] aIterator A pointer to the iterator.
* @param[out] aEntry A pointer to the entry to populate.
@@ -404,6 +419,21 @@ otError otBorderRoutingGetNextPrefixTableEntry(otInstance
otBorderRoutingPrefixTableEntry *aEntry);
/**
+ * Iterates over the discovered router entries on the infrastructure link.
+ *
+ * @param[in] aInstance The OpenThread instance.
+ * @param[in,out] aIterator A pointer to the iterator.
+ * @param[out] aEntry A pointer to the entry to populate.
+ *
+ * @retval OT_ERROR_NONE Iterated to the next router, @p aEntry and @p aIterator are updated.
+ * @retval OT_ERROR_NOT_FOUND No more router entries.
+ *
+ */
+otError otBorderRoutingGetNextRouterEntry(otInstance *aInstance,
+ otBorderRoutingPrefixTableIterator *aIterator,
+ otBorderRoutingRouterEntry *aEntry);
+
+/**
* Enables / Disables DHCPv6 Prefix Delegation.
*
* `OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE` must be enabled.
@@ -415,6 +445,18 @@ otError otBorderRoutingGetNextPrefixTableEntry(otInstance
void otBorderRoutingDhcp6PdSetEnabled(otInstance *aInstance, bool aEnabled);
/**
+ * Gets the current state of DHCPv6 Prefix Delegation.
+ *
+ * Requires `OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE` to be enabled.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @returns The current state of DHCPv6 Prefix Delegation.
+ *
+ */
+otBorderRoutingDhcp6PdState otBorderRoutingDhcp6PdGetState(otInstance *aInstance);
+
+/**
* @}
*
*/
diff --git a/include/openthread/commissioner.h b/include/openthread/commissioner.h
index 9f714b389..410bd0f70 100644
--- a/include/openthread/commissioner.h
+++ b/include/openthread/commissioner.h
@@ -111,6 +111,7 @@ typedef struct otCommissioningDataset
bool mIsSessionIdSet : 1; ///< TRUE if Commissioner Session Id is set, FALSE otherwise.
bool mIsSteeringDataSet : 1; ///< TRUE if Steering Data is set, FALSE otherwise.
bool mIsJoinerUdpPortSet : 1; ///< TRUE if Joiner UDP Port is set, FALSE otherwise.
+ bool mHasExtraTlv : 1; ///< TRUE if the Dataset contains any extra unknown sub-TLV, FALSE otherwise.
} otCommissioningDataset;
#define OT_JOINER_MAX_PSKD_LENGTH 32 ///< Maximum string length of a Joiner PSKd (does not include null char).
diff --git a/include/openthread/dns.h b/include/openthread/dns.h
index 93fd287d7..0d02dd27e 100644
--- a/include/openthread/dns.h
+++ b/include/openthread/dns.h
@@ -62,6 +62,8 @@ extern "C" {
#define OT_DNS_TXT_KEY_MAX_LENGTH 9 ///< Recommended maximum length of TXT record key string (RFC 6763 - section 6.4).
+#define OT_DNS_TXT_KEY_ITER_MAX_LENGTH 64 ///< Maximum length of TXT key string supported by `otDnsTxtEntryIterator`.
+
/**
* Represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3).
*
@@ -104,7 +106,7 @@ typedef struct otDnsTxtEntryIterator
{
const void *mPtr;
uint16_t mData[2];
- char mChar[OT_DNS_TXT_KEY_MAX_LENGTH + 1];
+ char mChar[OT_DNS_TXT_KEY_ITER_MAX_LENGTH + 1];
} otDnsTxtEntryIterator;
/**
@@ -127,9 +129,9 @@ void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t *
* 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`.
+ * If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_ITER_MAX_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).
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index d450a0218..b67b303f1 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
-#define OPENTHREAD_API_VERSION (363)
+#define OPENTHREAD_API_VERSION (379)
/**
* @addtogroup api-instance
@@ -103,6 +103,23 @@ otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize);
otInstance *otInstanceInitSingle(void);
/**
+ * Initializes the OpenThread instance.
+ *
+ * This function initializes OpenThread and prepares it for subsequent OpenThread API calls. This function must be
+ * called before any other calls to OpenThread. This method utilizes static buffer to initialize the OpenThread
+ * instance.
+ *
+ * This function is available and can only be used when support for multiple OpenThread static instances is
+ * enabled (`OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE`)
+ *
+ * @param[in] aIdx The index of the OpenThread instance to initialize.
+ *
+ * @returns A pointer to the new OpenThread instance.
+ *
+ */
+otInstance *otInstanceInitMultiple(uint8_t aIdx);
+
+/**
* Gets the instance identifier.
*
* The instance identifier is set to a random value when the instance is constructed, and then its value will not
@@ -256,6 +273,20 @@ void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback a
void otInstanceReset(otInstance *aInstance);
/**
+ * Triggers a platform reset to bootloader mode, if supported.
+ *
+ * Requires `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE`.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ *
+ * @retval OT_ERROR_NONE Reset to bootloader successfully.
+ * @retval OT_ERROR_BUSY Failed due to another operation is ongoing.
+ * @retval OT_ERROR_NOT_CAPABLE Not capable of resetting to bootloader.
+ *
+ */
+otError otInstanceResetToBootloader(otInstance *aInstance);
+
+/**
* Deletes all the settings stored on non-volatile memory, and then triggers a platform reset.
*
* @param[in] aInstance A pointer to an OpenThread instance.
diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h
index 35c11057e..850c64c6b 100644
--- a/include/openthread/ip6.h
+++ b/include/openthread/ip6.h
@@ -144,6 +144,8 @@ struct otIp6Address
typedef struct otIp6Address otIp6Address;
/**
+ * @struct otIp6Prefix
+ *
* Represents an IPv6 prefix.
*
*/
@@ -178,15 +180,16 @@ enum
*/
typedef struct otNetifAddress
{
- otIp6Address mAddress; ///< The IPv6 unicast address.
- uint8_t mPrefixLength; ///< The Prefix length (in bits).
- uint8_t mAddressOrigin; ///< The IPv6 address origin.
- bool mPreferred : 1; ///< TRUE if the address is preferred, FALSE otherwise.
- bool mValid : 1; ///< TRUE if the address is valid, FALSE otherwise.
- bool mScopeOverrideValid : 1; ///< TRUE if the mScopeOverride value is valid, FALSE otherwise.
- unsigned int mScopeOverride : 4; ///< The IPv6 scope of this address.
- bool mRloc : 1; ///< TRUE if the address is an RLOC, FALSE otherwise.
- struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
+ otIp6Address mAddress; ///< The IPv6 unicast address.
+ uint8_t mPrefixLength; ///< The Prefix length (in bits).
+ uint8_t mAddressOrigin; ///< The IPv6 address origin.
+ bool mPreferred : 1; ///< TRUE if the address is preferred, FALSE otherwise.
+ bool mValid : 1; ///< TRUE if the address is valid, FALSE otherwise.
+ bool mScopeOverrideValid : 1; ///< TRUE if the mScopeOverride value is valid, FALSE otherwise.
+ unsigned int mScopeOverride : 4; ///< The IPv6 scope of this address.
+ bool mRloc : 1; ///< TRUE if the address is an RLOC, FALSE otherwise.
+ bool mMeshLocal : 1; ///< TRUE if the address is mesh-local, FALSE otherwise.
+ const struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
} otNetifAddress;
/**
@@ -296,6 +299,7 @@ bool otIp6IsEnabled(otInstance *aInstance);
* @retval OT_ERROR_NONE Successfully added (or updated) the Network Interface Address.
* @retval OT_ERROR_INVALID_ARGS The IP Address indicated by @p aAddress is an internal address.
* @retval OT_ERROR_NO_BUFS The Network Interface is already storing the maximum allowed external addresses.
+ *
*/
otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress);
@@ -308,6 +312,7 @@ otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAdd
* @retval OT_ERROR_NONE Successfully removed the Network Interface Address.
* @retval OT_ERROR_INVALID_ARGS The IP Address indicated by @p aAddress is an internal address.
* @retval OT_ERROR_NOT_FOUND The IP Address indicated by @p aAddress was not found.
+ *
*/
otError otIp6RemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
@@ -317,10 +322,23 @@ otError otIp6RemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAd
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the first Network Interface Address.
+ *
*/
const otNetifAddress *otIp6GetUnicastAddresses(otInstance *aInstance);
/**
+ * Indicates whether or not a unicast IPv6 address is assigned to the Thread interface.
+ *
+ * @param[in] aInstance A pointer to an OpenThread instance.
+ * @param[in] aAddress A pointer to the unicast address.
+ *
+ * @retval TRUE If @p aAddress is assigned to the Thread interface.
+ * @retval FALSE If @p aAddress is not assigned to the Thread interface.
+ *
+ */
+bool otIp6HasUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
+
+/**
* Subscribes the Thread interface to a Network Interface Multicast Address.
*
* The passed in instance @p aAddress will be copied by the Thread interface. The Thread interface only
@@ -450,8 +468,6 @@ typedef void (*otIp6ReceiveCallback)(otMessage *aMessage, void *aContext);
void otIp6SetReceiveCallback(otInstance *aInstance, otIp6ReceiveCallback aCallback, void *aCallbackContext);
/**
- * @struct otIp6AddressInfo
- *
* Represents IPv6 address information.
*
*/
@@ -528,7 +544,7 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled);
* @retval OT_ERROR_INVALID_SOURCE_ADDRESS Source address is invalid, e.g. an anycast address or a multicast address.
* @retval OT_ERROR_PARSE Encountered a malformed header when processing the message.
* @retval OT_ERROR_INVALID_ARGS The message's metadata is invalid, e.g. the message uses
- * `OT_MESSAGE_ORIGIN_THREAD_NETIF` as the origin.
+ * `OT_MESSAGE_ORIGIN_THREAD_NETIF` as the origin.
*
*/
otError otIp6Send(otInstance *aInstance, otMessage *aMessage);
@@ -849,7 +865,7 @@ otError otIp6RegisterMulticastListeners(otInstance *
/**
* Sets the Mesh Local IID (for test purpose).
*
- * `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` must be enabled.
+ * Requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE`.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aIid A pointer to the Mesh Local IID to set.
diff --git a/include/openthread/logging.h b/include/openthread/logging.h
index 143a0d511..c0fb61002 100644
--- a/include/openthread/logging.h
+++ b/include/openthread/logging.h
@@ -202,6 +202,45 @@ void otDumpInfoPlat(const char *aText, const void *aData, uint16_t aDataLength);
void otDumpDebgPlat(const char *aText, const void *aData, uint16_t aDataLength);
/**
+ * Emits a log message at given log level using a platform module name.
+ *
+ * This is is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below @p aLogLevel , this function does not emit any log message.
+ *
+ * The @p aPlatModuleName name is used to determine the log module name in the emitted log message, following the
+ * `P-{PlatModuleName}---` format. This means that the prefix string "P-" is added to indicate that this is a platform
+ * sub-module, followed by the next 12 characters of the @p PlatModuleName string, with padded hyphens `-` at the end
+ * to ensure that the region name is 14 characters long.
+
+ * @param[in] aLogLevel The log level.
+ * @param[in] aPlatModuleName The platform sub-module name.
+ * @param[in] aFormat The format string.
+ * @param[in] ... Arguments for the format specification.
+ *
+ */
+void otLogPlat(otLogLevel aLogLevel, const char *aPlatModuleName, const char *aFormat, ...)
+ OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(3, 4);
+
+/**
+ * Emits a log message at given log level using a platform module name.
+ *
+ * This is is intended for use by platform. If `OPENTHREAD_CONFIG_LOG_PLATFORM` is not set or the current log
+ * level is below @p aLogLevel , this function does not emit any log message.
+ *
+ * The @p aPlatModuleName name is used to determine the log module name in the emitted log message, following the
+ * `P-{PlatModuleName}---` format. This means that the prefix string "P-" is added to indicate that this is a platform
+ * sub-module, followed by the next 12 characters of the @p PlatModuleName string, with padded hyphens `-` at the end
+ * to ensure that the region name is 14 characters long.
+ *
+ * @param[in] aLogLevel The log level.
+ * @param[in] aPlatModuleName The platform sub-module name.
+ * @param[in] aFormat The format string.
+ * @param[in] aArgs Arguments for the format specification.
+ *
+ */
+void otLogPlatArgs(otLogLevel aLogLevel, const char *aPlatModuleName, const char *aFormat, va_list aArgs);
+
+/**
* Emits a log message at a given log level.
*
* Is intended for use by CLI only. If `OPENTHREAD_CONFIG_LOG_CLI` is not set or the current log
@@ -214,6 +253,45 @@ void otDumpDebgPlat(const char *aText, const void *aData, uint16_t aDataLength);
*/
void otLogCli(otLogLevel aLogLevel, const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 3);
+#define OT_LOG_HEX_DUMP_LINE_SIZE 73 ///< Hex dump line string size.
+
+/**
+ * Represents information used for generating hex dump output.
+ *
+ */
+typedef struct
+{
+ const uint8_t *mDataBytes; ///< The data byes.
+ uint16_t mDataLength; ///< The data length (number of bytes in @p mDataBytes)
+ const char *mTitle; ///< Title string to add table header (MUST NOT be `NULL`).
+ char mLine[OT_LOG_HEX_DUMP_LINE_SIZE]; ///< Buffer to output one line of generated hex dump.
+ uint16_t mIterator; ///< Iterator used by OT stack. MUST be initialized to zero.
+} otLogHexDumpInfo;
+
+/**
+ * Generates the next hex dump line.
+ *
+ * Can call this method back-to-back to generate the hex dump output line by line. On the first call the `mIterator`
+ * field in @p aInfo MUST be set to zero.
+ *
+ * Here is an example of the generated hex dump output:
+ *
+ * "==========================[{mTitle} len=070]============================"
+ * "| 41 D8 87 34 12 FF FF 25 | 4C 57 DA F2 FB 2F 62 7F | A..4...%LW.../b. |"
+ * "| 3B 01 F0 4D 4C 4D 4C 54 | 4F 00 15 15 00 00 00 00 | ;..MLMLTO....... |"
+ * "| 00 00 00 01 80 DB 60 82 | 7E 33 72 3B CC B3 A1 84 | ......`.~3r;.... |"
+ * "| 3B E6 AD B2 0B 45 E7 45 | C5 B9 00 1A CB 2D 6D 1C | ;....E.E.....-m. |"
+ * "| 10 3E 3C F5 D3 70 | | .><..p |"
+ * "------------------------------------------------------------------------"
+ *
+ * @param[in,out] aInfo A pointer to `otLogHexDumpInfo` to use to generate hex dump.
+ *
+ * @retval OT_ERROR_NONE Successfully generated the next line, `mLine` field in @p aInfo is updated.
+ * @retval OT_ERROR_NOT_FOUND Reached the end and no more line to generate.
+ *
+ */
+otError otLogGenerateNextHexDumpLine(otLogHexDumpInfo *aInfo);
+
/**
* @}
*
diff --git a/include/openthread/message.h b/include/openthread/message.h
index 99dc49cf1..3c2938c45 100644
--- a/include/openthread/message.h
+++ b/include/openthread/message.h
@@ -212,6 +212,28 @@ bool otMessageIsLoopbackToHostAllowed(const otMessage *aMessage);
void otMessageSetLoopbackToHostAllowed(otMessage *aMessage, bool aAllowLoopbackToHost);
/**
+ * Indicates whether the given message may be looped back in a case of a multicast destination address.
+ *
+ * If @p aMessage is used along with an `otMessageInfo`, the `mMulticastLoop` field from `otMessageInfo` structure
+ * takes precedence and will be used instead of the the value set on @p aMessage.
+ *
+ * This API is mainly intended for use along with `otIp6Send()` which expects an already prepared IPv6 message.
+ *
+ * @param[in] aMessage A pointer to the message.
+ *
+ */
+bool otMessageIsMulticastLoopEnabled(otMessage *aMessage);
+
+/**
+ * Controls whether the given message may be looped back in a case of a multicast destination address.
+ *
+ * @param[in] aMessage A pointer to the message.
+ * @param[in] aEnabled The configuration value.
+ *
+ */
+void otMessageSetMulticastLoopEnabled(otMessage *aMessage, bool aEnabled);
+
+/**
* Gets the message origin.
*
* @param[in] aMessage A pointer to a message buffer.
diff --git a/include/openthread/ncp.h b/include/openthread/ncp.h
index 7e07fa290..8c810fc84 100644
--- a/include/openthread/ncp.h
+++ b/include/openthread/ncp.h
@@ -90,6 +90,16 @@ void otNcpHdlcReceive(const uint8_t *aBuf, uint16_t aBufLength);
void otNcpHdlcInit(otInstance *aInstance, otNcpHdlcSendCallback aSendCallback);
/**
+ * Initialize the NCP based on HDLC framing.
+ *
+ * @param[in] aInstances The OpenThread instance pointers array.
+ * @param[in] aCount Number of elements in the array.
+ * @param[in] aSendCallback The function pointer used to send NCP data.
+ *
+ */
+void otNcpHdlcInitMulti(otInstance **aInstance, uint8_t aCount, otNcpHdlcSendCallback aSendCallback);
+
+/**
* Initialize the NCP based on SPI framing.
*
* @param[in] aInstance The OpenThread instance structure.
diff --git a/include/openthread/netdata.h b/include/openthread/netdata.h
index aae61148a..08bf504a9 100644
--- a/include/openthread/netdata.h
+++ b/include/openthread/netdata.h
@@ -35,6 +35,7 @@
#ifndef OPENTHREAD_NETDATA_H_
#define OPENTHREAD_NETDATA_H_
+#include <openthread/commissioner.h>
#include <openthread/ip6.h>
#ifdef __cplusplus
@@ -243,6 +244,15 @@ otError otNetDataGetNextLowpanContextInfo(otInstance *aInstance,
otLowpanContextInfo *aContextInfo);
/**
+ * Gets the Commissioning Dataset from the partition's Network Data.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[out] aDataset A pointer to a `otCommissioningDataset` to populate.
+ *
+ */
+void otNetDataGetCommissioningDataset(otInstance *aInstance, otCommissioningDataset *aDataset);
+
+/**
* Get the Network Data Version.
*
* @param[in] aInstance A pointer to an OpenThread instance.
diff --git a/include/openthread/ping_sender.h b/include/openthread/ping_sender.h
index 174cccc25..28b5f9a6c 100644
--- a/include/openthread/ping_sender.h
+++ b/include/openthread/ping_sender.h
@@ -120,6 +120,7 @@ typedef struct otPingSenderConfig
///< 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.
+ bool mMulticastLoop; ///< Allow looping back pings to multicast address that device is subscribed to.
} otPingSenderConfig;
/**
diff --git a/include/openthread/platform/misc.h b/include/openthread/platform/misc.h
index 7fbee54b1..b1b202111 100644
--- a/include/openthread/platform/misc.h
+++ b/include/openthread/platform/misc.h
@@ -62,6 +62,20 @@ extern "C" {
void otPlatReset(otInstance *aInstance);
/**
+ * Performs a hardware reset on the platform to launch bootloader mode, if supported.
+ *
+ * Used when `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE` is enabled.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ * @retval OT_ERROR_NONE Reset to bootloader successfully.
+ * @retval OT_ERROR_BUSY Failed due to another operation is ongoing.
+ * @retval OT_ERROR_NOT_CAPABLE Not capable of resetting to bootloader.
+ *
+ */
+otError otPlatResetToBootloader(otInstance *aInstance);
+
+/**
* Enumeration of possible reset reason codes.
*
* These are in the same order as the Spinel reset reason codes.
diff --git a/include/openthread/platform/multipan.h b/include/openthread/platform/multipan.h
new file mode 100644
index 000000000..69cd9839c
--- /dev/null
+++ b/include/openthread/platform/multipan.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief
+ * This file defines the multipan interface for OpenThread.
+ *
+ * Multipan RCP is a feature that allows single RCP operate in multiple networks.
+ *
+ * Currently we support two types of multipan RCP:
+ * - Full multipan: RCP operates in parallel on both networks (for example using more than one transceiver)
+ * - Switching RCP: RCP can communicate only with one network at a time and requires network switching mechanism.
+ * Switching can be automatic (for example time based, radio sleep based) or manually contolled by
+ * the host.
+ *
+ * Full multipan RCP and Automatic Switching RCP do not require any special care from the host side.
+ * Manual Switching RCP requires host to switch currently active network.
+ *
+ */
+
+#ifndef OPENTHREAD_PLATFORM_MULTIPAN_H_
+#define OPENTHREAD_PLATFORM_MULTIPAN_H_
+
+#include <stdint.h>
+
+#include <openthread/error.h>
+#include <openthread/instance.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup plat-multipan
+ *
+ * @brief
+ * This module includes the platform abstraction for multipan support.
+ *
+ * @{
+ *
+ */
+
+/**
+ * Get instance currently in control of the radio.
+ *
+ * If radio does not operate in parallel on all interfaces, this function returns an instance object with granted
+ * radio access.
+ *
+ * @param[out] aInstance Pointer to the variable for storing the active instance pointer.
+ *
+ * @retval OT_ERROR_NONE Successfully retrieved the property.
+ * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to lack of the support in radio.
+ * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously.
+ *
+ */
+otError otPlatMultipanGetActiveInstance(otInstance **aInstance);
+
+/**
+ * Set `aInstance` as the current active instance controlling radio.
+ *
+ * This function allows selecting the currently active instance on platforms that do not support parallel
+ * communication on multiple interfaces. In other words, if more than one instance is in a receive state, calling
+ * #otPlatMultipanSetActiveInstance guarantees that specified instance will be the one receiving. This function returns
+ * if the request was received properly. After interface switching is complete, the platform should call
+ * #otPlatMultipanSwitchoverDone. Switching interfaces may take longer if `aCompletePending` is set true.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aCompletePending True if ongoing radio operation should complete before interface switch (Soft switch),
+ * false for force switch.
+ *
+ * @retval OT_ERROR_NONE Successfully set the property.
+ * @retval OT_ERROR_BUSY Failed due to another operation ongoing.
+ * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to unknown instance or more instances than interfaces available.
+ * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously.
+ * @retval OT_ERROR_ALREADY Given interface is already active.
+ *
+ */
+otError otPlatMultipanSetActiveInstance(otInstance *aInstance, bool aCompletePending);
+
+/**
+ * The platform completed the interface switching procedure.
+ *
+ * Should be invoked immediately after processing #otPlatMultipanSetActiveInstance if no delay is needed, or if
+ * some longer radio operations need to complete first, after the switch in interfaces is fully complete.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aSuccess True if successfully switched the interfaces, false if switching failed.
+ *
+ */
+extern void otPlatMultipanSwitchoverDone(otInstance *aInstance, bool aSuccess);
+
+/**
+ * Get the instance pointer corresponding to the given IID.
+ *
+ * @param[in] aIid The IID of the interface.
+ *
+ * @retval Instance pointer if aIid is has an instance assigned, nullptr otherwise.
+ */
+otInstance *otPlatMultipanIidToInstance(uint8_t aIid);
+
+/**
+ * Get the IID corresponding to the given OpenThread instance pointer.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ *
+ * @retval IID of the given instance, broadcast IID otherwise.
+ */
+uint8_t otPlatMultipanInstanceToIid(otInstance *aInstance);
+
+/**
+ * @}
+ *
+ */
+
+#ifdef __cplusplus
+} // end of extern "C"
+#endif
+
+#endif // OPENTHREAD_PLATFORM_MULTIPAN_H_
diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h
index 7f39d9832..e2bc3db76 100644
--- a/include/openthread/platform/radio.h
+++ b/include/openthread/platform/radio.h
@@ -119,7 +119,7 @@ enum
* The value is a bit-field indicating the capabilities supported by the radio. See `OT_RADIO_CAPS_*` definitions.
*
*/
-typedef uint8_t otRadioCaps;
+typedef uint16_t otRadioCaps;
/**
* Defines constants that are used to indicate different radio capabilities. See `otRadioCaps`.
@@ -136,6 +136,7 @@ enum
OT_RADIO_CAPS_TRANSMIT_SEC = 1 << 5, ///< Radio supports tx security.
OT_RADIO_CAPS_TRANSMIT_TIMING = 1 << 6, ///< Radio supports tx at specific time.
OT_RADIO_CAPS_RECEIVE_TIMING = 1 << 7, ///< Radio supports rx at specific time.
+ OT_RADIO_CAPS_RX_ON_WHEN_IDLE = 1 << 8, ///< Radio supports RxOnWhenIdle handling.
};
#define OT_PANID_BROADCAST 0xffff ///< IEEE 802.15.4 Broadcast PAN ID
@@ -622,6 +623,38 @@ bool otPlatRadioGetPromiscuous(otInstance *aInstance);
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable);
/**
+ * Sets the rx-on-when-idle state to the radio platform.
+ *
+ * There are a few situations that the radio can enter sleep state if the device is in rx-off-when-idle state but
+ * it's hard and costly for the SubMac to identify these situations and instruct the radio to enter sleep:
+ *
+ * - Finalization of a regular frame reception task, provided that:
+ * - The frame is received without errors and passes the filtering and it's not an spurious ACK.
+ * - ACK is not requested or transmission of ACK is not possible due to internal conditions.
+ * - Finalization of a frame transmission or transmission of an ACK frame, when ACK is not requested in the transmitted
+ * frame.
+ * - Finalization of the reception operation of a requested ACK due to:
+ * - ACK timeout expiration.
+ * - Reception of an invalid ACK or not an ACK frame.
+ * - Reception of the proper ACK, unless the transmitted frame was a Data Request Command and the frame pending bit
+ * on the received ACK is set to true. In this case the radio platform implementation SHOULD keep the receiver on
+ * until a determined timeout which triggers an idle period start.`OPENTHREAD_CONFIG_MAC_DATA_POLL_TIMEOUT` can be
+ * taken as a reference for this.
+ * - Finalization of a stand alone CCA task.
+ * - Finalization of a CCA operation with busy result during CSMA/CA procedure.
+ * - Finalization of an Energy Detection task.
+ * - Finalization of a radio reception window scheduled with `otPlatRadioReceiveAt`.
+ *
+ * If a platform supports `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` it must also support `OT_RADIO_CAPS_CSMA_BACKOFF` and handle
+ * idle periods after CCA as described above.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aEnable TRUE to keep radio in Receive state, FALSE to put to Sleep state during idle periods.
+ *
+ */
+void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnable);
+
+/**
* Update MAC keys and key index
*
* Is used when radio provides OT_RADIO_CAPS_TRANSMIT_SEC capability.
diff --git a/include/openthread/platform/toolchain.h b/include/openthread/platform/toolchain.h
index 383aefbb3..a35e3ecde 100644
--- a/include/openthread/platform/toolchain.h
+++ b/include/openthread/platform/toolchain.h
@@ -58,6 +58,7 @@
#define OPENTHREAD_PLATFORM_TOOLCHAIN_H_
#include <stdbool.h>
+#include <stdint.h>
#ifdef __cplusplus
extern "C" {
diff --git a/include/openthread/srp_client.h b/include/openthread/srp_client.h
index 6eac2b1a8..71a217c37 100644
--- a/include/openthread/srp_client.h
+++ b/include/openthread/srp_client.h
@@ -460,10 +460,10 @@ otError otSrpClientSetHostName(otInstance *aInstance, const char *aName);
/**
* Enables auto host address mode.
*
- * When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread netif
- * excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is
- * added. The SRP client will automatically re-register when/if addresses on Thread netif are updated (new addresses
- * are added or existing addresses are removed).
+ * When enabled host IPv6 addresses are automatically set by SRP client using all the preferred unicast addresses on
+ * Thread netif excluding all link-local and mesh-local addresses. If there is no preferred address, then Mesh Local
+ * EID address is added. The SRP client will automatically re-register when/if addresses on Thread netif are updated
+ * (new addresses are added or existing addresses are removed or marked as non-preferred).
*
* The auto host address mode can be enabled before start or during operation of SRP client except when the host info
* is being removed (client is busy handling a remove request from an call to `otSrpClientRemoveHostAndServices()` and
diff --git a/script/check-simulation-build-cmake b/script/check-simulation-build-cmake
index fc7af8e05..ee1e2ffa5 100755
--- a/script/check-simulation-build-cmake
+++ b/script/check-simulation-build-cmake
@@ -188,7 +188,7 @@ build_all_features()
reset_source
"$(dirname "$0")"/cmake-build simulation \
-DOT_THREAD_VERSION=1.1 \
- -DOT_VENDOR_EXTENSION=../../src/core/common/extension_example.cpp
+ -DOT_VENDOR_EXTENSION=../../src/core/instance/extension_example.cpp
# Build Thread 1.3 with no additional features
reset_source
@@ -249,7 +249,7 @@ build_nest_common()
mkdir build && cd build
CFLAGS="${cppflags[*]} ${CFLAGS}" CXXFLAGS="${cppflags[*]} ${CXXFLAGS}" \
cmake -GNinja -DOT_PLATFORM=simulation \
- -DOT_VENDOR_EXTENSION=common/extension_example.cpp \
+ -DOT_VENDOR_EXTENSION=instance/extension_example.cpp \
-DOT_NCP_VENDOR_HOOK_SOURCE=example_vendor_hook.cpp \
..
ninja
diff --git a/script/test b/script/test
index e716f5abb..a9a71b3b5 100755
--- a/script/test
+++ b/script/test
@@ -132,6 +132,17 @@ build_simulation()
options+=("-DOT_LINK_METRICS_MANAGER=ON")
fi
+ if [[ ${OT_NODE_TYPE} == cli* ]]; then
+ # Only enable OT_PLATFORM_BOOTLOADER_MODE when testing cli.
+ # This is intended to test that the "reset bootloader" CLI command returns a "NotCapable" error
+
+ # Note: Setting this option to ON for all OT_NODE_TYPEs will cause the posix/expects CI check to fail.
+ # This is because the simulation RCP will have the SPINEL_CAP_RCP_RESET_TO_BOOTLOADER capability,
+ # causing the ot-cli POSIX app to send the reset to simulation RCP successfully instead of printing
+ # the expected error.
+ options+=("-DOT_PLATFORM_BOOTLOADER_MODE=ON")
+ fi
+
if [[ ${ot_extra_options[*]+x} ]]; then
options+=("${ot_extra_options[@]}")
fi
@@ -158,7 +169,12 @@ build_simulation()
build_posix()
{
local version="$1"
- local options=("-DOT_MESSAGE_USE_HEAP=ON" "-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
+ local options=(
+ "-DBUILD_TESTING=ON"
+ "-DOT_MESSAGE_USE_HEAP=ON"
+ "-DOT_PLATFORM_BOOTLOADER_MODE=ON"
+ "-DOT_THREAD_VERSION=${version}"
+ )
if [[ ${version} != "1.1" ]]; then
options+=("-DOT_DUA=ON")
diff --git a/src/cli/BUILD.gn b/src/cli/BUILD.gn
index fb68e8c86..b7ef7312a 100644
--- a/src/cli/BUILD.gn
+++ b/src/cli/BUILD.gn
@@ -49,6 +49,8 @@ openthread_cli_sources = [
"cli_history.hpp",
"cli_joiner.cpp",
"cli_joiner.hpp",
+ "cli_link_metrics.cpp",
+ "cli_link_metrics.hpp",
"cli_mac_filter.cpp",
"cli_mac_filter.hpp",
"cli_network_data.cpp",
diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt
index c203c2667..6be47773c 100644
--- a/src/cli/CMakeLists.txt
+++ b/src/cli/CMakeLists.txt
@@ -42,6 +42,7 @@ set(COMMON_SOURCES
cli_dns.cpp
cli_history.cpp
cli_joiner.cpp
+ cli_link_metrics.cpp
cli_mac_filter.cpp
cli_network_data.cpp
cli_output.cpp
diff --git a/src/cli/README.md b/src/cli/README.md
index 21a3dbf0b..c0b21e493 100644
--- a/src/cli/README.md
+++ b/src/cli/README.md
@@ -89,7 +89,7 @@ Done
- [parent](#parent)
- [parentpriority](#parentpriority)
- [partitionid](#partitionid)
-- [ping](#ping-async--i-source-ipaddr-size-count-interval-hoplimit-timeout)
+- [ping](#ping-async--i-source--m-ipaddr-size-count-interval-hoplimit-timeout)
- [platform](#platform)
- [pollperiod](#pollperiod-pollperiod)
- [preferrouterid](#preferrouterid-routerid)
@@ -1549,13 +1549,19 @@ fe80:0:0:0:f3d9:2a82:c8d8:fe43
Done
```
-Use `-v` to get more verbose information about the address.
+Use `-v` to get more verbose information about the address:
+
+- `origin`: can be `thread`, `slaac`, `dhcp6`, or `manual`, and indicates the origin of the address
+- `plen`: prefix length (in bits)
+- `preferred`: preferred flag (boolean)
+- `valid`: valid flag (boolean)
```bash
> ipaddr -v
-fdde:ad00:beef:0:0:ff:fe00:0 origin:thread
-fdde:ad00:beef:0:558:f56b:d688:799 origin:thread
-fe80:0:0:0:f3d9:2a82:c8d8:fe43 origin:thread
+fd5e:18fa:f4a5:b8:0:ff:fe00:fc00 origin:thread plen:64 preferred:0 valid:1
+fd5e:18fa:f4a5:b8:0:ff:fe00:dc00 origin:thread plen:64 preferred:0 valid:1
+fd5e:18fa:f4a5:b8:f8e:5d95:87a0:e82c origin:thread plen:64 preferred:0 valid:1
+fe80:0:0:0:4891:b191:e277:8826 origin:thread plen:64 preferred:1 valid:1
Done
```
@@ -2335,6 +2341,21 @@ Gets the IPv4 configured CIDR in the NAT64 translator.
Done
```
+### nat64 cidr \<IPv4 address\>
+
+Sets the IPv4 CIDR in the NAT64 translator.
+
+Note:
+
+- `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is required.
+- A valid CIDR must have a non-zero prefix length.
+- When updating the CIDR, NAT64 translator will be reset and all existing sessions will be expired.
+
+```bash
+> nat64 cidr 192.168.100.0/24
+Done
+```
+
### nat64 disable
Disable NAT64 functions, including the translator and the prefix publishing.
@@ -2722,12 +2743,13 @@ Set the preferred Thread Leader Partition ID.
Done
```
-### ping \[async\] \[-I source\] \<ipaddr\> \[size\] \[count\] \[interval\] \[hoplimit\] \[timeout\]
+### ping \[async\] \[-I source\] \[-m] \<ipaddr\> \[size\] \[count\] \[interval\] \[hoplimit\] \[timeout\]
Send an ICMPv6 Echo Request.
- async: Use the non-blocking mode. New commands are allowed before the ping process terminates.
- source: The source IPv6 address of the echo request.
+- -m: multicast loop, which allows looping back pings to multicast addresses that the device itself is subscribed to.
- size: The number of data bytes to be sent.
- count: The number of ICMPv6 Echo Requests to be sent.
- interval: The interval between two consecutive ICMPv6 Echo Requests in seconds. The value may have fractional form, for example `0.5`.
@@ -3068,6 +3090,17 @@ Signal a platform reset.
> reset
```
+### reset bootloader
+
+Signal a platform reset to bootloader mode, if supported.
+
+Requires `OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE`.
+
+```bash
+> reset bootloader
+Done
+```
+
### rloc16
Get the Thread RLOC16 value.
@@ -3598,7 +3631,6 @@ Done
> trel peers list
001 ExtAddr:5e5785ba3a63adb9 ExtPanId:f0d9c001f00d2e43 SockAddr:[fe80:0:0:0:cc79:2a29:d311:1aea]:9202
002 ExtAddr:ce792a29d3111aea ExtPanId:dead00beef00cafe SockAddr:[fe80:0:0:0:5c57:85ba:3a63:adb9]:9203
->>>>>>> [trel] implement new TREL model using DNS-SD
Done
```
diff --git a/src/cli/README_BR.md b/src/cli/README_BR.md
index b48eec29d..dcc174cfa 100644
--- a/src/cli/README_BR.md
+++ b/src/cli/README_BR.md
@@ -15,6 +15,7 @@ Usage : `br [command] ...`
- [prefixtable](#prefixtable)
- [rioprf](#rioprf)
- [routeprf](#routeprf)
+- [routers](#routers)
- [state](#state)
## Command Details
@@ -35,6 +36,7 @@ onlinkprefix
prefixtable
rioprf
routeprf
+routers
state
Done
```
@@ -180,10 +182,24 @@ Usage: `br prefixtable`
Get the discovered prefixes by Border Routing Manager on the infrastructure link.
+Info per prefix entry:
+
+- The prefix
+- Whether the prefix is on-link or route
+- Milliseconds since last received Router Advertisement containing this prefix
+- Prefix lifetime in seconds
+- Preferred lifetime in seconds only if prefix is on-link
+- Route preference (low, med, high) only if prefix is route (not on-link)
+- The router IPv6 address which advertising this prefix
+- Flags in received Router Advertisement header:
+ - M: Managed Address Config flag
+ - O: Other Config flag
+ - Stub: Stub Router flag (indicates whether the router is a stub router)
+
```bash
> br prefixtable
-prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, router:ff02:0:0:0:0:0:0:1
-prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, router:ff02:0:0:0:0:0:0:1
+prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
+prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800, router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
Done
```
@@ -254,3 +270,23 @@ Clear a previously set preference value for publishing routes in Thread Network
> br routeprf clear
Done
```
+
+### routers
+
+Usage: `br routers`
+
+Get the list of discovered routers by Border Routing Manager on the infrastructure link.
+
+Info per router:
+
+- The router IPv6 address
+- Flags in received Router Advertisement header:
+ - M: Managed Address Config flag
+ - O: Other Config flag
+ - Stub: Stub Router flag (indicates whether the router is a stub router)
+
+```bash
+> br routers
+ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
+Done
+```
diff --git a/src/cli/README_DATASET.md b/src/cli/README_DATASET.md
index cba2b9bc5..54f4c1e73 100644
--- a/src/cli/README_DATASET.md
+++ b/src/cli/README_DATASET.md
@@ -107,6 +107,117 @@ After the device successfully attaches to a Thread network, the device will retr
Done
```
+### Using the Pending Operational Dataset for Delayed Dataset Updates
+
+The Pending Operational Dataset can be used for a delayed update of network parameters on all devices of a Thread Network. If certain Active Operational Dataset parameters need to be changed, but the change would impact the connectivity of the network, delaying the update helps to let all devices receive the new parameters before the update is applied. Examples of such parameters are the channel, PAN ID, certain Security Policy bits, or Network Key.
+
+The delay timer determines the time period after which the Pending Operational Dataset takes effect and becomes the Active Operational Dataset. The following example shows how a Pending Operational Dataset with delay timer can be set at a Leader device. The Leader will initiate the distribution of the Pending Operational Dataset to the rest of the devices in the network.
+
+Normally, an active Commissioner will set a new Pending Operational Dataset. For testing purposes, we will do this in the example directly on the Leader using the CLI - so without using a Commissioner.
+
+1. The main parameter to change is the channel. We can display the current Active Operational Dataset to see that the current channel is 16.
+
+ ```bash
+ > dataset active
+ Active Timestamp: 1691070443
+ Channel: 16
+ Channel Mask: 0x07fff800
+ Ext PAN ID: 324a71d90cdc8345
+ Mesh Local Prefix: fd7d:da74:df5e:80c::/64
+ Network Key: be768535bac1b8d228960038311d6ca2
+ Network Name: OpenThread-bcaf
+ PAN ID: 0xbcaf
+ PSKc: e79b274ab22414a814ed5cce6a30be67
+ Security Policy: 672 onrc 0
+ Done
+ ```
+
+2. Create a new Dataset in the dataset buffer, by copying the Active Operational Dataset. Then change the channel number to 12 and increase the timestamp.
+
+ ```bash
+ > dataset init active
+ Done
+ > dataset activetimestamp 1696177379
+ Done
+ > dataset pendingtimestamp 1696177379
+ Done
+ > dataset channel 12
+ Done
+ ```
+
+3. Set the delay timer parameter to 5 minutes (300000 ms). Show the resulting Dataset that's ready to be used.
+
+ ```bash
+ > dataset delay 300000
+ Done
+ > dataset
+ Pending Timestamp: 1696177379
+ Active Timestamp: 1696177379
+ Channel: 12
+ Channel Mask: 0x07fff800
+ Delay: 300000
+ Ext PAN ID: 324a71d90cdc8345
+ Mesh Local Prefix: fd7d:da74:df5e:80c::/64
+ Network Key: be768535bac1b8d228960038311d6ca2
+ Network Name: OpenThread-bcaf
+ PAN ID: 0xbcaf
+ PSKc: e79b274ab22414a814ed5cce6a30be67
+ Security Policy: 672 onrc 0
+ Done
+ ```
+
+4. Commit the new Dataset as the Pending Operational Dataset. This also starts the delay timer countdown. The Leader then starts the distribution of the Pending Operational Dataset to other devices in the network.
+
+ ```bash
+ > dataset commit pending
+ Done
+ ```
+
+5. To verify that the delay timer is counting down, display the Pending Operational Dataset after a few seconds.
+
+ ```bash
+ > dataset pending
+ Pending Timestamp: 1696177379
+ Active Timestamp: 1696177379
+ Channel: 12
+ Channel Mask: 0x07fff800
+ Delay: 293051
+ Ext PAN ID: 324a71d90cdc8345
+ Mesh Local Prefix: fd7d:da74:df5e:80c::/64
+ Network Key: be768535bac1b8d228960038311d6ca2
+ Network Name: OpenThread-bcaf
+ PAN ID: 0xbcaf
+ PSKc: e79b274ab22414a814ed5cce6a30be67
+ Security Policy: 672 onrc 0
+ Done
+ ```
+
+ This shows that indeed the delay timer has started counting down from its initial value `300000`. The same can be optionally checked on other devices in the network.
+
+6) After about 5 minutes, check that the Pending Operational Dataset has been applied at the Leader. This can also be checked at other devices on the network: these should have applied the new Dataset too, at approximately the same time as the Leader has done this.
+
+ ```bash
+ > dataset active
+ Active Timestamp: 1696177379
+ Channel: 12
+ Channel Mask: 0x07fff800
+ Ext PAN ID: 324a71d90cdc8345
+ Mesh Local Prefix: fd7d:da74:df5e:80c::/64
+ Network Key: be768535bac1b8d228960038311d6ca2
+ Network Name: OpenThread-bcaf
+ PAN ID: 0xbcaf
+ PSKc: e79b274ab22414a814ed5cce6a30be67
+ Security Policy: 672 onrc 0
+ Done
+ ```
+
+ This shows that the Active Operational Dataset has now been updated to use channel 12. And the Pending Operational Dataset is no longer present, as can be seen by this command:
+
+ ```bash
+ > dataset pending
+ Error 23: NotFound
+ ```
+
## Command List
- [help](#help)
@@ -199,7 +310,7 @@ Done
Usage: `dataset activetimestamp [timestamp]`
-Get active timestamp seconds.
+Get active timestamp seconds. It represents a "Unix time", in number of seconds since Jan 1st, 1970.
```bash
> dataset activetimestamp
@@ -278,7 +389,7 @@ Done
Usage: `dataset delay [delay]`
-Get delay timer value.
+Get delay timer value. The timer value is in milliseconds.
```bash
> dataset delay
@@ -289,7 +400,7 @@ Done
Set delay timer value.
```bash
-> dataset delay 1000
+> dataset delay 100000
Done
```
@@ -318,13 +429,27 @@ Done
Usage: `dataset init <active|new|pending|tlvs <hex-encoded TLVs>>`
-Initialize operational dataset buffer.
+Initialize operational dataset buffer. Use `new` to initialize with randomly selected values:
```bash
> dataset init new
Done
```
+Use `active` or `pending` to initialize the dataset buffer with a copy of the current Active Operational Dataset or Pending Operational Dataset, respectively:
+
+```bash
+> dataset init active
+Done
+```
+
+Use the `tlvs` option to initialize the dataset buffer from a string of hex-encoded TLVs:
+
+```bash
+> dataset init tlvs 0e080000000000010000000300001235060004001fffe002088665f03e6e42e7750708fda576e5f9a5bd8c0510506071d8391be671569e080d52870fd5030f4f70656e5468726561642d633538640102c58d04108a926cf8b13275a012ceedeeae40910d0c0402a0f7f8
+Done
+```
+
### meshlocalprefix
Usage: `dataset meshlocalprefix [prefix]`
@@ -460,7 +585,7 @@ Done
Usage: `dataset pendingtimestamp [timestamp]`
-Get pending timestamp seconds.
+Get pending timestamp seconds. It represents a "Unix time", in number of seconds since Jan 1st, 1970.
```bash
> dataset pendingtimestamp
@@ -479,7 +604,7 @@ Done
Usage: `pskc [-p] [<key>|<passphrase>]`
-Get pskc.
+Get PSKc.
```bash
> dataset pskc
@@ -487,9 +612,9 @@ Get pskc.
Done
```
-Set pskc.
+Set PSKc.
-With `-p`(**only for FTD**) generate pskc from \<passphrase\> (UTF-8 encoded) together with network name and extended PAN ID in the dataset buffer if set or values in the current stack if not, otherwise set pskc as \<key\> (hex format).
+With `-p`(**only for FTD**) generate PSKc from \<passphrase\> (UTF-8 encoded) together with network name and extended PAN ID in the dataset buffer if set or values in the current stack if not, otherwise set PSKc as \<key\> (hex format).
```bash
> dataset pskc 67c0c203aa0b042bfb5381c47aef4d9e
diff --git a/src/cli/README_NETDATA.md b/src/cli/README_NETDATA.md
index ec828f32b..ad33bb993 100644
--- a/src/cli/README_NETDATA.md
+++ b/src/cli/README_NETDATA.md
@@ -379,6 +379,15 @@ Service entries are listed under `Services` header:
- Context ID
- Compress flag (`c` if marked or `-` otherwise).
+Commissioning Dataset information is printed under `Commissioning` header:
+
+- Session ID if present in Dataset or `-` otherwise
+- Border Agent RLOC16 (in hex) if present in Dataset or `-` otherwise
+- Joiner UDP port number if present in Dataset or `-` otherwise
+- Steering Data (as hex bytes) if present in Dataset or `-` otherwise
+- Flags:
+ - e: if Dataset contains any extra unknown TLV
+
Print Network Data received from the Leader.
```bash
@@ -392,6 +401,8 @@ Services:
44970 5d fddead00beef00007bad0069ce45948504d2 s a000
Contexts:
fd00:dead:beef:cafe::/64 1 c
+Commissioning:
+1248 dc00 9988 00000000000120000000000000000000 e
Done
```
diff --git a/src/cli/README_SRP_CLIENT.md b/src/cli/README_SRP_CLIENT.md
index ae48fbf1e..ca486f310 100644
--- a/src/cli/README_SRP_CLIENT.md
+++ b/src/cli/README_SRP_CLIENT.md
@@ -187,7 +187,7 @@ fd00:0:0:0:0:0:0:beef
Done
```
-Enable auto host address mode. When enabled client will automatically use all Thread netif unicast addresses excluding all link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID address is added. SRP client will automatically re-register if/when addresses on Thread netif get changed (e.g., new address is added or existing address is removed).
+Enable auto host address mode. When enabled client will automatically use all preferred Thread netif unicast addresses excluding all link-local and mesh-local addresses. If there is no preferred address, then Mesh Local EID address is added. SRP client will automatically re-register if/when addresses on Thread netif get changed (e.g., new address is added or existing address is removed or marked as non-preferred).
```bash
> srp client host address auto
diff --git a/src/cli/README_TCP.md b/src/cli/README_TCP.md
index 8e3414531..4d0e304a9 100644
--- a/src/cli/README_TCP.md
+++ b/src/cli/README_TCP.md
@@ -31,20 +31,20 @@ On node 2, initialize the TCP CLI module, connect to node 1, and send a simple m
### Result
-After running the `tcp connect` command on node 1, you should see a printout on node 1 similar to below:
+After running the `tcp connect` command on node 2, you should see a printout on node 2 similar to below:
```bash
TCP: Connection established
```
-In addition, you should also see a printout on node 2 similar to below:
+In addition, you should also see a printout on node 1 similar to below:
```bash
Accepted connection from [fe80:0:0:0:8f3:f602:bf9b:52f2]:49152
TCP: Connection established
```
-After running the `tcp send` command on node 1, you should see a printout on node 2 similar to below:
+After running the `tcp send` command on node 2, you should see a printout on node 1 similar to below:
```bash
TCP: Received 5 bytes: hello
diff --git a/src/cli/README_UDP.md b/src/cli/README_UDP.md
index 14444cdaf..720aa880f 100644
--- a/src/cli/README_UDP.md
+++ b/src/cli/README_UDP.md
@@ -169,7 +169,7 @@ The address can be an IPv4 address, which will be synthesized to an IPv6 address
> Note: The command will return `InvalidState` when the preferred NAT64 prefix is unavailable.
```bash
-> udp send 172.17.0.1 1234
+> udp send 172.17.0.1 1234 hello
Sending to synthesized IPv6 address: fdde:ad00:beef:2:0:0:ac11:1
Done
```
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index 9c329178e..cf9fea6ee 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -67,9 +67,6 @@
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include <openthread/backbone_router_ftd.h>
#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-#include <openthread/link_metrics.h>
-#endif
#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
#include <openthread/channel_manager.h>
@@ -90,6 +87,7 @@
#include <openthread/radio_stats.h>
#endif
#include "common/new.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "mac/channel_mask.hpp"
@@ -147,12 +145,12 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
, mHistory(aInstance, *this)
#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+ , mLinkMetrics(aInstance, *this)
+#endif
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
, mLocateInProgress(false)
#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
- , mLinkMetricsQueryInProgress(false)
-#endif
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
{
#if (OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_CONFIG_CLI_REGISTER_IP6_RECV_CALLBACK
@@ -276,11 +274,34 @@ template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
template <> otError Interpreter::Process<Cmd("reset")>(Arg aArgs[])
{
- OT_UNUSED_VARIABLE(aArgs);
+ otError error = OT_ERROR_NONE;
- otInstanceReset(GetInstancePtr());
+ if (aArgs[0].IsEmpty())
+ {
+ otInstanceReset(GetInstancePtr());
+ }
- return OT_ERROR_NONE;
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+ /**
+ * @cli reset bootloader
+ * @code
+ * reset bootloader
+ * @endcode
+ * @cparam reset bootloader
+ * @par api_copy
+ * #otInstanceResetToBootloader
+ */
+ else if (aArgs[0] == "bootloader")
+ {
+ error = otInstanceResetToBootloader(GetInstancePtr());
+ }
+#endif
+ else
+ {
+ error = OT_ERROR_INVALID_COMMAND;
+ }
+
+ return error;
}
void Interpreter::ProcessLine(char *aBuf)
@@ -1268,7 +1289,7 @@ template <> otError Interpreter::Process<Cmd("channel")>(Arg aArgs[])
if (otChannelMonitorIsEnabled(GetInstancePtr()))
{
uint32_t channelMask = otLinkGetSupportedChannelMask(GetInstancePtr());
- uint8_t channelNum = sizeof(channelMask) * CHAR_BIT;
+ uint8_t channelNum = BitSizeOf(channelMask);
OutputLine("interval: %lu", ToUlong(otChannelMonitorGetSampleInterval(GetInstancePtr())));
OutputLine("threshold: %d", otChannelMonitorGetRssiThreshold(GetInstancePtr()));
@@ -2588,7 +2609,7 @@ template <> otError Interpreter::Process<Cmd("discover")>(Arg aArgs[])
uint8_t channel;
SuccessOrExit(error = aArgs[0].ParseAsUint8(channel));
- VerifyOrExit(channel < sizeof(scanChannels) * CHAR_BIT, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(channel < BitSizeOf(scanChannels), error = OT_ERROR_INVALID_ARGS);
scanChannels = 1 << channel;
}
@@ -3125,13 +3146,18 @@ template <> otError Interpreter::Process<Cmd("ipaddr")>(Arg aArgs[])
* @endcode
* @code
* ipaddr -v
- * fdde:ad00:beef:0:0:ff:fe00:0 origin:thread
- * fdde:ad00:beef:0:558:f56b:d688:799 origin:thread
- * fe80:0:0:0:f3d9:2a82:c8d8:fe43 origin:thread
+ * fd5e:18fa:f4a5:b8:0:ff:fe00:fc00 origin:thread plen:64 preferred:0 valid:1
+ * fd5e:18fa:f4a5:b8:0:ff:fe00:dc00 origin:thread plen:64 preferred:0 valid:1
+ * fd5e:18fa:f4a5:b8:f8e:5d95:87a0:e82c origin:thread plen:64 preferred:0 valid:1
+ * fe80:0:0:0:4891:b191:e277:8826 origin:thread plen:64 preferred:1 valid:1
* Done
* @endcode
* @cparam ipaddr [@ca{-v}]
- * Use `-v` to get verbose IP Address information.
+ * Use `-v` to get more verbose information about the address:
+ * - `origin`: can be `thread`, `slaac`, `dhcp6`, `manual` and indicates the origin of the address
+ * - `plen`: prefix length
+ * - `preferred`: preferred flag (boolean)
+ * - `valid`: valid flag (boolean)
* @par api_copy
* #otIp6GetUnicastAddresses
*/
@@ -3145,7 +3171,8 @@ template <> otError Interpreter::Process<Cmd("ipaddr")>(Arg aArgs[])
if (verbose)
{
- OutputFormat(" origin:%s", AddressOriginToString(addr->mAddressOrigin));
+ OutputFormat(" origin:%s plen:%u preferred:%u valid:%u", AddressOriginToString(addr->mAddressOrigin),
+ addr->mPrefixLength, addr->mPreferred, addr->mValid);
}
OutputNewLine();
@@ -3643,241 +3670,8 @@ exit:
#endif // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-void Interpreter::HandleLinkMetricsReport(const otIp6Address *aAddress,
- const otLinkMetricsValues *aMetricsValues,
- otLinkMetricsStatus aStatus,
- void *aContext)
-{
- static_cast<Interpreter *>(aContext)->HandleLinkMetricsReport(aAddress, aMetricsValues, aStatus);
-}
-void Interpreter::PrintLinkMetricsValue(const otLinkMetricsValues *aMetricsValues)
-{
- static const char kLinkMetricsTypeAverage[] = "(Exponential Moving Average)";
-
- if (aMetricsValues->mMetrics.mPduCount)
- {
- OutputLine(" - PDU Counter: %lu (Count/Summation)", ToUlong(aMetricsValues->mPduCountValue));
- }
-
- if (aMetricsValues->mMetrics.mLqi)
- {
- OutputLine(" - LQI: %u %s", aMetricsValues->mLqiValue, kLinkMetricsTypeAverage);
- }
-
- if (aMetricsValues->mMetrics.mLinkMargin)
- {
- OutputLine(" - Margin: %u (dB) %s", aMetricsValues->mLinkMarginValue, kLinkMetricsTypeAverage);
- }
-
- if (aMetricsValues->mMetrics.mRssi)
- {
- OutputLine(" - RSSI: %d (dBm) %s", aMetricsValues->mRssiValue, kLinkMetricsTypeAverage);
- }
-}
-
-void Interpreter::HandleLinkMetricsReport(const otIp6Address *aAddress,
- const otLinkMetricsValues *aMetricsValues,
- otLinkMetricsStatus aStatus)
-{
- OutputFormat("Received Link Metrics Report from: ");
- OutputIp6AddressLine(*aAddress);
-
- if (aMetricsValues != nullptr)
- {
- PrintLinkMetricsValue(aMetricsValues);
- }
- else
- {
- OutputLine("Link Metrics Report, status: %s", LinkMetricsStatusToStr(aStatus));
- }
-
- if (mLinkMetricsQueryInProgress)
- {
- mLinkMetricsQueryInProgress = false;
- OutputResult(OT_ERROR_NONE);
- }
-}
-
-void Interpreter::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
- otLinkMetricsStatus aStatus,
- void *aContext)
-{
- static_cast<Interpreter *>(aContext)->HandleLinkMetricsMgmtResponse(aAddress, aStatus);
-}
-
-void Interpreter::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus)
-{
- OutputFormat("Received Link Metrics Management Response from: ");
- OutputIp6AddressLine(*aAddress);
-
- OutputLine("Status: %s", LinkMetricsStatusToStr(aStatus));
-}
-
-void Interpreter::HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
- const otExtAddress *aExtAddress,
- const otLinkMetricsValues *aMetricsValues,
- void *aContext)
-{
- static_cast<Interpreter *>(aContext)->HandleLinkMetricsEnhAckProbingIe(aShortAddress, aExtAddress, aMetricsValues);
-}
-
-void Interpreter::HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
- const otExtAddress *aExtAddress,
- const otLinkMetricsValues *aMetricsValues)
-{
- OutputFormat("Received Link Metrics data in Enh Ack from neighbor, short address:0x%02x , extended address:",
- aShortAddress);
- OutputExtAddressLine(*aExtAddress);
-
- if (aMetricsValues != nullptr)
- {
- PrintLinkMetricsValue(aMetricsValues);
- }
-}
-
-const char *Interpreter::LinkMetricsStatusToStr(otLinkMetricsStatus aStatus)
-{
- static const char *const kStatusStrings[] = {
- "Success", // (0) OT_LINK_METRICS_STATUS_SUCCESS
- "Cannot support new series", // (1) OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES
- "Series ID already registered", // (2) OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED
- "Series ID not recognized", // (3) OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED
- "No matching series ID", // (4) OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED
- };
-
- const char *str = "Unknown error";
-
- static_assert(0 == OT_LINK_METRICS_STATUS_SUCCESS, "STATUS_SUCCESS is incorrect");
- static_assert(1 == OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES, "CANNOT_SUPPORT_NEW_SERIES is incorrect");
- static_assert(2 == OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED, "SERIESID_ALREADY_REGISTERED is incorrect");
- static_assert(3 == OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED, "SERIESID_NOT_RECOGNIZED is incorrect");
- static_assert(4 == OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED, "NO_MATCHING_FRAMES_RECEIVED is incorrect");
-
- if (aStatus < OT_ARRAY_LENGTH(kStatusStrings))
- {
- str = kStatusStrings[aStatus];
- }
- else if (aStatus == OT_LINK_METRICS_STATUS_OTHER_ERROR)
- {
- str = "Other error";
- }
-
- return str;
-}
-
-template <> otError Interpreter::Process<Cmd("linkmetrics")>(Arg aArgs[])
-{
- otError error = OT_ERROR_INVALID_COMMAND;
-
- if (aArgs[0] == "query")
- {
- otIp6Address address;
- bool isSingle;
- bool blocking;
- uint8_t seriesId;
- otLinkMetrics linkMetrics;
-
- SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
-
- /**
- * @cli linkmetrics query single
- * @code
- * linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 single qmr
- * Done
- * > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
- * - LQI: 76 (Exponential Moving Average)
- * - Margin: 82 (dB) (Exponential Moving Average)
- * - RSSI: -18 (dBm) (Exponential Moving Average)
- * @endcode
- * @cparam linkmetrics query @ca{peer-ipaddr} single [@ca{pqmr}]
- * - `peer-ipaddr`: Peer address.
- * - [`p`, `q`, `m`, and `r`] map to #otLinkMetrics.
- * - `p`: Layer 2 Number of PDUs received.
- * - `q`: Layer 2 LQI.
- * - `m`: Link Margin.
- * - `r`: RSSI.
- * @par
- * Perform a Link Metrics query (Single Probe).
- * @sa otLinkMetricsQuery
- */
- if (aArgs[2] == "single")
- {
- isSingle = true;
- SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[3]));
- }
- /**
- * @cli linkmetrics query forward
- * @code
- * linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 forward 1
- * Done
- * > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
- * - PDU Counter: 2 (Count/Summation)
- * - LQI: 76 (Exponential Moving Average)
- * - Margin: 82 (dB) (Exponential Moving Average)
- * - RSSI: -18 (dBm) (Exponential Moving Average)
- * @endcode
- * @cparam linkmetrics query @ca{peer-ipaddr} forward @ca{series-id}
- * - `peer-ipaddr`: Peer address.
- * - `series-id`: The Series ID.
- * @par
- * Perform a Link Metrics query (Forward Tracking Series).
- * @sa otLinkMetricsQuery
- */
- else if (aArgs[2] == "forward")
- {
- isSingle = false;
- SuccessOrExit(error = aArgs[3].ParseAsUint8(seriesId));
- }
- else
- {
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
-
- blocking = (aArgs[4] == "block");
-
- SuccessOrExit(error = otLinkMetricsQuery(GetInstancePtr(), &address, isSingle ? 0 : seriesId,
- isSingle ? &linkMetrics : nullptr, HandleLinkMetricsReport, this));
-
- if (blocking)
- {
- mLinkMetricsQueryInProgress = true;
- error = OT_ERROR_PENDING;
- }
- }
- else if (aArgs[0] == "mgmt")
- {
- error = ProcessLinkMetricsMgmt(aArgs + 1);
- }
- /**
- * @cli linkmetrics probe
- * @code
- * linkmetrics probe fe80:0:0:0:3092:f334:1455:1ad2 1 10
- * Done
- * @endcode
- * @cparam linkmetrics probe @ca{peer-ipaddr} @ca{series-id} @ca{length}
- * - `peer-ipaddr`: Peer address.
- * - `series-id`: The Series ID for which this Probe message targets.
- * - `length`: The length of the Probe message. A valid range is [0, 64].
- * @par api_copy
- * #otLinkMetricsSendLinkProbe
- */
- else if (aArgs[0] == "probe")
- {
- otIp6Address address;
- uint8_t seriesId;
- uint8_t length;
-
- SuccessOrExit(error = aArgs[1].ParseAsIp6Address(address));
- SuccessOrExit(error = aArgs[2].ParseAsUint8(seriesId));
- SuccessOrExit(error = aArgs[3].ParseAsUint8(length));
-
- error = otLinkMetricsSendLinkProbe(GetInstancePtr(), &address, seriesId, length);
- }
-
-exit:
- return error;
-}
+template <> otError Interpreter::Process<Cmd("linkmetrics")>(Arg aArgs[]) { return mLinkMetrics.Process(aArgs); }
#if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
template <> otError Interpreter::Process<Cmd("linkmetricsmgr")>(Arg aArgs[])
@@ -3945,213 +3739,6 @@ exit:
}
#endif // OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
-otError Interpreter::ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags)
-{
- otError error = OT_ERROR_NONE;
-
- VerifyOrExit(!aFlags.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-
- memset(&aLinkMetrics, 0, sizeof(aLinkMetrics));
-
- for (const char *arg = aFlags.GetCString(); *arg != '\0'; arg++)
- {
- switch (*arg)
- {
- case 'p':
- aLinkMetrics.mPduCount = true;
- break;
-
- case 'q':
- aLinkMetrics.mLqi = true;
- break;
-
- case 'm':
- aLinkMetrics.mLinkMargin = true;
- break;
-
- case 'r':
- aLinkMetrics.mRssi = true;
- break;
-
- default:
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
- }
-
-exit:
- return error;
-}
-
-otError Interpreter::ProcessLinkMetricsMgmt(Arg aArgs[])
-{
- otError error;
- otIp6Address address;
- otLinkMetricsSeriesFlags seriesFlags;
- bool clear = false;
-
- SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
-
- memset(&seriesFlags, 0, sizeof(otLinkMetricsSeriesFlags));
-
- /**
- * @cli linkmetrics mgmt forward
- * @code
- * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
- * Done
- * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
- * Status: SUCCESS
- * @endcode
- * @cparam linkmetrics mgmt @ca{peer-ipaddr} forward @ca{series-id} [@ca{ldraX}][@ca{pqmr}]
- * - `peer-ipaddr`: Peer address.
- * - `series-id`: The Series ID.
- * - [`l`, `d`, `r`, and `a`] map to #otLinkMetricsSeriesFlags. `X` represents none of the
- * `otLinkMetricsSeriesFlags`, and stops the accounting and removes the series.
- * - `l`: MLE Link Probe.
- * - `d`: MAC Data.
- * - `r`: MAC Data Request.
- * - `a`: MAC Ack.
- * - `X`: Can only be used without any other flags.
- * - [`p`, `q`, `m`, and `r`] map to #otLinkMetricsValues.
- * - `p`: Layer 2 Number of PDUs received.
- * - `q`: Layer 2 LQI.
- * - `m`: Link Margin.
- * - `r`: RSSI.
- * @par api_copy
- * #otLinkMetricsConfigForwardTrackingSeries
- */
- if (aArgs[1] == "forward")
- {
- uint8_t seriesId;
- otLinkMetrics linkMetrics;
-
- memset(&linkMetrics, 0, sizeof(otLinkMetrics));
- SuccessOrExit(error = aArgs[2].ParseAsUint8(seriesId));
- VerifyOrExit(!aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
-
- for (const char *arg = aArgs[3].GetCString(); *arg != '\0'; arg++)
- {
- switch (*arg)
- {
- case 'l':
- seriesFlags.mLinkProbe = true;
- break;
-
- case 'd':
- seriesFlags.mMacData = true;
- break;
-
- case 'r':
- seriesFlags.mMacDataRequest = true;
- break;
-
- case 'a':
- seriesFlags.mMacAck = true;
- break;
-
- case 'X':
- VerifyOrExit(arg == aArgs[3].GetCString() && *(arg + 1) == '\0' && aArgs[4].IsEmpty(),
- error = OT_ERROR_INVALID_ARGS); // Ensure the flags only contain 'X'
- clear = true;
- break;
-
- default:
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
- }
-
- if (!clear)
- {
- SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[4]));
- VerifyOrExit(aArgs[5].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
- }
-
- error = otLinkMetricsConfigForwardTrackingSeries(GetInstancePtr(), &address, seriesId, seriesFlags,
- clear ? nullptr : &linkMetrics,
- &Interpreter::HandleLinkMetricsMgmtResponse, this);
- }
- else if (aArgs[1] == "enhanced-ack")
- {
- otLinkMetricsEnhAckFlags enhAckFlags;
- otLinkMetrics linkMetrics;
- otLinkMetrics *pLinkMetrics = &linkMetrics;
-
- /**
- * @cli linkmetrics mgmt enhanced-ack clear
- * @code
- * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
- * Done
- * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
- * Status: Success
- * @endcode
- * @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack clear
- * `peer-ipaddr` should be the Link Local address of the neighboring device.
- * @par
- * Sends a Link Metrics Management Request to clear an Enhanced-ACK Based Probing.
- * @sa otLinkMetricsConfigEnhAckProbing
- */
- if (aArgs[2] == "clear")
- {
- enhAckFlags = OT_LINK_METRICS_ENH_ACK_CLEAR;
- pLinkMetrics = nullptr;
- }
- /**
- * @cli linkmetrics mgmt enhanced-ack register
- * @code
- * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
- * Done
- * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
- * Status: Success
- * @endcode
- * @code
- * > linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
- * Done
- * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
- * Status: Cannot support new series
- * @endcode
- * @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack register [@ca{qmr}][@ca{r}]
- * [`q`, `m`, and `r`] map to #otLinkMetricsValues. Per spec 4.11.3.4.4.6, you can
- * only use a maximum of two options at once, for example `q`, or `qm`.
- * - `q`: Layer 2 LQI.
- * - `m`: Link Margin.
- * - `r`: RSSI.
- * .
- * The additional `r` is optional and only used for reference devices. When this option
- * is specified, Type/Average Enum of each Type Id Flags is set to reserved. This is
- * used to verify that the Probing Subject correctly handles invalid Type Id Flags, and
- * only available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
- * @par
- * Sends a Link Metrics Management Request to register an Enhanced-ACK Based Probing.
- * @sa otLinkMetricsConfigEnhAckProbing
- */
- else if (aArgs[2] == "register")
- {
- enhAckFlags = OT_LINK_METRICS_ENH_ACK_REGISTER;
- SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[3]));
-#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- if (aArgs[4] == "r")
- {
- linkMetrics.mReserved = true;
- }
-#endif
- }
- else
- {
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
-
- error = otLinkMetricsConfigEnhAckProbing(GetInstancePtr(), &address, enhAckFlags, pLinkMetrics,
- &Interpreter::HandleLinkMetricsMgmtResponse, this,
- &Interpreter::HandleLinkMetricsEnhAckProbingIe, this);
- }
- else
- {
- error = OT_ERROR_INVALID_ARGS;
- }
-
-exit:
- return error;
-}
-
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
@@ -6013,7 +5600,7 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
* 1 packets transmitted, 1 packets received. Packet loss = 0.0%. Round-trip min/avg/max = 0/0.0/0 ms.
* Done
* @endcode
- * @cparam ping [@ca{async}] [@ca{-I source}] @ca{ipaddrc} [@ca{size}] [@ca{count}] <!--
+ * @cparam ping [@ca{async}] [@ca{-I source}] [@ca{-m}] @ca{ipaddrc} [@ca{size}] [@ca{count}] <!--
* --> [@ca{interval}] [@ca{hoplimit}] [@ca{timeout}]
* @par
* Send an ICMPv6 Echo Request.
@@ -6021,6 +5608,9 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
* The address can be an IPv4 address, which will be synthesized to an IPv6 address using the preferred NAT64 prefix
* from the network data.
* @par
+ * The optional `-m` flag sets the multicast loop flag, which allows looping back pings to multicast addresses that the
+ * device itself is subscribed to.
+ * @par
* Note: The command will return InvalidState when the preferred NAT64 prefix is unavailable.
* @sa otPingSenderPing
*/
@@ -6059,26 +5649,17 @@ template <> otError Interpreter::Process<Cmd("ping")>(Arg aArgs[])
SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource));
#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- {
- bool valid = false;
- const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(GetInstancePtr());
-
- for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext)
- {
- if (otIp6IsAddressEqual(&addr->mAddress, &config.mSource))
- {
- valid = true;
- break;
- }
- }
-
- VerifyOrExit(valid, error = OT_ERROR_INVALID_ARGS);
- }
+ VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS);
#endif
-
aArgs += 2;
}
+ if (aArgs[0] == "-m")
+ {
+ config.mMulticastLoop = true;
+ aArgs++;
+ }
+
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
if (nat64SynthesizedAddress)
{
@@ -6239,70 +5820,19 @@ void Interpreter::HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx,
void Interpreter::HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx)
{
- OT_UNUSED_VARIABLE(aIsTx);
-
- OutputNewLine();
+ otLogHexDumpInfo info;
- for (size_t i = 0; i < 44; i++)
- {
- OutputFormat("=");
- }
-
- OutputFormat("[len = %3u]", aFrame->mLength);
-
- for (size_t i = 0; i < 28; i++)
- {
- OutputFormat("=");
- }
+ info.mDataBytes = aFrame->mPsdu;
+ info.mDataLength = aFrame->mLength;
+ info.mTitle = (aIsTx) ? "TX" : "RX";
+ info.mIterator = 0;
OutputNewLine();
- for (size_t i = 0; i < aFrame->mLength; i += 16)
- {
- OutputFormat("|");
-
- for (size_t j = 0; j < 16; j++)
- {
- if (i + j < aFrame->mLength)
- {
- OutputFormat(" %02X", aFrame->mPsdu[i + j]);
- }
- else
- {
- OutputFormat(" ..");
- }
- }
-
- OutputFormat("|");
-
- for (size_t j = 0; j < 16; j++)
- {
- if (i + j < aFrame->mLength)
- {
- if (31 < aFrame->mPsdu[i + j] && aFrame->mPsdu[i + j] < 127)
- {
- OutputFormat(" %c", aFrame->mPsdu[i + j]);
- }
- else
- {
- OutputFormat(" ?");
- }
- }
- else
- {
- OutputFormat(" .");
- }
- }
-
- OutputLine("|");
- }
-
- for (size_t i = 0; i < 83; i++)
+ while (otLogGenerateNextHexDumpLine(&info) == OT_ERROR_NONE)
{
- OutputFormat("-");
+ OutputLine("%s", info.mLine);
}
-
- OutputNewLine();
}
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
@@ -7141,7 +6671,7 @@ template <> otError Interpreter::Process<Cmd("scan")>(Arg aArgs[])
uint8_t channel;
SuccessOrExit(error = aArgs->ParseAsUint8(channel));
- VerifyOrExit(channel < sizeof(scanChannels) * CHAR_BIT, error = OT_ERROR_INVALID_ARGS);
+ VerifyOrExit(channel < BitSizeOf(scanChannels), error = OT_ERROR_INVALID_ARGS);
scanChannels = 1 << channel;
}
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index a581088a1..81c5fe7d0 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -65,6 +65,7 @@
#include "cli/cli_dns.hpp"
#include "cli/cli_history.hpp"
#include "cli/cli_joiner.hpp"
+#include "cli/cli_link_metrics.hpp"
#include "cli/cli_mac_filter.hpp"
#include "cli/cli_network_data.hpp"
#include "cli/cli_output.hpp"
@@ -82,8 +83,8 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/type_traits.hpp"
+#include "instance/instance.hpp"
namespace ot {
@@ -113,6 +114,7 @@ class Interpreter : public OutputImplementer, public Output
friend class Commissioner;
friend class Dns;
friend class Joiner;
+ friend class LinkMetrics;
friend class NetworkData;
friend class SrpClient;
friend class SrpServer;
@@ -412,12 +414,6 @@ private:
#if OPENTHREAD_FTD
void OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
- otError ProcessLinkMetricsQuery(Arg aArgs[]);
- otError ProcessLinkMetricsMgmt(Arg aArgs[]);
- otError ProcessLinkMetricsProbe(Arg aArgs[]);
- otError ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags);
-#endif
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
static void HandleLocateResult(void *aContext,
otError aError,
@@ -507,35 +503,6 @@ private:
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
void HandleSntpResponse(uint64_t aTime, otError aResult);
#endif
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
- void PrintLinkMetricsValue(const otLinkMetricsValues *aMetricsValues);
-
- static void HandleLinkMetricsReport(const otIp6Address *aAddress,
- const otLinkMetricsValues *aMetricsValues,
- otLinkMetricsStatus aStatus,
- void *aContext);
-
- void HandleLinkMetricsReport(const otIp6Address *aAddress,
- const otLinkMetricsValues *aMetricsValues,
- otLinkMetricsStatus aStatus);
-
- static void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
- otLinkMetricsStatus aStatus,
- void *aContext);
-
- void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus);
-
- static void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
- const otExtAddress *aExtAddress,
- const otLinkMetricsValues *aMetricsValues,
- void *aContext);
-
- void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
- const otExtAddress *aExtAddress,
- const otLinkMetricsValues *aMetricsValues);
-
- const char *LinkMetricsStatusToStr(otLinkMetricsStatus aStatus);
-#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
static void HandleDetachGracefullyResult(void *aContext);
void HandleDetachGracefullyResult(void);
@@ -624,6 +591,9 @@ private:
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
History mHistory;
#endif
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+ LinkMetrics mLinkMetrics;
+#endif
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
@@ -632,10 +602,6 @@ private:
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
bool mLocateInProgress : 1;
#endif
-
-#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
- bool mLinkMetricsQueryInProgress : 1;
-#endif
};
// Specializations of `FormatStringFor<ValueType>()`
diff --git a/src/cli/cli_br.cpp b/src/cli/cli_br.cpp
index d1fd81b4d..bd4d0dfe5 100644
--- a/src/cli/cli_br.cpp
+++ b/src/cli/cli_br.cpp
@@ -37,8 +37,6 @@
#include <string.h>
-#include <openthread/border_routing.h>
-
#include "cli/cli.hpp"
namespace ot {
@@ -381,13 +379,26 @@ exit:
* @code
* br prefixtable
* prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med,
- * router:ff02:0:0:0:0:0:0:1
+ * router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
* prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800,
- * router:ff02:0:0:0:0:0:0:1
+ * router:ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
* Done
* @endcode
- * @par api_copy
- * #otBorderRoutingGetNextPrefixTableEntry
+ * @par
+ * Get the discovered prefixes by Border Routing Manager on the infrastructure link.
+ * Info per prefix entry:
+ * - The prefix
+ * - Whether the prefix is on-link or route
+ * - Milliseconds since last received Router Advertisement containing this prefix
+ * - Prefix lifetime in seconds
+ * - Preferred lifetime in seconds only if prefix is on-link
+ * - Route preference (low, med, high) only if prefix is route (not on-link)
+ * - The router IPv6 address which advertising this prefix
+ * - Flags in received Router Advertisement header:
+ * - M: Managed Address Config flag
+ * - O: Other Config flag
+ * - Stub: Stub Router flag (indicates whether the router is a stub router)
+ * @sa otBorderRoutingGetNextPrefixTableEntry
*/
template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
{
@@ -416,14 +427,57 @@ template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
OutputFormat("route-prf:%s, ", Interpreter::PreferenceToString(entry.mRoutePreference));
}
- otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string));
- OutputLine("router:%s", string);
+ OutputFormat("router:");
+ OutputRouterInfo(entry.mRouter);
}
exit:
return error;
}
+/**
+ * @cli br routers
+ * @code
+ * br routers
+ * ff02:0:0:0:0:0:0:1 (M:0 O:0 Stub:1)
+ * Done
+ * @endcode
+ * @par
+ * Get the list of discovered routers by Border Routing Manager on the infrastructure link.
+ * Info per router:
+ * - The router IPv6 address
+ * - Flags in received Router Advertisement header:
+ * - M: Managed Address Config flag
+ * - O: Other Config flag
+ * - Stub: Stub Router flag (indicates whether the router is a stub router)
+ * @sa otBorderRoutingGetNextRouterEntry
+ */
+template <> otError Br::Process<Cmd("routers")>(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otBorderRoutingPrefixTableIterator iterator;
+ otBorderRoutingRouterEntry entry;
+
+ VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);
+
+ while (otBorderRoutingGetNextRouterEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
+ {
+ OutputRouterInfo(entry);
+ }
+
+exit:
+ return error;
+}
+
+void Br::OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry)
+{
+ OutputIp6Address(aEntry.mAddress);
+ OutputLine(" (M:%u O:%u Stub:%u)", aEntry.mManagedAddressConfigFlag, aEntry.mOtherConfigFlag,
+ aEntry.mStubRouterFlag);
+}
+
template <> otError Br::Process<Cmd("rioprf")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -587,6 +641,7 @@ otError Br::Process(Arg aArgs[])
CmdEntry("prefixtable"),
CmdEntry("rioprf"),
CmdEntry("routeprf"),
+ CmdEntry("routers"),
CmdEntry("state"),
};
diff --git a/src/cli/cli_br.hpp b/src/cli/cli_br.hpp
index f953344e3..01fcdcf94 100644
--- a/src/cli/cli_br.hpp
+++ b/src/cli/cli_br.hpp
@@ -36,6 +36,8 @@
#include "openthread-core-config.h"
+#include <openthread/border_routing.h>
+
#include "cli/cli_config.h"
#include "cli/cli_output.hpp"
@@ -92,6 +94,7 @@ private:
template <CommandId kCommandId> otError Process(Arg aArgs[]);
otError ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags);
+ void OutputRouterInfo(const otBorderRoutingRouterEntry &aEntry);
};
} // namespace Cli
diff --git a/src/cli/cli_link_metrics.cpp b/src/cli/cli_link_metrics.cpp
new file mode 100644
index 000000000..b8c284611
--- /dev/null
+++ b/src/cli/cli_link_metrics.cpp
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements the CLI interpreter for Link Metrics function.
+ */
+
+#include "cli_link_metrics.hpp"
+
+#include <openthread/link_metrics.h>
+
+#include "cli/cli.hpp"
+#include "cli/cli_output.hpp"
+#include "common/code_utils.hpp"
+
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+
+namespace ot {
+namespace Cli {
+
+LinkMetrics::LinkMetrics(otInstance *aInstance, OutputImplementer &aOutputImplementer)
+ : Output(aInstance, aOutputImplementer)
+ , mLinkMetricsQueryInProgress(false)
+{
+}
+
+template <> otError LinkMetrics::Process<Cmd("query")>(Arg aArgs[])
+{
+ otError error = OT_ERROR_NONE;
+ otIp6Address address;
+ bool isSingle;
+ bool blocking;
+ uint8_t seriesId;
+ otLinkMetrics linkMetrics;
+
+ SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
+
+ /**
+ * @cli linkmetrics query single
+ * @code
+ * linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 single qmr
+ * Done
+ * > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
+ * - LQI: 76 (Exponential Moving Average)
+ * - Margin: 82 (dB) (Exponential Moving Average)
+ * - RSSI: -18 (dBm) (Exponential Moving Average)
+ * @endcode
+ * @cparam linkmetrics query @ca{peer-ipaddr} single [@ca{pqmr}]
+ * - `peer-ipaddr`: Peer address.
+ * - [`p`, `q`, `m`, and `r`] map to #otLinkMetrics.
+ * - `p`: Layer 2 Number of PDUs received.
+ * - `q`: Layer 2 LQI.
+ * - `m`: Link Margin.
+ * - `r`: RSSI.
+ * @par
+ * Perform a Link Metrics query (Single Probe).
+ * @sa otLinkMetricsQuery
+ */
+ if (aArgs[1] == "single")
+ {
+ isSingle = true;
+ SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[2]));
+ }
+ /**
+ * @cli linkmetrics query forward
+ * @code
+ * linkmetrics query fe80:0:0:0:3092:f334:1455:1ad2 forward 1
+ * Done
+ * > Received Link Metrics Report from: fe80:0:0:0:3092:f334:1455:1ad2
+ * - PDU Counter: 2 (Count/Summation)
+ * - LQI: 76 (Exponential Moving Average)
+ * - Margin: 82 (dB) (Exponential Moving Average)
+ * - RSSI: -18 (dBm) (Exponential Moving Average)
+ * @endcode
+ * @cparam linkmetrics query @ca{peer-ipaddr} forward @ca{series-id}
+ * - `peer-ipaddr`: Peer address.
+ * - `series-id`: The Series ID.
+ * @par
+ * Perform a Link Metrics query (Forward Tracking Series).
+ * @sa otLinkMetricsQuery
+ */
+ else if (aArgs[1] == "forward")
+ {
+ isSingle = false;
+ SuccessOrExit(error = aArgs[2].ParseAsUint8(seriesId));
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+
+ blocking = (aArgs[3] == "block");
+
+ SuccessOrExit(error = otLinkMetricsQuery(GetInstancePtr(), &address, isSingle ? 0 : seriesId,
+ isSingle ? &linkMetrics : nullptr, HandleLinkMetricsReport, this));
+
+ if (blocking)
+ {
+ mLinkMetricsQueryInProgress = true;
+ error = OT_ERROR_PENDING;
+ }
+exit:
+ return error;
+}
+
+template <> otError LinkMetrics::Process<Cmd("mgmt")>(Arg aArgs[])
+{
+ otError error;
+ otIp6Address address;
+ otLinkMetricsSeriesFlags seriesFlags;
+ bool clear = false;
+
+ SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
+
+ memset(&seriesFlags, 0, sizeof(otLinkMetricsSeriesFlags));
+
+ /**
+ * @cli linkmetrics mgmt forward
+ * @code
+ * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 forward 1 dra pqmr
+ * Done
+ * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
+ * Status: SUCCESS
+ * @endcode
+ * @cparam linkmetrics mgmt @ca{peer-ipaddr} forward @ca{series-id} [@ca{ldraX}][@ca{pqmr}]
+ * - `peer-ipaddr`: Peer address.
+ * - `series-id`: The Series ID.
+ * - [`l`, `d`, `r`, and `a`] map to #otLinkMetricsSeriesFlags. `X` represents none of the
+ * `otLinkMetricsSeriesFlags`, and stops the accounting and removes the series.
+ * - `l`: MLE Link Probe.
+ * - `d`: MAC Data.
+ * - `r`: MAC Data Request.
+ * - `a`: MAC Ack.
+ * - `X`: Can only be used without any other flags.
+ * - [`p`, `q`, `m`, and `r`] map to #otLinkMetricsValues.
+ * - `p`: Layer 2 Number of PDUs received.
+ * - `q`: Layer 2 LQI.
+ * - `m`: Link Margin.
+ * - `r`: RSSI.
+ * @par api_copy
+ * #otLinkMetricsConfigForwardTrackingSeries
+ */
+ if (aArgs[1] == "forward")
+ {
+ uint8_t seriesId;
+ otLinkMetrics linkMetrics;
+
+ memset(&linkMetrics, 0, sizeof(otLinkMetrics));
+ SuccessOrExit(error = aArgs[2].ParseAsUint8(seriesId));
+ VerifyOrExit(!aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ for (const char *arg = aArgs[3].GetCString(); *arg != '\0'; arg++)
+ {
+ switch (*arg)
+ {
+ case 'l':
+ seriesFlags.mLinkProbe = true;
+ break;
+
+ case 'd':
+ seriesFlags.mMacData = true;
+ break;
+
+ case 'r':
+ seriesFlags.mMacDataRequest = true;
+ break;
+
+ case 'a':
+ seriesFlags.mMacAck = true;
+ break;
+
+ case 'X':
+ VerifyOrExit(arg == aArgs[3].GetCString() && *(arg + 1) == '\0' && aArgs[4].IsEmpty(),
+ error = OT_ERROR_INVALID_ARGS); // Ensure the flags only contain 'X'
+ clear = true;
+ break;
+
+ default:
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+ }
+
+ if (!clear)
+ {
+ SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[4]));
+ VerifyOrExit(aArgs[5].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ }
+
+ error = otLinkMetricsConfigForwardTrackingSeries(GetInstancePtr(), &address, seriesId, seriesFlags,
+ clear ? nullptr : &linkMetrics,
+ &LinkMetrics::HandleLinkMetricsMgmtResponse, this);
+ }
+ else if (aArgs[1] == "enhanced-ack")
+ {
+ otLinkMetricsEnhAckFlags enhAckFlags;
+ otLinkMetrics linkMetrics;
+ otLinkMetrics *pLinkMetrics = &linkMetrics;
+
+ /**
+ * @cli linkmetrics mgmt enhanced-ack clear
+ * @code
+ * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack clear
+ * Done
+ * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
+ * Status: Success
+ * @endcode
+ * @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack clear
+ * `peer-ipaddr` should be the Link Local address of the neighboring device.
+ * @par
+ * Sends a Link Metrics Management Request to clear an Enhanced-ACK Based Probing.
+ * @sa otLinkMetricsConfigEnhAckProbing
+ */
+ if (aArgs[2] == "clear")
+ {
+ enhAckFlags = OT_LINK_METRICS_ENH_ACK_CLEAR;
+ pLinkMetrics = nullptr;
+ }
+ /**
+ * @cli linkmetrics mgmt enhanced-ack register
+ * @code
+ * linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm
+ * Done
+ * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
+ * Status: Success
+ * @endcode
+ * @code
+ * > linkmetrics mgmt fe80:0:0:0:3092:f334:1455:1ad2 enhanced-ack register qm r
+ * Done
+ * > Received Link Metrics Management Response from: fe80:0:0:0:3092:f334:1455:1ad2
+ * Status: Cannot support new series
+ * @endcode
+ * @cparam linkmetrics mgmt @ca{peer-ipaddr} enhanced-ack register [@ca{qmr}][@ca{r}]
+ * [`q`, `m`, and `r`] map to #otLinkMetricsValues. Per spec 4.11.3.4.4.6, you can
+ * only use a maximum of two options at once, for example `q`, or `qm`.
+ * - `q`: Layer 2 LQI.
+ * - `m`: Link Margin.
+ * - `r`: RSSI.
+ * .
+ * The additional `r` is optional and only used for reference devices. When this option
+ * is specified, Type/Average Enum of each Type Id Flags is set to reserved. This is
+ * used to verify that the Probing Subject correctly handles invalid Type Id Flags, and
+ * only available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
+ * @par
+ * Sends a Link Metrics Management Request to register an Enhanced-ACK Based Probing.
+ * @sa otLinkMetricsConfigEnhAckProbing
+ */
+ else if (aArgs[2] == "register")
+ {
+ enhAckFlags = OT_LINK_METRICS_ENH_ACK_REGISTER;
+ SuccessOrExit(error = ParseLinkMetricsFlags(linkMetrics, aArgs[3]));
+#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+ if (aArgs[4] == "r")
+ {
+ linkMetrics.mReserved = true;
+ }
+#endif
+ }
+ else
+ {
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+
+ error = otLinkMetricsConfigEnhAckProbing(GetInstancePtr(), &address, enhAckFlags, pLinkMetrics,
+ &LinkMetrics::HandleLinkMetricsMgmtResponse, this,
+ &LinkMetrics::HandleLinkMetricsEnhAckProbingIe, this);
+ }
+ else
+ {
+ error = OT_ERROR_INVALID_ARGS;
+ }
+
+exit:
+ return error;
+}
+
+template <> otError LinkMetrics::Process<Cmd("probe")>(Arg aArgs[])
+{
+ /**
+ * @cli linkmetrics probe
+ * @code
+ * linkmetrics probe fe80:0:0:0:3092:f334:1455:1ad2 1 10
+ * Done
+ * @endcode
+ * @cparam linkmetrics probe @ca{peer-ipaddr} @ca{series-id} @ca{length}
+ * - `peer-ipaddr`: Peer address.
+ * - `series-id`: The Series ID for which this Probe message targets.
+ * - `length`: The length of the Probe message. A valid range is [0, 64].
+ * @par api_copy
+ * #otLinkMetricsSendLinkProbe
+ */
+ otError error = OT_ERROR_NONE;
+
+ otIp6Address address;
+ uint8_t seriesId;
+ uint8_t length;
+
+ SuccessOrExit(error = aArgs[0].ParseAsIp6Address(address));
+ SuccessOrExit(error = aArgs[1].ParseAsUint8(seriesId));
+ SuccessOrExit(error = aArgs[2].ParseAsUint8(length));
+
+ error = otLinkMetricsSendLinkProbe(GetInstancePtr(), &address, seriesId, length);
+exit:
+ return error;
+}
+
+otError LinkMetrics::Process(Arg aArgs[])
+{
+#define CmdEntry(aCommandString) \
+ { \
+ aCommandString, &LinkMetrics::Process<Cmd(aCommandString)> \
+ }
+
+ static constexpr Command kCommands[] = {
+ CmdEntry("mgmt"),
+ CmdEntry("probe"),
+ CmdEntry("query"),
+ };
+
+ static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
+
+ otError error = OT_ERROR_INVALID_COMMAND;
+ const Command *command;
+
+ if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
+ {
+ OutputCommandTable(kCommands);
+ ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
+ }
+
+ command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
+ VerifyOrExit(command != nullptr);
+
+ error = (this->*command->mHandler)(aArgs + 1);
+
+exit:
+ return error;
+}
+
+otError LinkMetrics::ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags)
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(!aFlags.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+
+ memset(&aLinkMetrics, 0, sizeof(aLinkMetrics));
+
+ for (const char *arg = aFlags.GetCString(); *arg != '\0'; arg++)
+ {
+ switch (*arg)
+ {
+ case 'p':
+ aLinkMetrics.mPduCount = true;
+ break;
+
+ case 'q':
+ aLinkMetrics.mLqi = true;
+ break;
+
+ case 'm':
+ aLinkMetrics.mLinkMargin = true;
+ break;
+
+ case 'r':
+ aLinkMetrics.mRssi = true;
+ break;
+
+ default:
+ ExitNow(error = OT_ERROR_INVALID_ARGS);
+ }
+ }
+
+exit:
+ return error;
+}
+
+void LinkMetrics::HandleLinkMetricsReport(const otIp6Address *aAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ otLinkMetricsStatus aStatus,
+ void *aContext)
+{
+ static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsReport(aAddress, aMetricsValues, aStatus);
+}
+
+void LinkMetrics::PrintLinkMetricsValue(const otLinkMetricsValues *aMetricsValues)
+{
+ static const char kLinkMetricsTypeAverage[] = "(Exponential Moving Average)";
+
+ if (aMetricsValues->mMetrics.mPduCount)
+ {
+ OutputLine(" - PDU Counter: %lu (Count/Summation)", ToUlong(aMetricsValues->mPduCountValue));
+ }
+
+ if (aMetricsValues->mMetrics.mLqi)
+ {
+ OutputLine(" - LQI: %u %s", aMetricsValues->mLqiValue, kLinkMetricsTypeAverage);
+ }
+
+ if (aMetricsValues->mMetrics.mLinkMargin)
+ {
+ OutputLine(" - Margin: %u (dB) %s", aMetricsValues->mLinkMarginValue, kLinkMetricsTypeAverage);
+ }
+
+ if (aMetricsValues->mMetrics.mRssi)
+ {
+ OutputLine(" - RSSI: %d (dBm) %s", aMetricsValues->mRssiValue, kLinkMetricsTypeAverage);
+ }
+}
+
+void LinkMetrics::HandleLinkMetricsReport(const otIp6Address *aAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ otLinkMetricsStatus aStatus)
+{
+ OutputFormat("Received Link Metrics Report from: ");
+ OutputIp6AddressLine(*aAddress);
+
+ if (aMetricsValues != nullptr)
+ {
+ PrintLinkMetricsValue(aMetricsValues);
+ }
+ else
+ {
+ OutputLine("Link Metrics Report, status: %s", LinkMetricsStatusToStr(aStatus));
+ }
+
+ if (mLinkMetricsQueryInProgress)
+ {
+ mLinkMetricsQueryInProgress = false;
+ OutputResult(OT_ERROR_NONE);
+ }
+}
+
+void LinkMetrics::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
+ otLinkMetricsStatus aStatus,
+ void *aContext)
+{
+ static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsMgmtResponse(aAddress, aStatus);
+}
+
+void LinkMetrics::HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus)
+{
+ OutputFormat("Received Link Metrics Management Response from: ");
+ OutputIp6AddressLine(*aAddress);
+
+ OutputLine("Status: %s", LinkMetricsStatusToStr(aStatus));
+}
+
+void LinkMetrics::HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
+ const otExtAddress *aExtAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ void *aContext)
+{
+ static_cast<LinkMetrics *>(aContext)->HandleLinkMetricsEnhAckProbingIe(aShortAddress, aExtAddress, aMetricsValues);
+}
+
+void LinkMetrics::HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
+ const otExtAddress *aExtAddress,
+ const otLinkMetricsValues *aMetricsValues)
+{
+ OutputFormat("Received Link Metrics data in Enh Ack from neighbor, short address:0x%02x , extended address:",
+ aShortAddress);
+ OutputExtAddressLine(*aExtAddress);
+
+ if (aMetricsValues != nullptr)
+ {
+ PrintLinkMetricsValue(aMetricsValues);
+ }
+}
+
+const char *LinkMetrics::LinkMetricsStatusToStr(otLinkMetricsStatus aStatus)
+{
+ static const char *const kStatusStrings[] = {
+ "Success", // (0) OT_LINK_METRICS_STATUS_SUCCESS
+ "Cannot support new series", // (1) OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES
+ "Series ID already registered", // (2) OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED
+ "Series ID not recognized", // (3) OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED
+ "No matching series ID", // (4) OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED
+ };
+
+ const char *str = "Unknown error";
+
+ static_assert(0 == OT_LINK_METRICS_STATUS_SUCCESS, "STATUS_SUCCESS is incorrect");
+ static_assert(1 == OT_LINK_METRICS_STATUS_CANNOT_SUPPORT_NEW_SERIES, "CANNOT_SUPPORT_NEW_SERIES is incorrect");
+ static_assert(2 == OT_LINK_METRICS_STATUS_SERIESID_ALREADY_REGISTERED, "SERIESID_ALREADY_REGISTERED is incorrect");
+ static_assert(3 == OT_LINK_METRICS_STATUS_SERIESID_NOT_RECOGNIZED, "SERIESID_NOT_RECOGNIZED is incorrect");
+ static_assert(4 == OT_LINK_METRICS_STATUS_NO_MATCHING_FRAMES_RECEIVED, "NO_MATCHING_FRAMES_RECEIVED is incorrect");
+
+ if (aStatus < OT_ARRAY_LENGTH(kStatusStrings))
+ {
+ str = kStatusStrings[aStatus];
+ }
+ else if (aStatus == OT_LINK_METRICS_STATUS_OTHER_ERROR)
+ {
+ str = "Other error";
+ }
+
+ return str;
+}
+
+void LinkMetrics::OutputResult(otError aError) { Interpreter::GetInterpreter().OutputResult(aError); }
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
diff --git a/src/cli/cli_link_metrics.hpp b/src/cli/cli_link_metrics.hpp
new file mode 100644
index 000000000..d62be780e
--- /dev/null
+++ b/src/cli/cli_link_metrics.hpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file contains definitions for the CLI interpreter for Link Metrics function.
+ */
+
+#ifndef CLI_LINK_METRICS_HPP_
+#define CLI_LINK_METRICS_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/link_metrics.h>
+
+#include "cli/cli_output.hpp"
+
+#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+
+namespace ot {
+namespace Cli {
+
+/**
+ * Implements the Link Metrics CLI interpreter.
+ *
+ */
+
+class LinkMetrics : private Output
+{
+public:
+ typedef Utils::CmdLineParser::Arg Arg;
+
+ /**
+ * Constructor
+ *
+ * @param[in] aInstance The OpenThread Instance.
+ * @param[in] aOutputImplementer An `OutputImplementer`.
+ *
+ */
+ LinkMetrics(otInstance *aInstance, OutputImplementer &aOutputImplementer);
+
+ /**
+ * Processes a CLI sub-command.
+ *
+ * @param[in] aArgs An array of command line arguments.
+ *
+ * @retval OT_ERROR_NONE Successfully executed the CLI command.
+ * @retval OT_ERROR_PENDING The CLI command was successfully started but final result is pending.
+ * @retval OT_ERROR_INVALID_COMMAND Invalid or unknown CLI command.
+ * @retval OT_ERROR_INVALID_ARGS Invalid arguments.
+ * @retval ... Error during execution of the CLI command.
+ *
+ */
+ otError Process(Arg aArgs[]);
+
+private:
+ static constexpr uint8_t kIndentSize = 4;
+
+ using Command = CommandEntry<LinkMetrics>;
+
+ template <CommandId kCommandId> otError Process(Arg aArgs[]);
+
+ otError ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags);
+
+ void PrintLinkMetricsValue(const otLinkMetricsValues *aMetricsValues);
+
+ static void HandleLinkMetricsReport(const otIp6Address *aAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ otLinkMetricsStatus aStatus,
+ void *aContext);
+
+ void HandleLinkMetricsReport(const otIp6Address *aAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ otLinkMetricsStatus aStatus);
+
+ static void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress,
+ otLinkMetricsStatus aStatus,
+ void *aContext);
+
+ void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, otLinkMetricsStatus aStatus);
+
+ static void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
+ const otExtAddress *aExtAddress,
+ const otLinkMetricsValues *aMetricsValues,
+ void *aContext);
+
+ void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
+ const otExtAddress *aExtAddress,
+ const otLinkMetricsValues *aMetricsValues);
+
+ const char *LinkMetricsStatusToStr(otLinkMetricsStatus aStatus);
+
+ void OutputResult(otError aError);
+
+ bool mLinkMetricsQueryInProgress;
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
+
+#endif // CLI_LINK_METRICS_HPP_
diff --git a/src/cli/cli_network_data.cpp b/src/cli/cli_network_data.cpp
index 2406b634c..85c3e262a 100644
--- a/src/cli/cli_network_data.cpp
+++ b/src/cli/cli_network_data.cpp
@@ -662,6 +662,33 @@ exit:
return;
}
+void NetworkData::OutputCommissioningDataset(bool aLocal)
+{
+ otCommissioningDataset dataset;
+
+ VerifyOrExit(!aLocal);
+
+ otNetDataGetCommissioningDataset(GetInstancePtr(), &dataset);
+
+ OutputLine("Commissioning:");
+
+ dataset.mIsSessionIdSet ? OutputFormat("%u ", dataset.mSessionId) : OutputFormat("- ");
+ dataset.mIsLocatorSet ? OutputFormat("%04x ", dataset.mLocator) : OutputFormat("- ");
+ dataset.mIsJoinerUdpPortSet ? OutputFormat("%u ", dataset.mJoinerUdpPort) : OutputFormat("- ");
+ dataset.mIsSteeringDataSet ? OutputBytes(dataset.mSteeringData.m8, dataset.mSteeringData.mLength)
+ : OutputFormat("-");
+
+ if (dataset.mHasExtraTlv)
+ {
+ OutputFormat(" e");
+ }
+
+ OutputNewLine();
+
+exit:
+ return;
+}
+
otError NetworkData::OutputBinary(bool aLocal)
{
otError error;
@@ -701,6 +728,8 @@ exit:
* 44970 01 9a04b000000e10 s 4000
* Contexts:
* fd00:dead:beef:cafe::/64 1 c
+ * Commissioning:
+ * 1248 dc00 9988 00000000000120000000000000000000 e
* Done
* @endcode
* @code
@@ -751,6 +780,14 @@ exit:
* * Context ID
* * Compress flag (`c` if marked or `-` otherwise).
* @par
+ * Commissioning Dataset information is printed under `Commissioning` header:
+ * * Session ID if present in Dataset or `-` otherwise
+ * * Border Agent RLOC16 (in hex) if present in Dataset or `-` otherwise
+ * * Joiner UDP port number if present in Dataset or `-` otherwise
+ * * Steering Data (as hex bytes) if present in Dataset or `-` otherwise
+ * * Flags:
+ * * e: If Dataset contains any extra unknown TLV
+ * @par
* @moreinfo{@netdata}.
* @csa{br omrprefix}
* @csa{br onlinkprefix}
@@ -809,6 +846,7 @@ template <> otError NetworkData::Process<Cmd("show")>(Arg aArgs[])
OutputRoutes(local);
OutputServices(local);
OutputLowpanContexts(local);
+ OutputCommissioningDataset(local);
error = OT_ERROR_NONE;
}
diff --git a/src/cli/cli_network_data.hpp b/src/cli/cli_network_data.hpp
index 635ff383b..15af65084 100644
--- a/src/cli/cli_network_data.hpp
+++ b/src/cli/cli_network_data.hpp
@@ -143,6 +143,7 @@ private:
void OutputRoutes(bool aLocal);
void OutputServices(bool aLocal);
void OutputLowpanContexts(bool aLocal);
+ void OutputCommissioningDataset(bool aLocal);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
static void HandleNetdataFull(void *aContext) { static_cast<NetworkData *>(aContext)->HandleNetdataFull(); }
diff --git a/src/cli/cli_srp_client.cpp b/src/cli/cli_srp_client.cpp
index 290dec528..58c9ef457 100644
--- a/src/cli/cli_srp_client.cpp
+++ b/src/cli/cli_srp_client.cpp
@@ -71,6 +71,17 @@ template <> otError SrpClient::Process<Cmd("autostart")>(Arg aArgs[])
otError error = OT_ERROR_NONE;
bool enable;
+ /**
+ * @cli srp client autostart (get)
+ * @code
+ * srp client autostart
+ * Disabled
+ * Done
+ * @endcode
+ * @par
+ * Indicates the current state of auto-start mode (enabled or disabled).
+ * @sa otSrpClientIsAutoStartModeEnabled
+ */
if (aArgs[0].IsEmpty())
{
OutputEnabledDisabledStatus(otSrpClientIsAutoStartModeEnabled(GetInstancePtr()));
@@ -79,10 +90,50 @@ template <> otError SrpClient::Process<Cmd("autostart")>(Arg aArgs[])
SuccessOrExit(error = Interpreter::ParseEnableOrDisable(aArgs[0], enable));
+ /**
+ * @cli srp client autostart enable
+ * @code
+ * srp client autostart enable
+ * Done
+ * @endcode
+ * @par
+ * Enables auto-start mode.
+ * @par
+ * When auto-start is enabled, the SRP client monitors Thread
+ * network data to discover SRP servers, to select the preferred
+ * server, and to automatically start and stop the client when
+ * an SRP server is detected.
+ * @par
+ * Three categories of network data entries indicate the presence of an SRP sever,
+ * and are preferred in the following order:
+ * -# Unicast entries in which the server address is included in the service
+ * data. If there are multiple options, the option with the lowest numerical
+ * IPv6 address is preferred.
+ * -# Anycast entries that each have a sequence number. The largest sequence
+ * number as specified by Serial Number Arithmetic Logic
+ * in RFC-1982 is preferred.
+ * -# Unicast entries in which the server address information is included
+ * with the server data. If there are multiple options, the option with the
+ * lowest numerical IPv6 address is preferred.
+ * @sa otSrpClientEnableAutoStartMode
+ */
if (enable)
{
otSrpClientEnableAutoStartMode(GetInstancePtr(), /* aCallback */ nullptr, /* aContext */ nullptr);
}
+ /**
+ * @cli srp client autostart disable
+ * @code
+ * srp client autostart disable
+ * Done
+ * @endcode
+ * @par
+ * Disables the auto-start mode.
+ * @par
+ * Disabling auto-start mode does not stop a running client.
+ * However, the SRP client stops monitoring Thread network data.
+ * @sa otSrpClientDisableAutoStartMode
+ */
else
{
otSrpClientDisableAutoStartMode(GetInstancePtr());
@@ -94,6 +145,22 @@ exit:
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
+/**
+ * @cli srp client callback (get,enable,disable)
+ * @code
+ * srp client callback enable
+ * Done
+ * @endcode
+ * @code
+ * srp client callback
+ * Enabled
+ * Done
+ * @endcode
+ * @cparam srp client callback [@ca{enable}|@ca{disable}]
+ * @par
+ * Gets or enables/disables printing callback events from the SRP client.
+ * @sa otSrpClientSetCallback
+ */
template <> otError SrpClient::Process<Cmd("callback")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -114,10 +181,38 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
+ /**
+ * @cli srp client host
+ * @code
+ * 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
+ * @endcode
+ * @par api_copy
+ * #otSrpClientGetHostInfo
+ */
if (aArgs[0].IsEmpty())
{
OutputHostInfo(0, *otSrpClientGetHostInfo(GetInstancePtr()));
}
+ /**
+ * @cli srp client host name (get,set)
+ * @code
+ * srp client host name dev4312
+ * Done
+ * @endcode
+ * @code
+ * srp client host name
+ * dev4312
+ * Done
+ * @endcode
+ * @cparam srp client host name [@ca{name}]
+ * To set the client host name when the host has either been removed or not yet
+ * registered with the server, use the `name` parameter.
+ * @par
+ * Gets or sets the host name of the SRP client.
+ * @sa otSrpClientSetHostName
+ */
else if (aArgs[0] == "name")
{
if (aArgs[1].IsEmpty())
@@ -149,6 +244,24 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
IgnoreError(otSrpClientSetHostName(GetInstancePtr(), hostName));
}
}
+ /**
+ * @cli srp client host state
+ * @code
+ * srp client host state
+ * Registered
+ * Done
+ * @endcode
+ * @par
+ * Returns the state of the SRP client host. Possible states:
+ * * `ToAdd`: Item to be added/registered.
+ * * `Adding`: Item is being added/registered.
+ * * `ToRefresh`: Item to be refreshed for lease renewal.
+ * * `Refreshing`: Item is beig refreshed.
+ * * `ToRemove`: Item to be removed.
+ * * `Removing`: Item is being removed.
+ * * `Registered`: Item is registered with server.
+ * * `Removed`: Item has been removed.
+ */
else if (aArgs[0] == "state")
{
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
@@ -156,6 +269,24 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
}
else if (aArgs[0] == "address")
{
+ /**
+ * @cli srp client host address (get)
+ * @code
+ * srp client host address
+ * auto
+ * Done
+ * @endcode
+ * @code
+ * srp client host address
+ * fd00:0:0:0:0:0:0:1234
+ * fd00:0:0:0:0:0:0:beef
+ * Done
+ * @endcode
+ * @par
+ * Indicates whether auto address mode is enabled. If auto address mode is not
+ * enabled, then the list of SRP client host addresses is returned.
+ * @sa otSrpClientGetHostInfo
+ */
if (aArgs[1].IsEmpty())
{
const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(GetInstancePtr());
@@ -172,6 +303,33 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
}
}
}
+ /**
+ * @cli srp client host address (set)
+ * @code
+ * srp client host address auto
+ * Done
+ * @endcode
+ * @code
+ * srp client host address fd00::cafe
+ * Done
+ * @endcode
+ * @cparam srp client host address [auto|@ca{address...}]
+ * * Use the `auto` parameter to enable auto host address mode.
+ * When enabled, the client automatically uses all preferred Thread
+ * `netif` unicast addresses except for link-local and mesh-local
+ * addresses. If there is no valid address, the mesh local
+ * EID address gets added. The SRP client automatically
+ * re-registers if addresses on the Thread `netif` are
+ * added or removed or marked as non-preferred.
+ * * Explicitly specify the list of host addresses, separating
+ * each address by a space. You can set this list while the client is
+ * running. This will also disable auto host address mode.
+ * @par
+ * Enable auto host address mode or explicitly set the list of host
+ * addresses.
+ * @sa otSrpClientEnableAutoHostAddress
+ * @sa otSrpClientSetHostAddresses
+ */
else if (aArgs[1] == "auto")
{
error = otSrpClientEnableAutoHostAddress(GetInstancePtr());
@@ -209,6 +367,25 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
IgnoreError(otSrpClientSetHostAddresses(GetInstancePtr(), hostAddressArray, numAddresses));
}
}
+ /**
+ * @cli srp client host remove
+ * @code
+ * srp client host remove 1
+ * Done
+ * @endcode
+ * @cparam srp client host remove [@ca{removekeylease}] [@ca{sendunregtoserver}]
+ * * The parameter `removekeylease` is an optional boolean value that indicates
+ * whether the host key lease should also be removed (default is `false`).
+ * * The parameter `sendunregtoserver` is an optional boolean value that indicates
+ * whether the client host should send an "update" message to the server
+ * even when the client host information has not yet been registered with the
+ * server (default is `false`). This parameter can be specified only if the
+ * `removekeylease` parameter is specified first in the command.
+ * @par
+ * Removes SRP client host information and all services from the SRP server.
+ * @sa otSrpClientRemoveHostAndServices
+ * @sa otSrpClientSetHostName
+ */
else if (aArgs[0] == "remove")
{
bool removeKeyLease = false;
@@ -227,6 +404,17 @@ template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
error = otSrpClientRemoveHostAndServices(GetInstancePtr(), removeKeyLease, sendUnregToServer);
}
+ /**
+ * @cli srp client host clear
+ * @code
+ * srp client host clear
+ * Done
+ * @endcode
+ * @par
+ * Clears all host information and all services.
+ * @sa otSrpClientBuffersFreeAllServices
+ * @sa otSrpClientClearHostAndServices
+ */
else if (aArgs[0] == "clear")
{
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
@@ -242,11 +430,45 @@ exit:
return error;
}
+/**
+ * @cli srp client leaseinterval (get,set)
+ * @code
+ * srp client leaseinterval 3600
+ * Done
+ * @endcode
+ * @code
+ * srp client leaseinterval
+ * 3600
+ * Done
+ * @endcode
+ * @cparam srp client leaseinterval [@ca{interval}]
+ * @par
+ * Gets or sets the lease interval in seconds.
+ * @sa otSrpClientGetLeaseInterval
+ * @sa otSrpClientSetLeaseInterval
+ */
template <> otError SrpClient::Process<Cmd("leaseinterval")>(Arg aArgs[])
{
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetLeaseInterval, otSrpClientSetLeaseInterval);
}
+/**
+ * @cli srp client keyleaseinterval (get,set)
+ * @code
+ * srp client keyleaseinterval 864000
+ * Done
+ * @endcode
+ * @code
+ * srp client keyleaseinterval
+ * 864000
+ * Done
+ * @endcode
+ * @cparam srp client keyleaseinterval [@ca{interval}]
+ * @par
+ * Gets or sets the key lease interval in seconds.
+ * @sa otSrpClientGetKeyLeaseInterval
+ * @sa otSrpClientSetKeyLeaseInterval
+ */
template <> otError SrpClient::Process<Cmd("keyleaseinterval")>(Arg aArgs[])
{
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetKeyLeaseInterval,
@@ -258,6 +480,19 @@ template <> otError SrpClient::Process<Cmd("server")>(Arg aArgs[])
otError error = OT_ERROR_NONE;
const otSockAddr *serverSockAddr = otSrpClientGetServerAddress(GetInstancePtr());
+ /**
+ * @cli srp client server
+ * @code
+ * srp client server
+ * &lsqb;fd00:0:0:0:d88a:618b:384d:e760&rsqb;:4724
+ * Done
+ * @endcode
+ * @par
+ * Gets the socket address (IPv6 address and port number) of the SRP server
+ * that is being used by the SRP client. If the client is not running, the address
+ * is unspecified (all zeros) with a port number of 0.
+ * @sa otSrpClientGetServerAddress
+ */
if (aArgs[0].IsEmpty())
{
OutputSockAddrLine(*serverSockAddr);
@@ -266,10 +501,30 @@ template <> otError SrpClient::Process<Cmd("server")>(Arg aArgs[])
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
+ /**
+ * @cli srp client server address
+ * @code
+ * srp client server address
+ * fd00:0:0:0:d88a:618b:384d:e760
+ * Done
+ * @endcode
+ * @par
+ * Returns the server's IPv6 address.
+ */
if (aArgs[0] == "address")
{
OutputIp6AddressLine(serverSockAddr->mAddress);
}
+ /**
+ * @cli srp client server port
+ * @code
+ * srp client server port
+ * 4724
+ * Done
+ * @endcode
+ * @par
+ * Returns the server's port number.
+ */
else if (aArgs[0] == "port")
{
OutputLine("%u", serverSockAddr->mPort);
@@ -288,14 +543,70 @@ template <> otError SrpClient::Process<Cmd("service")>(Arg aArgs[])
otError error = OT_ERROR_NONE;
bool isRemove;
+ /**
+ * @cli srp client service
+ * @code
+ * srp client service
+ * instance:"ins2", name:"_test2._udp,_sub1,_sub2", state:Registered, port:111, priority:1, weight:1
+ * instance:"ins1", name:"_test1._udp", state:Registered, port:777, priority:0, weight:0
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otSrpClientGetServices
+ */
if (aArgs[0].IsEmpty())
{
OutputServiceList(0, otSrpClientGetServices(GetInstancePtr()));
}
+ /**
+ * @cli srp client service add
+ * @code
+ * srp client service add ins1 _test1._udp 777
+ * Done
+ * @endcode
+ * @code
+ * srp client service add ins2 _test2._udp,_sub1,_sub2 111 1 1
+ * Done
+ * @endcode
+ * @cparam srp client service add @ca{instancename} @ca{servicename} <!--
+ * * --> @ca{port} [@ca{priority}] <!--
+ * * --> [@ca{weight}] [@ca{txt}]
+ * The `servicename` parameter can optionally include a list of service subtype labels that are
+ * separated by commas. The examples here use generic naming. The `priority` and `weight` (both are `uint16_t`
+ * values) parameters are optional, and if not provided zero is used. The optional `txt` parameter sets the TXT data
+ * associated with the service. The `txt` value must be in hex-string format and is treated as an already encoded
+ * TXT data byte sequence.
+ * @par
+ * Adds a service with a given instance name, service name, and port number.
+ * @sa otSrpClientAddService
+ */
else if (aArgs[0] == "add")
{
error = ProcessServiceAdd(aArgs);
}
+ /**
+ * @cli srp client service remove
+ * @code
+ * srp client service remove ins2 _test2._udp
+ * Done
+ * @endcode
+ * @cparam srp client service remove @ca{instancename} @ca{servicename}
+ * @par
+ * Requests a service to be unregistered with the SRP server.
+ * @sa otSrpClientRemoveService
+ */
+ /**
+ * @cli srp client service name clear
+ * @code
+ * srp client service clear ins2 _test2._udp
+ * Done
+ * @endcode
+ * @cparam srp client service clear @ca{instancename} @ca{servicename}
+ * @par
+ * Clears a service, immediately removing it from the client service list,
+ * with no interaction with the SRP server.
+ * @sa otSrpClientClearService
+ */
else if ((isRemove = (aArgs[0] == "remove")) || (aArgs[0] == "clear"))
{
// `remove`|`clear` <instance-name> <service-name>
@@ -327,6 +638,23 @@ template <> otError SrpClient::Process<Cmd("service")>(Arg aArgs[])
}
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+ /**
+ * @cli srp client service key (get,set)
+ * @code
+ * srp client service key enable
+ * Done
+ * @endcode
+ * @code
+ * srp client service key
+ * Enabled
+ * Done
+ * @endcode
+ * @par
+ * Gets or sets the service key record inclusion mode in the SRP client.
+ * This command is intended for testing only, and requires that
+ * `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` be enabled.
+ * @sa otSrpClientIsServiceKeyRecordEnabled
+ */
else if (aArgs[0] == "key")
{
// `key [enable/disable]`
@@ -508,6 +836,17 @@ void SrpClient::OutputService(uint8_t aIndentSize, const otSrpClientService &aSe
aService.mPort, aService.mPriority, aService.mWeight);
}
+/**
+ * @cli srp client start
+ * @code
+ * srp client start fd00::d88a:618b:384d:e760 4724
+ * Done
+ * @endcode
+ * @cparam srp client start @ca{serveraddr} @ca{serverport}
+ * @par
+ * Starts the SRP client operation.
+ * @sa otSrpClientStart
+ */
template <> otError SrpClient::Process<Cmd("start")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -523,6 +862,16 @@ exit:
return error;
}
+/**
+ * @cli srp client state
+ * @code
+ * srp client state
+ * Enabled
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otSrpClientIsRunning
+ */
template <> otError SrpClient::Process<Cmd("state")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -535,6 +884,15 @@ exit:
return error;
}
+/**
+ * @cli srp client stop
+ * @code
+ * srp client stop
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otSrpClientStop
+ */
template <> otError SrpClient::Process<Cmd("stop")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -546,6 +904,23 @@ exit:
return error;
}
+/**
+ * @cli srp client ttl (get,set)
+ * @code
+ * srp client ttl 3600
+ * Done
+ * @endcode
+ * @code
+ * srp client ttl
+ * 3600
+ * Done
+ * @endcode
+ * @cparam srp client ttl [@ca{value}]
+ * @par
+ * Gets or sets the `ttl`(time to live) value in seconds.
+ * @sa otSrpClientGetTtl
+ * @sa otSrpClientSetTtl
+ */
template <> otError SrpClient::Process<Cmd("ttl")>(Arg aArgs[])
{
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetTtl, otSrpClientSetTtl);
diff --git a/src/cli/cli_srp_server.cpp b/src/cli/cli_srp_server.cpp
index 5a96d5fe6..98213d524 100644
--- a/src/cli/cli_srp_server.cpp
+++ b/src/cli/cli_srp_server.cpp
@@ -43,6 +43,26 @@
namespace ot {
namespace Cli {
+/**
+ * @cli srp server addrmode (get,set)
+ * @code
+ * srp server addrmode anycast
+ * Done
+ * @endcode
+ * @code
+ * srp server addrmode
+ * anycast
+ * Done
+ * @endcode
+ * @cparam srp server addrmode [@ca{anycast}|@ca{unicast}]
+ * @par
+ * Gets or sets the address mode used by the SRP server.
+ * @par
+ * The address mode tells the SRP server how to determine its address and port number,
+ * which then get published in the Thread network data.
+ * @sa otSrpServerGetAddressMode
+ * @sa otSrpServerSetAddressMode
+ */
template <> otError SrpServer::Process<Cmd("addrmode")>(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_ARGS;
@@ -75,32 +95,53 @@ template <> otError SrpServer::Process<Cmd("addrmode")>(Arg aArgs[])
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+
/**
- * @cli srp server auto
+ * @cli srp server auto (enable,disable)
+ * @code
+ * srp server auto enable
+ * Done
+ * @endcode
* @code
* srp server auto
- * Disabled
+ * Enabled
* Done
* @endcode
- * @par api_copy
- * #otSrpServerIsAutoEnableMode
+ * @cparam srp server auto [@ca{enable}|@ca{disable}]
+ * @par
+ * Enables or disables the auto-enable mode on the SRP server.
+ * @par
+ * When this mode is enabled, the Border Routing Manager controls if and when
+ * to enable or disable the SRP server.
+ * @par
+ * This command requires that `OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE` be enabled.
+ * @sa otSrpServerIsAutoEnableMode
+ * @sa otSrpServerSetAutoEnableMode
*/
template <> otError SrpServer::Process<Cmd("auto")>(Arg aArgs[])
{
- /**
- * @cli srp server auto enable
- * @code
- * srp server auto enable
- * Done
- * @endcode
- * @par api_copy
- * #otSrpServerSetAutoEnableMode
- */
return Interpreter::GetInterpreter().ProcessEnableDisable(aArgs, otSrpServerIsAutoEnableMode,
otSrpServerSetAutoEnableMode);
}
#endif
+/**
+ * @cli srp server domain (get,set)
+ * @code
+ * srp server domain thread.service.arpa.
+ * Done
+ * @endcode
+ * @code
+ * srp server domain
+ * thread.service.arpa.
+ * Done
+ * @endcode
+ * @cparam srp server domain [@ca{domain-name}]
+ * @par
+ * Gets or sets the domain name of the SRP server.
+ * @sa otSrpServerGetDomain
+ * @sa otSrpServerSetDomain
+ */
template <> otError SrpServer::Process<Cmd("domain")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -117,6 +158,23 @@ template <> otError SrpServer::Process<Cmd("domain")>(Arg aArgs[])
return error;
}
+/**
+ * @cli srp server state
+ * @code
+ * srp server state
+ * running
+ * Done
+ * @endcode
+ * @par
+ * Returns one of the following possible states of the SRP server:
+ * * `disabled`: The SRP server is not enabled.
+ * * `stopped`: The SRP server is enabled but not active due to existing
+ * SRP servers that are already active in the Thread network.
+ * The SRP server may become active when the existing
+ * SRP servers are no longer active within the Thread network.
+ * * `running`: The SRP server is active and can handle service registrations.
+ * @sa otSrpServerGetState
+ */
template <> otError SrpServer::Process<Cmd("state")>(Arg aArgs[])
{
static const char *const kStateStrings[] = {
@@ -145,6 +203,17 @@ template <> otError SrpServer::Process<Cmd("enable")>(Arg aArgs[])
return OT_ERROR_NONE;
}
+/**
+ * @cli srp server (enable,disable)
+ * @code
+ * srp server disable
+ * Done
+ * @endcode
+ * @cparam srp server [@ca{enable}|@ca{disable}]
+ * @par
+ * Enables or disables the SRP server.
+ * @sa otSrpServerSetEnabled
+ */
template <> otError SrpServer::Process<Cmd("disable")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
@@ -178,6 +247,26 @@ exit:
return error;
}
+/**
+ * @cli srp server lease (get,set)
+ * @code
+ * srp server lease 1800 7200 86400 1209600
+ * Done
+ * @endcode
+ * @code
+ * srp server lease
+ * min lease: 1800
+ * max lease: 7200
+ * min key-lease: 86400
+ * max key-lease: 1209600
+ * Done
+ * @endcode
+ * @cparam srp server lease [@ca{min-lease} @ca{max-lease} @ca{min-key-lease} @ca{max-key-lease}]
+ * @par
+ * Gets or sets the SRP server lease values in number of seconds.
+ * @sa otSrpServerGetLeaseConfig
+ * @sa otSrpServerSetLeaseConfig
+ */
template <> otError SrpServer::Process<Cmd("lease")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -206,6 +295,24 @@ exit:
return error;
}
+/**
+ * @cli srp server host
+ * @code
+ * 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
+ * @endcode
+ * @par
+ * Returns information about all registered hosts.
+ * @sa otSrpServerGetNextHost
+ * @sa otSrpServerHostGetAddresses
+ * @sa otSrpServerHostGetFullName
+ */
template <> otError SrpServer::Process<Cmd("host")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -268,6 +375,46 @@ void SrpServer::OutputHostAddresses(const otSrpServerHost *aHost)
OutputFormat("]");
}
+/**
+ * @cli srp server service
+ * @code
+ * srp server service
+ * srp-api-test-1._ipps._tcp.default.service.arpa.
+ * deleted: false
+ * subtypes: (null)
+ * port: 49152
+ * priority: 0
+ * weight: 0
+ * ttl: 7200
+ * lease: 7200
+ * key-lease: 1209600
+ * TXT: [616263, xyz=585960]
+ * 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
+ * subtypes: _sub1,_sub2
+ * port: 49152
+ * priority: 0
+ * weight: 0
+ * ttl: 3600
+ * lease: 3600
+ * key-lease: 1209600
+ * TXT: [616263, xyz=585960]
+ * host: srp-api-test-0.default.service.arpa.
+ * addresses: [fdde:ad00:beef:0:0:ff:fe00:fc10]
+ * Done
+ * @endcode
+ * @par
+ * Returns information about registered services.
+ * @par
+ * The `TXT` record is displayed
+ * as an array of entries. If an entry contains a key, the key is printed in
+ * ASCII format. The value portion is printed in hexadecimal bytes.
+ * @sa otSrpServerServiceGetInstanceName
+ * @sa otSrpServerServiceGetServiceName
+ * @sa otSrpServerServiceGetSubTypeServiceNameAt
+ */
template <> otError SrpServer::Process<Cmd("service")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -340,6 +487,25 @@ exit:
return error;
}
+/**
+ * @cli srp server seqnum (get,set)
+ * @code
+ * srp server seqnum 20
+ * Done
+ * @endcode
+ * @code
+ * srp server seqnum
+ * 20
+ * Done
+ * @endcode
+ * @cparam srp server seqnum [@ca{seqnum}]
+ * @par
+ * Gets or sets the sequence number used with the anycast address mode.
+ * The sequence number is included in the "DNS/SRP Service Anycast Address"
+ * entry that is published in the Network Data.
+ * @sa otSrpServerGetAnycastModeSequenceNumber
+ * @sa otSrpServerSetAnycastModeSequenceNumber
+ */
template <> otError SrpServer::Process<Cmd("seqnum")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
diff --git a/src/cli/cli_tcp.cpp b/src/cli/cli_tcp.cpp
index 67534f0b9..ddfc098db 100644
--- a/src/cli/cli_tcp.cpp
+++ b/src/cli/cli_tcp.cpp
@@ -85,6 +85,32 @@ void TcpExample::MbedTlsDebugOutput(void *ctx, int level, const char *file, int
}
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
+/**
+ * @cli tcp init
+ * @code
+ * tcp init tls
+ * Done
+ * @endcode
+ * @cparam tcp init [@ca{mode}] [@ca{size}]
+ * * The `mode` has three possible values:
+ * * `tls`: Specifies that the TCP connection between two nodes should also
+ * use the TLS protocol on top of TCP. When two nodes communicate over TCP,
+ * both nodes must either use TLS or neither node should use TLS because
+ * a non-TLS endpoint cannot communicate with a TLS endpoint.
+ * * `linked` or `circular`: Either one of these options means that TLS
+ * is not to be used, and the specified buffering type should be used for TCP
+ * buffering. The behavior of `linked` and `circular` is identical. Examine the code
+ * for the differences between these two buffering types.
+ * Two endpoints of a TCP connection are not required to use the same buffering type.
+ * * The `size` parameter sets the size of the receive buffer to associate with the
+ * example TCP endpoint. If left unspecified, the maximum size is used. The
+ * maximum size is set in `OPENTHREAD_CONFIG_CLI_TCP_RECEIVE_BUFFER_SIZE`.
+ * @par
+ * Initializes the example TCP listener and the example TCP endpoint provided
+ * by the `tcp` CLI.
+ * @sa otTcpListenerInitialize
+ * @sa otTcpEndpointInitialize
+ */
template <> otError TcpExample::Process<Cmd("init")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -234,6 +260,15 @@ exit:
return error;
}
+/**
+ * @cli tcp deinit
+ * @code
+ * tcp deinit
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otTcpEndpointDeinitialize
+ */
template <> otError TcpExample::Process<Cmd("deinit")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -273,6 +308,23 @@ exit:
return error;
}
+/**
+ * @cli tcp bind
+ * @code
+ * tcp bind :: 30000
+ * Done
+ * @endcode
+ * @cparam tcp bind @ca{ip} @ca{port}
+ * * `ip`: IPv6 address to bind to. If you wish to have the TCP/IPv6 stack assign
+ * the binding IPv6 address, use the unspecified IPv6 address: `::`.
+ * * `port`: TCP port number to bind to.
+ * @par
+ * Associates an IPv6 address and a port to the example TCP endpoint provided by
+ * the `tcp` CLI. Associating the TCP endpoint to an IPv6
+ * address and port is referred to as "naming the TCP endpoint." This binds the
+ * endpoint for communication.
+ * @sa otTcpBind
+ */
template <> otError TcpExample::Process<Cmd("bind")>(Arg aArgs[])
{
otError error;
@@ -290,6 +342,34 @@ exit:
return error;
}
+/**
+ * @cli tcp connect
+ * @code
+ * tcp connect fe80:0:0:0:a8df:580a:860:ffa4 30000
+ * Done
+ * TCP: Connection established
+ * @endcode
+ * @code
+ * tcp connect 172.17.0.1 1234
+ * Connecting to synthesized IPv6 address: fdde:ad00:beef:2:0:0:ac11:1
+ * Done
+ * @endcode
+ * @cparam tcp connect @ca{ip} @ca{port} [@ca{fastopen}]
+ * * `ip`: IP address of the peer The address can be an IPv4 address,
+ * which gets synthesized to an IPv6 address using the preferred
+ * NAT64 prefix from the network data. The command returns `InvalidState`
+ * when the preferred NAT64 prefix is unavailable.
+ * * `port`: TCP port number of the peer.
+ * * `fastopen`: This parameter is optional. If set to `fast`, TCP Fast Open is enabled
+ * for this connection. Otherwise, if this parameter is set to `slow` or not used,
+ * TCP Fast Open is disabled.
+ * @par
+ * Establishes a connection with the specified peer.
+ * @par
+ * If the connection establishment is successful, the resulting TCP connection
+ * is associated with the example TCP endpoint.
+ * @sa otTcpConnect
+ */
template <> otError TcpExample::Process<Cmd("connect")>(Arg aArgs[])
{
otError error;
@@ -357,6 +437,19 @@ exit:
return error;
}
+/**
+ * @cli tcp send
+ * @code
+ * tcp send hello
+ * Done
+ * @endcode
+ * @cparam tcp send @ca{message}
+ * The `message` parameter contains the message you want to send to the
+ * remote TCP endpoint.
+ * @par
+ * Sends data over the TCP connection associated with the example TCP endpoint
+ * that is provided with the `tcp` CLI.
+ */
template <> otError TcpExample::Process<Cmd("send")>(Arg aArgs[])
{
otError error;
@@ -408,6 +501,28 @@ template <> otError TcpExample::Process<Cmd("benchmark")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
+ /**
+ * @cli tcp benchmark result
+ * @code
+ * tcp benchmark result
+ * TCP Benchmark Status: Ongoing
+ * Done
+ * @endcode
+ * @code
+ * tcp benchmark result
+ * TCP Benchmark Status: Completed
+ * TCP Benchmark Complete: Transferred 73728 bytes in 7056 milliseconds
+ * TCP Goodput: 83.592 kb/s
+ * @endcode
+ * @par
+ * Shows the latest result of the TCP benchmark test. Possible status values:
+ * * Ongoing
+ * * Completed
+ * * Untested
+ * @par
+ * This command is primarily intended for creating scripts that automate
+ * the TCP benchmark test.
+ */
if (aArgs[0] == "result")
{
OutputFormat("TCP Benchmark Status: ");
@@ -425,6 +540,23 @@ template <> otError TcpExample::Process<Cmd("benchmark")>(Arg aArgs[])
OutputLine("Untested");
}
}
+ /**
+ * @cli tcp benchmark run
+ * @code
+ * tcp benchmark run
+ * Done
+ * TCP Benchmark Complete: Transferred 73728 bytes in 7233 milliseconds
+ * TCP Goodput: 81.546 kb/s
+ * @endcode
+ * @cparam tcp benchmark run [@ca{size}]
+ * Use the `size` parameter to specify the number of bytes to send
+ * for the benchmark. If you do not use the `size` parameter, the default
+ * value (`OPENTHREAD_CONFIG_CLI_TCP_DEFAULT_BENCHMARK_SIZE`) is used.
+ * @par
+ * Transfers the specified number of bytes using the TCP connection
+ * currently associated with the example TCP endpoint provided by the `tcp` CLI.
+ * @note You must establish a TCP connection before you run this command.
+ */
else if (aArgs[0] == "run")
{
VerifyOrExit(!mSendBusy, error = OT_ERROR_BUSY);
@@ -481,6 +613,18 @@ exit:
return error;
}
+/**
+ * @cli tcp sendend
+ * @code
+ * tcp sendend
+ * Done
+ * @endcode
+ * @par
+ * Sends the "end of stream" signal over the TCP connection
+ * associated with the example TCP endpoint provided by the `tcp` CLI. This
+ * alerts the peer that it will not receive any more data over this TCP connection.
+ * @sa otTcpSendEndOfStream
+ */
template <> otError TcpExample::Process<Cmd("sendend")>(Arg aArgs[])
{
otError error;
@@ -494,6 +638,18 @@ exit:
return error;
}
+/**
+ * @cli tcp abort
+ * @code
+ * tcp abort
+ * TCP: Connection reset
+ * Done
+ * @endcode
+ * @par
+ * Unceremoniously ends the TCP connection associated with the
+ * example TCP endpoint, transitioning the TCP endpoint to the closed state.
+ * @sa otTcpAbort
+ */
template <> otError TcpExample::Process<Cmd("abort")>(Arg aArgs[])
{
otError error;
@@ -509,6 +665,25 @@ exit:
return error;
}
+/**
+ * @cli tcp listen
+ * @code
+ * tcp listen :: 30000
+ * Done
+ * @endcode
+ * @cparam tcp listen @ca{ip} @ca{port}
+ * The following parameters are required:
+ * * `ip`: IPv6 address or the unspecified IPv6 address (`::`) of the example
+ * TCP listener provided by the `tcp` CLI.
+ * * `port`: TCP port of the example TCP listener.
+ * If no TCP connection is associated with the example TCP endpoint, then any
+ * incoming connections matching the specified IPv6 address and port are accepted
+ * and are associated with the example TCP endpoint.
+ * @par
+ * Uses the example TCP listener to listen for incoming connections on the
+ * specified IPv6 address and port.
+ * @sa otTcpListen
+ */
template <> otError TcpExample::Process<Cmd("listen")>(Arg aArgs[])
{
otError error;
@@ -527,6 +702,16 @@ exit:
return error;
}
+/**
+ * @cli tcp stoplistening
+ * @code
+ * tcp stoplistening
+ * Done
+ * @endcode
+ * @par
+ * Instructs the example TCP listener to stop listening for incoming TCP connections.
+ * @sa otTcpStopListening
+ */
template <> otError TcpExample::Process<Cmd("stoplistening")>(Arg aArgs[])
{
otError error;
diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp
index d5f379288..0ec70ccea 100644
--- a/src/cli/cli_udp.cpp
+++ b/src/cli/cli_udp.cpp
@@ -50,6 +50,36 @@ UdpExample::UdpExample(otInstance *aInstance, OutputImplementer &aOutputImplemen
memset(&mSocket, 0, sizeof(mSocket));
}
+/**
+ * @cli udp bind
+ * @code
+ * udp bind :: 1234
+ * Done
+ * @endcode
+ * @code
+ * udp bind -u :: 1234
+ * Done
+ * @endcode
+ * @code
+ * udp bind -b :: 1234
+ * Done
+ * @endcode
+ * @cparam udp bind [@ca{netif}] @ca{ip} @ca{port}
+ * - `netif`: The binding network interface, which is determined as follows:
+ * - No value (leaving out this parameter from the command): Thread network interface is used.
+ * - `-u`: Unspecified network interface, which means that the UDP/IPv6 stack determines which
+ * network interface to bind the socket to.
+ * - `-b`: Backbone network interface is used.
+ * - `ip`: IPv6 address to bind to. If you wish to have the UDP/IPv6 stack assign the binding
+ * IPv6 address, then you can use the following value to use the unspecified
+ * IPv6 address: `::`. Each example uses the unspecified IPv6 address.
+ * - `port`: UDP port number to bind to. Each of the examples is using port number 1234.
+ * @par
+ * Assigns an IPv6 address and a port to an open socket, which binds the socket for communication.
+ * Assigning the IPv6 address and port is referred to as naming the socket.
+ * @sa otUdpBind
+ * @sa @udp
+ */
template <> otError UdpExample::Process<Cmd("bind")>(Arg aArgs[])
{
otError error;
@@ -77,6 +107,28 @@ exit:
return error;
}
+/**
+ * @cli udp connect
+ * @code
+ * udp connect fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234
+ * Done
+ * @endcode
+ * @code
+ * udp connect 172.17.0.1 1234
+ * Connecting to synthesized IPv6 address: fdde:ad00:beef:2:0:0:ac11:1
+ * Done
+ * @endcode
+ * @cparam udp connect @ca{ip} @ca{port}
+ * The following parameters are required:
+ * - `ip`: IP address of the peer.
+ * - `port`: UDP port number of the peer.
+ * The address can be an IPv4 address, which gets synthesized to an IPv6 address
+ * using the preferred NAT64 prefix from the network data. The command returns
+ * `InvalidState` when the preferred NAT64 prefix is unavailable.
+ * @par api_copy
+ * #otUdpConnect
+ * @sa @udp
+ */
template <> otError UdpExample::Process<Cmd("connect")>(Arg aArgs[])
{
otError error;
@@ -100,6 +152,15 @@ exit:
return error;
}
+/**
+ * @cli udp close
+ * @code
+ * udp close
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otUdpClose
+ */
template <> otError UdpExample::Process<Cmd("close")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
@@ -107,6 +168,15 @@ template <> otError UdpExample::Process<Cmd("close")>(Arg aArgs[])
return otUdpClose(GetInstancePtr(), &mSocket);
}
+/**
+ * @cli udp open
+ * @code
+ * udp open
+ * Done
+ * @endcode
+ * @par api_copy
+ * #otUdpOpen
+ */
template <> otError UdpExample::Process<Cmd("open")>(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgs);
@@ -120,6 +190,67 @@ exit:
return error;
}
+/**
+ * @cli udp send
+ * @code
+ * udp send hello
+ * Done
+ * @endcode
+ * @code
+ * udp send -t hello
+ * Done
+ * @endcode
+ * @code
+ * udp send -x 68656c6c6f
+ * Done
+ * @endcode
+ * @code
+ * udp send -s 800
+ * Done
+ * @endcode
+ * @code
+ * udp send fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234 hello
+ * Done
+ * @endcode
+ * @code
+ * udp send 172.17.0.1 1234 hello
+ * Sending to synthesized IPv6 address: fdde:ad00:beef:2:0:0:ac11:1
+ * Done
+ * @endcode
+ * @code
+ * udp send fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234 -t hello
+ * Done
+ * @endcode
+ * @code
+ * udp send fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234 -x 68656c6c6f
+ * Done
+ * @endcode
+ * @code
+ * udp send fdde:ad00:beef:0:bb1:ebd6:ad10:f33 1234 -s 800
+ * Done
+ * @endcode
+ * @cparam udp send [@ca{ip} @ca{port}] [@ca{type}] @ca{value}
+ * The `ip` and `port` are optional as a pair, but if you specify one you must
+ * specify the other. If `ip` and `port` are not specified, the socket peer address
+ * is used from `udp connect`.
+ * - `ip`: Destination address. This address can be either an IPv4 or IPv6 address,
+ * An IPv4 address gets synthesized to an IPv6 address with the preferred
+ * NAT64 prefix from the network data. (If the preferred NAT64 prefix
+ * is unavailable, the command returns `InvalidState`).
+ * - `port`: UDP destination port.
+ * - `type`/`value` combinations:
+ * - `-t`: The payload in the `value` parameter is treated as text. If no `type` value
+ * is entered, the payload in the `value` parameter is also treated as text.
+ * - `-s`: Auto-generated payload with the specified length given in the `value` parameter.
+ * - `-x`: Binary data in hexadecimal representation given in the `value` parameter.
+ * @par
+ * Sends a UDP message using the socket.
+ * @csa{udp open}
+ * @csa{udp bind}
+ * @csa{udp connect}
+ * @sa otUdpSend
+ * @sa @udp
+ */
template <> otError UdpExample::Process<Cmd("send")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -201,10 +332,33 @@ template <> otError UdpExample::Process<Cmd("linksecurity")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
+ /**
+ * @cli udp linksecurity
+ * @code
+ * udp linksecurity
+ * Enabled
+ * Done
+ * @endcode
+ * @par
+ * Indicates whether link security is enabled or disabled.
+ */
if (aArgs[0].IsEmpty())
{
OutputEnabledDisabledStatus(mLinkSecurityEnabled);
}
+ /**
+ * @cli udp linksecurity (enable,disable)
+ * @code
+ * udp linksecurity enable
+ * Done
+ * @endcode
+ * @code
+ * udp linksecurity disable
+ * Done
+ * @endcode
+ * @par
+ * Enables or disables link security.
+ */
else
{
error = Interpreter::ParseEnableOrDisable(aArgs[0], mLinkSecurityEnabled);
diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn
index d44f410fd..37843dd2e 100644
--- a/src/core/BUILD.gn
+++ b/src/core/BUILD.gn
@@ -396,7 +396,6 @@ openthread_core_files = [
"common/equatable.hpp",
"common/error.cpp",
"common/error.hpp",
- "common/extension.hpp",
"common/frame_builder.cpp",
"common/frame_builder.hpp",
"common/frame_data.cpp",
@@ -409,8 +408,6 @@ openthread_core_files = [
"common/heap_data.hpp",
"common/heap_string.cpp",
"common/heap_string.hpp",
- "common/instance.cpp",
- "common/instance.hpp",
"common/iterator_utils.hpp",
"common/linked_list.hpp",
"common/locator.hpp",
@@ -474,6 +471,9 @@ openthread_core_files = [
"crypto/storage.hpp",
"diags/factory_diags.cpp",
"diags/factory_diags.hpp",
+ "instance/extension.hpp",
+ "instance/instance.cpp",
+ "instance/instance.hpp",
"mac/channel_mask.cpp",
"mac/channel_mask.hpp",
"mac/data_poll_handler.cpp",
@@ -657,7 +657,6 @@ openthread_core_files = [
"thread/network_data_leader.cpp",
"thread/network_data_leader.hpp",
"thread/network_data_leader_ftd.cpp",
- "thread/network_data_leader_ftd.hpp",
"thread/network_data_local.cpp",
"thread/network_data_local.hpp",
"thread/network_data_notifier.cpp",
@@ -737,7 +736,6 @@ openthread_radio_sources = [
"common/error.hpp",
"common/frame_builder.cpp",
"common/frame_builder.hpp",
- "common/instance.cpp",
"common/log.cpp",
"common/random.cpp",
"common/string.cpp",
@@ -749,6 +747,7 @@ openthread_radio_sources = [
"crypto/crypto_platform.cpp",
"crypto/storage.cpp",
"diags/factory_diags.cpp",
+ "instance/instance.cpp",
"mac/link_raw.cpp",
"mac/mac_frame.cpp",
"mac/mac_types.cpp",
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c8e4079ab..813979ad7 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -106,7 +106,6 @@ set(COMMON_SOURCES
common/heap.cpp
common/heap_data.cpp
common/heap_string.cpp
- common/instance.cpp
common/log.cpp
common/message.cpp
common/notifier.cpp
@@ -129,6 +128,7 @@ set(COMMON_SOURCES
crypto/sha256.cpp
crypto/storage.cpp
diags/factory_diags.cpp
+ instance/instance.cpp
mac/channel_mask.cpp
mac/data_poll_handler.cpp
mac/data_poll_sender.cpp
@@ -265,7 +265,6 @@ set(RADIO_COMMON_SOURCES
common/binary_search.cpp
common/error.cpp
common/frame_builder.cpp
- common/instance.cpp
common/log.cpp
common/random.cpp
common/string.cpp
@@ -277,6 +276,7 @@ set(RADIO_COMMON_SOURCES
crypto/crypto_platform.cpp
crypto/storage.cpp
diags/factory_diags.cpp
+ instance/instance.cpp
mac/link_raw.cpp
mac/mac_frame.cpp
mac/mac_types.cpp
diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp
index 5694768e9..dcccf5bb6 100644
--- a/src/core/api/border_router_api.cpp
+++ b/src/core/api/border_router_api.cpp
@@ -39,7 +39,7 @@
#include "border_router/routing_manager.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
using namespace ot;
diff --git a/src/core/api/border_routing_api.cpp b/src/core/api/border_routing_api.cpp
index 1ed017c57..9fbfbcb4b 100644
--- a/src/core/api/border_routing_api.cpp
+++ b/src/core/api/border_routing_api.cpp
@@ -39,7 +39,7 @@
#include <openthread/platform/border_routing.h>
#include "border_router/routing_manager.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
using namespace ot;
@@ -172,6 +172,16 @@ otError otBorderRoutingGetNextPrefixTableEntry(otInstance
return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextPrefixTableEntry(*aIterator, *aEntry);
}
+otError otBorderRoutingGetNextRouterEntry(otInstance *aInstance,
+ otBorderRoutingPrefixTableIterator *aIterator,
+ otBorderRoutingRouterEntry *aEntry)
+{
+ AssertPointerIsNotNull(aIterator);
+ AssertPointerIsNotNull(aEntry);
+
+ return AsCoreType(aInstance).Get<BorderRouter::RoutingManager>().GetNextRouterEntry(*aIterator, *aEntry);
+}
+
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
void otBorderRoutingDhcp6PdSetEnabled(otInstance *aInstance, bool aEnabled)
{
diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp
index b218d29e7..25f3208e7 100644
--- a/src/core/api/coap_api.cpp
+++ b/src/core/api/coap_api.cpp
@@ -211,7 +211,7 @@ otError otCoapSendRequestBlockWiseWithParameters(otInstance *aIn
Error error;
const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
if (aTxParameters != nullptr)
{
@@ -238,7 +238,7 @@ otError otCoapSendRequestWithParameters(otInstance *aInstance,
const Coap::TxParameters &txParameters = Coap::TxParameters::From(aTxParameters);
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
if (aTxParameters != nullptr)
{
@@ -296,7 +296,7 @@ otError otCoapSendResponseBlockWiseWithParameters(otInstance *aI
{
otError error;
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
error = AsCoreType(aInstance).GetApplicationCoap().SendMessage(AsCoapMessage(aMessage), AsCoreType(aMessageInfo),
Coap::TxParameters::From(aTxParameters), nullptr,
@@ -313,7 +313,7 @@ otError otCoapSendResponseWithParameters(otInstance *aInstance,
{
otError error;
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
error = AsCoreType(aInstance).GetApplicationCoap().SendMessage(
AsCoapMessage(aMessage), AsCoreType(aMessageInfo), Coap::TxParameters::From(aTxParameters), nullptr, nullptr);
diff --git a/src/core/api/dns_api.cpp b/src/core/api/dns_api.cpp
index 41be0c4fd..fe064b660 100644
--- a/src/core/api/dns_api.cpp
+++ b/src/core/api/dns_api.cpp
@@ -35,7 +35,7 @@
#include <openthread/dns_client.h>
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "net/dns_types.hpp"
using namespace ot;
diff --git a/src/core/api/dns_server_api.cpp b/src/core/api/dns_server_api.cpp
index 62e69fc17..80e88e432 100644
--- a/src/core/api/dns_server_api.cpp
+++ b/src/core/api/dns_server_api.cpp
@@ -33,7 +33,7 @@
#include "openthread-core-config.h"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "net/dns_types.hpp"
#include "net/dnssd_server.hpp"
diff --git a/src/core/api/instance_api.cpp b/src/core/api/instance_api.cpp
index ad2a89e16..5d6d5971e 100644
--- a/src/core/api/instance_api.cpp
+++ b/src/core/api/instance_api.cpp
@@ -58,6 +58,16 @@
using namespace ot;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+otInstance *otInstanceInitMultiple(uint8_t aIdx)
+{
+ Instance *instance;
+
+ instance = Instance::InitMultiple(aIdx);
+
+ return instance;
+}
+#endif // OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize)
{
Instance *instance;
@@ -86,6 +96,10 @@ void otInstanceFinalize(otInstance *aInstance) { AsCoreType(aInstance).Finalize(
void otInstanceReset(otInstance *aInstance) { AsCoreType(aInstance).Reset(); }
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+otError otInstanceResetToBootloader(otInstance *aInstance) { return AsCoreType(aInstance).ResetToBootloader(); }
+#endif
+
#if OPENTHREAD_CONFIG_UPTIME_ENABLE
uint64_t otInstanceGetUptime(otInstance *aInstance) { return AsCoreType(aInstance).Get<Uptime>().GetUptime(); }
diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp
index 710001919..5ca4f50d9 100644
--- a/src/core/api/ip6_api.cpp
+++ b/src/core/api/ip6_api.cpp
@@ -75,6 +75,11 @@ const otNetifAddress *otIp6GetUnicastAddresses(otInstance *aInstance)
return AsCoreType(aInstance).Get<ThreadNetif>().GetUnicastAddresses().GetHead();
}
+bool otIp6HasUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress)
+{
+ return AsCoreType(aInstance).Get<ThreadNetif>().HasUnicastAddress(AsCoreType(aAddress));
+}
+
otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress)
{
return AsCoreType(aInstance).Get<ThreadNetif>().AddExternalUnicastAddress(AsCoreType(aAddress));
@@ -134,9 +139,9 @@ otError otIp6Send(otInstance *aInstance, otMessage *aMessage)
{
otError error;
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
- error = AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage));
+ error = AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(OwnedPtr<Message>(AsCoreTypePtr(aMessage)));
exit:
return error;
@@ -244,8 +249,8 @@ otError otIp6RegisterMulticastListeners(otInstance *
otIp6RegisterMulticastListenersCallback aCallback,
void *aContext)
{
- return AsCoreType(aInstance).Get<MlrManager>().RegisterMulticastListeners(aAddresses, aAddressNum, aTimeout,
- aCallback, aContext);
+ return AsCoreType(aInstance).Get<MlrManager>().RegisterMulticastListeners(AsCoreTypePtr(aAddresses), aAddressNum,
+ aTimeout, aCallback, aContext);
}
#endif
diff --git a/src/core/api/logging_api.cpp b/src/core/api/logging_api.cpp
index edce6b920..6abbb3245 100644
--- a/src/core/api/logging_api.cpp
+++ b/src/core/api/logging_api.cpp
@@ -35,9 +35,10 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "common/string.hpp"
+#include "instance/instance.hpp"
using namespace ot;
@@ -179,6 +180,38 @@ void otDumpDebgPlat(const char *aText, const void *aData, uint16_t aDataLength)
#endif
}
+void otLogPlat(otLogLevel aLogLevel, const char *aPlatModuleName, const char *aFormat, ...)
+{
+#if OPENTHREAD_CONFIG_LOG_PLATFORM
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(aLogLevel, aPlatModuleName, aFormat, args);
+ va_end(args);
+#else
+ OT_UNUSED_VARIABLE(aLogLevel);
+ OT_UNUSED_VARIABLE(aPlatModuleName);
+ OT_UNUSED_VARIABLE(aFormat);
+#endif
+}
+
+void otLogPlatArgs(otLogLevel aLogLevel, const char *aPlatModuleName, const char *aFormat, va_list aArgs)
+{
+#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_PLATFORM
+ String<kMaxLogModuleNameLength> moduleName;
+
+ OT_ASSERT(aLogLevel >= kLogLevelNone && aLogLevel <= kLogLevelDebg);
+
+ moduleName.Append("P-%s", aPlatModuleName);
+ Logger::LogVarArgs(moduleName.AsCString(), static_cast<LogLevel>(aLogLevel), aFormat, aArgs);
+#else
+ OT_UNUSED_VARIABLE(aLogLevel);
+ OT_UNUSED_VARIABLE(aPlatModuleName);
+ OT_UNUSED_VARIABLE(aFormat);
+ OT_UNUSED_VARIABLE(aArgs);
+#endif
+}
+
void otLogCli(otLogLevel aLogLevel, const char *aFormat, ...)
{
#if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_CLI
@@ -199,3 +232,10 @@ exit:
#endif
return;
}
+
+otError otLogGenerateNextHexDumpLine(otLogHexDumpInfo *aInfo)
+{
+ AssertPointerIsNotNull(aInfo);
+
+ return GenerateNextHexDumpLine(*aInfo);
+}
diff --git a/src/core/api/message_api.cpp b/src/core/api/message_api.cpp
index f564e3abd..41dedc199 100644
--- a/src/core/api/message_api.cpp
+++ b/src/core/api/message_api.cpp
@@ -62,6 +62,13 @@ void otMessageSetLoopbackToHostAllowed(otMessage *aMessage, bool aAllowLoopbackT
return AsCoreType(aMessage).SetLoopbackToHostAllowed(aAllowLoopbackToHost);
}
+bool otMessageIsMulticastLoopEnabled(otMessage *aMessage) { return AsCoreType(aMessage).GetMulticastLoop(); }
+
+void otMessageSetMulticastLoopEnabled(otMessage *aMessage, bool aEnabled)
+{
+ AsCoreType(aMessage).SetMulticastLoop(aEnabled);
+}
+
otMessageOrigin otMessageGetOrigin(const otMessage *aMessage) { return MapEnum(AsCoreType(aMessage).GetOrigin()); }
void otMessageSetOrigin(otMessage *aMessage, otMessageOrigin aOrigin)
diff --git a/src/core/api/nat64_api.cpp b/src/core/api/nat64_api.cpp
index 7405b9d6c..02aa785b4 100644
--- a/src/core/api/nat64_api.cpp
+++ b/src/core/api/nat64_api.cpp
@@ -39,7 +39,7 @@
#include "border_router/routing_manager.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "net/ip4_types.hpp"
#include "net/ip6_headers.hpp"
#include "net/nat64_translator.hpp"
diff --git a/src/core/api/netdata_api.cpp b/src/core/api/netdata_api.cpp
index 28e06c7f5..50fcd0ce2 100644
--- a/src/core/api/netdata_api.cpp
+++ b/src/core/api/netdata_api.cpp
@@ -104,6 +104,11 @@ otError otNetDataGetNextLowpanContextInfo(otInstance *aInstance,
AsCoreType(aContextInfo));
}
+void otNetDataGetCommissioningDataset(otInstance *aInstance, otCommissioningDataset *aDataset)
+{
+ return AsCoreType(aInstance).Get<NetworkData::Leader>().GetCommissioningDataset(AsCoreType(aDataset));
+}
+
uint8_t otNetDataGetVersion(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Mle::MleRouter>().GetLeaderData().GetDataVersion(NetworkData::kFullSet);
diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp
index 1811cf49b..6bf2ca39d 100644
--- a/src/core/api/thread_api.cpp
+++ b/src/core/api/thread_api.cpp
@@ -395,7 +395,18 @@ otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled)
uint16_t otThreadGetVersion(void) { return kThreadVersion; }
-bool otThreadIsSingleton(otInstance *aInstance) { return AsCoreType(aInstance).Get<Mle::MleRouter>().IsSingleton(); }
+bool otThreadIsSingleton(otInstance *aInstance)
+{
+ bool isSingleton = false;
+
+#if OPENTHREAD_FTD
+ isSingleton = AsCoreType(aInstance).Get<Mle::MleRouter>().IsSingleton();
+#else
+ OT_UNUSED_VARIABLE(aInstance);
+#endif
+
+ return isSingleton;
+}
otError otThreadDiscover(otInstance *aInstance,
uint32_t aScanChannels,
diff --git a/src/core/api/trel_api.cpp b/src/core/api/trel_api.cpp
index 29c1563a6..687c1169c 100644
--- a/src/core/api/trel_api.cpp
+++ b/src/core/api/trel_api.cpp
@@ -39,7 +39,7 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
using namespace ot;
diff --git a/src/core/api/udp_api.cpp b/src/core/api/udp_api.cpp
index 48dc5845f..5141a50b6 100644
--- a/src/core/api/udp_api.cpp
+++ b/src/core/api/udp_api.cpp
@@ -74,7 +74,7 @@ otError otUdpSend(otInstance *aInstance, otUdpSocket *aSocket, otMessage *aMessa
{
otError error;
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
error = AsCoreType(aInstance).Get<Ip6::Udp>().SendTo(AsCoreType(aSocket), AsCoreType(aMessage),
AsCoreType(aMessageInfo));
@@ -124,10 +124,9 @@ otError otUdpSendDatagram(otInstance *aInstance, otMessage *aMessage, otMessageI
{
otError error;
- VerifyOrExit(AsCoreType(aMessage).GetOrigin() != Message::kOriginThreadNetif, error = kErrorInvalidArgs);
+ VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs);
- return AsCoreType(aInstance).Get<Ip6::Udp>().SendDatagram(AsCoreType(aMessage), AsCoreType(aMessageInfo),
- Ip6::kProtoUdp);
+ return AsCoreType(aInstance).Get<Ip6::Udp>().SendDatagram(AsCoreType(aMessage), AsCoreType(aMessageInfo));
exit:
return error;
}
diff --git a/src/core/backbone_router/bbr_leader.cpp b/src/core/backbone_router/bbr_leader.cpp
index efced1bb5..5b605ac5e 100644
--- a/src/core/backbone_router/bbr_leader.cpp
+++ b/src/core/backbone_router/bbr_leader.cpp
@@ -35,8 +35,8 @@
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace BackboneRouter {
diff --git a/src/core/backbone_router/bbr_leader.hpp b/src/core/backbone_router/bbr_leader.hpp
index 465765d45..4102651f2 100644
--- a/src/core/backbone_router/bbr_leader.hpp
+++ b/src/core/backbone_router/bbr_leader.hpp
@@ -39,6 +39,7 @@
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
#include <openthread/backbone_router.h>
+#include <openthread/backbone_router_ftd.h>
#include <openthread/ip6.h>
#include "coap/coap.hpp"
@@ -72,10 +73,10 @@ static_assert(kParentAggregateDelay > 1, "kParentAggregateDelay should be larger
*/
enum DomainPrefixEvent : uint8_t
{
- kDomainPrefixAdded, ///< Domain Prefix Added.
- kDomainPrefixRemoved, ///< Domain Prefix Removed.
- kDomainPrefixRefreshed, ///< Domain Prefix Changed.
- kDomainPrefixUnchanged, ///< Domain Prefix did not change.
+ kDomainPrefixAdded = OT_BACKBONE_ROUTER_DOMAIN_PREFIX_ADDED, ///< Domain Prefix Added.
+ kDomainPrefixRemoved = OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED, ///< Domain Prefix Removed.
+ kDomainPrefixRefreshed = OT_BACKBONE_ROUTER_DOMAIN_PREFIX_CHANGED, ///< Domain Prefix Changed.
+ kDomainPrefixUnchanged, ///< Domain Prefix did not change.
};
/**
diff --git a/src/core/backbone_router/bbr_local.cpp b/src/core/backbone_router/bbr_local.cpp
index 7c1289b06..66cb8f519 100644
--- a/src/core/backbone_router/bbr_local.cpp
+++ b/src/core/backbone_router/bbr_local.cpp
@@ -36,10 +36,10 @@
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/mle_types.hpp"
#include "thread/thread_netif.hpp"
@@ -51,19 +51,19 @@ RegisterLogModule("BbrLocal");
Local::Local(Instance &aInstance)
: InstanceLocator(aInstance)
+ , mIsServiceAdded(false)
, mState(kStateDisabled)
- , mMlrTimeout(kDefaultMlrTimeout)
- , mReregistrationDelay(kDefaultRegistrationDelay)
- , mRegistrationTimeout(0)
, mSequenceNumber(Random::NonCrypto::GetUint8() % 127)
, mRegistrationJitter(kDefaultRegistrationJitter)
- , mIsServiceAdded(false)
+ , mReregistrationDelay(kDefaultRegistrationDelay)
+ , mRegistrationTimeout(0)
+ , mMlrTimeout(kDefaultMlrTimeout)
{
mDomainPrefixConfig.GetPrefix().SetLength(0);
// Primary Backbone Router Aloc
- mBackboneRouterPrimaryAloc.InitAsThreadOriginRealmLocalScope();
- mBackboneRouterPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::kAloc16BackboneRouterPrimary);
+ mBbrPrimaryAloc.InitAsThreadOriginMeshLocal();
+ mBbrPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::kAloc16BackboneRouterPrimary);
// All Network Backbone Routers Multicast Address.
mAllNetworkBackboneRouters.Clear();
@@ -110,7 +110,7 @@ void Local::Reset(void)
if (mState == kStatePrimary)
{
// Increase sequence number when changing from Primary to Secondary.
- SequenceNumberIncrease();
+ IncrementSequenceNumber();
Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
SetState(kStateSecondary);
}
@@ -168,7 +168,7 @@ Error Local::SetConfig(const Config &aConfig)
}
exit:
- LogBackboneRouterService("Set", error);
+ LogService(kActionSet, error);
return error;
}
@@ -199,7 +199,7 @@ Error Local::AddService(RegisterMode aMode)
mIsServiceAdded = true;
exit:
- LogBackboneRouterService("Add", error);
+ LogService(kActionAdd, error);
return error;
}
@@ -212,28 +212,31 @@ void Local::RemoveService(void)
mIsServiceAdded = false;
exit:
- LogBackboneRouterService("Remove", error);
+ LogService(kActionRemove, error);
}
void Local::SetState(State aState)
{
VerifyOrExit(mState != aState);
- if (mState == kStateDisabled)
+ switch (mState)
{
+ case kStateDisabled:
// Update All Network Backbone Routers Multicast Address for both Secondary and Primary state.
mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
+ break;
+ case kStateSecondary:
+ break;
+ case kStatePrimary:
+ Get<ThreadNetif>().RemoveUnicastAddress(mBbrPrimaryAloc);
+ break;
}
- if (mState == kStatePrimary)
- {
- Get<ThreadNetif>().RemoveUnicastAddress(mBackboneRouterPrimaryAloc);
- }
- else if (aState == kStatePrimary)
+ if (aState == kStatePrimary)
{
- // Add Primary Backbone Router Aloc for Primary Backbone Router.
- mBackboneRouterPrimaryAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(mBackboneRouterPrimaryAloc);
+ // Add Primary Backbone Router ALOC for Primary Backbone Router.
+ mBbrPrimaryAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
+ Get<ThreadNetif>().AddUnicastAddress(mBbrPrimaryAloc);
}
mState = aState;
@@ -274,7 +277,7 @@ void Local::HandleBackboneRouterPrimaryUpdate(Leader::State aState, const Config
mSequenceNumber = aConfig.mSequenceNumber;
mReregistrationDelay = aConfig.mReregistrationDelay;
mMlrTimeout = aConfig.mMlrTimeout;
- SequenceNumberIncrease();
+ IncrementSequenceNumber();
Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
IgnoreError(AddService(kForceRegistration));
}
@@ -353,7 +356,7 @@ Error Local::SetDomainPrefix(const NetworkData::OnMeshPrefixConfig &aConfig)
}
mDomainPrefixConfig = aConfig;
- LogDomainPrefix("Set", kErrorNone);
+ LogDomainPrefix(kActionSet, kErrorNone);
if (IsEnabled())
{
@@ -364,7 +367,7 @@ exit:
return error;
}
-void Local::ApplyMeshLocalPrefix(void)
+void Local::ApplyNewMeshLocalPrefix(void)
{
VerifyOrExit(IsEnabled());
@@ -372,13 +375,6 @@ void Local::ApplyMeshLocalPrefix(void)
mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
Get<BackboneTmfAgent>().SubscribeMulticast(mAllNetworkBackboneRouters);
- if (IsPrimary())
- {
- Get<ThreadNetif>().RemoveUnicastAddress(mBackboneRouterPrimaryAloc);
- mBackboneRouterPrimaryAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(mBackboneRouterPrimaryAloc);
- }
-
exit:
return;
}
@@ -401,22 +397,10 @@ void Local::HandleDomainPrefixUpdate(DomainPrefixEvent aEvent)
Get<BackboneTmfAgent>().SubscribeMulticast(mAllDomainBackboneRouters);
}
- if (mDomainPrefixCallback.IsSet())
+ if (aEvent != kDomainPrefixUnchanged)
{
- switch (aEvent)
- {
- case kDomainPrefixAdded:
- mDomainPrefixCallback.Invoke(OT_BACKBONE_ROUTER_DOMAIN_PREFIX_ADDED, Get<Leader>().GetDomainPrefix());
- break;
- case kDomainPrefixRemoved:
- mDomainPrefixCallback.Invoke(OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED, Get<Leader>().GetDomainPrefix());
- break;
- case kDomainPrefixRefreshed:
- mDomainPrefixCallback.Invoke(OT_BACKBONE_ROUTER_DOMAIN_PREFIX_CHANGED, Get<Leader>().GetDomainPrefix());
- break;
- default:
- break;
- }
+ mDomainPrefixCallback.InvokeIfSet(static_cast<otBackboneRouterDomainPrefixEvent>(aEvent),
+ Get<Leader>().GetDomainPrefix());
}
exit:
@@ -432,10 +416,10 @@ void Local::RemoveDomainPrefixFromNetworkData(void)
error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mDomainPrefixConfig.GetPrefix());
}
- LogDomainPrefix("Remove", error);
+ LogDomainPrefix(kActionRemove, error);
}
-void Local::SequenceNumberIncrease(void)
+void Local::IncrementSequenceNumber(void)
{
switch (mSequenceNumber)
{
@@ -462,21 +446,38 @@ void Local::AddDomainPrefixToNetworkData(void)
error = Get<NetworkData::Local>().AddOnMeshPrefix(mDomainPrefixConfig);
}
- LogDomainPrefix("Add", error);
+ LogDomainPrefix(kActionAdd, error);
}
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
-void Local::LogDomainPrefix(const char *aAction, Error aError)
+
+const char *Local::ActionToString(Action aAction)
{
- LogInfo("%s Domain Prefix: %s, %s", aAction, mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
+ static const char *const kActionStrings[] = {
+ "Set", // (0) kActionSet
+ "Add", // (1) kActionAdd
+ "Remove", // (2) kActionRemove
+ };
+
+ static_assert(0 == kActionSet, "kActionSet value is incorrect");
+ static_assert(1 == kActionAdd, "kActionAdd value is incorrect");
+ static_assert(2 == kActionRemove, "kActionRemove value is incorrect");
+
+ return kActionStrings[aAction];
+}
+
+void Local::LogDomainPrefix(Action aAction, Error aError)
+{
+ LogInfo("%s Domain Prefix: %s, %s", ActionToString(aAction), mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
ErrorToString(aError));
}
-void Local::LogBackboneRouterService(const char *aAction, Error aError)
+void Local::LogService(Action aAction, Error aError)
{
- LogInfo("%s BBR Service: seqno (%u), delay (%us), timeout (%lus), %s", aAction, mSequenceNumber,
+ LogInfo("%s BBR Service: seqno (%u), delay (%us), timeout (%lus), %s", ActionToString(aAction), mSequenceNumber,
mReregistrationDelay, ToUlong(mMlrTimeout), ErrorToString(aError));
}
+
#endif
} // namespace BackboneRouter
diff --git a/src/core/backbone_router/bbr_local.hpp b/src/core/backbone_router/bbr_local.hpp
index 5578dc208..754f5a2a1 100644
--- a/src/core/backbone_router/bbr_local.hpp
+++ b/src/core/backbone_router/bbr_local.hpp
@@ -76,6 +76,8 @@ class Local : public InstanceLocator, private NonCopyable
friend class ot::TimeTicker;
public:
+ typedef otBackboneRouterDomainPrefixCallback DomainPrefixCallback; ///< Domain Prefix callback.
+
/**
* Represents Backbone Router state.
*
@@ -256,7 +258,7 @@ public:
* Applies the Mesh Local Prefix.
*
*/
- void ApplyMeshLocalPrefix(void);
+ void ApplyNewMeshLocalPrefix(void);
/**
* Updates the subscription of All Domain Backbone Routers Multicast Address.
@@ -273,44 +275,49 @@ public:
* @param[in] aContext A user context pointer.
*
*/
- void SetDomainPrefixCallback(otBackboneRouterDomainPrefixCallback aCallback, void *aContext)
+ void SetDomainPrefixCallback(DomainPrefixCallback aCallback, void *aContext)
{
mDomainPrefixCallback.Set(aCallback, aContext);
}
private:
+ enum Action : uint8_t
+ {
+ kActionSet,
+ kActionAdd,
+ kActionRemove,
+ };
+
void SetState(State aState);
void RemoveService(void);
void HandleTimeTick(void);
void AddDomainPrefixToNetworkData(void);
void RemoveDomainPrefixFromNetworkData(void);
- void SequenceNumberIncrease(void);
+ void IncrementSequenceNumber(void);
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
- void LogBackboneRouterService(const char *aAction, Error aError);
- void LogDomainPrefix(const char *aAction, Error aError);
+ static const char *ActionToString(Action aAction);
+ void LogService(Action aAction, Error aError);
+ void LogDomainPrefix(Action aAction, Error aError);
#else
- void LogBackboneRouterService(const char *, Error) {}
- void LogDomainPrefix(const char *, Error) {}
+ void LogService(Action, Error) {}
+ void LogDomainPrefix(Action, Error) {}
#endif
- State mState;
- uint32_t mMlrTimeout;
- uint16_t mReregistrationDelay;
- uint16_t mRegistrationTimeout;
- uint8_t mSequenceNumber;
- uint8_t mRegistrationJitter;
-
// Indicates whether or not already add Backbone Router Service to local server data.
// Used to check whether or not in restore stage after reset or whether to remove
// Backbone Router service for Secondary Backbone Router if it was added by force.
- bool mIsServiceAdded;
-
+ bool mIsServiceAdded;
+ State mState;
+ uint8_t mSequenceNumber;
+ uint8_t mRegistrationJitter;
+ uint16_t mReregistrationDelay;
+ uint16_t mRegistrationTimeout;
+ uint32_t mMlrTimeout;
NetworkData::OnMeshPrefixConfig mDomainPrefixConfig;
-
- Ip6::Netif::UnicastAddress mBackboneRouterPrimaryAloc;
- Ip6::Address mAllNetworkBackboneRouters;
- Ip6::Address mAllDomainBackboneRouters;
- Callback<otBackboneRouterDomainPrefixCallback> mDomainPrefixCallback;
+ Ip6::Netif::UnicastAddress mBbrPrimaryAloc;
+ Ip6::Address mAllNetworkBackboneRouters;
+ Ip6::Address mAllDomainBackboneRouters;
+ Callback<DomainPrefixCallback> mDomainPrefixCallback;
};
} // namespace BackboneRouter
diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp
index 09c1c7656..551cfa22d 100644
--- a/src/core/backbone_router/bbr_manager.cpp
+++ b/src/core/backbone_router/bbr_manager.cpp
@@ -37,11 +37,11 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/mle_types.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
@@ -176,11 +176,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
if (Tlv::Find<ThreadCommissionerSessionIdTlv>(aMessage, commissionerSessionId) == kErrorNone)
{
- const MeshCoP::CommissionerSessionIdTlv *commissionerSessionIdTlv = As<MeshCoP::CommissionerSessionIdTlv>(
- Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kCommissionerSessionId));
+ uint16_t localSessionId;
- VerifyOrExit(commissionerSessionIdTlv != nullptr &&
- commissionerSessionIdTlv->GetCommissionerSessionId() == commissionerSessionId,
+ VerifyOrExit((Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId) == kErrorNone) &&
+ (localSessionId == commissionerSessionId),
status = ThreadStatusTlv::kMlrGeneralFailure);
hasCommissionerSessionIdTlv = true;
diff --git a/src/core/backbone_router/multicast_listeners_table.cpp b/src/core/backbone_router/multicast_listeners_table.cpp
index 4f477cdee..22e4e320a 100644
--- a/src/core/backbone_router/multicast_listeners_table.cpp
+++ b/src/core/backbone_router/multicast_listeners_table.cpp
@@ -37,10 +37,10 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/mle_types.hpp"
#include "thread/thread_netif.hpp"
#include "thread/uri_paths.hpp"
diff --git a/src/core/border_router/infra_if.cpp b/src/core/border_router/infra_if.cpp
index 011400c4d..07b5dc509 100644
--- a/src/core/border_router/infra_if.cpp
+++ b/src/core/border_router/infra_if.cpp
@@ -37,9 +37,9 @@
#include "border_router/routing_manager.hpp"
#include "common/as_core_type.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/logging.hpp"
+#include "instance/instance.hpp"
#include "net/icmp6.hpp"
namespace ot {
diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp
index 97fbad55f..e48536819 100644
--- a/src/core/border_router/routing_manager.cpp
+++ b/src/core/border_router/routing_manager.cpp
@@ -44,13 +44,13 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
#include "common/random.hpp"
#include "common/settings.hpp"
+#include "instance/instance.hpp"
#include "meshcop/extended_panid.hpp"
#include "net/ip6.hpp"
#include "net/nat64_translator.hpp"
@@ -186,7 +186,6 @@ void RoutingManager::UpdateRioPreference(RoutePreference aPreference)
RoutePreferenceToString(aPreference));
mRioPreference = aPreference;
- VerifyOrExit(mIsRunning);
ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
exit:
@@ -343,6 +342,9 @@ void RoutingManager::Start(void)
mOmrPrefixManager.Start();
mRoutePublisher.Start();
mRsSender.Start();
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ mPdPrefixManager.Start();
+#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mNat64PrefixManager.Start();
#endif
@@ -355,14 +357,20 @@ void RoutingManager::Stop(void)
mOmrPrefixManager.Stop();
mOnLinkPrefixManager.Stop();
-
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ mPdPrefixManager.Stop();
+#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mNat64PrefixManager.Stop();
#endif
SendRouterAdvertisement(kInvalidateAllPrevPrefixes);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
+ mAdvertisedPrefixes.Free();
+#else
mAdvertisedPrefixes.Clear();
+#endif
mDiscoveredPrefixTable.RemoveAllEntries();
mDiscoveredPrefixStaleTimer.Stop();
@@ -540,6 +548,8 @@ void RoutingManager::ScheduleRoutingPolicyEvaluation(ScheduleMode aMode)
uint32_t delay = 0;
TimeMilli evaluateTime;
+ VerifyOrExit(mIsRunning);
+
switch (aMode)
{
case kImmediately:
@@ -586,6 +596,9 @@ void RoutingManager::ScheduleRoutingPolicyEvaluation(ScheduleMode aMode)
}
}
#endif
+
+exit:
+ return;
}
void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
@@ -612,6 +625,12 @@ void RoutingManager::SendRouterAdvertisement(RouterAdvTxMode aRaTxMode)
LogInfo("Preparing RA");
+ mDiscoveredPrefixTable.DetermineAndSetFlags(raMsg);
+
+ LogInfo("- RA Header - flags - M:%u O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
+ raMsg.GetHeader().IsOtherConfigFlagSet());
+ LogInfo("- RA Header - default route - lifetime:%u", raMsg.GetHeader().GetRouterLifetime());
+
#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
SuccessOrAssert(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
LogInfo("- FlagsExt - StubRouter:1");
@@ -1234,7 +1253,7 @@ void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const Ip6
UpdateRouterOnRx(*router);
- RemoveRoutersWithNoEntries();
+ RemoveRoutersWithNoEntriesOrFlags();
exit:
return;
@@ -1464,7 +1483,7 @@ void RoutingManager::DiscoveredPrefixTable::RemovePrefix(const Entry::Matcher &a
VerifyOrExit(!removedEntries.IsEmpty());
FreeEntries(removedEntries);
- RemoveRoutersWithNoEntries();
+ RemoveRoutersWithNoEntriesOrFlags();
SignalTableChanged();
@@ -1474,21 +1493,17 @@ exit:
void RoutingManager::DiscoveredPrefixTable::RemoveAllEntries(void)
{
- // Remove all entries from the table and unpublish them
- // from Network Data.
+ // Remove all entries from the table.
for (Router &router : mRouters)
{
- if (!router.mEntries.IsEmpty())
- {
- SignalTableChanged();
- }
-
FreeEntries(router.mEntries);
}
- RemoveRoutersWithNoEntries();
+ FreeRouters(mRouters);
mEntryTimer.Stop();
+
+ SignalTableChanged();
}
void RoutingManager::DiscoveredPrefixTable::RemoveOrDeprecateOldEntries(TimeMilli aTimeThreshold)
@@ -1584,11 +1599,11 @@ TimeMilli RoutingManager::DiscoveredPrefixTable::CalculateNextStaleTime(TimeMill
return foundOnLink ? Min(onLinkStaleTime, routeStaleTime) : routeStaleTime;
}
-void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntries(void)
+void RoutingManager::DiscoveredPrefixTable::RemoveRoutersWithNoEntriesOrFlags(void)
{
LinkedList<Router> routersToFree;
- mRouters.RemoveAllMatching(Router::kContainsNoEntries, routersToFree);
+ mRouters.RemoveAllMatching(Router::kContainsNoEntriesOrFlags, routersToFree);
FreeRouters(routersToFree);
}
@@ -1660,7 +1675,7 @@ void RoutingManager::DiscoveredPrefixTable::RemoveExpiredEntries(void)
router.mEntries.RemoveAllMatching(Entry::ExpirationChecker(now), expiredEntries);
}
- RemoveRoutersWithNoEntries();
+ RemoveRoutersWithNoEntriesOrFlags();
if (!expiredEntries.IsEmpty())
{
@@ -1784,13 +1799,45 @@ exit:
return;
}
-void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
+void RoutingManager::DiscoveredPrefixTable::DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const
{
- Iterator &iterator = static_cast<Iterator &>(aIterator);
+ // Determine the `M` and `O` flags to include in the RA message
+ // header `aRaMessage` to be emitted.
+ //
+ // If any discovered router on infrastructure which is not itself a
+ // stub router (e.g., another Thread BR) includes the `M` or `O`
+ // flag, we also include the same flag.
+ //
+ // If a router has failed to respond to max number of NS probe
+ // attempts, we consider it as offline and ignore its flags.
+
+ for (const Router &router : mRouters)
+ {
+ if (router.mStubRouterFlag)
+ {
+ continue;
+ }
+
+ if (router.mNsProbeCount > Router::kMaxNsProbes)
+ {
+ continue;
+ }
- iterator.SetInitTime();
- iterator.SetRouter(mRouters.GetHead());
- iterator.SetEntry(mRouters.IsEmpty() ? nullptr : mRouters.GetHead()->mEntries.GetHead());
+ if (router.mManagedAddressConfigFlag)
+ {
+ aRaMessage.GetHeader().SetManagedAddressConfigFlag();
+ }
+
+ if (router.mOtherConfigFlag)
+ {
+ aRaMessage.GetHeader().SetOtherConfigFlag();
+ }
+ }
+}
+
+void RoutingManager::DiscoveredPrefixTable::InitIterator(PrefixTableIterator &aIterator) const
+{
+ static_cast<Iterator &>(aIterator).Init(mRouters);
}
Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &aIterator,
@@ -1802,7 +1849,7 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a
VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
OT_ASSERT(iterator.GetEntry() != nullptr);
- aEntry.mRouterAddress = iterator.GetRouter()->mAddress;
+ iterator.GetRouter()->CopyInfoTo(aEntry.mRouter);
aEntry.mPrefix = iterator.GetEntry()->GetPrefix();
aEntry.mIsOnLink = iterator.GetEntry()->IsOnLinkPrefix();
aEntry.mMsecSinceLastUpdate = iterator.GetInitTime() - iterator.GetEntry()->GetLastUpdateTime();
@@ -1811,21 +1858,60 @@ Error RoutingManager::DiscoveredPrefixTable::GetNextEntry(PrefixTableIterator &a
aEntry.mRoutePreference =
static_cast<otRoutePreference>(aEntry.mIsOnLink ? 0 : iterator.GetEntry()->GetRoutePreference());
- // Advance the iterator
- iterator.SetEntry(iterator.GetEntry()->GetNext());
+ iterator.Advance(Iterator::kToNextEntry);
+
+exit:
+ return error;
+}
+
+Error RoutingManager::DiscoveredPrefixTable::GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
+{
+ Error error = kErrorNone;
+ Iterator &iterator = static_cast<Iterator &>(aIterator);
- if (iterator.GetEntry() == nullptr)
+ VerifyOrExit(iterator.GetRouter() != nullptr, error = kErrorNotFound);
+
+ iterator.GetRouter()->CopyInfoTo(aEntry);
+ iterator.Advance(Iterator::kToNextRouter);
+
+exit:
+ return error;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+// DiscoveredPrefixTable::Iterator
+
+void RoutingManager::DiscoveredPrefixTable::Iterator::Init(const LinkedList<Router> &aRouters)
+{
+ SetInitTime();
+ SetRouter(aRouters.GetHead());
+ SetEntry(aRouters.IsEmpty() ? nullptr : aRouters.GetHead()->mEntries.GetHead());
+}
+
+void RoutingManager::DiscoveredPrefixTable::Iterator::Advance(AdvanceMode aMode)
+{
+ switch (aMode)
{
- iterator.SetRouter(iterator.GetRouter()->GetNext());
+ case kToNextEntry:
+ SetEntry(GetEntry()->GetNext());
- if (iterator.GetRouter() != nullptr)
+ if (GetEntry() != nullptr)
{
- iterator.SetEntry(iterator.GetRouter()->mEntries.GetHead());
+ break;
}
- }
-exit:
- return error;
+ OT_FALL_THROUGH;
+
+ case kToNextRouter:
+ SetRouter(GetRouter()->GetNext());
+
+ if (GetRouter() != nullptr)
+ {
+ SetEntry(GetRouter()->mEntries.GetHead());
+ }
+
+ break;
+ }
}
//---------------------------------------------------------------------------------------------------------------------
@@ -1950,6 +2036,38 @@ uint32_t RoutingManager::DiscoveredPrefixTable::Entry::CalculateExpireDelay(uint
}
//---------------------------------------------------------------------------------------------------------------------
+// DiscoveredPrefixTable::Router
+
+bool RoutingManager::DiscoveredPrefixTable::Router::Matches(EmptyChecker aChecker) const
+{
+ // Checks whether or not a `Router` instance has any useful info. An
+ // entry can be removed if it does not advertise M or O flags and
+ // also does not have any advertised prefix entries (RIO/PIO). If
+ // the router already failed to respond to max NS probe attempts,
+ // we consider it as offline and therefore do not consider its
+ // flags anymore.
+
+ OT_UNUSED_VARIABLE(aChecker);
+
+ bool hasFlags = false;
+
+ if (mNsProbeCount <= kMaxNsProbes)
+ {
+ hasFlags = (mManagedAddressConfigFlag || mOtherConfigFlag);
+ }
+
+ return !hasFlags && mEntries.IsEmpty();
+}
+
+void RoutingManager::DiscoveredPrefixTable::Router::CopyInfoTo(RouterEntry &aEntry) const
+{
+ aEntry.mAddress = mAddress;
+ aEntry.mManagedAddressConfigFlag = mManagedAddressConfigFlag;
+ aEntry.mOtherConfigFlag = mOtherConfigFlag;
+ aEntry.mStubRouterFlag = mStubRouterFlag;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
// FavoredOmrPrefix
bool RoutingManager::FavoredOmrPrefix::IsInfrastructureDerived(void) const
@@ -3209,11 +3327,7 @@ void RoutingManager::Nat64PrefixManager::HandleDiscoverDone(const Ip6::Prefix &a
mInfraIfPrefix = aPrefix;
LogInfo("Infraif NAT64 prefix: %s", mInfraIfPrefix.IsValidNat64() ? mInfraIfPrefix.ToString().AsCString() : "none");
-
- if (Get<RoutingManager>().mIsRunning)
- {
- Get<RoutingManager>().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
- }
+ Get<RoutingManager>().ScheduleRoutingPolicyEvaluation(kAfterRandomDelay);
}
Nat64::State RoutingManager::Nat64PrefixManager::GetState(void) const
@@ -3320,14 +3434,76 @@ exit:
}
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+const char *RoutingManager::PdPrefixManager::StateToString(Dhcp6PdState aState)
+{
+ static const char *const kStateStrings[] = {
+ "Disabled", // (0) kDisabled
+ "Stopped", // (1) kStopped
+ "Running", // (2) kRunning
+ };
+
+ static_assert(0 == kDhcp6PdStateDisabled, "kDhcp6PdStateDisabled value is incorrect");
+ static_assert(1 == kDhcp6PdStateStopped, "kDhcp6PdStateStopped value is incorrect");
+ static_assert(2 == kDhcp6PdStateRunning, "kDhcp6PdStateRunning value is incorrect");
+
+ return kStateStrings[aState];
+}
+
RoutingManager::PdPrefixManager::PdPrefixManager(Instance &aInstance)
: InstanceLocator(aInstance)
, mEnabled(false)
+ , mIsRunning(false)
, mTimer(aInstance)
{
mPrefix.Clear();
}
+void RoutingManager::PdPrefixManager::StartStop(bool aStart)
+{
+ Dhcp6PdState oldState = GetState();
+
+ VerifyOrExit(aStart != mIsRunning);
+ mIsRunning = aStart;
+ EvaluateStateChange(oldState);
+
+exit:
+ return;
+}
+
+RoutingManager::Dhcp6PdState RoutingManager::PdPrefixManager::GetState(void) const
+{
+ Dhcp6PdState state = kDhcp6PdStateDisabled;
+
+ if (mEnabled)
+ {
+ state = mIsRunning ? kDhcp6PdStateRunning : kDhcp6PdStateStopped;
+ }
+
+ return state;
+}
+
+void RoutingManager::PdPrefixManager::EvaluateStateChange(Dhcp6PdState aOldState)
+{
+ Dhcp6PdState newState = GetState();
+
+ VerifyOrExit(aOldState != newState);
+ LogInfo("PdPrefixManager: %s -> %s", StateToString(aOldState), StateToString(newState));
+
+ // TODO: We may also want to inform the platform that PD is stopped.
+ switch (newState)
+ {
+ case kDhcp6PdStateDisabled:
+ case kDhcp6PdStateStopped:
+ WithdrawPrefix();
+ break;
+ case kDhcp6PdStateRunning:
+ break;
+ }
+
+exit:
+ return;
+}
+
Error RoutingManager::PdPrefixManager::GetPrefixInfo(PrefixTableEntry &aInfo) const
{
Error error = kErrorNone;
@@ -3363,7 +3539,7 @@ void RoutingManager::PdPrefixManager::ProcessPlatformGeneratedRa(const uint8_t *
Error error = kErrorNone;
Ip6::Nd::RouterAdvertMessage::Icmp6Packet packet;
- VerifyOrExit(mEnabled, LogWarn("Ignore platform generated RA since PD is disabled."));
+ VerifyOrExit(IsRunning(), LogWarn("Ignore platform generated RA since PD is disabled or not running."));
packet.Init(aRouterAdvert, aLength);
error = Process(Ip6::Nd::RouterAdvertMessage(packet));
@@ -3454,15 +3630,11 @@ exit:
void RoutingManager::PdPrefixManager::SetEnabled(bool aEnabled)
{
- VerifyOrExit(mEnabled != aEnabled);
+ Dhcp6PdState oldState = GetState();
+ VerifyOrExit(mEnabled != aEnabled);
mEnabled = aEnabled;
- if (!aEnabled)
- {
- WithdrawPrefix();
- }
-
- LogInfo("PdPrefixManager is %s", aEnabled ? "enabled" : "disabled");
+ EvaluateStateChange(oldState);
exit:
return;
diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp
index c78862931..10062e8f6 100644
--- a/src/core/border_router/routing_manager.hpp
+++ b/src/core/border_router/routing_manager.hpp
@@ -54,6 +54,7 @@
#include "common/array.hpp"
#include "common/error.hpp"
#include "common/heap_allocatable.hpp"
+#include "common/heap_array.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
@@ -86,6 +87,7 @@ public:
typedef NetworkData::RoutePreference RoutePreference; ///< Route preference (high, medium, low).
typedef otBorderRoutingPrefixTableIterator PrefixTableIterator; ///< Prefix Table Iterator.
typedef otBorderRoutingPrefixTableEntry PrefixTableEntry; ///< Prefix Table Entry.
+ typedef otBorderRoutingRouterEntry RouterEntry; ///< Router Entry.
/**
* This constant specifies the maximum number of route prefixes that may be published by `RoutingManager`
@@ -119,9 +121,9 @@ public:
*/
enum Dhcp6PdState : uint8_t
{
- kDhcp6PdStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Disabled.
- kDhcp6PdStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Enabled, but currently stopped.
- kDhcp6PdStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Enabled, and running.
+ kDhcp6PdStateDisabled = OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, ///< Disabled.
+ kDhcp6PdStateStopped = OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED, ///< Enabled, but currently stopped.
+ kDhcp6PdStateRunning = OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING, ///< Enabled, and running.
};
/**
@@ -465,6 +467,21 @@ public:
return mDiscoveredPrefixTable.GetNextEntry(aIterator, aEntry);
}
+ /**
+ * Iterates over discovered router entries on infrastructure link.
+ *
+ * @param[in,out] aIterator An iterator.
+ * @param[out] aEntry A reference to the entry to populate.
+ *
+ * @retval kErrorNone Got the next router info, @p aEntry is updated and @p aIterator is advanced.
+ * @retval kErrorNotFound No more routers.
+ *
+ */
+ Error GetNextRouterEntry(PrefixTableIterator &aIterator, RouterEntry &aEntry) const
+ {
+ return mDiscoveredPrefixTable.GetNextRouter(aIterator, aEntry);
+ }
+
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
/**
* Determines whether to enable/disable SRP server when the auto-enable mode is changed on SRP server.
@@ -618,8 +635,11 @@ private:
TimeMilli CalculateNextStaleTime(TimeMilli aNow) const;
+ void DetermineAndSetFlags(Ip6::Nd::RouterAdvertMessage &aRaMessage) const;
+
void InitIterator(PrefixTableIterator &aIterator) const;
Error GetNextEntry(PrefixTableIterator &aIterator, PrefixTableEntry &aEntry) const;
+ Error GetNextRouter(PrefixTableIterator &aIterator, RouterEntry &aEntry) const;
void HandleEntryTimer(void);
void HandleRouterTimer(void);
@@ -752,11 +772,12 @@ private:
enum EmptyChecker : uint8_t
{
- kContainsNoEntries
+ kContainsNoEntriesOrFlags
};
bool Matches(const Ip6::Address &aAddress) const { return aAddress == mAddress; }
- bool Matches(EmptyChecker) const { return mEntries.IsEmpty(); }
+ bool Matches(EmptyChecker aChecker) const;
+ void CopyInfoTo(RouterEntry &aEntry) const;
Router *mNext;
Ip6::Address mAddress;
@@ -771,12 +792,23 @@ private:
class Iterator : public PrefixTableIterator
{
public:
+ enum AdvanceMode : uint8_t
+ {
+ kToNextEntry,
+ kToNextRouter,
+ };
+
+ void Init(const LinkedList<Router> &aRouters);
+ void Advance(AdvanceMode aMode);
+
const Router *GetRouter(void) const { return static_cast<const Router *>(mPtr1); }
- void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
const Entry *GetEntry(void) const { return static_cast<const Entry *>(mPtr2); }
- void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
TimeMilli GetInitTime(void) const { return TimeMilli(mData32); }
- void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
+
+ private:
+ void SetRouter(const Router *aRouter) { mPtr1 = aRouter; }
+ void SetEntry(const Entry *aEntry) { mPtr2 = aEntry; }
+ void SetInitTime(void) { mData32 = TimerMilli::GetNow().GetValue(); }
};
void ProcessRaHeader(const Ip6::Nd::RouterAdvertMessage::Header &aRaHeader, Router &aRouter);
@@ -786,7 +818,7 @@ private:
bool Contains(const Entry::Checker &aChecker) const;
void RemovePrefix(const Entry::Matcher &aMatcher);
void RemoveOrDeprecateEntriesFromInactiveRouters(void);
- void RemoveRoutersWithNoEntries(void);
+ void RemoveRoutersWithNoEntriesOrFlags(void);
void FreeRouters(LinkedList<Router> &aRouters);
void FreeEntries(LinkedList<Entry> &aEntries);
void UpdateNetworkDataOnChangeTo(Entry &aEntry);
@@ -954,7 +986,12 @@ private:
typedef Ip6::Prefix OnMeshPrefix;
- class OnMeshPrefixArray : public Array<OnMeshPrefix, kMaxOnMeshPrefixes>
+ class OnMeshPrefixArray :
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE
+ public Heap::Array<OnMeshPrefix>
+#else
+ public Array<OnMeshPrefix, kMaxOnMeshPrefixes>
+#endif
{
public:
void Add(const OnMeshPrefix &aPrefix);
@@ -1132,20 +1169,19 @@ private:
explicit PdPrefixManager(Instance &aInstance);
void SetEnabled(bool aEnabled);
+ void Start(void) { StartStop(/* aStart= */ true); }
+ void Stop(void) { StartStop(/* aStart= */ false); }
bool IsRunning(void) const { return GetState() == Dhcp6PdState::kDhcp6PdStateRunning; }
bool HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); }
const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); }
- Dhcp6PdState GetState(void) const
- {
- // TODO: We need to stop and inform the platform when there is already a GUA prefix advertised in the
- // network.
- return mEnabled ? kDhcp6PdStateRunning : kDhcp6PdStateDisabled;
- }
+ Dhcp6PdState GetState(void) const;
void ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength);
Error GetPrefixInfo(PrefixTableEntry &aInfo) const;
void HandleTimer(void) { WithdrawPrefix(); }
+ static const char *StateToString(Dhcp6PdState aState);
+
static bool IsValidPdPrefix(const Ip6::Prefix &aPrefix)
{
// We should accept ULA prefix since it could be used by the internet infrastructure like NAT64.
@@ -1155,11 +1191,14 @@ private:
private:
Error Process(const Ip6::Nd::RouterAdvertMessage &aMessage);
+ void EvaluateStateChange(Dhcp6PdState aOldState);
void WithdrawPrefix(void);
+ void StartStop(bool aStart);
using PlatformOmrPrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>;
bool mEnabled;
+ bool mIsRunning;
PlatformOmrPrefixTimer mTimer;
DiscoveredPrefixTable::Entry mPrefix;
};
diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp
index 38e561858..696d0fc83 100644
--- a/src/core/coap/coap.cpp
+++ b/src/core/coap/coap.cpp
@@ -32,10 +32,10 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#include "net/udp6.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/coap/coap_message.cpp b/src/core/coap/coap_message.cpp
index 72fb6148e..cbf544813 100644
--- a/src/core/coap/coap_message.cpp
+++ b/src/core/coap/coap_message.cpp
@@ -38,9 +38,9 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Coap {
@@ -139,7 +139,7 @@ uint8_t Message::WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer)
else
{
rval = kOption2ByteExtension;
- Encoding::BigEndian::WriteUint16(aValue - kOption2ByteExtensionOffset, aBuffer);
+ BigEndian::WriteUint16(aValue - kOption2ByteExtensionOffset, aBuffer);
aBuffer += sizeof(uint16_t);
}
@@ -183,7 +183,7 @@ Error Message::AppendUintOption(uint16_t aNumber, uint32_t aValue)
const uint8_t *value = &buffer[0];
uint16_t length = sizeof(uint32_t);
- Encoding::BigEndian::WriteUint32(aValue, buffer);
+ BigEndian::WriteUint32(aValue, buffer);
while ((length > 0) && (value[0] == 0))
{
@@ -551,7 +551,7 @@ Error Option::Iterator::ReadOptionValue(uint64_t &aUintValue) const
for (uint16_t pos = 0; pos < mOption.mLength; pos++)
{
- aUintValue <<= CHAR_BIT;
+ aUintValue <<= kBitsPerByte;
aUintValue |= buffer[pos];
}
@@ -592,7 +592,7 @@ Error Option::Iterator::ReadExtendedOptionField(uint16_t &aValue)
uint16_t value16;
SuccessOrExit(error = Read(sizeof(uint16_t), &value16));
- value16 = Encoding::BigEndian::HostSwap16(value16);
+ value16 = BigEndian::HostSwap16(value16);
aValue = value16 + Message::kOption2ByteExtensionOffset;
}
else
diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp
index f7910663b..789c91939 100644
--- a/src/core/coap/coap_message.hpp
+++ b/src/core/coap/coap_message.hpp
@@ -59,8 +59,6 @@ namespace ot {
*/
namespace Coap {
-using ot::Encoding::BigEndian::HostSwap16;
-
/**
* @addtogroup core-coap
*
@@ -315,7 +313,7 @@ public:
* @returns The Message ID value.
*
*/
- uint16_t GetMessageId(void) const { return HostSwap16(GetHelpData().mHeader.mMessageId); }
+ uint16_t GetMessageId(void) const { return BigEndian::HostSwap16(GetHelpData().mHeader.mMessageId); }
/**
* Sets the Message ID value.
@@ -323,7 +321,7 @@ public:
* @param[in] aMessageId The Message ID value.
*
*/
- void SetMessageId(uint16_t aMessageId) { GetHelpData().mHeader.mMessageId = HostSwap16(aMessageId); }
+ void SetMessageId(uint16_t aMessageId) { GetHelpData().mHeader.mMessageId = BigEndian::HostSwap16(aMessageId); }
/**
* Returns the Token length.
diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp
index 3f5730afb..7d0fbe1b3 100644
--- a/src/core/coap/coap_secure.cpp
+++ b/src/core/coap/coap_secure.cpp
@@ -30,10 +30,10 @@
#if OPENTHREAD_CONFIG_DTLS_ENABLE
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/new.hpp"
+#include "instance/instance.hpp"
#include "meshcop/dtls.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/common/bit_vector.hpp b/src/core/common/bit_vector.hpp
index 8c6962c13..9b24043d0 100644
--- a/src/core/common/bit_vector.hpp
+++ b/src/core/common/bit_vector.hpp
@@ -40,6 +40,7 @@
#include "common/debug.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
+#include "common/numeric_limits.hpp"
namespace ot {
@@ -122,7 +123,7 @@ public:
}
private:
- uint8_t mMask[BitVectorBytes(N)];
+ uint8_t mMask[BytesForBitSize(N)];
};
/**
diff --git a/src/core/common/encoding.hpp b/src/core/common/encoding.hpp
index 3427a7c89..d56c5aafd 100644
--- a/src/core/common/encoding.hpp
+++ b/src/core/common/encoding.hpp
@@ -45,11 +45,9 @@
#endif
#endif
-#include <limits.h>
#include <stdint.h>
namespace ot {
-namespace Encoding {
inline uint16_t Swap16(uint16_t v) { return (((v & 0x00ffU) << 8) & 0xff00) | (((v & 0xff00U) >> 8) & 0x00ff); }
@@ -82,8 +80,6 @@ inline uint32_t Reverse32(uint32_t v)
return v;
}
-#define BitVectorBytes(x) static_cast<uint8_t>(((x) + (CHAR_BIT - 1)) / CHAR_BIT)
-
namespace BigEndian {
#if BYTE_ORDER_BIG_ENDIAN
@@ -172,6 +168,23 @@ inline uint64_t ReadUint64(const uint8_t *aBuffer)
}
/**
+ * Reads a `UintType` integer value from a given buffer assuming big-endian encoding.
+ *
+ * @tparam UintType The unsigned int type.
+ *
+ * @param[in] aBuffer Pointer to the buffer to read from.
+ *
+ * @returns The `UintType` value read from the buffer.
+ *
+ */
+template <typename UintType> UintType Read(const uint8_t *aBuffer);
+
+template <> inline uint8_t Read(const uint8_t *aBuffer) { return *aBuffer; }
+template <> inline uint16_t Read(const uint8_t *aBuffer) { return ReadUint16(aBuffer); }
+template <> inline uint32_t Read(const uint8_t *aBuffer) { return ReadUint32(aBuffer); }
+template <> inline uint64_t Read(const uint8_t *aBuffer) { return ReadUint64(aBuffer); }
+
+/**
* Writes a `uint16_t` value to a given buffer using big-endian encoding.
*
* @param[in] aValue The value to write to buffer.
@@ -232,6 +245,22 @@ inline void WriteUint64(uint64_t aValue, uint8_t *aBuffer)
aBuffer[7] = (aValue >> 0) & 0xff;
}
+/**
+ * Writes a `UintType` integer value to a given buffer assuming big-endian encoding.
+ *
+ * @tparam UintType The unsigned int type.
+ *
+ * @param[in] aValue The value to write to buffer.
+ * @param[in] aBuffer Pointer to the buffer to write to.
+ *
+ */
+template <typename UintType> void Write(UintType aValue, uint8_t *aBuffer);
+
+template <> inline void Write(uint8_t aValue, uint8_t *aBuffer) { *aBuffer = aValue; }
+template <> inline void Write(uint16_t aValue, uint8_t *aBuffer) { WriteUint16(aValue, aBuffer); }
+template <> inline void Write(uint32_t aValue, uint8_t *aBuffer) { WriteUint32(aValue, aBuffer); }
+template <> inline void Write(uint64_t aValue, uint8_t *aBuffer) { WriteUint64(aValue, aBuffer); }
+
} // namespace BigEndian
namespace LittleEndian {
@@ -322,6 +351,23 @@ inline uint64_t ReadUint64(const uint8_t *aBuffer)
}
/**
+ * Reads a `UintType` integer value from a given buffer assuming little-endian encoding.
+ *
+ * @tparam UintType The unsigned int type.
+ *
+ * @param[in] aBuffer Pointer to the buffer to read from.
+ *
+ * @returns The `UintType` value read from the buffer.
+ *
+ */
+template <typename UintType> UintType Read(const uint8_t *aBuffer);
+
+template <> inline uint8_t Read(const uint8_t *aBuffer) { return *aBuffer; }
+template <> inline uint16_t Read(const uint8_t *aBuffer) { return ReadUint16(aBuffer); }
+template <> inline uint32_t Read(const uint8_t *aBuffer) { return ReadUint32(aBuffer); }
+template <> inline uint64_t Read(const uint8_t *aBuffer) { return ReadUint64(aBuffer); }
+
+/**
* Writes a `uint16_t` value to a given buffer using little-endian encoding.
*
* @param[in] aValue The value to write to buffer.
@@ -382,8 +428,24 @@ inline void WriteUint64(uint64_t aValue, uint8_t *aBuffer)
aBuffer[7] = (aValue >> 56) & 0xff;
}
+/**
+ * Writes a `UintType` integer value to a given buffer assuming little-endian encoding.
+ *
+ * @tparam UintType The unsigned int type.
+ *
+ * @param[in] aValue The value to write to buffer.
+ * @param[in] aBuffer Pointer to the buffer to write to.
+ *
+ */
+template <typename UintType> void Write(UintType aValue, uint8_t *aBuffer);
+
+template <> inline void Write(uint8_t aValue, uint8_t *aBuffer) { *aBuffer = aValue; }
+template <> inline void Write(uint16_t aValue, uint8_t *aBuffer) { WriteUint16(aValue, aBuffer); }
+template <> inline void Write(uint32_t aValue, uint8_t *aBuffer) { WriteUint32(aValue, aBuffer); }
+template <> inline void Write(uint64_t aValue, uint8_t *aBuffer) { WriteUint64(aValue, aBuffer); }
+
} // namespace LittleEndian
-} // namespace Encoding
+
} // namespace ot
#endif // ENCODING_HPP_
diff --git a/src/core/common/frame_builder.cpp b/src/core/common/frame_builder.cpp
index 88247ca67..abc647819 100644
--- a/src/core/common/frame_builder.cpp
+++ b/src/core/common/frame_builder.cpp
@@ -54,24 +54,18 @@ void FrameBuilder::Init(void *aBuffer, uint16_t aLength)
Error FrameBuilder::AppendUint8(uint8_t aUint8) { return Append<uint8_t>(aUint8); }
-Error FrameBuilder::AppendBigEndianUint16(uint16_t aUint16)
-{
- return Append<uint16_t>(Encoding::BigEndian::HostSwap16(aUint16));
-}
+Error FrameBuilder::AppendBigEndianUint16(uint16_t aUint16) { return Append<uint16_t>(BigEndian::HostSwap16(aUint16)); }
-Error FrameBuilder::AppendBigEndianUint32(uint32_t aUint32)
-{
- return Append<uint32_t>(Encoding::BigEndian::HostSwap32(aUint32));
-}
+Error FrameBuilder::AppendBigEndianUint32(uint32_t aUint32) { return Append<uint32_t>(BigEndian::HostSwap32(aUint32)); }
Error FrameBuilder::AppendLittleEndianUint16(uint16_t aUint16)
{
- return Append<uint16_t>(Encoding::LittleEndian::HostSwap16(aUint16));
+ return Append<uint16_t>(LittleEndian::HostSwap16(aUint16));
}
Error FrameBuilder::AppendLittleEndianUint32(uint32_t aUint32)
{
- return Append<uint32_t>(Encoding::LittleEndian::HostSwap32(aUint32));
+ return Append<uint32_t>(LittleEndian::HostSwap32(aUint32));
}
Error FrameBuilder::AppendBytes(const void *aBuffer, uint16_t aLength)
diff --git a/src/core/common/frame_data.cpp b/src/core/common/frame_data.cpp
index 04d2aa94c..a9c390003 100644
--- a/src/core/common/frame_data.cpp
+++ b/src/core/common/frame_data.cpp
@@ -45,7 +45,7 @@ Error FrameData::ReadBigEndianUint16(uint16_t &aUint16)
Error error;
SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
- aUint16 = Encoding::BigEndian::HostSwap16(aUint16);
+ aUint16 = BigEndian::HostSwap16(aUint16);
exit:
return error;
@@ -56,7 +56,7 @@ Error FrameData::ReadBigEndianUint32(uint32_t &aUint32)
Error error;
SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
- aUint32 = Encoding::BigEndian::HostSwap32(aUint32);
+ aUint32 = BigEndian::HostSwap32(aUint32);
exit:
return error;
@@ -67,7 +67,7 @@ Error FrameData::ReadLittleEndianUint16(uint16_t &aUint16)
Error error;
SuccessOrExit(error = ReadBytes(&aUint16, sizeof(uint16_t)));
- aUint16 = Encoding::LittleEndian::HostSwap16(aUint16);
+ aUint16 = LittleEndian::HostSwap16(aUint16);
exit:
return error;
@@ -78,7 +78,7 @@ Error FrameData::ReadLittleEndianUint32(uint32_t &aUint32)
Error error;
SuccessOrExit(error = ReadBytes(&aUint32, sizeof(uint32_t)));
- aUint32 = Encoding::LittleEndian::HostSwap32(aUint32);
+ aUint32 = LittleEndian::HostSwap32(aUint32);
exit:
return error;
diff --git a/src/core/common/heap.cpp b/src/core/common/heap.cpp
index 7b431ee30..cc403467b 100644
--- a/src/core/common/heap.cpp
+++ b/src/core/common/heap.cpp
@@ -33,7 +33,7 @@
#include "heap.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Heap {
diff --git a/src/core/common/locator_getters.hpp b/src/core/common/locator_getters.hpp
index 990b8c6d6..ad9067f54 100644
--- a/src/core/common/locator_getters.hpp
+++ b/src/core/common/locator_getters.hpp
@@ -37,9 +37,9 @@
#include "openthread-core-config.h"
-#include "common/instance.hpp"
#include "common/locator.hpp"
#include "common/tasklet.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/common/log.cpp b/src/core/common/log.cpp
index 04c74bbb2..1809cd54b 100644
--- a/src/core/common/log.cpp
+++ b/src/core/common/log.cpp
@@ -38,9 +38,10 @@
#include <openthread/platform/logging.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/num_utils.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
/*
* Verify debug UART dependency.
@@ -169,99 +170,120 @@ template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName,
const void *aData,
uint16_t aDataLength);
-void Logger::DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *aData, const uint16_t aDataLength)
+void Logger::DumpInModule(const char *aModuleName,
+ LogLevel aLogLevel,
+ const char *aText,
+ const void *aData,
+ uint16_t aDataLength)
{
- ot::String<kStringLineLength> string;
+ HexDumpInfo info;
+
+ VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
- string.Append("|");
+ info.mDataBytes = reinterpret_cast<const uint8_t *>(aData);
+ info.mDataLength = aDataLength;
+ info.mTitle = aText;
+ info.mIterator = 0;
- for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
+ while (GenerateNextHexDumpLine(info) == kErrorNone)
{
- if (i < aDataLength)
- {
- string.Append(" %02X", aData[i]);
- }
- else
- {
- string.Append(" ..");
- }
+ LogInModule(aModuleName, aLogLevel, "%s", info.mLine);
+ }
- if (!((i + 1) % 8))
- {
- string.Append(" |");
- }
+exit:
+ return;
+}
+
+#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
+
+#endif // OT_SHOULD_LOG
+
+Error GenerateNextHexDumpLine(HexDumpInfo &aInfo)
+{
+ constexpr uint16_t kIterTableStartLine = 0;
+ constexpr uint16_t kIterFirstDataLine = NumericLimits<uint16_t>::kMax - 2;
+ constexpr uint16_t kIterTableEndLine = NumericLimits<uint16_t>::kMax - 1;
+ constexpr uint16_t kIterFinished = NumericLimits<uint16_t>::kMax;
+ constexpr uint16_t kWidth = 72;
+ constexpr uint16_t kTitleSuffixLen = sizeof("[ len=000]") - 1;
+ constexpr uint16_t kDumpBytesPerLine = 16;
+
+ Error error = kErrorNone;
+ StringWriter writer(aInfo.mLine, sizeof(aInfo.mLine));
+
+ switch (aInfo.mIterator)
+ {
+ case kIterTableStartLine:
+ {
+ uint16_t txtLen = StringLength(aInfo.mTitle, kWidth - kTitleSuffixLen) + kTitleSuffixLen;
+
+ writer.AppendCharMultipleTimes('=', static_cast<uint16_t>((kWidth - txtLen) / 2));
+ writer.Append("[%s len=%03u]", aInfo.mTitle, aInfo.mDataLength);
+ writer.AppendCharMultipleTimes('=', static_cast<uint16_t>(kWidth - txtLen - (kWidth - txtLen) / 2));
+ aInfo.mIterator = kIterFirstDataLine;
+ break;
}
- string.Append(" ");
+ case kIterTableEndLine:
+ writer.AppendCharMultipleTimes('-', kWidth);
+ aInfo.mIterator = kIterFinished;
+ break;
+
+ case kIterFinished:
+ error = kErrorNotFound;
+ break;
- for (uint8_t i = 0; i < kDumpBytesPerLine; i++)
+ case kIterFirstDataLine:
+ aInfo.mIterator = 0;
+ OT_FALL_THROUGH;
+
+ default:
{
- char c = '.';
+ uint16_t startIndex = aInfo.mIterator;
+ uint16_t endIndex = aInfo.mIterator + kDumpBytesPerLine;
+
+ writer.Append("|");
- if (i < aDataLength)
+ for (uint16_t i = startIndex; i < endIndex; i++)
{
- char byteAsChar = static_cast<char>(0x7f & aData[i]);
+ (i < aInfo.mDataLength) ? writer.Append(" %02X", aInfo.mDataBytes[i]) : writer.Append(" ");
- if (isprint(byteAsChar))
+ if ((i % 8) == 7)
{
- c = byteAsChar;
+ writer.Append(" |");
}
}
- string.Append("%c", c);
- }
+ writer.Append(" ");
- LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
-}
+ for (uint16_t i = startIndex; i < endIndex; i++)
+ {
+ char c = ' ';
-void Logger::DumpInModule(const char *aModuleName,
- LogLevel aLogLevel,
- const char *aText,
- const void *aData,
- uint16_t aDataLength)
-{
- constexpr uint16_t kWidth = 72;
- constexpr uint16_t kTextSuffixLen = sizeof("[ len=000]") - 1;
+ if (i < aInfo.mDataLength)
+ {
+ uint8_t byte = aInfo.mDataBytes[i];
- uint16_t txtLen = StringLength(aText, kWidth - kTextSuffixLen) + kTextSuffixLen;
- ot::String<kStringLineLength> string;
+ c = ((byte < 127) && isprint(static_cast<char>(byte))) ? static_cast<char>(byte) : '.';
+ }
- VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
+ writer.Append("%c", c);
+ }
- for (uint16_t i = 0; i < static_cast<uint16_t>((kWidth - txtLen) / 2); i++)
- {
- string.Append("=");
- }
+ writer.Append(" |");
- string.Append("[%s len=%03u]", aText, aDataLength);
+ aInfo.mIterator = endIndex;
- for (uint16_t i = 0; i < static_cast<uint16_t>(kWidth - txtLen - (kWidth - txtLen) / 2); i++)
- {
- string.Append("=");
- }
-
- LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
+ if (aInfo.mIterator >= aInfo.mDataLength)
+ {
+ aInfo.mIterator = kIterTableEndLine;
+ }
- for (uint16_t i = 0; i < aDataLength; i += kDumpBytesPerLine)
- {
- DumpLine(aModuleName, aLogLevel, static_cast<const uint8_t *>(aData) + i,
- Min(static_cast<uint8_t>(aDataLength - i), kDumpBytesPerLine));
+ break;
}
-
- string.Clear();
-
- for (uint16_t i = 0; i < kWidth; i++)
- {
- string.Append("-");
}
- LogInModule(aModuleName, aLogLevel, "%s", string.AsCString());
-
-exit:
- return;
+ return error;
}
-#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
-
-#endif // OT_SHOULD_LOG
} // namespace ot
diff --git a/src/core/common/log.hpp b/src/core/common/log.hpp
index 6d46030db..47293e0b3 100644
--- a/src/core/common/log.hpp
+++ b/src/core/common/log.hpp
@@ -40,6 +40,8 @@
#include <openthread/platform/logging.h>
#include <openthread/platform/toolchain.h>
+#include "common/error.hpp"
+
namespace ot {
/**
@@ -332,8 +334,6 @@ public:
template <LogLevel kLogLevel>
static void DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength);
-
- static void DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *aData, uint16_t aDataLength);
#endif
};
@@ -372,6 +372,32 @@ extern template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName,
#endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
#endif // OT_SHOULD_LOG
+typedef otLogHexDumpInfo HexDumpInfo; ///< Represents the hex dump info.
+
+/**
+ * Generates the next hex dump line.
+ *
+ * Can call this method back-to-back to generate the hex dump output line by line. On the first call the `mIterator`
+ * field in @p aInfo MUST be set to zero.
+ *
+ * Here is an example of the generated hex dump output:
+ *
+ * "==========================[{mTitle} len=070]============================"
+ * "| 41 D8 87 34 12 FF FF 25 | 4C 57 DA F2 FB 2F 62 7F | A..4...%LW.../b. |"
+ * "| 3B 01 F0 4D 4C 4D 4C 54 | 4F 00 15 15 00 00 00 00 | ;..MLMLTO....... |"
+ * "| 00 00 00 01 80 DB 60 82 | 7E 33 72 3B CC B3 A1 84 | ......`.~3r;.... |"
+ * "| 3B E6 AD B2 0B 45 E7 45 | C5 B9 00 1A CB 2D 6D 1C | ;....E.E.....-m. |"
+ * "| 10 3E 3C F5 D3 70 | | .><..p |"
+ * "------------------------------------------------------------------------"
+ *
+ * @param[in,out] aInfo A reference to a `LogHexDumpInfo` to use to generate hex dump.
+ *
+ * @retval kErrorNone Successfully generated the next line, `mLine` field in @p aInfo is updated.
+ * @retval kErrorNotFound Reached the end and no more line to generate.
+ *
+ */
+Error GenerateNextHexDumpLine(HexDumpInfo &aInfo);
+
} // namespace ot
#endif // LOG_HPP_
diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp
index bdb513ab8..1c7028d0f 100644
--- a/src/core/common/message.cpp
+++ b/src/core/common/message.cpp
@@ -37,11 +37,11 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/heap.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/ip6.hpp"
diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp
index 5edb3344e..66153e240 100644
--- a/src/core/common/message.hpp
+++ b/src/core/common/message.hpp
@@ -1185,6 +1185,33 @@ public:
void SetOrigin(Origin aOrigin) { GetMetadata().mOrigin = aOrigin; }
/**
+ * Indicates whether or not the message origin is Thread Netif.
+ *
+ * @retval TRUE If the message origin is Thread Netif.
+ * @retval FALSE If the message origin is not Thread Netif.
+ *
+ */
+ bool IsOriginThreadNetif(void) const { return GetOrigin() == kOriginThreadNetif; }
+
+ /**
+ * Indicates whether or not the message origin is a trusted source on host.
+ *
+ * @retval TRUE If the message origin is a trusted source on host.
+ * @retval FALSE If the message origin is not a trusted source on host.
+ *
+ */
+ bool IsOriginHostTrusted(void) const { return GetOrigin() == kOriginHostTrusted; }
+
+ /**
+ * Indicates whether or not the message origin is an untrusted source on host.
+ *
+ * @retval TRUE If the message origin is an untrusted source on host.
+ * @retval FALSE If the message origin is not an untrusted source on host.
+ *
+ */
+ bool IsOriginHostUntrusted(void) const { return GetOrigin() == kOriginHostUntrusted; }
+
+ /**
* Indicates whether or not link security is enabled for the message.
*
* @retval TRUE If link security is enabled.
diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp
index f25e71eb5..f1f9863a6 100644
--- a/src/core/common/notifier.cpp
+++ b/src/core/common/notifier.cpp
@@ -210,7 +210,7 @@ void Notifier::LogEvents(Events aEvents) const
bool didLog = false;
String<kFlagsStringBufferSize> string;
- for (uint8_t bit = 0; bit < sizeof(Events::Flags) * CHAR_BIT; bit++)
+ for (uint8_t bit = 0; bit < BitSizeOf(Events::Flags); bit++)
{
VerifyOrExit(flags != 0);
diff --git a/src/core/common/numeric_limits.hpp b/src/core/common/numeric_limits.hpp
index 35e984394..911df2380 100644
--- a/src/core/common/numeric_limits.hpp
+++ b/src/core/common/numeric_limits.hpp
@@ -38,6 +38,28 @@
namespace ot {
+static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte.
+
+/**
+ * Returns the bit-size (number of bits) of a given type or variable.
+ *
+ * @param[in] aItem The item (type or variable or expression) to get the bit-size of.
+ *
+ * @returns Number of bits of @p aItem.
+ *
+ */
+#define BitSizeOf(aItem) (sizeof(aItem) * kBitsPerByte)
+
+/**
+ * Determines number of byes to represent a given number of bits.
+ *
+ * @param[in] aBitSize The bit-size (number of bits).
+ *
+ * @returns Number of bytes to represent @p aBitSize.
+ *
+ */
+#define BytesForBitSize(aBitSize) static_cast<uint8_t>(((aBitSize) + (kBitsPerByte - 1)) / kBitsPerByte)
+
/**
* Provides a way to query properties of arithmetic types.
*
diff --git a/src/core/common/settings.cpp b/src/core/common/settings.cpp
index c9b6f3ad7..504eb7c56 100644
--- a/src/core/common/settings.cpp
+++ b/src/core/common/settings.cpp
@@ -35,9 +35,9 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
#include "meshcop/dataset.hpp"
#include "thread/mle.hpp"
diff --git a/src/core/common/settings.hpp b/src/core/common/settings.hpp
index f7f538136..199eb9fe0 100644
--- a/src/core/common/settings.hpp
+++ b/src/core/common/settings.hpp
@@ -190,7 +190,7 @@ public:
* @returns The RLOC16.
*
*/
- uint16_t GetRloc16(void) const { return Encoding::LittleEndian::HostSwap16(mRloc16); }
+ uint16_t GetRloc16(void) const { return LittleEndian::HostSwap16(mRloc16); }
/**
* Sets the RLOC16.
@@ -198,7 +198,7 @@ public:
* @param[in] aRloc16 The RLOC16.
*
*/
- void SetRloc16(uint16_t aRloc16) { mRloc16 = Encoding::LittleEndian::HostSwap16(aRloc16); }
+ void SetRloc16(uint16_t aRloc16) { mRloc16 = LittleEndian::HostSwap16(aRloc16); }
/**
* Returns the key sequence.
@@ -206,7 +206,7 @@ public:
* @returns The key sequence.
*
*/
- uint32_t GetKeySequence(void) const { return Encoding::LittleEndian::HostSwap32(mKeySequence); }
+ uint32_t GetKeySequence(void) const { return LittleEndian::HostSwap32(mKeySequence); }
/**
* Sets the key sequence.
@@ -214,7 +214,7 @@ public:
* @param[in] aKeySequence The key sequence.
*
*/
- void SetKeySequence(uint32_t aKeySequence) { mKeySequence = Encoding::LittleEndian::HostSwap32(aKeySequence); }
+ void SetKeySequence(uint32_t aKeySequence) { mKeySequence = LittleEndian::HostSwap32(aKeySequence); }
/**
* Returns the MLE frame counter.
@@ -222,7 +222,7 @@ public:
* @returns The MLE frame counter.
*
*/
- uint32_t GetMleFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mMleFrameCounter); }
+ uint32_t GetMleFrameCounter(void) const { return LittleEndian::HostSwap32(mMleFrameCounter); }
/**
* Sets the MLE frame counter.
@@ -232,7 +232,7 @@ public:
*/
void SetMleFrameCounter(uint32_t aMleFrameCounter)
{
- mMleFrameCounter = Encoding::LittleEndian::HostSwap32(aMleFrameCounter);
+ mMleFrameCounter = LittleEndian::HostSwap32(aMleFrameCounter);
}
/**
@@ -241,7 +241,7 @@ public:
* @returns The MAC frame counter.
*
*/
- uint32_t GetMacFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mMacFrameCounter); }
+ uint32_t GetMacFrameCounter(void) const { return LittleEndian::HostSwap32(mMacFrameCounter); }
/**
* Sets the MAC frame counter.
@@ -251,7 +251,7 @@ public:
*/
void SetMacFrameCounter(uint32_t aMacFrameCounter)
{
- mMacFrameCounter = Encoding::LittleEndian::HostSwap32(aMacFrameCounter);
+ mMacFrameCounter = LittleEndian::HostSwap32(aMacFrameCounter);
}
/**
@@ -260,7 +260,7 @@ public:
* @returns The previous partition ID.
*
*/
- uint32_t GetPreviousPartitionId(void) const { return Encoding::LittleEndian::HostSwap32(mPreviousPartitionId); }
+ uint32_t GetPreviousPartitionId(void) const { return LittleEndian::HostSwap32(mPreviousPartitionId); }
/**
* Sets the previous partition id.
@@ -270,7 +270,7 @@ public:
*/
void SetPreviousPartitionId(uint32_t aPreviousPartitionId)
{
- mPreviousPartitionId = Encoding::LittleEndian::HostSwap32(aPreviousPartitionId);
+ mPreviousPartitionId = LittleEndian::HostSwap32(aPreviousPartitionId);
}
/**
@@ -311,7 +311,7 @@ public:
* @returns The Thread version.
*
*/
- uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
+ uint16_t GetVersion(void) const { return LittleEndian::HostSwap16(mVersion); }
/**
* Sets the Thread version.
@@ -319,7 +319,7 @@ public:
* @param[in] aVersion The Thread version.
*
*/
- void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
+ void SetVersion(uint16_t aVersion) { mVersion = LittleEndian::HostSwap16(aVersion); }
private:
void Log(Action aAction) const;
@@ -381,7 +381,7 @@ public:
* @returns The Thread version.
*
*/
- uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
+ uint16_t GetVersion(void) const { return LittleEndian::HostSwap16(mVersion); }
/**
* Sets the Thread version.
@@ -389,7 +389,7 @@ public:
* @param[in] aVersion The Thread version.
*
*/
- void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
+ void SetVersion(uint16_t aVersion) { mVersion = LittleEndian::HostSwap16(aVersion); }
private:
void Log(Action aAction) const;
@@ -443,7 +443,7 @@ public:
* @returns The child timeout.
*
*/
- uint32_t GetTimeout(void) const { return Encoding::LittleEndian::HostSwap32(mTimeout); }
+ uint32_t GetTimeout(void) const { return LittleEndian::HostSwap32(mTimeout); }
/**
* Sets the child timeout.
@@ -451,7 +451,7 @@ public:
* @param[in] aTimeout The child timeout.
*
*/
- void SetTimeout(uint32_t aTimeout) { mTimeout = Encoding::LittleEndian::HostSwap32(aTimeout); }
+ void SetTimeout(uint32_t aTimeout) { mTimeout = LittleEndian::HostSwap32(aTimeout); }
/**
* Returns the RLOC16.
@@ -459,7 +459,7 @@ public:
* @returns The RLOC16.
*
*/
- uint16_t GetRloc16(void) const { return Encoding::LittleEndian::HostSwap16(mRloc16); }
+ uint16_t GetRloc16(void) const { return LittleEndian::HostSwap16(mRloc16); }
/**
* Sets the RLOC16.
@@ -467,7 +467,7 @@ public:
* @param[in] aRloc16 The RLOC16.
*
*/
- void SetRloc16(uint16_t aRloc16) { mRloc16 = Encoding::LittleEndian::HostSwap16(aRloc16); }
+ void SetRloc16(uint16_t aRloc16) { mRloc16 = LittleEndian::HostSwap16(aRloc16); }
/**
* Returns the Thread device mode.
@@ -491,7 +491,7 @@ public:
* @returns The Thread version.
*
*/
- uint16_t GetVersion(void) const { return Encoding::LittleEndian::HostSwap16(mVersion); }
+ uint16_t GetVersion(void) const { return LittleEndian::HostSwap16(mVersion); }
/**
* Sets the Thread version.
@@ -499,7 +499,7 @@ public:
* @param[in] aVersion The Thread version.
*
*/
- void SetVersion(uint16_t aVersion) { mVersion = Encoding::LittleEndian::HostSwap16(aVersion); }
+ void SetVersion(uint16_t aVersion) { mVersion = LittleEndian::HostSwap16(aVersion); }
private:
void Log(Action aAction) const;
@@ -705,7 +705,7 @@ public:
* @returns The server port number.
*
*/
- uint16_t GetServerPort(void) const { return Encoding::LittleEndian::HostSwap16(mServerPort); }
+ uint16_t GetServerPort(void) const { return LittleEndian::HostSwap16(mServerPort); }
/**
* Sets the server port number.
@@ -713,7 +713,7 @@ public:
* @param[in] aPort The server port number.
*
*/
- void SetServerPort(uint16_t aPort) { mServerPort = Encoding::LittleEndian::HostSwap16(aPort); }
+ void SetServerPort(uint16_t aPort) { mServerPort = LittleEndian::HostSwap16(aPort); }
private:
void Log(Action aAction) const;
@@ -750,7 +750,7 @@ public:
* @returns The server port number.
*
*/
- uint16_t GetPort(void) const { return Encoding::LittleEndian::HostSwap16(mPort); }
+ uint16_t GetPort(void) const { return LittleEndian::HostSwap16(mPort); }
/**
* Sets the server port number.
@@ -758,7 +758,7 @@ public:
* @param[in] aPort The server port number.
*
*/
- void SetPort(uint16_t aPort) { mPort = Encoding::LittleEndian::HostSwap16(aPort); }
+ void SetPort(uint16_t aPort) { mPort = LittleEndian::HostSwap16(aPort); }
private:
void Log(Action aAction) const;
diff --git a/src/core/common/string.cpp b/src/core/common/string.cpp
index c7aa7218a..4019628d5 100644
--- a/src/core/common/string.cpp
+++ b/src/core/common/string.cpp
@@ -160,6 +160,35 @@ bool StringMatch(const char *aFirstString, const char *aSecondString, StringMatc
return Match(aFirstString, aSecondString, aMode) == kFullMatch;
}
+Error StringCopy(char *aTargetBuffer, uint16_t aTargetSize, const char *aSource, StringEncodingCheck aEncodingCheck)
+{
+ Error error = kErrorNone;
+ uint16_t length;
+
+ if (aSource == nullptr)
+ {
+ aTargetBuffer[0] = kNullChar;
+ ExitNow();
+ }
+
+ length = StringLength(aSource, aTargetSize);
+ VerifyOrExit(length < aTargetSize, error = kErrorInvalidArgs);
+
+ switch (aEncodingCheck)
+ {
+ case kStringNoEncodingCheck:
+ break;
+ case kStringCheckUtf8Encoding:
+ VerifyOrExit(IsValidUtf8String(aSource), error = kErrorParse);
+ break;
+ }
+
+ memcpy(aTargetBuffer, aSource, length + 1); // `+ 1` to also copy null char.
+
+exit:
+ return error;
+}
+
Error StringParseUint8(const char *&aString, uint8_t &aUint8)
{
return StringParseUint8(aString, aUint8, NumericLimits<uint8_t>::kMax);
@@ -281,6 +310,16 @@ StringWriter &StringWriter::AppendHexBytes(const uint8_t *aBytes, uint16_t aLeng
return *this;
}
+StringWriter &StringWriter::AppendCharMultipleTimes(char aChar, uint16_t aCount)
+{
+ while (aCount--)
+ {
+ Append("%c", aChar);
+ }
+
+ return *this;
+}
+
bool IsValidUtf8String(const char *aString) { return IsValidUtf8String(aString, strlen(aString)); }
bool IsValidUtf8String(const char *aString, size_t aLength)
diff --git a/src/core/common/string.hpp b/src/core/common/string.hpp
index 035bc3f32..0c73bb603 100644
--- a/src/core/common/string.hpp
+++ b/src/core/common/string.hpp
@@ -67,6 +67,16 @@ enum StringMatchMode : uint8_t
kStringCaseInsensitiveMatch, ///< Case insensitive match (uppercase and lowercase characters are treated as equal).
};
+/**
+ * Represents string encoding check when copying string.
+ *
+ */
+enum StringEncodingCheck : uint8_t
+{
+ kStringNoEncodingCheck, ///< Do not check the string encoding.
+ kStringCheckUtf8Encoding, ///< Validate that string follows UTF-8 encoding.
+};
+
static constexpr char kNullChar = '\0'; ///< null character.
/**
@@ -157,6 +167,43 @@ bool StringEndsWith(const char *aString, const char *aSubString, StringMatchMode
bool StringMatch(const char *aFirstString, const char *aSecondString, StringMatchMode aMode = kStringExactMatch);
/**
+ * Copies a string into a given target buffer with a given size if it fits.
+ *
+ * @param[out] aTargetBuffer A pointer to the target buffer to copy into.
+ * @param[out] aTargetSize The size (number of characters) in @p aTargetBuffer array.
+ * @param[in] aSource A pointer to null-terminated string to copy from. Can be `nullptr` which treated as "".
+ * @param[in] aEncodingCheck Specifies the encoding format check (e.g., UTF-8) to perform.
+ *
+ * @retval kErrorNone The @p aSource fits in the given buffer. @p aTargetBuffer is updated.
+ * @retval kErrorInvalidArgs The @p aSource does not fit in the given buffer.
+ * @retval kErrorParse The @p aSource does not follow the encoding format specified by @p aEncodingCheck.
+ *
+ */
+Error StringCopy(char *TargetBuffer, uint16_t aTargetSize, const char *aSource, StringEncodingCheck aEncodingCheck);
+
+/**
+ * Copies a string into a given target buffer with a given size if it fits.
+ *
+ * @tparam kSize The size of buffer.
+ *
+ * @param[out] aTargetBuffer A reference to the target buffer array to copy into.
+ * @param[in] aSource A pointer to null-terminated string to copy from. Can be `nullptr` which treated as "".
+ * @param[in] aEncodingCheck Specifies the encoding format check (e.g., UTF-8) to perform.
+ *
+ * @retval kErrorNone The @p aSource fits in the given buffer. @p aTargetBuffer is updated.
+ * @retval kErrorInvalidArgs The @p aSource does not fit in the given buffer.
+ * @retval kErrorParse The @p aSource does not follow the encoding format specified by @p aEncodingCheck.
+ *
+ */
+template <uint16_t kSize>
+Error StringCopy(char (&aTargetBuffer)[kSize],
+ const char *aSource,
+ StringEncodingCheck aEncodingCheck = kStringNoEncodingCheck)
+{
+ return StringCopy(aTargetBuffer, kSize, aSource, aEncodingCheck);
+}
+
+/**
* Parses a decimal number from a string as `uint8_t` and skips over the parsed characters.
*
* If the string does not start with a digit, `kErrorParse` is returned.
@@ -377,6 +424,15 @@ public:
StringWriter &AppendHexBytes(const uint8_t *aBytes, uint16_t aLength);
/**
+ * Appends a given character a given number of times.
+ *
+ * @param[in] aChar The character to append.
+ * @param[in] aCount Number of times to append @p aChar.
+ *
+ */
+ StringWriter &AppendCharMultipleTimes(char aChar, uint16_t aCount);
+
+ /**
* Converts all uppercase letter characters in the string to lowercase.
*
*/
diff --git a/src/core/common/time_ticker.cpp b/src/core/common/time_ticker.cpp
index 368650481..4cc59c1c6 100644
--- a/src/core/common/time_ticker.cpp
+++ b/src/core/common/time_ticker.cpp
@@ -35,9 +35,9 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/mle_router.hpp"
namespace ot {
diff --git a/src/core/common/time_ticker.hpp b/src/core/common/time_ticker.hpp
index 4f7bc5877..e8b37d07b 100644
--- a/src/core/common/time_ticker.hpp
+++ b/src/core/common/time_ticker.hpp
@@ -36,10 +36,9 @@
#include "openthread-core-config.h"
-#include <limits.h>
-
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
+#include "common/numeric_limits.hpp"
#include "common/time.hpp"
#include "common/timer.hpp"
@@ -124,7 +123,7 @@ private:
uint32_t mReceivers;
TickerTimer mTimer;
- static_assert(kNumReceivers < sizeof(mReceivers) * CHAR_BIT, "Too many `Receiver`s - does not fit in a bit mask");
+ static_assert(kNumReceivers < BitSizeOf(mReceivers), "Too many `Receiver`s - does not fit in a bit mask");
};
} // namespace ot
diff --git a/src/core/common/timer.cpp b/src/core/common/timer.cpp
index 7722cae3f..5484f20d0 100644
--- a/src/core/common/timer.cpp
+++ b/src/core/common/timer.cpp
@@ -36,8 +36,8 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp
index a5ed15b45..04756d24a 100644
--- a/src/core/common/tlvs.cpp
+++ b/src/core/common/tlvs.cpp
@@ -216,7 +216,7 @@ template <typename UintType> Error Tlv::ReadUintTlv(const Message &aMessage, uin
Error error;
SuccessOrExit(error = ReadTlvValue(aMessage, aOffset, &aValue, sizeof(aValue)));
- aValue = Encoding::BigEndian::HostSwap<UintType>(aValue);
+ aValue = BigEndian::HostSwap<UintType>(aValue);
exit:
return error;
@@ -271,7 +271,7 @@ template Error Tlv::FindUintTlv<uint8_t>(const Message &aMessage, uint8_t aType,
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);
-Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength)
+Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength)
{
Error error;
uint16_t offset;
@@ -294,7 +294,7 @@ Error Tlv::AppendStringTlv(Message &aMessage, uint8_t aType, uint8_t aMaxStringL
template <typename UintType> Error Tlv::AppendUintTlv(Message &aMessage, uint8_t aType, UintType aValue)
{
- UintType value = Encoding::BigEndian::HostSwap<UintType>(aValue);
+ UintType value = BigEndian::HostSwap<UintType>(aValue);
return AppendTlv(aMessage, aType, &value, sizeof(UintType));
}
@@ -322,4 +322,32 @@ exit:
return error;
}
+const Tlv *Tlv::FindTlv(const void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType)
+{
+ const Tlv *tlv;
+ const Tlv *end = reinterpret_cast<const Tlv *>(reinterpret_cast<const uint8_t *>(aTlvsStart) + aTlvsLength);
+
+ for (tlv = reinterpret_cast<const Tlv *>(aTlvsStart); tlv < end; tlv = tlv->GetNext())
+ {
+ VerifyOrExit((tlv + 1) <= end, tlv = nullptr);
+
+ if (tlv->IsExtended())
+ {
+ VerifyOrExit((As<ExtendedTlv>(tlv) + 1) <= As<ExtendedTlv>(end), tlv = nullptr);
+ }
+
+ VerifyOrExit(tlv->GetNext() <= end, tlv = nullptr);
+
+ if (tlv->GetType() == aType)
+ {
+ ExitNow();
+ }
+ }
+
+ tlv = nullptr;
+
+exit:
+ return tlv;
+}
+
} // namespace ot
diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp
index 79bd5bd62..fd2d6791f 100644
--- a/src/core/common/tlvs.hpp
+++ b/src/core/common/tlvs.hpp
@@ -39,14 +39,13 @@
#include <openthread/thread.h>
#include <openthread/platform/toolchain.h>
+#include "common/const_cast.hpp"
#include "common/encoding.hpp"
#include "common/error.hpp"
#include "common/type_traits.hpp"
namespace ot {
-using ot::Encoding::BigEndian::HostSwap16;
-
class Message;
/**
@@ -175,6 +174,77 @@ public:
Error AppendTo(Message &aMessage) const;
/**
+ * Reads the value of TLV treating it as a given simple TLV type.
+ *
+ * This method requires the TLV to be already validated, in particular, its length MUST NOT be less than the
+ * required size of the value type. The TLV MUST NOT be extended. If these conditions are not met, the behavior of
+ * this method is undefined.
+ *
+ * @tparam SimpleTlvType The simple TLV type to read (must be a sub-class of `SimpleTlvInfo`).
+ *
+ * @returns The TLV value as `SimpleTlvType::ValueType`.
+ *
+ */
+ template <typename SimpleTlvType> const typename SimpleTlvType::ValueType &ReadValueAs(void) const
+ {
+ return *reinterpret_cast<const typename SimpleTlvType::ValueType *>(this + 1);
+ }
+
+ /**
+ * Reads the value of TLV treating it as a given integer-value TLV type.
+ *
+ * This method requires the TLV to be already validated, in particular, its length MUST NOT be less than the
+ * required size of the value type. The TLV MUST NOT be extended. If these conditions are not met, the behavior of
+ * this method is undefined.
+ *
+ * @tparam UintTlvType The integer simple TLV type to read (must be a sub-class of `UintTlvInfo`).
+ *
+ * @returns The TLV value as `UintTlvInfo::UintValueType`.
+ *
+ */
+ template <typename UintTlvType> typename UintTlvType::UintValueType ReadValueAs(void) const
+ {
+ return BigEndian::Read<typename UintTlvType::UintValueType>(reinterpret_cast<const uint8_t *>(this + 1));
+ }
+
+ /**
+ * Writes the value of TLV treating it as a given simple TLV type.
+ *
+ * This method requires the TLV to be already validated, in particular, its length MUST NOT be less than the
+ * required size of the value type. The TLV MUST NOT be extended. If these conditions are not met, the behavior of
+ * this method is undefined.
+ *
+ * @tparam SimpleTlvType The simple TLV type to read (must be a sub-class of `SimpleTlvInfo`).
+ *
+ * @param[in] aValue The new TLV value.
+ *
+ */
+ template <typename SimpleTlvType> void WriteValueAs(const typename SimpleTlvType::ValueType &aValue)
+ {
+ memcpy(this + 1, &aValue, sizeof(aValue));
+ }
+
+ /**
+ * Writes the value of TLV treating it as a given integer-value TLV type.
+ *
+ * This method requires the TLV to be already validated, in particular, its length MUST NOT be less than the
+ * required size of the value type. The TLV MUST NOT be extended. If these conditions are not met, the behavior of
+ * this method is undefined.
+ *
+ * @tparam UintTlvType The integer simple TLV type to read (must be a sub-class of `UintTlvInfo`).
+ *
+ * @param[in] aValue The new TLV value.
+ *
+ */
+ template <typename UintTlvType> void WriteValueAs(typename UintTlvType::UintValueType aValue)
+ {
+ return BigEndian::Write<typename UintTlvType::UintValueType>(aValue, reinterpret_cast<uint8_t *>(this + 1));
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Static methods for reading/finding/appending TLVs in a `Message`.
+
+ /**
* Reads a TLV's value in a message at a given offset expecting a minimum length for the value.
*
* Can be used independent of whether the read TLV (from the message) is an Extended TLV or not.
@@ -538,6 +608,68 @@ public:
return AppendStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue);
}
+ //------------------------------------------------------------------------------------------------------------------
+ // Static methods for finding TLVs within a sequence of TLVs.
+
+ /**
+ * Searches in a given sequence of TLVs to find the first TLV of a given type.
+ *
+ * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
+ * @param[in] aTlvsLength The length (number of bytes) in the TLV sequence.
+ * @param[in] aType The TLV type to search for.
+ *
+ * @returns A pointer to the TLV within the TLV sequence if found, or `nullptr` if not found.
+ *
+ */
+ static const Tlv *FindTlv(const void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType);
+
+ /**
+ * Searches in a given sequence of TLVs to find the first TLV of a given type.
+ *
+ * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
+ * @param[in] aTlvsLength The length (number of bytes) in the TLV sequence.
+ * @param[in] aType The TLV type to search for.
+ *
+ * @returns A pointer to the TLV within the TLV sequence if found, or `nullptr` if not found.
+ *
+ */
+ static Tlv *FindTlv(void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType)
+ {
+ return AsNonConst(FindTlv(AsConst(aTlvsStart), aTlvsLength, aType));
+ }
+
+ /**
+ * Searches in a given sequence of TLVs to find the first TLV with a give template `TlvType`.
+ *
+ * @tparam kTlvType The TLV Type.
+ *
+ * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
+ * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
+ *
+ * @returns A pointer to the TLV if found, or `nullptr` if not found.
+ *
+ */
+ template <typename TlvType> static TlvType *Find(void *aTlvsStart, uint16_t aTlvsLength)
+ {
+ return static_cast<TlvType *>(FindTlv(aTlvsStart, aTlvsLength, TlvType::kType));
+ }
+
+ /**
+ * Searches in a given sequence of TLVs to find the first TLV with a give template `TlvType`.
+ *
+ * @tparam kTlvType The TLV Type.
+ *
+ * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
+ * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
+ *
+ * @returns A pointer to the TLV if found, or `nullptr` if not found.
+ *
+ */
+ template <typename TlvType> static const TlvType *Find(const void *aTlvsStart, uint16_t aTlvsLength)
+ {
+ return static_cast<const TlvType *>(FindTlv(aTlvsStart, aTlvsLength, TlvType::kType));
+ }
+
protected:
static const uint8_t kExtendedLength = 255; // Extended Length value.
@@ -554,7 +686,7 @@ private:
uint16_t mSize;
};
- static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength);
+ static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength);
static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength);
static Error ReadStringTlv(const Message &aMessage, uint16_t aOffset, uint8_t aMaxStringLength, char *aValue);
static Error FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue);
@@ -575,7 +707,7 @@ public:
* Returns the Length value.
*
*/
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
+ uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
/**
* Sets the Length value.
@@ -586,7 +718,7 @@ public:
void SetLength(uint16_t aLength)
{
Tlv::SetLength(kExtendedLength);
- mLength = HostSwap16(aLength);
+ mLength = BigEndian::HostSwap16(aLength);
}
private:
diff --git a/src/core/common/uptime.cpp b/src/core/common/uptime.cpp
index 4cf0a34c7..3d9e6afde 100644
--- a/src/core/common/uptime.cpp
+++ b/src/core/common/uptime.cpp
@@ -37,8 +37,8 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/config/ip6.h b/src/core/config/ip6.h
index 75976e1a1..8f349f138 100644
--- a/src/core/config/ip6.h
+++ b/src/core/config/ip6.h
@@ -178,8 +178,8 @@
* Define as 1 to enable support for TLS over TCP.
*
*/
-#if OPENTHREAD_CONFIG_TCP_ENABLE && !defined(OPENTHREAD_CONFIG_TLS_ENABLE)
-#define OPENTHREAD_CONFIG_TLS_ENABLE 1
+#ifndef OPENTHREAD_CONFIG_TLS_ENABLE
+#define OPENTHREAD_CONFIG_TLS_ENABLE OPENTHREAD_CONFIG_TCP_ENABLE
#endif
/**
diff --git a/src/core/config/mac.h b/src/core/config/mac.h
index 2694e0dc8..d0cefa624 100644
--- a/src/core/config/mac.h
+++ b/src/core/config/mac.h
@@ -396,6 +396,16 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE
+ *
+ * Define to 1 to enable software rx off when idle switching.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE
+#define OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE 0
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
*
* Define to 1 to enable csl transmitter logic.
@@ -426,6 +436,28 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
+ *
+ * This setting configures the usage of local time rather than radio time for calculating the
+ * elapsed time since last CSL synchronization event in order to schedule the duration of the
+ * CSL receive window.
+ *
+ * This is done at expense of too short or too long receive windows depending on the drift
+ * between the two clocks within the CSL timeout period. In order to compensate for a too
+ * short receive window, CSL uncertainty can be increased.
+ *
+ * This setting can be useful for platforms in which is important to reduce the number of
+ * radio API calls, for instance when they are costly. One typical situation is a multicore
+ * chip architecture in which different instances of current time are being kept in host and
+ * radio cores. In this case, accessing the radio core current time API requires serialization
+ * and it is more costly than just accessing local host time.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
+#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC 0
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_MAC_CSL_MIN_PERIOD
*
* This setting configures the minimum CSL period that could be used, in units of milliseconds.
diff --git a/src/core/config/misc.h b/src/core/config/misc.h
index df9fd28fa..c9be7ec5e 100644
--- a/src/core/config/misc.h
+++ b/src/core/config/misc.h
@@ -142,6 +142,16 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ *
+ * Define to 1 to enable multipan RCP support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+#define OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE 0
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
*
* Define to 1 to enable Thread Test Harness reference device support.
@@ -521,6 +531,26 @@
#endif
/**
+ * @def OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ *
+ * Define to 1 to enable multiple static instance support.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+#define OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE 0
+#endif
+
+/**
+ * @def OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM
+ *
+ * Define number of OpenThread instance for static allocation buffer.
+ *
+ */
+#ifndef OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM
+#define OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM 3
+#endif
+
+/**
* @def OPENTHREAD_CONFIG_ALLOW_EMPTY_NETWORK_NAME
*
* Define as 1 to enable support for an empty network name (zero-length: "")
diff --git a/src/core/crypto/aes_ccm.cpp b/src/core/crypto/aes_ccm.cpp
index bb9bec125..9d32d1cb4 100644
--- a/src/core/crypto/aes_ccm.cpp
+++ b/src/core/crypto/aes_ccm.cpp
@@ -33,8 +33,6 @@
#include "aes_ccm.hpp"
-#include <limits.h>
-
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
@@ -285,7 +283,7 @@ void AesCcm::GenerateNonce(const Mac::ExtAddress &aAddress,
memcpy(aNonce, aAddress.m8, sizeof(Mac::ExtAddress));
aNonce += sizeof(Mac::ExtAddress);
- Encoding::BigEndian::WriteUint32(aFrameCounter, aNonce);
+ BigEndian::WriteUint32(aFrameCounter, aNonce);
aNonce += sizeof(uint32_t);
aNonce[0] = aSecurityLevel;
diff --git a/src/core/crypto/crypto_platform.cpp b/src/core/crypto/crypto_platform.cpp
index 0b9250d42..6c7e54cee 100644
--- a/src/core/crypto/crypto_platform.cpp
+++ b/src/core/crypto/crypto_platform.cpp
@@ -51,12 +51,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/new.hpp"
#include "config/crypto.h"
#include "crypto/ecdsa.hpp"
#include "crypto/hmac_sha256.hpp"
#include "crypto/storage.hpp"
+#include "instance/instance.hpp"
using namespace ot;
using namespace Crypto;
@@ -110,7 +110,7 @@ OT_TOOL_WEAK otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCr
VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed);
context = static_cast<mbedtls_aes_context *>(aContext->mContext);
- VerifyOrExit((mbedtls_aes_setkey_enc(context, key.GetBytes(), (key.GetLength() * CHAR_BIT)) == 0),
+ VerifyOrExit((mbedtls_aes_setkey_enc(context, key.GetBytes(), (key.GetLength() * kBitsPerByte)) == 0),
error = kErrorFailed);
exit:
diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp
index 5eed151f3..249594f77 100644
--- a/src/core/diags/factory_diags.cpp
+++ b/src/core/diags/factory_diags.cpp
@@ -43,8 +43,8 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "radio/radio.hpp"
#include "utils/parse_cmdline.hpp"
diff --git a/src/core/common/extension.hpp b/src/core/instance/extension.hpp
index ac93e0169..ac93e0169 100644
--- a/src/core/common/extension.hpp
+++ b/src/core/instance/extension.hpp
diff --git a/src/core/common/extension_example.cpp b/src/core/instance/extension_example.cpp
index f392b31fb..c1bebfbd5 100644
--- a/src/core/common/extension_example.cpp
+++ b/src/core/instance/extension_example.cpp
@@ -37,8 +37,8 @@
#include <stdint.h>
#include "common/code_utils.hpp"
-#include "common/extension.hpp"
#include "common/new.hpp"
+#include "instance/extension.hpp"
namespace ot {
namespace Extension {
diff --git a/src/core/common/instance.cpp b/src/core/instance/instance.cpp
index 6dcc3e892..706671a97 100644
--- a/src/core/common/instance.cpp
+++ b/src/core/instance/instance.cpp
@@ -48,6 +48,16 @@ OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
#endif
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+
+#define INSTANCE_SIZE_ALIGNED OT_ALIGNED_VAR_SIZE(sizeof(ot::Instance), uint64_t)
+#define MULTI_INSTANCE_SIZE (OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM * INSTANCE_SIZE_ALIGNED)
+
+// Define the raw storage used for OpenThread instance (in multi-instance case).
+static uint64_t gMultiInstanceRaw[MULTI_INSTANCE_SIZE];
+
+#endif
+
#if OPENTHREAD_MTD || OPENTHREAD_FTD
#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
OT_DEFINE_ALIGNED_VAR(sHeapRaw, sizeof(Utils::Heap), uint64_t);
@@ -288,6 +298,25 @@ Instance &Instance::Get(void)
}
#else // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+
+Instance *Instance::InitMultiple(uint8_t aIdx)
+{
+ size_t bufferSize;
+ uint64_t *instanceBuffer = gMultiInstanceRaw + aIdx * INSTANCE_SIZE_ALIGNED;
+ Instance *instance = reinterpret_cast<Instance *>(instanceBuffer);
+
+ VerifyOrExit(aIdx < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ VerifyOrExit(!instance->mIsInitialized);
+
+ bufferSize = (&gMultiInstanceRaw[MULTI_INSTANCE_SIZE] - instanceBuffer) * sizeof(uint64_t);
+ instance = Instance::Init(instanceBuffer, &bufferSize);
+
+exit:
+ return instance;
+}
+
+#endif // #if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
Instance *Instance::Init(void *aBuffer, size_t *aBufferSize)
{
@@ -312,6 +341,10 @@ exit:
void Instance::Reset(void) { otPlatReset(this); }
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+Error Instance::ResetToBootloader(void) { return otPlatResetToBootloader(this); }
+#endif
+
#if OPENTHREAD_RADIO
void Instance::ResetRadioStack(void)
{
diff --git a/src/core/common/instance.hpp b/src/core/instance/instance.hpp
index d213c692e..596a5c68c 100644
--- a/src/core/common/instance.hpp
+++ b/src/core/instance/instance.hpp
@@ -47,7 +47,6 @@
#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/error.hpp"
-#include "common/extension.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
@@ -57,6 +56,7 @@
#include "common/timer.hpp"
#include "common/uptime.hpp"
#include "diags/factory_diags.hpp"
+#include "instance/extension.hpp"
#include "mac/link_raw.hpp"
#include "radio/radio.hpp"
#include "utils/otns.hpp"
@@ -186,6 +186,21 @@ public:
*/
static Instance *Init(void *aBuffer, size_t *aBufferSize);
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ /**
+ * This static method initializes the OpenThread instance.
+ *
+ * This method utilizes static buffer to initialize the OpenThread instance.
+ * This function must be called before any other calls on OpenThread instance.
+ *
+ * @param[in] aIdx The index of the OpenThread instance to initialize.
+ *
+ * @returns A pointer to the new OpenThread instance.
+ *
+ */
+ static Instance *InitMultiple(uint8_t aIdx);
+#endif
+
#else // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
/**
@@ -236,6 +251,18 @@ public:
*/
void Reset(void);
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+ /**
+ * Triggers a platform reset to bootloader mode, if supported.
+ *
+ * @retval kErrorNone Reset to bootloader successfully.
+ * @retval kErrorBusy Failed due to another operation is ongoing.
+ * @retval kErrorNotCapable Not capable of resetting to bootloader.
+ *
+ */
+ Error ResetToBootloader(void);
+#endif
+
#if OPENTHREAD_RADIO
/**
* Resets the internal states of the radio.
@@ -701,7 +728,9 @@ template <> inline RadioSelector &Instance::Get(void) { return mRadioSelector; }
template <> inline Mle::Mle &Instance::Get(void) { return mMleRouter; }
+#if OPENTHREAD_FTD
template <> inline Mle::MleRouter &Instance::Get(void) { return mMleRouter; }
+#endif
template <> inline Mle::DiscoverScanner &Instance::Get(void) { return mDiscoverScanner; }
diff --git a/src/core/mac/channel_mask.hpp b/src/core/mac/channel_mask.hpp
index 36ad78d45..7549760f7 100644
--- a/src/core/mac/channel_mask.hpp
+++ b/src/core/mac/channel_mask.hpp
@@ -36,10 +36,10 @@
#include "openthread-core-config.h"
-#include <limits.h>
#include <openthread/platform/radio.h>
#include "common/equatable.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "radio/radio.hpp"
@@ -147,7 +147,7 @@ public:
*/
bool ContainsChannel(uint8_t aChannel) const
{
- return (aChannel < sizeof(mMask) * CHAR_BIT) ? ((1UL << aChannel) & mMask) != 0 : false;
+ return (aChannel < BitSizeOf(mMask)) ? ((1UL << aChannel) & mMask) != 0 : false;
}
/**
@@ -158,7 +158,7 @@ public:
*/
void AddChannel(uint8_t aChannel)
{
- if (aChannel < sizeof(mMask) * CHAR_BIT)
+ if (aChannel < BitSizeOf(mMask))
{
mMask |= (1UL << aChannel);
}
@@ -172,7 +172,7 @@ public:
*/
void RemoveChannel(uint8_t aChannel)
{
- if (aChannel < sizeof(mMask) * CHAR_BIT)
+ if (aChannel < BitSizeOf(mMask))
{
mMask &= ~(1UL << aChannel);
}
diff --git a/src/core/mac/data_poll_handler.cpp b/src/core/mac/data_poll_handler.cpp
index d832c1c79..226ab087e 100644
--- a/src/core/mac/data_poll_handler.cpp
+++ b/src/core/mac/data_poll_handler.cpp
@@ -36,9 +36,9 @@
#if OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp
index 93fad6b83..80e18f7a5 100644
--- a/src/core/mac/data_poll_sender.cpp
+++ b/src/core/mac/data_poll_sender.cpp
@@ -34,11 +34,11 @@
#include "data_poll_sender.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
#include "thread/mesh_forwarder.hpp"
diff --git a/src/core/mac/link_raw.cpp b/src/core/mac/link_raw.cpp
index b9c4f6ee4..be433815f 100644
--- a/src/core/mac/link_raw.cpp
+++ b/src/core/mac/link_raw.cpp
@@ -40,10 +40,10 @@
#include <openthread/platform/diag.h>
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_frame.hpp"
namespace ot {
diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp
index 314085147..15f560631 100644
--- a/src/core/mac/mac.cpp
+++ b/src/core/mac/mac.cpp
@@ -40,12 +40,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
#include "crypto/aes_ccm.hpp"
#include "crypto/sha256.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_frame.hpp"
#include "radio/radio.hpp"
#include "thread/child.hpp"
@@ -414,7 +414,7 @@ void Mac::SetRxOnWhenIdle(bool aRxOnWhenIdle)
#endif
}
- mLinks.SetRxOnWhenBackoff(mRxOnWhenIdle || mPromiscuous);
+ mLinks.SetRxOnWhenIdle(mRxOnWhenIdle || mPromiscuous);
UpdateIdleMode();
exit:
@@ -1659,6 +1659,8 @@ Error Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame)
VerifyOrExit(aAckFrame.GetSecurityEnabled(), error = kErrorNone);
VerifyOrExit(aAckFrame.IsVersion2015());
+ SuccessOrExit(aAckFrame.ValidatePsdu());
+
IgnoreError(aAckFrame.GetSecurityLevel(securityLevel));
VerifyOrExit(securityLevel == Frame::kSecurityEncMic32);
@@ -2101,7 +2103,7 @@ void Mac::SetPromiscuous(bool aPromiscuous)
mShouldDelaySleep = false;
#endif
- mLinks.SetRxOnWhenBackoff(mRxOnWhenIdle || mPromiscuous);
+ mLinks.SetRxOnWhenIdle(mRxOnWhenIdle || mPromiscuous);
UpdateIdleMode();
}
@@ -2225,12 +2227,9 @@ void Mac::LogFrameRxFailure(const RxFrame *aFrame, Error aError) 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 OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
+#if OPENTHREAD_CONFIG_MULTI_RADIO
if (aFrame.GetRadioType() == kRadioTypeIeee802154)
-#elif OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
- if (true)
-#else
- if (false)
#endif
{
uint8_t maxAttempts = aFrame.GetMaxFrameRetries() + 1;
@@ -2239,10 +2238,22 @@ void Mac::LogFrameTxFailure(const TxFrame &aFrame, Error aError, uint8_t aRetryC
LogInfo("Frame tx attempt %u/%u failed, error:%s, %s", curAttempt, maxAttempts, ErrorToString(aError),
aFrame.ToInfoString().AsCString());
}
- else
+#else
+ OT_UNUSED_VARIABLE(aRetryCount);
+ OT_UNUSED_VARIABLE(aWillRetx);
+#endif
+
+#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+#if OPENTHREAD_CONFIG_MULTI_RADIO
+ if (aFrame.GetRadioType() == kRadioTypeTrel)
+#endif
{
- LogInfo("Frame tx failed, error:%s, %s", ErrorToString(aError), aFrame.ToInfoString().AsCString());
+ if (Get<Trel::Interface>().IsEnabled())
+ {
+ LogInfo("Frame tx failed, error:%s, %s", ErrorToString(aError), aFrame.ToInfoString().AsCString());
+ }
}
+#endif
}
void Mac::LogBeacon(const char *aActionText) const { LogInfo("%s Beacon", aActionText); }
diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp
index 3e26a6ba8..47debefb3 100644
--- a/src/core/mac/mac_frame.cpp
+++ b/src/core/mac/mac_frame.cpp
@@ -47,11 +47,6 @@
namespace ot {
namespace Mac {
-using ot::Encoding::LittleEndian::ReadUint16;
-using ot::Encoding::LittleEndian::ReadUint32;
-using ot::Encoding::LittleEndian::WriteUint16;
-using ot::Encoding::LittleEndian::WriteUint32;
-
void HeaderIe::Init(uint16_t aId, uint8_t aLen)
{
Init();
@@ -237,9 +232,9 @@ void Frame::InitMacHeader(Type aType,
mLength += GetFcsSize();
}
-uint16_t Frame::GetFrameControlField(void) const { return ReadUint16(mPsdu); }
+uint16_t Frame::GetFrameControlField(void) const { return LittleEndian::ReadUint16(mPsdu); }
-void Frame::SetFrameControlField(uint16_t aFcf) { WriteUint16(aFcf, mPsdu); }
+void Frame::SetFrameControlField(uint16_t aFcf) { LittleEndian::WriteUint16(aFcf, mPsdu); }
Error Frame::ValidatePsdu(void) const
{
@@ -364,7 +359,7 @@ Error Frame::GetDstPanId(PanId &aPanId) const
uint8_t index = FindDstPanIdIndex();
VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
- aPanId = ReadUint16(&mPsdu[index]);
+ aPanId = LittleEndian::ReadUint16(&mPsdu[index]);
exit:
return error;
@@ -375,7 +370,7 @@ void Frame::SetDstPanId(PanId aPanId)
uint8_t index = FindDstPanIdIndex();
OT_ASSERT(index != kInvalidIndex);
- WriteUint16(aPanId, &mPsdu[index]);
+ LittleEndian::WriteUint16(aPanId, &mPsdu[index]);
}
uint8_t Frame::FindDstAddrIndex(void) const { return kFcfSize + kDsnSize + (IsDstPanIdPresent() ? sizeof(PanId) : 0); }
@@ -390,7 +385,7 @@ Error Frame::GetDstAddr(Address &aAddress) const
switch (GetFrameControlField() & kFcfDstAddrMask)
{
case kFcfDstAddrShort:
- aAddress.SetShort(ReadUint16(&mPsdu[index]));
+ aAddress.SetShort(LittleEndian::ReadUint16(&mPsdu[index]));
break;
case kFcfDstAddrExt:
@@ -409,7 +404,7 @@ exit:
void Frame::SetDstAddr(ShortAddress aShortAddress)
{
OT_ASSERT((GetFrameControlField() & kFcfDstAddrMask) == kFcfDstAddrShort);
- WriteUint16(aShortAddress, &mPsdu[FindDstAddrIndex()]);
+ LittleEndian::WriteUint16(aShortAddress, &mPsdu[FindDstAddrIndex()]);
}
void Frame::SetDstAddr(const ExtAddress &aExtAddress)
@@ -515,7 +510,7 @@ Error Frame::GetSrcPanId(PanId &aPanId) const
uint8_t index = FindSrcPanIdIndex();
VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
- aPanId = ReadUint16(&mPsdu[index]);
+ aPanId = LittleEndian::ReadUint16(&mPsdu[index]);
exit:
return error;
@@ -527,7 +522,7 @@ Error Frame::SetSrcPanId(PanId aPanId)
uint8_t index = FindSrcPanIdIndex();
VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
- WriteUint16(aPanId, &mPsdu[index]);
+ LittleEndian::WriteUint16(aPanId, &mPsdu[index]);
exit:
return error;
@@ -575,7 +570,7 @@ Error Frame::GetSrcAddr(Address &aAddress) const
switch (fcf & kFcfSrcAddrMask)
{
case kFcfSrcAddrShort:
- aAddress.SetShort(ReadUint16(&mPsdu[index]));
+ aAddress.SetShort(LittleEndian::ReadUint16(&mPsdu[index]));
break;
case kFcfSrcAddrExt:
@@ -603,7 +598,7 @@ void Frame::SetSrcAddr(ShortAddress aShortAddress)
OT_ASSERT((GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrShort);
OT_ASSERT(index != kInvalidIndex);
- WriteUint16(aShortAddress, &mPsdu[index]);
+ LittleEndian::WriteUint16(aShortAddress, &mPsdu[index]);
}
void Frame::SetSrcAddr(const ExtAddress &aExtAddress)
@@ -703,7 +698,7 @@ Error Frame::GetFrameCounter(uint32_t &aFrameCounter) const
// Security Control
index += kSecurityControlSize;
- aFrameCounter = ReadUint32(&mPsdu[index]);
+ aFrameCounter = LittleEndian::ReadUint32(&mPsdu[index]);
exit:
return error;
@@ -718,7 +713,7 @@ void Frame::SetFrameCounter(uint32_t aFrameCounter)
// Security Control
index += kSecurityControlSize;
- WriteUint32(aFrameCounter, &mPsdu[index]);
+ LittleEndian::WriteUint32(aFrameCounter, &mPsdu[index]);
static_cast<Mac::TxFrame *>(this)->SetIsHeaderUpdated(true);
}
@@ -1396,7 +1391,7 @@ void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending)
{
fcf |= kFcfFramePending;
}
- WriteUint16(fcf, mPsdu);
+ LittleEndian::WriteUint16(fcf, mPsdu);
mPsdu[kSequenceIndex] = aFrame.GetSequence();
diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp
index 267e2f735..ccf8a500e 100644
--- a/src/core/mac/mac_frame.hpp
+++ b/src/core/mac/mac_frame.hpp
@@ -36,23 +36,16 @@
#include "openthread-core-config.h"
-#include <limits.h>
-#include <stdint.h>
-
#include "common/as_core_type.hpp"
#include "common/const_cast.hpp"
#include "common/encoding.hpp"
+#include "common/numeric_limits.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/network_name.hpp"
namespace ot {
namespace Mac {
-using ot::Encoding::LittleEndian::HostSwap16;
-using ot::Encoding::LittleEndian::HostSwap64;
-using ot::Encoding::LittleEndian::ReadUint24;
-using ot::Encoding::LittleEndian::WriteUint24;
-
/**
* @addtogroup core-mac
*
@@ -89,7 +82,7 @@ public:
* @returns the IE Element Id.
*
*/
- uint16_t GetId(void) const { return (HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; }
+ uint16_t GetId(void) const { return (LittleEndian::HostSwap16(mFields.m16) & kIdMask) >> kIdOffset; }
/**
* Sets the IE Element Id.
@@ -99,7 +92,8 @@ public:
*/
void SetId(uint16_t aId)
{
- mFields.m16 = HostSwap16((HostSwap16(mFields.m16) & ~kIdMask) | ((aId << kIdOffset) & kIdMask));
+ mFields.m16 = LittleEndian::HostSwap16((LittleEndian::HostSwap16(mFields.m16) & ~kIdMask) |
+ ((aId << kIdOffset) & kIdMask));
}
/**
@@ -159,7 +153,7 @@ public:
* @returns The Vendor OUI.
*
*/
- uint32_t GetVendorOui(void) const { return ReadUint24(mOui); }
+ uint32_t GetVendorOui(void) const { return LittleEndian::ReadUint24(mOui); }
/**
* Sets the Vendor OUI.
@@ -167,7 +161,7 @@ public:
* @param[in] aVendorOui A Vendor OUI.
*
*/
- void SetVendorOui(uint32_t aVendorOui) { WriteUint24(aVendorOui, mOui); }
+ void SetVendorOui(uint32_t aVendorOui) { LittleEndian::WriteUint24(aVendorOui, mOui); }
/**
* Returns the Vendor IE sub-type.
@@ -238,7 +232,7 @@ public:
* @returns the network time, in microseconds.
*
*/
- uint64_t GetTime(void) const { return HostSwap64(mTime); }
+ uint64_t GetTime(void) const { return LittleEndian::HostSwap64(mTime); }
/**
* Sets the network time.
@@ -246,7 +240,7 @@ public:
* @param[in] aTime The network time.
*
*/
- void SetTime(uint64_t aTime) { mTime = HostSwap64(aTime); }
+ void SetTime(uint64_t aTime) { mTime = LittleEndian::HostSwap64(aTime); }
private:
uint8_t mSequence;
@@ -1115,9 +1109,9 @@ protected:
static constexpr uint8_t kKeyIdModeMask = 3 << 3;
static constexpr uint8_t kMic0Size = 0;
- static constexpr uint8_t kMic32Size = 32 / CHAR_BIT;
- static constexpr uint8_t kMic64Size = 64 / CHAR_BIT;
- static constexpr uint8_t kMic128Size = 128 / CHAR_BIT;
+ static constexpr uint8_t kMic32Size = 32 / kBitsPerByte;
+ static constexpr uint8_t kMic64Size = 64 / kBitsPerByte;
+ static constexpr uint8_t kMic128Size = 128 / kBitsPerByte;
static constexpr uint8_t kMaxMicSize = kMic128Size;
static constexpr uint8_t kKeySourceSizeMode0 = 0;
@@ -1559,7 +1553,7 @@ public:
*/
void Init(void)
{
- mSuperframeSpec = HostSwap16(kSuperFrameSpec);
+ mSuperframeSpec = LittleEndian::HostSwap16(kSuperFrameSpec);
mGtsSpec = 0;
mPendingAddressSpec = 0;
}
@@ -1573,7 +1567,8 @@ public:
*/
bool IsValid(void) const
{
- return (mSuperframeSpec == HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) && (mPendingAddressSpec == 0);
+ return (mSuperframeSpec == LittleEndian::HostSwap16(kSuperFrameSpec)) && (mGtsSpec == 0) &&
+ (mPendingAddressSpec == 0);
}
/**
@@ -1754,7 +1749,7 @@ public:
* @returns the CSL Period.
*
*/
- uint16_t GetPeriod(void) const { return HostSwap16(mPeriod); }
+ uint16_t GetPeriod(void) const { return LittleEndian::HostSwap16(mPeriod); }
/**
* Sets the CSL Period.
@@ -1762,7 +1757,7 @@ public:
* @param[in] aPeriod The CSL Period.
*
*/
- void SetPeriod(uint16_t aPeriod) { mPeriod = HostSwap16(aPeriod); }
+ void SetPeriod(uint16_t aPeriod) { mPeriod = LittleEndian::HostSwap16(aPeriod); }
/**
* Returns the CSL Phase.
@@ -1770,7 +1765,7 @@ public:
* @returns the CSL Phase.
*
*/
- uint16_t GetPhase(void) const { return HostSwap16(mPhase); }
+ uint16_t GetPhase(void) const { return LittleEndian::HostSwap16(mPhase); }
/**
* Sets the CSL Phase.
@@ -1778,7 +1773,7 @@ public:
* @param[in] aPhase The CSL Phase.
*
*/
- void SetPhase(uint16_t aPhase) { mPhase = HostSwap16(aPhase); }
+ void SetPhase(uint16_t aPhase) { mPhase = LittleEndian::HostSwap16(aPhase); }
private:
uint16_t mPhase;
diff --git a/src/core/mac/mac_links.cpp b/src/core/mac/mac_links.cpp
index 19b9df38f..481f0f0eb 100644
--- a/src/core/mac/mac_links.cpp
+++ b/src/core/mac/mac_links.cpp
@@ -34,8 +34,8 @@
#include "mac_links.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Mac {
diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp
index 605866d18..5d9a8f09a 100644
--- a/src/core/mac/mac_links.hpp
+++ b/src/core/mac/mac_links.hpp
@@ -402,17 +402,17 @@ public:
}
/**
- * Indicates whether radio should stay in Receive or Sleep during CSMA backoff.
+ * Indicates whether radio should stay in Receive or Sleep during idle periods.
*
- * @param[in] aRxOnWhenBackoff TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff.
+ * @param[in] aRxOnWhenIdle TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods.
*
*/
- void SetRxOnWhenBackoff(bool aRxOnWhenBackoff)
+ void SetRxOnWhenIdle(bool aRxOnWhenIdle)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
- mSubMac.SetRxOnWhenBackoff(aRxOnWhenBackoff);
+ mSubMac.SetRxOnWhenIdle(aRxOnWhenIdle);
#endif
- OT_UNUSED_VARIABLE(aRxOnWhenBackoff);
+ OT_UNUSED_VARIABLE(aRxOnWhenIdle);
}
/**
diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp
index a5b3a5f32..2884d8673 100644
--- a/src/core/mac/sub_mac.cpp
+++ b/src/core/mac/sub_mac.cpp
@@ -39,12 +39,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_frame.hpp"
namespace ot {
@@ -76,7 +76,7 @@ void SubMac::Init(void)
mTransmitRetries = 0;
mShortAddress = kShortAddrInvalid;
mExtAddress.Clear();
- mRxOnWhenBackoff = true;
+ mRxOnWhenIdle = true;
mEnergyScanMaxRssi = Radio::kInvalidRssi;
mEnergyScanEndTime = Time{0};
#if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY
@@ -141,10 +141,14 @@ otRadioCaps SubMac::GetCaps(void) const
caps |= OT_RADIO_CAPS_RECEIVE_TIMING;
#endif
+#if OPENTHREAD_CONFIG_MAC_SOFTWARE_RX_ON_WHEN_IDLE_ENABLE
+ caps |= OT_RADIO_CAPS_RX_ON_WHEN_IDLE;
+#endif
+
#else
caps = OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES |
OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_TRANSMIT_SEC | OT_RADIO_CAPS_TRANSMIT_TIMING |
- OT_RADIO_CAPS_RECEIVE_TIMING;
+ OT_RADIO_CAPS_RECEIVE_TIMING | OT_RADIO_CAPS_RX_ON_WHEN_IDLE;
#endif
return caps;
@@ -176,6 +180,20 @@ void SubMac::SetExtAddress(const ExtAddress &aExtAddress)
LogDebg("RadioExtAddress: %s", mExtAddress.ToString().AsCString());
}
+void SubMac::SetRxOnWhenIdle(bool aRxOnWhenIdle)
+{
+ mRxOnWhenIdle = aRxOnWhenIdle;
+
+ if (RadioSupportsRxOnWhenIdle())
+ {
+#if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE
+ Get<Radio>().SetRxOnWhenIdle(mRxOnWhenIdle);
+#endif
+ }
+
+ LogDebg("RxOnWhenIdle: %d", mRxOnWhenIdle);
+}
+
Error SubMac::Enable(void)
{
Error error = kErrorNone;
@@ -211,17 +229,22 @@ exit:
Error SubMac::Sleep(void)
{
- Error error = Get<Radio>().Sleep();
+ Error error = kErrorNone;
+ VerifyOrExit(ShouldHandleTransitionToSleep());
+
+ error = Get<Radio>().Sleep();
+
+exit:
if (error != kErrorNone)
{
LogWarn("RadioSleep() failed, error: %s", ErrorToString(error));
- ExitNow();
+ }
+ else
+ {
+ SetState(kStateSleep);
}
- SetState(kStateSleep);
-
-exit:
return error;
}
@@ -352,7 +375,11 @@ void SubMac::HandleReceiveDone(RxFrame *aFrame, Error aError)
// Assuming the risk of the parent missing the Enh-ACK in favor of smaller CSL receive window
if ((mCslPeriod > 0) && aFrame->mInfo.mRxInfo.mAckedWithSecEnhAck)
{
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
+ mCslLastSync = TimerMicro::GetNow();
+#else
mCslLastSync = TimeMicro(static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp));
+#endif
}
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
@@ -507,7 +534,7 @@ void SubMac::StartTimerForBackoff(uint8_t aBackoffExponent)
backoff = Random::NonCrypto::GetUint32InRange(0, static_cast<uint32_t>(1UL << aBackoffExponent));
backoff *= (kUnitBackoffPeriod * Radio::kSymbolTime);
- if (mRxOnWhenBackoff)
+ if (mRxOnWhenIdle)
{
IgnoreError(Get<Radio>().Receive(mTransmitFrame.GetChannel()));
}
@@ -613,9 +640,13 @@ void SubMac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aErro
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
// Actual synchronization timestamp should be from the sent frame instead of the current time.
// Assuming the error here since it is bounded and has very small effect on the final window duration.
- if (mCslPeriod > 0)
+ if (aAckFrame != nullptr && aFrame.GetHeaderIe(CslIe::kHeaderIeId) != nullptr)
{
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
+ mCslLastSync = TimerMicro::GetNow();
+#else
mCslLastSync = TimeMicro(static_cast<uint32_t>(otPlatRadioGetNow(&GetInstance())));
+#endif
}
#endif
break;
@@ -970,6 +1001,8 @@ exit:
return swTxDelay;
}
+bool SubMac::ShouldHandleTransitionToSleep(void) const { return (mRxOnWhenIdle || !RadioSupportsRxOnWhenIdle()); }
+
void SubMac::SetState(State aState)
{
if (mState != aState)
@@ -1232,9 +1265,13 @@ void SubMac::HandleCslTimer(void)
void SubMac::GetCslWindowEdges(uint32_t &aAhead, uint32_t &aAfter)
{
uint32_t semiPeriod = mCslPeriod * kUsPerTenSymbols / 2;
- uint32_t curTime = static_cast<uint32_t>(otPlatRadioGetNow(&GetInstance()));
- uint32_t elapsed;
- uint32_t semiWindow;
+ uint32_t curTime, elapsed, semiWindow;
+
+#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_LOCAL_TIME_SYNC
+ curTime = TimerMicro::GetNow().GetValue();
+#else
+ curTime = static_cast<uint32_t>(otPlatRadioGetNow(&GetInstance()));
+#endif
elapsed = curTime - mCslLastSync.GetValue();
diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp
index 96af31303..211babd0b 100644
--- a/src/core/mac/sub_mac.hpp
+++ b/src/core/mac/sub_mac.hpp
@@ -278,12 +278,12 @@ public:
}
/**
- * Indicates whether radio should stay in Receive or Sleep during CSMA backoff.
+ * Indicates whether radio should stay in Receive or Sleep during idle periods.
*
- * @param[in] aRxOnWhenBackoff TRUE to keep radio in Receive, FALSE to put to Sleep during CSMA backoff.
+ * @param[in] aRxOnWhenIdle TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods.
*
*/
- void SetRxOnWhenBackoff(bool aRxOnWhenBackoff) { mRxOnWhenBackoff = aRxOnWhenBackoff; }
+ void SetRxOnWhenIdle(bool aRxOnWhenIdle);
/**
* Enables the radio.
@@ -604,6 +604,7 @@ private:
bool RadioSupportsEnergyScan(void) const { return ((mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) != 0); }
bool RadioSupportsTransmitTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) != 0); }
bool RadioSupportsReceiveTiming(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RECEIVE_TIMING) != 0); }
+ bool RadioSupportsRxOnWhenIdle(void) const { return ((mRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0); }
bool ShouldHandleTransmitSecurity(void) const;
bool ShouldHandleCsmaBackOff(void) const;
@@ -611,6 +612,7 @@ private:
bool ShouldHandleRetries(void) const;
bool ShouldHandleEnergyScan(void) const;
bool ShouldHandleTransmitTargetTime(void) const;
+ bool ShouldHandleTransitionToSleep(void) const;
void ProcessTransmitSecurity(void);
void SignalFrameCounterUsed(uint32_t aFrameCounter, uint8_t aKeyId);
@@ -642,7 +644,7 @@ private:
uint8_t mTransmitRetries;
ShortAddress mShortAddress;
ExtAddress mExtAddress;
- bool mRxOnWhenBackoff : 1;
+ bool mRxOnWhenIdle : 1;
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
bool mRadioFilterEnabled : 1;
#endif
diff --git a/src/core/mac/sub_mac_callbacks.cpp b/src/core/mac/sub_mac_callbacks.cpp
index ba0269e0f..a6e761531 100644
--- a/src/core/mac/sub_mac_callbacks.cpp
+++ b/src/core/mac/sub_mac_callbacks.cpp
@@ -34,8 +34,8 @@
#include "sub_mac.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#include "mac/mac.hpp"
diff --git a/src/core/meshcop/announce_begin_client.cpp b/src/core/meshcop/announce_begin_client.cpp
index f0cde456f..5d3b9d9c5 100644
--- a/src/core/meshcop/announce_begin_client.cpp
+++ b/src/core/meshcop/announce_begin_client.cpp
@@ -38,9 +38,9 @@
#include "coap/coap_message.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp
index d38d78d8a..142c6060b 100644
--- a/src/core/meshcop/border_agent.cpp
+++ b/src/core/meshcop/border_agent.cpp
@@ -38,11 +38,11 @@
#include "coap/coap_message.hpp"
#include "common/as_core_type.hpp"
#include "common/heap.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/owned_ptr.hpp"
#include "common/settings.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
@@ -240,7 +240,7 @@ BorderAgent::BorderAgent(Instance &aInstance)
, mIdInitialized(false)
#endif
{
- mCommissionerAloc.InitAsThreadOriginRealmLocalScope();
+ mCommissionerAloc.InitAsThreadOriginMeshLocal();
}
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
@@ -334,7 +334,7 @@ template <> void BorderAgent::HandleTmf<kUriProxyTx>(Coap::Message &aMessage, co
SuccessOrExit(error = Tlv::Find<Ip6AddressTlv>(aMessage, messageInfo.GetPeerAddr()));
- SuccessOrExit(error = Get<Ip6::Udp>().SendDatagram(*message, messageInfo, Ip6::kProtoUdp));
+ SuccessOrExit(error = Get<Ip6::Udp>().SendDatagram(*message, messageInfo));
mUdpProxyPort = udpEncapHeader.GetSourcePort();
LogInfo("Proxy transmit sent to %s", messageInfo.GetPeerAddr().ToString().AsCString());
@@ -654,21 +654,6 @@ exit:
return;
}
-void BorderAgent::ApplyMeshLocalPrefix(void)
-{
- VerifyOrExit(mState == kStateActive);
-
- if (Get<ThreadNetif>().HasUnicastAddress(mCommissionerAloc))
- {
- Get<ThreadNetif>().RemoveUnicastAddress(mCommissionerAloc);
- mCommissionerAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(mCommissionerAloc);
- }
-
-exit:
- return;
-}
-
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
void BorderAgent::LogError(const char *aActionText, Error aError)
{
diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp
index dd96b450a..9f721d662 100644
--- a/src/core/meshcop/border_agent.hpp
+++ b/src/core/meshcop/border_agent.hpp
@@ -142,12 +142,6 @@ public:
State GetState(void) const { return mState; }
/**
- * Applies the Mesh Local Prefix.
- *
- */
- void ApplyMeshLocalPrefix(void);
-
- /**
* Returns the UDP Proxy port to which the commissioner is currently
* bound.
*
diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp
index 1bc30b042..3009a4742 100644
--- a/src/core/meshcop/commissioner.cpp
+++ b/src/core/meshcop/commissioner.cpp
@@ -41,9 +41,9 @@
#include "common/array.hpp"
#include "common/as_core_type.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "meshcop/joiner.hpp"
#include "meshcop/joiner_router.hpp"
#include "meshcop/meshcop.hpp"
@@ -74,12 +74,8 @@ Commissioner::Commissioner(Instance &aInstance)
{
memset(reinterpret_cast<void *>(mJoiners), 0, sizeof(mJoiners));
- mCommissionerAloc.Clear();
- mCommissionerAloc.mPrefixLength = 64;
- mCommissionerAloc.mPreferred = true;
- mCommissionerAloc.mValid = true;
- mCommissionerAloc.mScopeOverride = Ip6::Address::kRealmLocalScope;
- mCommissionerAloc.mScopeOverrideValid = true;
+ mCommissionerAloc.InitAsThreadOriginMeshLocal();
+ mCommissionerAloc.mPreferred = true;
IgnoreError(SetId("OpenThread Commissioner"));
@@ -353,21 +349,10 @@ exit:
Error Commissioner::SetId(const char *aId)
{
- Error error = kErrorNone;
- uint8_t len;
+ Error error = kErrorNone;
VerifyOrExit(IsDisabled(), error = kErrorInvalidState);
- VerifyOrExit(aId != nullptr);
- VerifyOrExit(IsValidUtf8String(aId), error = kErrorInvalidArgs);
-
- len = static_cast<uint8_t>(StringLength(aId, sizeof(mCommissionerId)));
-
- // CommissionerIdTlv::SetCommissionerId trims the string to the maximum array size.
- // Prevent this from happening returning an error.
- VerifyOrExit(len < CommissionerIdTlv::kMaxLength, error = kErrorInvalidArgs);
-
- memcpy(mCommissionerId, aId, len);
- mCommissionerId[len] = '\0';
+ error = StringCopy(mCommissionerId, aId, kStringCheckUtf8Encoding);
exit:
return error;
@@ -407,8 +392,8 @@ exit:
void Commissioner::SendCommissionerSet(void)
{
- Error error = kErrorNone;
- Dataset dataset;
+ Error error = kErrorNone;
+ CommissioningDataset dataset;
VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
@@ -586,26 +571,7 @@ void Commissioner::RemoveJoiner(Joiner &aJoiner, uint32_t aDelay)
Error Commissioner::SetProvisioningUrl(const char *aProvisioningUrl)
{
- Error error = kErrorNone;
- uint8_t len;
-
- if (aProvisioningUrl == nullptr)
- {
- mProvisioningUrl[0] = '\0';
- ExitNow();
- }
-
- VerifyOrExit(IsValidUtf8String(aProvisioningUrl), error = kErrorInvalidArgs);
-
- len = static_cast<uint8_t>(StringLength(aProvisioningUrl, sizeof(mProvisioningUrl)));
-
- VerifyOrExit(len < sizeof(mProvisioningUrl), error = kErrorInvalidArgs);
-
- memcpy(mProvisioningUrl, aProvisioningUrl, len);
- mProvisioningUrl[len] = '\0';
-
-exit:
- return error;
+ return StringCopy(mProvisioningUrl, aProvisioningUrl, kStringCheckUtf8Encoding);
}
void Commissioner::HandleTimer(void)
@@ -705,7 +671,9 @@ exit:
return;
}
-Error Commissioner::SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength)
+Error Commissioner::SendMgmtCommissionerSetRequest(const CommissioningDataset &aDataset,
+ const uint8_t *aTlvs,
+ uint8_t aLength)
{
Error error = kErrorNone;
Coap::Message *message;
@@ -783,20 +751,17 @@ exit:
Error Commissioner::SendPetition(void)
{
- Error error = kErrorNone;
- Coap::Message *message = nullptr;
- Tmf::MessageInfo messageInfo(GetInstance());
- CommissionerIdTlv commissionerIdTlv;
+ Error error = kErrorNone;
+ Coap::Message *message = nullptr;
+ Tmf::MessageInfo messageInfo(GetInstance());
mTransmitAttempts++;
message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(kUriLeaderPetition);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
- commissionerIdTlv.Init();
- commissionerIdTlv.SetCommissionerId(mCommissionerId);
+ SuccessOrExit(error = Tlv::Append<CommissionerIdTlv>(*message, mCommissionerId));
- SuccessOrExit(error = commissionerIdTlv.AppendTo(*message));
SuccessOrExit(error = messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
SuccessOrExit(
error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, Commissioner::HandleLeaderPetitionResponse, this));
@@ -1155,18 +1120,6 @@ exit:
return error;
}
-void Commissioner::ApplyMeshLocalPrefix(void)
-{
- VerifyOrExit(mState == kStateActive);
-
- Get<ThreadNetif>().RemoveUnicastAddress(mCommissionerAloc);
- mCommissionerAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(mCommissionerAloc);
-
-exit:
- return;
-}
-
// LCOV_EXCL_START
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp
index 74c910c9d..b62a8d269 100644
--- a/src/core/meshcop/commissioner.hpp
+++ b/src/core/meshcop/commissioner.hpp
@@ -97,134 +97,6 @@ public:
typedef otCommissionerJoinerCallback JoinerCallback; ///< Joiner state change callback function pointer type.
/**
- * Represents a Commissioning Dataset.
- *
- */
- class Dataset : public otCommissioningDataset, public Clearable<Dataset>
- {
- public:
- /**
- * Indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
- *
- * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
- *
- */
- bool IsLocatorSet(void) const { return mIsLocatorSet; }
-
- /**
- * Gets the Border Router RLOC16 Locator in the Dataset.
- *
- * MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
- *
- * @returns The Border Router RLOC16 Locator in the Dataset.
- *
- */
- uint16_t GetLocator(void) const { return mLocator; }
-
- /**
- * Sets the Border Router RLOCG16 Locator in the Dataset.
- *
- * @param[in] aLocator A Locator.
- *
- */
- void SetLocator(uint16_t aLocator)
- {
- mIsLocatorSet = true;
- mLocator = aLocator;
- }
-
- /**
- * Indicates whether or not the Session ID is set in the Dataset.
- *
- * @returns TRUE if Session ID is set, FALSE otherwise.
- *
- */
- bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
-
- /**
- * Gets the Session ID in the Dataset.
- *
- * MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
- *
- * @returns The Session ID in the Dataset.
- *
- */
- uint16_t GetSessionId(void) const { return mSessionId; }
-
- /**
- * Sets the Session ID in the Dataset.
- *
- * @param[in] aSessionId The Session ID.
- *
- */
- void SetSessionId(uint16_t aSessionId)
- {
- mIsSessionIdSet = true;
- mSessionId = aSessionId;
- }
-
- /**
- * Indicates whether or not the Steering Data is set in the Dataset.
- *
- * @returns TRUE if Steering Data is set, FALSE otherwise.
- *
- */
- bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
-
- /**
- * Gets the Steering Data in the Dataset.
- *
- * MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
- *
- * @returns The Steering Data in the Dataset.
- *
- */
- const SteeringData &GetSteeringData(void) const { return AsCoreType(&mSteeringData); }
-
- /**
- * Returns a reference to the Steering Data in the Dataset to be updated by caller.
- *
- * @returns A reference to the Steering Data in the Dataset.
- *
- */
- SteeringData &UpdateSteeringData(void)
- {
- mIsSteeringDataSet = true;
- return AsCoreType(&mSteeringData);
- }
-
- /**
- * Indicates whether or not the Joiner UDP port is set in the Dataset.
- *
- * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
- *
- */
- bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
-
- /**
- * Gets the Joiner UDP port in the Dataset.
- *
- * MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
- *
- * @returns The Joiner UDP port in the Dataset.
- *
- */
- uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
-
- /**
- * Sets the Joiner UDP Port in the Dataset.
- *
- * @param[in] aJoinerUdpPort The Joiner UDP Port.
- *
- */
- void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
- {
- mIsJoinerUdpPortSet = true;
- mJoinerUdpPort = aJoinerUdpPort;
- }
- };
-
- /**
* Initializes the Commissioner object.
*
* @param[in] aInstance A reference to the OpenThread instance.
@@ -460,7 +332,7 @@ public:
* @retval kErrorInvalidState Commissioner service is not started.
*
*/
- Error SendMgmtCommissionerSetRequest(const Dataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
+ Error SendMgmtCommissionerSetRequest(const CommissioningDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength);
/**
* Returns a reference to the AnnounceBeginClient instance.
@@ -486,12 +358,6 @@ public:
*/
PanIdQueryClient &GetPanIdQueryClient(void) { return mPanIdQuery; }
- /**
- * Applies the Mesh Local Prefix.
- *
- */
- void ApplyMeshLocalPrefix(void);
-
private:
static constexpr uint32_t kPetitionAttemptDelay = 5; // COMM_PET_ATTEMPT_DELAY (seconds)
static constexpr uint8_t kPetitionRetryCount = 2; // COMM_PET_RETRY_COUNT
@@ -622,8 +488,8 @@ private:
Ip6::Netif::UnicastAddress mCommissionerAloc;
- char mProvisioningUrl[OT_PROVISIONING_URL_MAX_SIZE + 1]; // + 1 is for null char at end of string.
- char mCommissionerId[CommissionerIdTlv::kMaxLength + 1];
+ ProvisioningUrlTlv::StringType mProvisioningUrl;
+ CommissionerIdTlv::StringType mCommissionerId;
State mState;
@@ -639,7 +505,6 @@ DeclareTmfHandler(Commissioner, kUriJoinerFinalize);
DefineMapEnum(otCommissionerState, MeshCoP::Commissioner::State);
DefineMapEnum(otCommissionerJoinerEvent, MeshCoP::Commissioner::JoinerEvent);
-DefineCoreType(otCommissioningDataset, MeshCoP::Commissioner::Dataset);
} // namespace ot
diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp
index 60aa0dae0..00c8d6d17 100644
--- a/src/core/meshcop/dataset.cpp
+++ b/src/core/meshcop/dataset.cpp
@@ -38,9 +38,9 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "meshcop/timestamp.hpp"
@@ -179,7 +179,7 @@ exit:
return rval;
}
-const Tlv *Dataset::GetTlv(Tlv::Type aType) const { return Tlv::FindTlv(mTlvs, mLength, aType); }
+const Tlv *Dataset::FindTlv(Tlv::Type aType) const { return As<Tlv>(Tlv::FindTlv(mTlvs, mLength, aType)); }
void Dataset::ConvertTo(Info &aDatasetInfo) const
{
@@ -190,7 +190,7 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
switch (cur->GetType())
{
case Tlv::kActiveTimestamp:
- aDatasetInfo.SetActiveTimestamp(As<ActiveTimestampTlv>(cur)->GetTimestamp());
+ aDatasetInfo.SetActiveTimestamp(cur->ReadValueAs<ActiveTimestampTlv>());
break;
case Tlv::kChannel:
@@ -210,19 +210,19 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
}
case Tlv::kDelayTimer:
- aDatasetInfo.SetDelay(As<DelayTimerTlv>(cur)->GetDelayTimer());
+ aDatasetInfo.SetDelay(cur->ReadValueAs<DelayTimerTlv>());
break;
case Tlv::kExtendedPanId:
- aDatasetInfo.SetExtendedPanId(As<ExtendedPanIdTlv>(cur)->GetExtendedPanId());
+ aDatasetInfo.SetExtendedPanId(cur->ReadValueAs<ExtendedPanIdTlv>());
break;
case Tlv::kMeshLocalPrefix:
- aDatasetInfo.SetMeshLocalPrefix(As<MeshLocalPrefixTlv>(cur)->GetMeshLocalPrefix());
+ aDatasetInfo.SetMeshLocalPrefix(cur->ReadValueAs<MeshLocalPrefixTlv>());
break;
case Tlv::kNetworkKey:
- aDatasetInfo.SetNetworkKey(As<NetworkKeyTlv>(cur)->GetNetworkKey());
+ aDatasetInfo.SetNetworkKey(cur->ReadValueAs<NetworkKeyTlv>());
break;
case Tlv::kNetworkName:
@@ -230,15 +230,15 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
break;
case Tlv::kPanId:
- aDatasetInfo.SetPanId(As<PanIdTlv>(cur)->GetPanId());
+ aDatasetInfo.SetPanId(cur->ReadValueAs<PanIdTlv>());
break;
case Tlv::kPendingTimestamp:
- aDatasetInfo.SetPendingTimestamp(As<PendingTimestampTlv>(cur)->GetTimestamp());
+ aDatasetInfo.SetPendingTimestamp(cur->ReadValueAs<PendingTimestampTlv>());
break;
case Tlv::kPskc:
- aDatasetInfo.SetPskc(As<PskcTlv>(cur)->GetPskc());
+ aDatasetInfo.SetPskc(cur->ReadValueAs<PskcTlv>());
break;
case Tlv::kSecurityPolicy:
@@ -286,7 +286,7 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
Timestamp activeTimestamp;
aDatasetInfo.GetActiveTimestamp(activeTimestamp);
- IgnoreError(SetTlv(Tlv::kActiveTimestamp, activeTimestamp));
+ IgnoreError(Write<ActiveTimestampTlv>(activeTimestamp));
}
if (aDatasetInfo.IsPendingTimestampPresent())
@@ -294,12 +294,12 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
Timestamp pendingTimestamp;
aDatasetInfo.GetPendingTimestamp(pendingTimestamp);
- IgnoreError(SetTlv(Tlv::kPendingTimestamp, pendingTimestamp));
+ IgnoreError(Write<PendingTimestampTlv>(pendingTimestamp));
}
if (aDatasetInfo.IsDelayPresent())
{
- IgnoreError(SetTlv(Tlv::kDelayTimer, aDatasetInfo.GetDelay()));
+ IgnoreError(Write<DelayTimerTlv>(aDatasetInfo.GetDelay()));
}
if (aDatasetInfo.IsChannelPresent())
@@ -307,7 +307,7 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
ChannelTlv tlv;
tlv.Init();
tlv.SetChannel(aDatasetInfo.GetChannel());
- IgnoreError(SetTlv(tlv));
+ IgnoreError(WriteTlv(tlv));
}
if (aDatasetInfo.IsChannelMaskPresent())
@@ -315,39 +315,39 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
ChannelMaskTlv tlv;
tlv.Init();
tlv.SetChannelMask(aDatasetInfo.GetChannelMask());
- IgnoreError(SetTlv(tlv));
+ IgnoreError(WriteTlv(tlv));
}
if (aDatasetInfo.IsExtendedPanIdPresent())
{
- IgnoreError(SetTlv(Tlv::kExtendedPanId, aDatasetInfo.GetExtendedPanId()));
+ IgnoreError(Write<ExtendedPanIdTlv>(aDatasetInfo.GetExtendedPanId()));
}
if (aDatasetInfo.IsMeshLocalPrefixPresent())
{
- IgnoreError(SetTlv(Tlv::kMeshLocalPrefix, aDatasetInfo.GetMeshLocalPrefix()));
+ IgnoreError(Write<MeshLocalPrefixTlv>(aDatasetInfo.GetMeshLocalPrefix()));
}
if (aDatasetInfo.IsNetworkKeyPresent())
{
- IgnoreError(SetTlv(Tlv::kNetworkKey, aDatasetInfo.GetNetworkKey()));
+ IgnoreError(Write<NetworkKeyTlv>(aDatasetInfo.GetNetworkKey()));
}
if (aDatasetInfo.IsNetworkNamePresent())
{
NameData nameData = aDatasetInfo.GetNetworkName().GetAsData();
- IgnoreError(SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
+ IgnoreError(WriteTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
}
if (aDatasetInfo.IsPanIdPresent())
{
- IgnoreError(SetTlv(Tlv::kPanId, aDatasetInfo.GetPanId()));
+ IgnoreError(Write<PanIdTlv>(aDatasetInfo.GetPanId()));
}
if (aDatasetInfo.IsPskcPresent())
{
- IgnoreError(SetTlv(Tlv::kPskc, aDatasetInfo.GetPskc()));
+ IgnoreError(Write<PskcTlv>(aDatasetInfo.GetPskc()));
}
if (aDatasetInfo.IsSecurityPolicyPresent())
@@ -356,7 +356,7 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
tlv.Init();
tlv.SetSecurityPolicy(aDatasetInfo.GetSecurityPolicy());
- IgnoreError(SetTlv(tlv));
+ IgnoreError(WriteTlv(tlv));
}
mUpdateTime = TimerMilli::GetNow();
@@ -366,21 +366,20 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
Error Dataset::GetTimestamp(Type aType, Timestamp &aTimestamp) const
{
- Error error = kErrorNone;
+ Error error = kErrorNone;
+ const Tlv *tlv;
if (aType == kActive)
{
- const ActiveTimestampTlv *tlv = GetTlv<ActiveTimestampTlv>();
-
+ tlv = FindTlv(Tlv::kActiveTimestamp);
VerifyOrExit(tlv != nullptr, error = kErrorNotFound);
- aTimestamp = tlv->GetTimestamp();
+ aTimestamp = tlv->ReadValueAs<ActiveTimestampTlv>();
}
else
{
- const PendingTimestampTlv *tlv = GetTlv<PendingTimestampTlv>();
-
+ tlv = FindTlv(Tlv::kPendingTimestamp);
VerifyOrExit(tlv != nullptr, error = kErrorNotFound);
- aTimestamp = tlv->GetTimestamp();
+ aTimestamp = tlv->ReadValueAs<PendingTimestampTlv>();
}
exit:
@@ -389,35 +388,38 @@ exit:
void Dataset::SetTimestamp(Type aType, const Timestamp &aTimestamp)
{
- IgnoreError(SetTlv((aType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp, aTimestamp));
+ if (aType == kActive)
+ {
+ IgnoreError(Write<ActiveTimestampTlv>(aTimestamp));
+ }
+ else
+ {
+ IgnoreError(Write<PendingTimestampTlv>(aTimestamp));
+ }
}
-Error Dataset::SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength)
+Error Dataset::WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength)
{
Error error = kErrorNone;
uint16_t bytesAvailable = sizeof(mTlvs) - mLength;
- Tlv *old = GetTlv(aType);
- Tlv tlv;
+ Tlv *oldTlv = FindTlv(aType);
+ Tlv *newTlv;
- if (old != nullptr)
+ if (oldTlv != nullptr)
{
- bytesAvailable += sizeof(Tlv) + old->GetLength();
+ bytesAvailable += sizeof(Tlv) + oldTlv->GetLength();
}
VerifyOrExit(sizeof(Tlv) + aLength <= bytesAvailable, error = kErrorNoBufs);
- if (old != nullptr)
- {
- RemoveTlv(old);
- }
+ RemoveTlv(oldTlv);
- tlv.SetType(aType);
- tlv.SetLength(aLength);
- memcpy(mTlvs + mLength, &tlv, sizeof(Tlv));
- mLength += sizeof(Tlv);
+ newTlv = GetTlvsEnd();
+ mLength += sizeof(Tlv) + aLength;
- memcpy(mTlvs + mLength, aValue, aLength);
- mLength += aLength;
+ newTlv->SetType(aType);
+ newTlv->SetLength(aLength);
+ memcpy(newTlv->GetValue(), aValue, aLength);
mUpdateTime = TimerMilli::GetNow();
@@ -425,7 +427,7 @@ exit:
return error;
}
-Error Dataset::SetTlv(const Tlv &aTlv) { return SetTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength()); }
+Error Dataset::WriteTlv(const Tlv &aTlv) { return WriteTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength()); }
Error Dataset::ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
{
@@ -445,16 +447,7 @@ exit:
return error;
}
-void Dataset::RemoveTlv(Tlv::Type aType)
-{
- Tlv *tlv;
-
- VerifyOrExit((tlv = GetTlv(aType)) != nullptr);
- RemoveTlv(tlv);
-
-exit:
- return;
-}
+void Dataset::RemoveTlv(Tlv::Type aType) { RemoveTlv(FindTlv(aType)); }
Error Dataset::AppendMleDatasetTlv(Type aType, Message &aMessage) const
{
@@ -479,19 +472,19 @@ Error Dataset::AppendMleDatasetTlv(Type aType, Message &aMessage) const
}
else if (cur->GetType() == Tlv::kDelayTimer)
{
- uint32_t elapsed = TimerMilli::GetNow() - mUpdateTime;
- DelayTimerTlv delayTimer = *As<DelayTimerTlv>(cur);
+ uint32_t elapsed = TimerMilli::GetNow() - mUpdateTime;
+ uint32_t delayTimer = cur->ReadValueAs<DelayTimerTlv>();
- if (delayTimer.GetDelayTimer() > elapsed)
+ if (delayTimer > elapsed)
{
- delayTimer.SetDelayTimer(delayTimer.GetDelayTimer() - elapsed);
+ delayTimer -= elapsed;
}
else
{
- delayTimer.SetDelayTimer(0);
+ delayTimer = 0;
}
- SuccessOrExit(error = delayTimer.AppendTo(aMessage));
+ SuccessOrExit(error = Tlv::Append<DelayTimerTlv>(aMessage, delayTimer));
}
else
{
@@ -505,11 +498,14 @@ exit:
void Dataset::RemoveTlv(Tlv *aTlv)
{
- uint8_t *start = reinterpret_cast<uint8_t *>(aTlv);
- uint16_t length = sizeof(Tlv) + aTlv->GetLength();
+ if (aTlv != nullptr)
+ {
+ uint8_t *start = reinterpret_cast<uint8_t *>(aTlv);
+ uint16_t length = sizeof(Tlv) + aTlv->GetLength();
- memmove(start, start + length, mLength - (static_cast<uint8_t>(start - mTlvs) + length));
- mLength -= length;
+ memmove(start, start + length, mLength - (static_cast<uint8_t>(start - mTlvs) + length));
+ mLength -= length;
+ }
}
Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdated) const
@@ -545,11 +541,11 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdate
}
case Tlv::kPanId:
- mac.SetPanId(As<PanIdTlv>(cur)->GetPanId());
+ mac.SetPanId(cur->ReadValueAs<PanIdTlv>());
break;
case Tlv::kExtendedPanId:
- aInstance.Get<ExtendedPanIdManager>().SetExtPanId(As<ExtendedPanIdTlv>(cur)->GetExtendedPanId());
+ aInstance.Get<ExtendedPanIdManager>().SetExtPanId(cur->ReadValueAs<ExtendedPanIdTlv>());
break;
case Tlv::kNetworkName:
@@ -558,30 +554,29 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsNetworkKeyUpdate
case Tlv::kNetworkKey:
{
- const NetworkKeyTlv *key = As<NetworkKeyTlv>(cur);
- NetworkKey networkKey;
+ NetworkKey networkKey;
keyManager.GetNetworkKey(networkKey);
- if (aIsNetworkKeyUpdated && (key->GetNetworkKey() != networkKey))
+ if (aIsNetworkKeyUpdated && (cur->ReadValueAs<NetworkKeyTlv>() != networkKey))
{
*aIsNetworkKeyUpdated = true;
}
- keyManager.SetNetworkKey(key->GetNetworkKey());
+ keyManager.SetNetworkKey(cur->ReadValueAs<NetworkKeyTlv>());
break;
}
#if OPENTHREAD_FTD
case Tlv::kPskc:
- keyManager.SetPskc(As<PskcTlv>(cur)->GetPskc());
+ keyManager.SetPskc(cur->ReadValueAs<PskcTlv>());
break;
#endif
case Tlv::kMeshLocalPrefix:
- aInstance.Get<Mle::MleRouter>().SetMeshLocalPrefix(As<MeshLocalPrefixTlv>(cur)->GetMeshLocalPrefix());
+ aInstance.Get<Mle::MleRouter>().SetMeshLocalPrefix(cur->ReadValueAs<MeshLocalPrefixTlv>());
break;
case Tlv::kSecurityPolicy:
@@ -605,5 +600,45 @@ void Dataset::ConvertToActive(void)
const char *Dataset::TypeToString(Type aType) { return (aType == kActive) ? "Active" : "Pending"; }
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
+void Dataset::SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef)
+{
+ using namespace ot::Crypto::Storage;
+
+ Tlv *tlv = FindTlv(aTlvType);
+
+ VerifyOrExit(tlv != nullptr);
+ VerifyOrExit(tlv->GetLength() > 0);
+
+ SuccessOrAssert(ImportKey(aKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent, tlv->GetValue(),
+ tlv->GetLength()));
+
+ memset(tlv->GetValue(), 0, tlv->GetLength());
+
+exit:
+ return;
+}
+
+Error Dataset::ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef)
+{
+ using namespace ot::Crypto::Storage;
+
+ Error error = kErrorNone;
+ Tlv *tlv = FindTlv(aTlvType);
+ size_t readLength;
+
+ VerifyOrExit(tlv != nullptr);
+ VerifyOrExit(tlv->GetLength() > 0);
+
+ SuccessOrExit(error = ExportKey(aKeyRef, tlv->GetValue(), tlv->GetLength(), readLength));
+ VerifyOrExit(readLength == tlv->GetLength(), error = OT_ERROR_FAILED);
+
+exit:
+ return error;
+}
+
+#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
} // namespace MeshCoP
} // namespace ot
diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp
index 50ecb2c62..131a271a2 100644
--- a/src/core/meshcop/dataset.hpp
+++ b/src/core/meshcop/dataset.hpp
@@ -623,48 +623,127 @@ public:
bool IsValid(void) const;
/**
- * Returns a pointer to the TLV with a given type.
+ * Indicates whether or not a given TLV type is present in the Dataset.
*
- * @param[in] aType A TLV type.
+ * @param[in] aType The TLV type to check.
*
- * @returns A pointer to the TLV or `nullptr` if none is found.
+ * @retval TRUE TLV with @p aType is present in the Dataset.
+ * @retval FALSE TLV with @p aType is not present in the Dataset.
*
*/
- Tlv *GetTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->GetTlv(aType)); }
+ bool ContainsTlv(Tlv::Type aType) const { return (FindTlv(aType) != nullptr); }
/**
- * Returns a pointer to the TLV with a given type.
+ * Indicates whether or not a given TLV type is present in the Dataset.
*
- * @param[in] aType The TLV type.
+ * @tparam aTlvType The TLV type to check.
*
- * @returns A pointer to the TLV or `nullptr` if none is found.
+ * @retval TRUE TLV of @p aTlvType is present in the Dataset.
+ * @retval FALSE TLV of @p aTlvType is not present in the Dataset.
*
*/
- const Tlv *GetTlv(Tlv::Type aType) const;
+ template <typename TlvType> bool Contains(void) const
+ {
+ return ContainsTlv(static_cast<Tlv::Type>(TlvType::kType));
+ }
+
+ /**
+ * Searches for a given TLV type in the Dataset.
+ *
+ * @param[in] aType The TLV type to find.
+ *
+ * @returns A pointer to the TLV or `nullptr` if not found.
+ *
+ */
+ Tlv *FindTlv(Tlv::Type aType) { return AsNonConst(AsConst(this)->FindTlv(aType)); }
+
+ /**
+ * Searches for a given TLV type in the Dataset.
+ *
+ * @param[in] aType The TLV type to find.
+ *
+ * @returns A pointer to the TLV or `nullptr` if not found.
+ *
+ */
+ const Tlv *FindTlv(Tlv::Type aType) const;
+
+ /**
+ * Writes a TLV to the Dataset.
+ *
+ * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
+ *
+ * @param[in] aTlv A reference to the TLV.
+ *
+ * @retval kErrorNone Successfully updated the TLV.
+ * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
+ *
+ */
+ Error WriteTlv(const Tlv &aTlv);
+
+ /**
+ * Writes a TLV in the Dataset.
+ *
+ * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
+ *
+ * @param[in] aType The TLV type.
+ * @param[in] aValue A pointer to a buffer containing the TLV value.
+ * @param[in] aLength The TLV length.
+ *
+ * @retval kErrorNone Successfully updated the TLV.
+ * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
+ *
+ */
+ Error WriteTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
/**
- * Returns a pointer to the TLV with a given template type `TlvType`
+ * Writes a simple TLV in the Dataset.
+ *
+ * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
+ *
+ * @tparam SimpleTlvType The simple TLV type (must be a sub-class of `SimpleTlvInfo`).
*
- * @returns A pointer to the TLV or `nullptr` if none is found.
+ * @param[in] aValue The TLV value.
+ *
+ * @retval kErrorNone Successfully updated the TLV.
+ * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
*
*/
- template <typename TlvType> TlvType *GetTlv(void)
+ template <typename SimpleTlvType> Error Write(const typename SimpleTlvType::ValueType &aValue)
{
- return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
+ return WriteTlv(static_cast<Tlv::Type>(SimpleTlvType::kType), &aValue, sizeof(aValue));
}
/**
- * Returns a pointer to the TLV with a given template type `TlvType`
+ * Writes a `uint` TLV in the Dataset.
+ *
+ * If the specified TLV type already exists, it will be replaced. Otherwise, the TLV will be appended.
+ *
+ * @tparam UintTlvType The integer simple TLV type (must be a sub-class of `UintTlvInfo`).
*
- * @returns A pointer to the TLV or `nullptr` if none is found.
+ * @param[in] aValue The TLV value.
+ *
+ * @retval kErrorNone Successfully updated the TLV.
+ * @retval kErrorNoBufs Could not add the TLV due to insufficient buffer space.
*
*/
- template <typename TlvType> const TlvType *GetTlv(void) const
+ template <typename UintTlvType> Error Write(typename UintTlvType::UintValueType aValue)
{
- return As<TlvType>(GetTlv(static_cast<Tlv::Type>(TlvType::kType)));
+ typename UintTlvType::UintValueType value = BigEndian::HostSwap(aValue);
+
+ return WriteTlv(static_cast<Tlv::Type>(UintTlvType::kType), &value, sizeof(value));
}
/**
+ * Removes a TLV from the Dataset.
+ *
+ * If the Dataset does not contain the given TLV type, no action is performed.
+ *
+ * @param[in] aType The TLV type to remove.
+ *
+ */
+ void RemoveTlv(Tlv::Type aType);
+
+ /**
* Returns a pointer to the byte representation of the Dataset.
*
* @returns A pointer to the byte representation of the Dataset.
@@ -742,49 +821,6 @@ public:
void SetTimestamp(Type aType, const Timestamp &aTimestamp);
/**
- * Sets a TLV in the Dataset.
- *
- * @param[in] aTlv A reference to the TLV.
- *
- * @retval kErrorNone Successfully set the TLV.
- * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
- *
- */
- Error SetTlv(const Tlv &aTlv);
-
- /**
- * Sets a TLV with a given TLV Type and Value.
- *
- * @param[in] aType The TLV Type.
- * @param[in] aValue A pointer to TLV Value.
- * @param[in] aLength The TLV Length in bytes (length of @p aValue).
- *
- * @retval kErrorNone Successfully set the TLV.
- * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
- *
- */
- Error SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength);
-
- /**
- * Sets a TLV with a given TLV Type and Value.
- *
- * @tparam ValueType The type of TLV's Value.
- *
- * @param[in] aType The TLV Type.
- * @param[in] aValue The TLV Value (of type `ValueType`).
- *
- * @retval kErrorNone Successfully set the TLV.
- * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
- *
- */
- template <typename ValueType> Error SetTlv(Tlv::Type aType, const ValueType &aValue)
- {
- static_assert(!TypeTraits::IsPointer<ValueType>::kValue, "ValueType must not be a pointer");
-
- return SetTlv(aType, &aValue, sizeof(ValueType));
- }
-
- /**
* Reads the Dataset from a given message and checks that it is well-formed and valid.
*
* @param[in] aMessage The message to read from.
@@ -829,14 +865,6 @@ public:
void SetFrom(const otOperationalDatasetTlvs &aDataset);
/**
- * Removes a TLV from the Dataset.
- *
- * @param[in] aType The type of a specific TLV.
- *
- */
- void RemoveTlv(Tlv::Type aType);
-
- /**
* Appends the MLE Dataset TLV but excluding MeshCoP Sub Timestamp TLV.
*
* @param[in] aType The type of the dataset, active or pending.
@@ -912,6 +940,35 @@ public:
*/
static const char *TypeToString(Type aType);
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
+ /**
+ * Saves a given TLV value in secure storage and clears the TLV value by setting all value bytes to zero.
+ *
+ * If the Dataset does not contain the @p aTlvType, no action is performed.
+ *
+ * @param[in] aTlvType The TLV type.
+ * @param[in] aKeyRef The `KeyRef` to use with secure storage.
+ *
+ */
+ void SaveTlvInSecureStorageAndClearValue(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
+
+ /**
+ * Reads and updates a given TLV value in Dataset from secure storage.
+ *
+ * If the Dataset does not contain the @p aTlvType, no action is performed and `kErrorNone` is returned.
+ *
+ * @param[in] aTlvType The TLV type.
+ * @param[in] aKeyRef The `KeyRef` to use with secure storage.
+ *
+ * @retval kErrorNone Successfully read the TLV value from secure storage and updated the Dataset.
+ * @retval KErrorFailed Could not read the @aKeyRef from secure storage.
+ *
+ */
+ Error ReadTlvFromSecureStorage(Tlv::Type aTlvType, Crypto::Storage::KeyRef aKeyRef);
+
+#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
private:
void RemoveTlv(Tlv *aTlv);
@@ -920,40 +977,6 @@ private:
uint16_t mLength; ///< The number of valid bytes in @var mTlvs
};
-/**
- * This is a template specialization of `SetTlv<ValueType>` with a `uint16_t` value type.
- *
- * @param[in] aType The TLV Type.
- * @param[in] aValue The TLV value (as `uint16_t`).
- *
- * @retval kErrorNone Successfully set the TLV.
- * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
- *
- */
-template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint16_t &aValue)
-{
- uint16_t value = Encoding::BigEndian::HostSwap16(aValue);
-
- return SetTlv(aType, &value, sizeof(uint16_t));
-}
-
-/**
- * This is a template specialization of `SetTlv<ValueType>` with a `uint32_t` value type
- *
- * @param[in] aType The TLV Type.
- * @param[in] aValue The TLV value (as `uint32_t`).
- *
- * @retval kErrorNone Successfully set the TLV.
- * @retval kErrorNoBufs Could not set the TLV due to insufficient buffer space.
- *
- */
-template <> inline Error Dataset::SetTlv(Tlv::Type aType, const uint32_t &aValue)
-{
- uint32_t value = Encoding::BigEndian::HostSwap32(aValue);
-
- return SetTlv(aType, &value, sizeof(uint32_t));
-}
-
} // namespace MeshCoP
DefineCoreType(otOperationalDatasetComponents, MeshCoP::Dataset::Components);
diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp
index 58370c3fb..4c971c7bb 100644
--- a/src/core/meshcop/dataset_local.cpp
+++ b/src/core/meshcop/dataset_local.cpp
@@ -37,11 +37,11 @@
#include <stdio.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/settings.hpp"
#include "crypto/storage.hpp"
+#include "instance/instance.hpp"
#include "meshcop/dataset.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/mle_tlvs.hpp"
@@ -90,9 +90,7 @@ exit:
Error DatasetLocal::Read(Dataset &aDataset) const
{
- DelayTimerTlv *delayTimer;
- uint32_t elapsed;
- Error error;
+ Error error;
error = Get<Settings>().ReadOperationalDataset(mType, aDataset);
VerifyOrExit(error == kErrorNone, aDataset.mLength = 0);
@@ -108,19 +106,25 @@ Error DatasetLocal::Read(Dataset &aDataset) const
}
else
{
- delayTimer = aDataset.GetTlv<DelayTimerTlv>();
- VerifyOrExit(delayTimer);
+ uint32_t elapsed;
+ uint32_t delayTimer;
+ Tlv *tlv = aDataset.FindTlv(Tlv::kDelayTimer);
+
+ VerifyOrExit(tlv != nullptr);
- elapsed = TimerMilli::GetNow() - mUpdateTime;
+ elapsed = TimerMilli::GetNow() - mUpdateTime;
+ delayTimer = tlv->ReadValueAs<DelayTimerTlv>();
- if (delayTimer->GetDelayTimer() > elapsed)
+ if (delayTimer > elapsed)
{
- delayTimer->SetDelayTimer(delayTimer->GetDelayTimer() - elapsed);
+ delayTimer -= elapsed;
}
else
{
- delayTimer->SetDelayTimer(0);
+ delayTimer = 0;
}
+
+ tlv->WriteValueAs<DelayTimerTlv>(delayTimer);
}
aDataset.mUpdateTime = TimerMilli::GetNow();
@@ -218,112 +222,64 @@ exit:
}
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-void DatasetLocal::DestroySecurelyStoredKeys(void) const
-{
- using namespace Crypto::Storage;
- KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
- KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
-
- // Destroy securely stored keys associated with the given operational dataset type.
- DestroyKey(networkKeyRef);
- DestroyKey(pskcRef);
-}
+const DatasetLocal::SecurelyStoredTlv DatasetLocal::kSecurelyStoredTlvs[] = {
+ {
+ Tlv::kNetworkKey,
+ Crypto::Storage::kActiveDatasetNetworkKeyRef,
+ Crypto::Storage::kPendingDatasetNetworkKeyRef,
+ },
+ {
+ Tlv::kPskc,
+ Crypto::Storage::kActiveDatasetPskcRef,
+ Crypto::Storage::kPendingDatasetPskcRef,
+ },
+};
-void DatasetLocal::MoveKeysToSecureStorage(Dataset &aDataset) const
+void DatasetLocal::DestroySecurelyStoredKeys(void) const
{
- using namespace Crypto::Storage;
-
- KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
- KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
- NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv<NetworkKeyTlv>();
- PskcTlv *pskcTlv = aDataset.GetTlv<PskcTlv>();
-
- if (networkKeyTlv != nullptr)
+ for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
- // If the dataset contains a network key, put it in the secure storage
- // and zero the corresponding TLV element.
- NetworkKey networkKey;
- SuccessOrAssert(ImportKey(networkKeyRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent,
- networkKeyTlv->GetNetworkKey().m8, NetworkKey::kSize));
- networkKey.Clear();
- networkKeyTlv->SetNetworkKey(networkKey);
+ Crypto::Storage::DestroyKey(entry.GetKeyRef(mType));
}
+}
- if (pskcTlv != nullptr)
+void DatasetLocal::MoveKeysToSecureStorage(Dataset &aDataset) const
+{
+ for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
- // If the dataset contains a PSKC, put it in the secure storage and zero
- // the corresponding TLV element.
- Pskc pskc;
- SuccessOrAssert(ImportKey(pskcRef, kKeyTypeRaw, kKeyAlgorithmVendor, kUsageExport, kTypePersistent,
- pskcTlv->GetPskc().m8, Pskc::kSize));
- pskc.Clear();
- pskcTlv->SetPskc(pskc);
+ aDataset.SaveTlvInSecureStorageAndClearValue(entry.mTlvType, entry.GetKeyRef(mType));
}
}
void DatasetLocal::EmplaceSecurelyStoredKeys(Dataset &aDataset) const
{
- using namespace Crypto::Storage;
+ bool moveKeys = false;
- KeyRef networkKeyRef = IsActive() ? kActiveDatasetNetworkKeyRef : kPendingDatasetNetworkKeyRef;
- KeyRef pskcRef = IsActive() ? kActiveDatasetPskcRef : kPendingDatasetPskcRef;
- NetworkKeyTlv *networkKeyTlv = aDataset.GetTlv<NetworkKeyTlv>();
- PskcTlv *pskcTlv = aDataset.GetTlv<PskcTlv>();
- bool moveKeys = false;
- size_t keyLen;
- Error error;
+ // If reading any of the TLVs fails, it indicates they are not yet
+ // stored in secure storage and are still contained in the `Dataset`
+ // read from `Settings`. In this case, we move the keys to secure
+ // storage and then clear them from 'Settings'.
- if (networkKeyTlv != nullptr)
+ for (const SecurelyStoredTlv &entry : kSecurelyStoredTlvs)
{
- // If the dataset contains a network key, its real value must have been moved to
- // the secure storage upon saving the dataset, so restore it back now.
- NetworkKey networkKey;
- error = ExportKey(networkKeyRef, networkKey.m8, NetworkKey::kSize, keyLen);
-
- if (error != kErrorNone)
+ if (aDataset.ReadTlvFromSecureStorage(entry.mTlvType, entry.GetKeyRef(mType)) != kErrorNone)
{
- // If ExportKey fails, key is not in secure storage and is stored in settings
moveKeys = true;
}
- else
- {
- OT_ASSERT(keyLen == NetworkKey::kSize);
- networkKeyTlv->SetNetworkKey(networkKey);
- }
- }
-
- if (pskcTlv != nullptr)
- {
- // If the dataset contains a PSKC, its real value must have been moved to
- // the secure storage upon saving the dataset, so restore it back now.
- Pskc pskc;
- error = ExportKey(pskcRef, pskc.m8, Pskc::kSize, keyLen);
-
- if (error != kErrorNone)
- {
- // If ExportKey fails, key is not in secure storage and is stored in settings
- moveKeys = true;
- }
- else
- {
- OT_ASSERT(keyLen == Pskc::kSize);
- pskcTlv->SetPskc(pskc);
- }
}
if (moveKeys)
{
- // Clear the networkkey and Pskc stored in the settings and move them to secure storage.
- // Store the network key and PSKC in the secure storage instead of settings.
Dataset dataset;
dataset.Set(GetType(), aDataset);
MoveKeysToSecureStorage(dataset);
- SuccessOrAssert(error = Get<Settings>().SaveOperationalDataset(mType, dataset));
+ SuccessOrAssert(Get<Settings>().SaveOperationalDataset(mType, dataset));
}
}
-#endif
+
+#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
} // namespace MeshCoP
} // namespace ot
diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp
index 2981b7c02..249f069d5 100644
--- a/src/core/meshcop/dataset_local.hpp
+++ b/src/core/meshcop/dataset_local.hpp
@@ -184,14 +184,29 @@ public:
Error Save(const Dataset &aDataset);
private:
- bool IsActive(void) const { return (mType == Dataset::kActive); }
- void SetTimestamp(const Dataset &aDataset);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+ struct SecurelyStoredTlv
+ {
+ Crypto::Storage::KeyRef GetKeyRef(Dataset::Type aType) const
+ {
+ return (aType == Dataset::kActive) ? mActiveKeyRef : mPendingKeyRef;
+ }
+
+ Tlv::Type mTlvType;
+ Crypto::Storage::KeyRef mActiveKeyRef;
+ Crypto::Storage::KeyRef mPendingKeyRef;
+ };
+
+ static const SecurelyStoredTlv kSecurelyStoredTlvs[];
+
void MoveKeysToSecureStorage(Dataset &aDataset) const;
void DestroySecurelyStoredKeys(void) const;
void EmplaceSecurelyStoredKeys(Dataset &aDataset) const;
#endif
+ bool IsActive(void) const { return (mType == Dataset::kActive); }
+ void SetTimestamp(const Dataset &aDataset);
+
Timestamp mTimestamp; ///< Active or Pending Timestamp
TimeMilli mUpdateTime; ///< Local time last updated
Dataset::Type mType; ///< Active or Pending
diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp
index e236fcc57..bc316980e 100644
--- a/src/core/meshcop/dataset_manager.cpp
+++ b/src/core/meshcop/dataset_manager.cpp
@@ -37,10 +37,10 @@
#include <stdio.h>
#include "common/as_core_type.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/notifier.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "radio/radio.hpp"
@@ -226,7 +226,7 @@ Error DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
SuccessOrExit(error = Read(dataset));
- channelMaskTlv = dataset.GetTlv<ChannelMaskTlv>();
+ channelMaskTlv = As<ChannelMaskTlv>(dataset.FindTlv(Tlv::kChannelMask));
VerifyOrExit(channelMaskTlv != nullptr, error = kErrorNotFound);
VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0);
@@ -418,7 +418,7 @@ void DatasetManager::SendGetResponse(const Coap::Message &aRequest,
continue;
}
- if ((tlv = dataset.GetTlv(static_cast<Tlv::Type>(aTlvs[index]))) != nullptr)
+ if ((tlv = dataset.FindTlv(static_cast<Tlv::Type>(aTlvs[index]))) != nullptr)
{
SuccessOrExit(error = tlv->AppendTo(*message));
}
@@ -738,41 +738,42 @@ exit:
void PendingDatasetManager::StartDelayTimer(void)
{
- DelayTimerTlv *delayTimer;
- Dataset dataset;
+ Tlv *tlv;
+ uint32_t delay;
+ Dataset dataset;
IgnoreError(Read(dataset));
mDelayTimer.Stop();
- if ((delayTimer = dataset.GetTlv<DelayTimerTlv>()) != nullptr)
- {
- uint32_t delay = delayTimer->GetDelayTimer();
+ tlv = dataset.FindTlv(Tlv::kDelayTimer);
+ VerifyOrExit(tlv != nullptr);
- // the Timer implementation does not support the full 32 bit range
- if (delay > Timer::kMaxDelay)
- {
- delay = Timer::kMaxDelay;
- }
+ delay = tlv->ReadValueAs<DelayTimerTlv>();
- mDelayTimer.StartAt(dataset.GetUpdateTime(), delay);
- LogInfo("delay timer started %lu", ToUlong(delay));
- }
+ // the Timer implementation does not support the full 32 bit range
+ delay = Min(delay, Timer::kMaxDelay);
+
+ mDelayTimer.StartAt(dataset.GetUpdateTime(), delay);
+ LogInfo("delay timer started %lu", ToUlong(delay));
+
+exit:
+ return;
}
void PendingDatasetManager::HandleDelayTimer(void)
{
- DelayTimerTlv *delayTimer;
- Dataset dataset;
+ Tlv *tlv;
+ Dataset dataset;
IgnoreError(Read(dataset));
// if the Delay Timer value is larger than what our Timer implementation can handle, we have to compute
// the remainder and wait some more.
- if ((delayTimer = dataset.GetTlv<DelayTimerTlv>()) != nullptr)
+ if ((tlv = dataset.FindTlv(Tlv::kDelayTimer)) != nullptr)
{
uint32_t elapsed = mDelayTimer.GetFireTime() - dataset.GetUpdateTime();
- uint32_t delay = delayTimer->GetDelayTimer();
+ uint32_t delay = tlv->ReadValueAs<DelayTimerTlv>();
if (elapsed < delay)
{
diff --git a/src/core/meshcop/dataset_manager.hpp b/src/core/meshcop/dataset_manager.hpp
index 6637f002c..36162a315 100644
--- a/src/core/meshcop/dataset_manager.hpp
+++ b/src/core/meshcop/dataset_manager.hpp
@@ -183,6 +183,12 @@ public:
protected:
/**
+ * Default Delay Timer value for a Pending Operational Dataset (ms)
+ *
+ */
+ static constexpr uint32_t kDefaultDelayTimer = OPENTHREAD_CONFIG_TMF_PENDING_DATASET_DEFAULT_DELAY;
+
+ /**
* Defines a generic Dataset TLV to read from a message.
*
*/
diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp
index 0fe978d30..3eec1a8b6 100644
--- a/src/core/meshcop/dataset_manager_ftd.cpp
+++ b/src/core/meshcop/dataset_manager_ftd.cpp
@@ -44,11 +44,11 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
#include "meshcop/dataset.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_leader.hpp"
@@ -167,14 +167,12 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo
// check commissioner session id
if (Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId) == kErrorNone)
{
- const CommissionerSessionIdTlv *localId;
+ uint16_t localSessionId;
isUpdateFromCommissioner = true;
- localId = As<CommissionerSessionIdTlv>(
- Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
-
- VerifyOrExit(localId != nullptr && localId->GetCommissionerSessionId() == sessionId);
+ SuccessOrExit(Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId));
+ VerifyOrExit(localSessionId == sessionId);
}
// verify an MGMT_ACTIVE_SET.req from a Commissioner does not affect connectivity
@@ -205,22 +203,24 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo
case Tlv::kDelayTimer:
{
- DelayTimerTlv &delayTimerTlv = As<DelayTimerTlv>(datasetTlv);
+ uint32_t delayTimer = datasetTlv.ReadValueAs<DelayTimerTlv>();
- if (doesAffectNetworkKey && delayTimerTlv.GetDelayTimer() < DelayTimerTlv::kDelayTimerDefault)
+ if (doesAffectNetworkKey && delayTimer < kDefaultDelayTimer)
{
- delayTimerTlv.SetDelayTimer(DelayTimerTlv::kDelayTimerDefault);
+ delayTimer = kDefaultDelayTimer;
}
- else if (delayTimerTlv.GetDelayTimer() < Get<Leader>().GetDelayTimerMinimal())
+ else
{
- delayTimerTlv.SetDelayTimer(Get<Leader>().GetDelayTimerMinimal());
+ delayTimer = Max(delayTimer, Get<Leader>().GetDelayTimerMinimal());
}
+
+ datasetTlv.WriteValueAs<DelayTimerTlv>(delayTimer);
}
OT_FALL_THROUGH;
default:
- SuccessOrExit(dataset.SetTlv(datasetTlv));
+ SuccessOrExit(dataset.WriteTlv(datasetTlv));
break;
}
@@ -240,16 +240,11 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo
// notify commissioner if update is from thread device
if (!isUpdateFromCommissioner)
{
- const CommissionerSessionIdTlv *localSessionId;
- Ip6::Address destination;
-
- localSessionId = As<CommissionerSessionIdTlv>(
- Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kCommissionerSessionId));
- VerifyOrExit(localSessionId != nullptr);
-
- SuccessOrExit(
- Get<Mle::MleRouter>().GetCommissionerAloc(destination, localSessionId->GetCommissionerSessionId()));
+ uint16_t localSessionId;
+ Ip6::Address destination;
+ SuccessOrExit(Get<NetworkData::Leader>().FindCommissioningSessionId(localSessionId));
+ SuccessOrExit(Get<Mle::MleRouter>().GetCommissionerAloc(destination, localSessionId));
Get<Leader>().SendDatasetChanged(destination);
}
@@ -307,61 +302,61 @@ Error ActiveDatasetManager::GenerateLocal(void)
IgnoreError(Read(dataset));
- if (dataset.GetTlv<ActiveTimestampTlv>() == nullptr)
+ if (!dataset.Contains<ActiveTimestampTlv>())
{
Timestamp timestamp;
timestamp.Clear();
- IgnoreError(dataset.SetTlv(Tlv::kActiveTimestamp, timestamp));
+ IgnoreError(dataset.Write<ActiveTimestampTlv>(timestamp));
}
- if (dataset.GetTlv<ChannelTlv>() == nullptr)
+ if (!dataset.Contains<ChannelTlv>())
{
ChannelTlv tlv;
tlv.Init();
tlv.SetChannel(Get<Mac::Mac>().GetPanChannel());
- IgnoreError(dataset.SetTlv(tlv));
+ IgnoreError(dataset.WriteTlv(tlv));
}
- if (dataset.GetTlv<ChannelMaskTlv>() == nullptr)
+ if (!dataset.Contains<ChannelMaskTlv>())
{
ChannelMaskTlv tlv;
tlv.Init();
tlv.SetChannelMask(Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
- IgnoreError(dataset.SetTlv(tlv));
+ IgnoreError(dataset.WriteTlv(tlv));
}
- if (dataset.GetTlv<ExtendedPanIdTlv>() == nullptr)
+ if (!dataset.Contains<ExtendedPanIdTlv>())
{
- IgnoreError(dataset.SetTlv(Tlv::kExtendedPanId, Get<ExtendedPanIdManager>().GetExtPanId()));
+ IgnoreError(dataset.Write<ExtendedPanIdTlv>(Get<ExtendedPanIdManager>().GetExtPanId()));
}
- if (dataset.GetTlv<MeshLocalPrefixTlv>() == nullptr)
+ if (!dataset.Contains<MeshLocalPrefixTlv>())
{
- IgnoreError(dataset.SetTlv(Tlv::kMeshLocalPrefix, Get<Mle::MleRouter>().GetMeshLocalPrefix()));
+ IgnoreError(dataset.Write<MeshLocalPrefixTlv>(Get<Mle::MleRouter>().GetMeshLocalPrefix()));
}
- if (dataset.GetTlv<NetworkKeyTlv>() == nullptr)
+ if (!dataset.Contains<NetworkKeyTlv>())
{
NetworkKey networkKey;
Get<KeyManager>().GetNetworkKey(networkKey);
- IgnoreError(dataset.SetTlv(Tlv::kNetworkKey, networkKey));
+ IgnoreError(dataset.Write<NetworkKeyTlv>(networkKey));
}
- if (dataset.GetTlv<NetworkNameTlv>() == nullptr)
+ if (!dataset.Contains<NetworkNameTlv>())
{
NameData nameData = Get<NetworkNameManager>().GetNetworkName().GetAsData();
- IgnoreError(dataset.SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
+ IgnoreError(dataset.WriteTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()));
}
- if (dataset.GetTlv<PanIdTlv>() == nullptr)
+ if (!dataset.Contains<PanIdTlv>())
{
- IgnoreError(dataset.SetTlv(Tlv::kPanId, Get<Mac::Mac>().GetPanId()));
+ IgnoreError(dataset.Write<PanIdTlv>(Get<Mac::Mac>().GetPanId()));
}
- if (dataset.GetTlv<PskcTlv>() == nullptr)
+ if (!dataset.Contains<PskcTlv>())
{
Pskc pskc;
@@ -374,16 +369,16 @@ Error ActiveDatasetManager::GenerateLocal(void)
SuccessOrExit(error = pskc.GenerateRandom());
}
- IgnoreError(dataset.SetTlv(Tlv::kPskc, pskc));
+ IgnoreError(dataset.Write<PskcTlv>(pskc));
}
- if (dataset.GetTlv<SecurityPolicyTlv>() == nullptr)
+ if (!dataset.Contains<SecurityPolicyTlv>())
{
SecurityPolicyTlv tlv;
tlv.Init();
tlv.SetSecurityPolicy(Get<KeyManager>().GetSecurityPolicy());
- IgnoreError(dataset.SetTlv(tlv));
+ IgnoreError(dataset.WriteTlv(tlv));
}
SuccessOrExit(error = mLocal.Save(dataset));
@@ -437,17 +432,14 @@ void PendingDatasetManager::ApplyActiveDataset(const Timestamp &aTimestamp, Coap
SuccessOrExit(datasetTlv.ReadFromMessage(aMessage, offset));
offset += static_cast<uint16_t>(datasetTlv.GetSize());
- IgnoreError(dataset.SetTlv(datasetTlv));
+ IgnoreError(dataset.WriteTlv(datasetTlv));
}
- // add delay timer tlv
- IgnoreError(dataset.SetTlv(Tlv::kDelayTimer, Get<Leader>().GetDelayTimerMinimal()));
+ IgnoreError(dataset.Write<DelayTimerTlv>(Get<Leader>().GetDelayTimerMinimal()));
- // add pending timestamp tlv
dataset.SetTimestamp(Dataset::kPending, aTimestamp);
IgnoreError(DatasetManager::Save(dataset));
- // reset delay timer
StartDelayTimer();
exit:
diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp
index 114bae550..c4b1145cf 100644
--- a/src/core/meshcop/dataset_updater.cpp
+++ b/src/core/meshcop/dataset_updater.cpp
@@ -37,10 +37,10 @@
#if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "meshcop/timestamp.hpp"
namespace ot {
@@ -123,7 +123,7 @@ void DatasetUpdater::PreparePendingDataset(void)
{
uint32_t delay = kDefaultDelay;
- SuccessOrExit(error = dataset.SetTlv(Tlv::kDelayTimer, delay));
+ SuccessOrExit(error = dataset.Write<DelayTimerTlv>(delay));
}
{
@@ -133,15 +133,20 @@ void DatasetUpdater::PreparePendingDataset(void)
{
timestamp = *Get<PendingDatasetManager>().GetTimestamp();
}
+ else
+ {
+ timestamp.Clear();
+ }
timestamp.AdvanceRandomTicks();
dataset.SetTimestamp(Dataset::kPending, timestamp);
}
{
- ActiveTimestampTlv *tlv = dataset.GetTlv<ActiveTimestampTlv>();
+ Timestamp timestamp = dataset.FindTlv(Tlv::kActiveTimestamp)->ReadValueAs<ActiveTimestampTlv>();
- tlv->GetTimestamp().AdvanceRandomTicks();
+ timestamp.AdvanceRandomTicks();
+ dataset.SetTimestamp(Dataset::kActive, timestamp);
}
SuccessOrExit(error = Get<PendingDatasetManager>().Save(dataset));
diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp
index 28337a62e..e3c2275f1 100644
--- a/src/core/meshcop/dtls.cpp
+++ b/src/core/meshcop/dtls.cpp
@@ -44,12 +44,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/timer.hpp"
#include "crypto/mbedtls.hpp"
#include "crypto/sha256.hpp"
+#include "instance/instance.hpp"
#include "thread/thread_netif.hpp"
#if OPENTHREAD_CONFIG_DTLS_ENABLE
diff --git a/src/core/meshcop/energy_scan_client.cpp b/src/core/meshcop/energy_scan_client.cpp
index 905d8a66f..beea65caa 100644
--- a/src/core/meshcop/energy_scan_client.cpp
+++ b/src/core/meshcop/energy_scan_client.cpp
@@ -40,10 +40,10 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp
index 86bd25ffe..50b02e923 100644
--- a/src/core/meshcop/joiner.cpp
+++ b/src/core/meshcop/joiner.cpp
@@ -42,10 +42,10 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "radio/radio.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp
index 09616023c..acadf1a9d 100644
--- a/src/core/meshcop/joiner_router.cpp
+++ b/src/core/meshcop/joiner_router.cpp
@@ -40,9 +40,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/mle.hpp"
@@ -75,7 +75,7 @@ void JoinerRouter::Start(void)
{
VerifyOrExit(Get<Mle::MleRouter>().IsFullThreadDevice());
- if (Get<NetworkData::Leader>().IsJoiningEnabled())
+ if (Get<NetworkData::Leader>().IsJoiningAllowed())
{
uint16_t port = GetJoinerUdpPort();
@@ -99,20 +99,24 @@ exit:
return;
}
-uint16_t JoinerRouter::GetJoinerUdpPort(void)
+uint16_t JoinerRouter::GetJoinerUdpPort(void) const
{
- uint16_t rval = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
- const JoinerUdpPortTlv *joinerUdpPort;
+ uint16_t port;
- VerifyOrExit(!mIsJoinerPortConfigured, rval = mJoinerUdpPort);
+ if (mIsJoinerPortConfigured)
+ {
+ ExitNow(port = mJoinerUdpPort);
+ }
- joinerUdpPort = As<JoinerUdpPortTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kJoinerUdpPort));
- VerifyOrExit(joinerUdpPort != nullptr);
+ if (Get<NetworkData::Leader>().FindJoinerUdpPort(port) == kErrorNone)
+ {
+ ExitNow();
+ }
- rval = joinerUdpPort->GetUdpPort();
+ port = kDefaultJoinerUdpPort;
exit:
- return rval;
+ return port;
}
void JoinerRouter::SetJoinerUdpPort(uint16_t aJoinerUdpPort)
@@ -137,7 +141,7 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
LogInfo("JoinerRouter::HandleUdpReceive");
- SuccessOrExit(error = GetBorderAgentRloc(Get<ThreadNetif>(), borderAgentRloc));
+ SuccessOrExit(error = Get<NetworkData::Leader>().FindBorderAgentRloc(borderAgentRloc));
message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayRx);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
@@ -286,72 +290,29 @@ exit:
Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void)
{
- Error error;
+ static const Tlv::Type kTlvTypes[] = {
+ Tlv::kNetworkKey, Tlv::kMeshLocalPrefix, Tlv::kExtendedPanId, Tlv::kNetworkName,
+ Tlv::kActiveTimestamp, Tlv::kChannelMask, Tlv::kPskc, Tlv::kSecurityPolicy,
+ };
+
+ Error error = kErrorNone;
Coap::Message *message = nullptr;
Dataset dataset;
- NetworkNameTlv networkName;
- const Tlv *tlv;
- NetworkKey networkKey;
message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(kUriJoinerEntrust);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
message->SetSubType(Message::kSubTypeJoinerEntrust);
- Get<KeyManager>().GetNetworkKey(networkKey);
- SuccessOrExit(error = Tlv::Append<NetworkKeyTlv>(*message, networkKey));
- SuccessOrExit(error = Tlv::Append<MeshLocalPrefixTlv>(*message, Get<Mle::MleRouter>().GetMeshLocalPrefix()));
- SuccessOrExit(error = Tlv::Append<ExtendedPanIdTlv>(*message, Get<ExtendedPanIdManager>().GetExtPanId()));
-
- networkName.Init();
- networkName.SetNetworkName(Get<NetworkNameManager>().GetNetworkName().GetAsData());
- SuccessOrExit(error = networkName.AppendTo(*message));
-
- IgnoreError(Get<ActiveDatasetManager>().Read(dataset));
-
- if ((tlv = dataset.GetTlv<ActiveTimestampTlv>()) != nullptr)
- {
- SuccessOrExit(error = tlv->AppendTo(*message));
- }
- else
- {
- ActiveTimestampTlv activeTimestamp;
- activeTimestamp.Init();
- SuccessOrExit(error = activeTimestamp.AppendTo(*message));
- }
-
- if ((tlv = dataset.GetTlv<ChannelMaskTlv>()) != nullptr)
- {
- SuccessOrExit(error = tlv->AppendTo(*message));
- }
- else
- {
- ChannelMaskBaseTlv channelMask;
- channelMask.Init();
- SuccessOrExit(error = channelMask.AppendTo(*message));
- }
+ SuccessOrExit(error = Get<ActiveDatasetManager>().Read(dataset));
- if ((tlv = dataset.GetTlv<PskcTlv>()) != nullptr)
+ for (Tlv::Type tlvType : kTlvTypes)
{
- SuccessOrExit(error = tlv->AppendTo(*message));
- }
- else
- {
- PskcTlv pskc;
- pskc.Init();
- SuccessOrExit(error = pskc.AppendTo(*message));
- }
+ const Tlv *tlv = dataset.FindTlv(tlvType);
- if ((tlv = dataset.GetTlv<SecurityPolicyTlv>()) != nullptr)
- {
+ VerifyOrExit(tlv != nullptr, error = kErrorInvalidState);
SuccessOrExit(error = tlv->AppendTo(*message));
}
- else
- {
- SecurityPolicyTlv securityPolicy;
- securityPolicy.Init();
- SuccessOrExit(error = securityPolicy.AppendTo(*message));
- }
SuccessOrExit(error = Tlv::Append<NetworkKeySequenceTlv>(*message, Get<KeyManager>().GetCurrentKeySequence()));
diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp
index d17c64290..bc76297ba 100644
--- a/src/core/meshcop/joiner_router.hpp
+++ b/src/core/meshcop/joiner_router.hpp
@@ -71,10 +71,10 @@ public:
/**
* Returns the Joiner UDP Port.
*
- * @returns The Joiner UDP Port number .
+ * @returns The Joiner UDP Port number.
*
*/
- uint16_t GetJoinerUdpPort(void);
+ uint16_t GetJoinerUdpPort(void) const;
/**
* Sets the Joiner UDP Port.
@@ -85,6 +85,7 @@ public:
void SetJoinerUdpPort(uint16_t aJoinerUdpPort);
private:
+ static constexpr uint16_t kDefaultJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
static constexpr uint32_t kJoinerEntrustTxDelay = 50; // in msec
struct JoinerEntrustMetadata
diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp
index 9dd65663c..35ad539b5 100644
--- a/src/core/meshcop/meshcop.cpp
+++ b/src/core/meshcop/meshcop.cpp
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 2017, The OpenThread Authors.
* All rights reserved.
@@ -118,7 +119,7 @@ bool JoinerDiscerner::Matches(const Mac::ExtAddress &aJoinerId) const
mask = GetMask();
- return (Encoding::BigEndian::ReadUint64(aJoinerId.m8) & mask) == (mValue & mask);
+ return (BigEndian::ReadUint64(aJoinerId.m8) & mask) == (mValue & mask);
}
void JoinerDiscerner::CopyTo(Mac::ExtAddress &aExtAddress) const
@@ -135,12 +136,12 @@ void JoinerDiscerner::CopyTo(Mac::ExtAddress &aExtAddress) const
OT_ASSERT(IsValid());
// Write full bytes
- while (remaining >= CHAR_BIT)
+ while (remaining >= kBitsPerByte)
{
*cur = static_cast<uint8_t>(value & 0xff);
- value >>= CHAR_BIT;
+ value >>= kBitsPerByte;
cur--;
- remaining -= CHAR_BIT;
+ remaining -= kBitsPerByte;
}
// Write any remaining bits (not a full byte)
@@ -167,11 +168,11 @@ JoinerDiscerner::InfoString JoinerDiscerner::ToString(void) const
{
InfoString string;
- if (mLength <= sizeof(uint16_t) * CHAR_BIT)
+ if (mLength <= BitSizeOf(uint16_t))
{
string.Append("0x%04x", static_cast<uint16_t>(mValue));
}
- else if (mLength <= sizeof(uint32_t) * CHAR_BIT)
+ else if (mLength <= BitSizeOf(uint32_t))
{
string.Append("0x%08lx", ToUlong(static_cast<uint32_t>(mValue)));
}
@@ -300,21 +301,6 @@ void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
aJoinerId.SetLocal(true);
}
-Error GetBorderAgentRloc(ThreadNetif &aNetif, uint16_t &aRloc)
-{
- Error error = kErrorNone;
- const BorderAgentLocatorTlv *borderAgentLocator;
-
- borderAgentLocator = As<BorderAgentLocatorTlv>(
- aNetif.Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
- VerifyOrExit(borderAgentLocator != nullptr, error = kErrorNotFound);
-
- aRloc = borderAgentLocator->GetBorderAgentLocator();
-
-exit:
- return error;
-}
-
#if OPENTHREAD_FTD
Error GeneratePskc(const char *aPassPhrase,
const NetworkName &aNetworkName,
diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp
index 7bf6f7806..339872bb3 100644
--- a/src/core/meshcop/meshcop.hpp
+++ b/src/core/meshcop/meshcop.hpp
@@ -37,8 +37,6 @@
#include "openthread-core-config.h"
-#include <limits.h>
-
#include <openthread/commissioner.h>
#include <openthread/instance.h>
#include <openthread/joiner.h>
@@ -49,6 +47,7 @@
#include "common/equatable.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop_tlvs.hpp"
@@ -393,10 +392,10 @@ public:
private:
static constexpr uint8_t kPermitAll = 0xff;
- uint8_t GetNumBits(void) const { return (mLength * CHAR_BIT); }
+ uint8_t GetNumBits(void) const { return (mLength * kBitsPerByte); }
- uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / CHAR_BIT)); }
- uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % CHAR_BIT)); }
+ uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / kBitsPerByte)); }
+ uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % kBitsPerByte)); }
bool GetBit(uint8_t aBit) const { return (m8[BitIndex(aBit)] & BitFlag(aBit)) != 0; }
void SetBit(uint8_t aBit) { m8[BitIndex(aBit)] |= BitFlag(aBit); }
@@ -407,6 +406,134 @@ private:
};
/**
+ * Represents a Commissioning Dataset.
+ *
+ */
+class CommissioningDataset : public otCommissioningDataset, public Clearable<CommissioningDataset>
+{
+public:
+ /**
+ * Indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
+ *
+ * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
+ *
+ */
+ bool IsLocatorSet(void) const { return mIsLocatorSet; }
+
+ /**
+ * Gets the Border Router RLOC16 Locator in the Dataset.
+ *
+ * MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
+ *
+ * @returns The Border Router RLOC16 Locator in the Dataset.
+ *
+ */
+ uint16_t GetLocator(void) const { return mLocator; }
+
+ /**
+ * Sets the Border Router RLOCG16 Locator in the Dataset.
+ *
+ * @param[in] aLocator A Locator.
+ *
+ */
+ void SetLocator(uint16_t aLocator)
+ {
+ mIsLocatorSet = true;
+ mLocator = aLocator;
+ }
+
+ /**
+ * Indicates whether or not the Session ID is set in the Dataset.
+ *
+ * @returns TRUE if Session ID is set, FALSE otherwise.
+ *
+ */
+ bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
+
+ /**
+ * Gets the Session ID in the Dataset.
+ *
+ * MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
+ *
+ * @returns The Session ID in the Dataset.
+ *
+ */
+ uint16_t GetSessionId(void) const { return mSessionId; }
+
+ /**
+ * Sets the Session ID in the Dataset.
+ *
+ * @param[in] aSessionId The Session ID.
+ *
+ */
+ void SetSessionId(uint16_t aSessionId)
+ {
+ mIsSessionIdSet = true;
+ mSessionId = aSessionId;
+ }
+
+ /**
+ * Indicates whether or not the Steering Data is set in the Dataset.
+ *
+ * @returns TRUE if Steering Data is set, FALSE otherwise.
+ *
+ */
+ bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
+
+ /**
+ * Gets the Steering Data in the Dataset.
+ *
+ * MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
+ *
+ * @returns The Steering Data in the Dataset.
+ *
+ */
+ const SteeringData &GetSteeringData(void) const { return static_cast<const SteeringData &>(mSteeringData); }
+
+ /**
+ * Returns a reference to the Steering Data in the Dataset to be updated by caller.
+ *
+ * @returns A reference to the Steering Data in the Dataset.
+ *
+ */
+ SteeringData &UpdateSteeringData(void)
+ {
+ mIsSteeringDataSet = true;
+ return static_cast<SteeringData &>(mSteeringData);
+ }
+
+ /**
+ * Indicates whether or not the Joiner UDP port is set in the Dataset.
+ *
+ * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
+ *
+ */
+ bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
+
+ /**
+ * Gets the Joiner UDP port in the Dataset.
+ *
+ * MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
+ *
+ * @returns The Joiner UDP port in the Dataset.
+ *
+ */
+ uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
+
+ /**
+ * Sets the Joiner UDP Port in the Dataset.
+ *
+ * @param[in] aJoinerUdpPort The Joiner UDP Port.
+ *
+ */
+ void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
+ {
+ mIsJoinerUdpPortSet = true;
+ mJoinerUdpPort = aJoinerUdpPort;
+ }
+};
+
+/**
* Generates PSKc.
*
* PSKc is used to establish the Commissioner Session.
@@ -434,18 +561,6 @@ Error GeneratePskc(const char *aPassPhrase,
*/
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId);
-/**
- * Gets the border agent RLOC.
- *
- * @param[in] aNetIf A reference to the thread interface.
- * @param[out] aRloc Border agent RLOC.
- *
- * @retval kErrorNone Successfully got the Border Agent Rloc.
- * @retval kErrorNotFound Border agent is not available.
- *
- */
-Error GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
-
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
/**
* Emits a log message indicating an error during a MeshCoP action.
@@ -467,6 +582,7 @@ inline void LogError(const char *, Error) {}
DefineCoreType(otJoinerPskd, MeshCoP::JoinerPskd);
DefineCoreType(otJoinerDiscerner, MeshCoP::JoinerDiscerner);
DefineCoreType(otSteeringData, MeshCoP::SteeringData);
+DefineCoreType(otCommissioningDataset, MeshCoP::CommissioningDataset);
} // namespace ot
diff --git a/src/core/meshcop/meshcop_leader.cpp b/src/core/meshcop/meshcop_leader.cpp
index 5f97185d4..64c028d1b 100644
--- a/src/core/meshcop/meshcop_leader.cpp
+++ b/src/core/meshcop/meshcop_leader.cpp
@@ -40,10 +40,10 @@
#include "coap/coap_message.hpp"
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
@@ -58,7 +58,7 @@ RegisterLogModule("MeshCoPLeader");
Leader::Leader(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimer(aInstance)
- , mDelayTimerMinimal(DelayTimerTlv::kDelayTimerMinimal)
+ , mDelayTimerMinimal(kMinDelayTimer)
, mSessionId(Random::NonCrypto::GetUint16())
{
}
@@ -67,43 +67,28 @@ template <> void Leader::HandleTmf<kUriLeaderPetition>(Coap::Message &aMessage,
{
OT_UNUSED_VARIABLE(aMessageInfo);
- CommissioningData data;
- CommissionerIdTlv commissionerId;
- StateTlv::State state = StateTlv::kReject;
+ CommissioningData data;
+ CommissionerIdTlv::StringType commissionerId;
+ StateTlv::State state = StateTlv::kReject;
LogInfo("Received %s", UriToString<kUriLeaderPetition>());
+ VerifyOrExit(Get<Mle::MleRouter>().IsLeader());
+
VerifyOrExit(Get<Mle::MleRouter>().IsRoutingLocator(aMessageInfo.GetPeerAddr()));
- SuccessOrExit(Tlv::FindTlv(aMessage, commissionerId));
+
+ SuccessOrExit(Tlv::Find<CommissionerIdTlv>(aMessage, commissionerId));
if (mTimer.IsRunning())
{
- VerifyOrExit((commissionerId.GetCommissionerIdLength() == mCommissionerId.GetCommissionerIdLength()) &&
- (!strncmp(commissionerId.GetCommissionerId(), mCommissionerId.GetCommissionerId(),
- commissionerId.GetCommissionerIdLength())));
-
+ VerifyOrExit(StringMatch(mCommissionerId, commissionerId));
ResignCommissioner();
}
- data.mBorderAgentLocator.Init();
- data.mBorderAgentLocator.SetBorderAgentLocator(aMessageInfo.GetPeerAddr().GetIid().GetLocator());
-
- data.mCommissionerSessionId.Init();
- data.mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);
-
- data.mSteeringData.Init();
- data.mSteeringData.SetLength(1);
- data.mSteeringData.Clear();
+ data.Init(aMessageInfo.GetPeerAddr().GetIid().GetLocator(), ++mSessionId);
+ SuccessOrExit(Get<NetworkData::Leader>().SetCommissioningData(&data, data.GetLength()));
- SuccessOrExit(
- Get<NetworkData::Leader>().SetCommissioningData(reinterpret_cast<uint8_t *>(&data), data.GetLength()));
-
- mCommissionerId = commissionerId;
-
- if (mCommissionerId.GetLength() > CommissionerIdTlv::kMaxLength)
- {
- mCommissionerId.SetLength(CommissionerIdTlv::kMaxLength);
- }
+ IgnoreError(StringCopy(mCommissionerId, commissionerId));
state = StateTlv::kAccept;
mTimer.Start(Time::SecToMsec(kTimeoutLeaderPetition));
@@ -126,7 +111,7 @@ void Leader::SendPetitionResponse(const Coap::Message &aRequest,
if (mTimer.IsRunning())
{
- SuccessOrExit(error = mCommissionerId.AppendTo(*message));
+ SuccessOrExit(error = Tlv::Append<CommissionerIdTlv>(*message, mCommissionerId));
}
if (aState == StateTlv::kAccept)
@@ -152,12 +137,13 @@ template <> void Leader::HandleTmf<kUriLeaderKeepAlive>(Coap::Message &aMessage,
LogInfo("Received %s", UriToString<kUriLeaderKeepAlive>());
+ VerifyOrExit(Get<Mle::MleRouter>().IsLeader());
+
SuccessOrExit(Tlv::Find<StateTlv>(aMessage, state));
SuccessOrExit(Tlv::Find<CommissionerSessionIdTlv>(aMessage, sessionId));
- borderAgentLocator =
- As<BorderAgentLocatorTlv>(Get<NetworkData::Leader>().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
+ borderAgentLocator = Get<NetworkData::Leader>().FindInCommissioningData<BorderAgentLocatorTlv>();
if ((borderAgentLocator == nullptr) || (sessionId != mSessionId))
{
@@ -231,16 +217,14 @@ exit:
Error Leader::SetDelayTimerMinimal(uint32_t aDelayTimerMinimal)
{
Error error = kErrorNone;
- VerifyOrExit((aDelayTimerMinimal != 0 && aDelayTimerMinimal < DelayTimerTlv::kDelayTimerDefault),
- error = kErrorInvalidArgs);
+
+ VerifyOrExit((aDelayTimerMinimal != 0 && aDelayTimerMinimal < kMinDelayTimer), error = kErrorInvalidArgs);
mDelayTimerMinimal = aDelayTimerMinimal;
exit:
return error;
}
-uint32_t Leader::GetDelayTimerMinimal(void) const { return mDelayTimerMinimal; }
-
void Leader::HandleTimer(void)
{
VerifyOrExit(Get<Mle::MleRouter>().IsLeader());
@@ -253,13 +237,12 @@ exit:
void Leader::SetEmptyCommissionerData(void)
{
- CommissionerSessionIdTlv mCommissionerSessionId;
+ CommissionerSessionIdTlv sessionIdTlv;
- mCommissionerSessionId.Init();
- mCommissionerSessionId.SetCommissionerSessionId(++mSessionId);
+ sessionIdTlv.Init();
+ sessionIdTlv.SetCommissionerSessionId(++mSessionId);
- IgnoreError(Get<NetworkData::Leader>().SetCommissioningData(reinterpret_cast<uint8_t *>(&mCommissionerSessionId),
- sizeof(Tlv) + mCommissionerSessionId.GetLength()));
+ IgnoreError(Get<NetworkData::Leader>().SetCommissioningData(&sessionIdTlv, sizeof(CommissionerSessionIdTlv)));
}
void Leader::ResignCommissioner(void)
@@ -270,6 +253,25 @@ void Leader::ResignCommissioner(void)
LogInfo("commissioner inactive");
}
+void Leader::CommissioningData::Init(uint16_t aBorderAgentRloc16, uint16_t aSessionId)
+{
+ mBorderAgentLocatorTlv.Init();
+ mBorderAgentLocatorTlv.SetBorderAgentLocator(aBorderAgentRloc16);
+
+ mSessionIdTlv.Init();
+ mSessionIdTlv.SetCommissionerSessionId(aSessionId);
+
+ mSteeringDataTlv.Init();
+ mSteeringDataTlv.SetLength(1);
+ mSteeringDataTlv.Clear();
+}
+
+uint8_t Leader::CommissioningData::GetLength(void) const
+{
+ return static_cast<uint8_t>(sizeof(BorderAgentLocatorTlv) + sizeof(CommissionerSessionIdTlv) +
+ mSteeringDataTlv.GetSize());
+}
+
} // namespace MeshCoP
} // namespace ot
diff --git a/src/core/meshcop/meshcop_leader.hpp b/src/core/meshcop/meshcop_leader.hpp
index 7a78ff9f2..50436b3c9 100644
--- a/src/core/meshcop/meshcop_leader.hpp
+++ b/src/core/meshcop/meshcop_leader.hpp
@@ -49,21 +49,6 @@
namespace ot {
namespace MeshCoP {
-OT_TOOL_PACKED_BEGIN
-class CommissioningData
-{
-public:
- uint8_t GetLength(void) const
- {
- return sizeof(Tlv) + mBorderAgentLocator.GetLength() + sizeof(Tlv) + mCommissionerSessionId.GetLength() +
- sizeof(Tlv) + mSteeringData.GetLength();
- }
-
- BorderAgentLocatorTlv mBorderAgentLocator;
- CommissionerSessionIdTlv mCommissionerSessionId;
- SteeringDataTlv mSteeringData;
-} OT_TOOL_PACKED_END;
-
class Leader : public InstanceLocator, private NonCopyable
{
friend class Tmf::Agent;
@@ -78,6 +63,14 @@ public:
explicit Leader(Instance &aInstance);
/**
+ * Sets the session ID.
+ *
+ * @param[in] aSessionId The session ID to use.
+ *
+ */
+ void SetSessionId(uint16_t aSessionId) { mSessionId = aSessionId; }
+
+ /**
* Sends a MGMT_DATASET_CHANGED message to commissioner.
*
* @param[in] aAddress The IPv6 address of destination.
@@ -102,7 +95,7 @@ public:
* @retval the minimal delay timer (in ms).
*
*/
- uint32_t GetDelayTimerMinimal(void) const;
+ uint32_t GetDelayTimerMinimal(void) const { return mDelayTimerMinimal; }
/**
* Sets empty Commissioner Data TLV in the Thread Network Data.
@@ -111,8 +104,22 @@ public:
void SetEmptyCommissionerData(void);
private:
+ static constexpr uint32_t kMinDelayTimer = OPENTHREAD_CONFIG_TMF_PENDING_DATASET_MINIMUM_DELAY; // (msec)
static constexpr uint32_t kTimeoutLeaderPetition = 50; // TIMEOUT_LEAD_PET (seconds)
+ OT_TOOL_PACKED_BEGIN
+ class CommissioningData
+ {
+ public:
+ void Init(uint16_t aBorderAgentRloc16, uint16_t aSessionId);
+ uint8_t GetLength(void) const;
+
+ private:
+ BorderAgentLocatorTlv mBorderAgentLocatorTlv;
+ CommissionerSessionIdTlv mSessionIdTlv;
+ SteeringDataTlv mSteeringDataTlv;
+ } OT_TOOL_PACKED_END;
+
void HandleTimer(void);
template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
@@ -135,8 +142,8 @@ private:
uint32_t mDelayTimerMinimal;
- CommissionerIdTlv mCommissionerId;
- uint16_t mSessionId;
+ CommissionerIdTlv::StringType mCommissionerId;
+ uint16_t mSessionId;
};
DeclareTmfHandler(Leader, kUriLeaderPetition);
diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp
index 0e643ac03..446846f45 100644
--- a/src/core/meshcop/meshcop_tlvs.cpp
+++ b/src/core/meshcop/meshcop_tlvs.cpp
@@ -36,6 +36,7 @@
#include "common/const_cast.hpp"
#include "common/debug.hpp"
#include "common/num_utils.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "meshcop/meshcop.hpp"
@@ -44,76 +45,52 @@ namespace MeshCoP {
bool Tlv::IsValid(const Tlv &aTlv)
{
- bool rval = true;
+ bool isValid = true;
+ uint8_t minLength = 0;
switch (aTlv.GetType())
{
- case Tlv::kChannel:
- rval = As<ChannelTlv>(aTlv).IsValid();
- break;
-
case Tlv::kPanId:
- rval = As<PanIdTlv>(aTlv).IsValid();
+ minLength = sizeof(PanIdTlv::UintValueType);
break;
-
case Tlv::kExtendedPanId:
- rval = As<ExtendedPanIdTlv>(aTlv).IsValid();
+ minLength = sizeof(ExtendedPanIdTlv::ValueType);
break;
-
- case Tlv::kNetworkName:
- rval = As<NetworkNameTlv>(aTlv).IsValid();
+ case Tlv::kPskc:
+ minLength = sizeof(PskcTlv::ValueType);
break;
-
case Tlv::kNetworkKey:
- rval = As<NetworkKeyTlv>(aTlv).IsValid();
+ minLength = sizeof(NetworkKeyTlv::ValueType);
break;
-
- case Tlv::kPskc:
- rval = As<PskcTlv>(aTlv).IsValid();
+ case Tlv::kMeshLocalPrefix:
+ minLength = sizeof(MeshLocalPrefixTlv::ValueType);
break;
- case Tlv::kMeshLocalPrefix:
- rval = As<MeshLocalPrefixTlv>(aTlv).IsValid();
+ case Tlv::kChannel:
+ isValid = As<ChannelTlv>(aTlv).IsValid();
+ break;
+ case Tlv::kNetworkName:
+ isValid = As<NetworkNameTlv>(aTlv).IsValid();
break;
case Tlv::kSecurityPolicy:
- rval = As<SecurityPolicyTlv>(aTlv).IsValid();
+ isValid = As<SecurityPolicyTlv>(aTlv).IsValid();
break;
case Tlv::kChannelMask:
- rval = As<ChannelMaskTlv>(aTlv).IsValid();
+ isValid = As<ChannelMaskTlv>(aTlv).IsValid();
break;
default:
break;
}
- return rval;
-}
-
-const Tlv *Tlv::FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType)
-{
- const Tlv *tlv;
- const Tlv *end = reinterpret_cast<const Tlv *>(aTlvsStart + aTlvsLength);
-
- for (tlv = reinterpret_cast<const Tlv *>(aTlvsStart); tlv < end; tlv = tlv->GetNext())
+ if (minLength > 0)
{
- VerifyOrExit((tlv + 1) <= end, tlv = nullptr);
- VerifyOrExit(!tlv->IsExtended() ||
- (reinterpret_cast<const ExtendedTlv *>(tlv) + 1 <= reinterpret_cast<const ExtendedTlv *>(end)),
- tlv = nullptr);
- VerifyOrExit(tlv->GetNext() <= end, tlv = nullptr);
-
- if (tlv->GetType() == aType)
- {
- ExitNow();
- }
+ isValid = (aTlv.GetLength() >= minLength);
}
- tlv = nullptr;
-
-exit:
- return tlv;
+ return isValid;
}
NameData NetworkNameTlv::GetNetworkName(void) const
@@ -171,7 +148,7 @@ bool ChannelTlv::IsValid(void) const
bool ret = false;
VerifyOrExit(GetLength() == sizeof(*this) - sizeof(Tlv));
- VerifyOrExit(mChannelPage < sizeof(uint32_t) * CHAR_BIT);
+ VerifyOrExit(mChannelPage < BitSizeOf(uint32_t));
VerifyOrExit((1U << mChannelPage) & Radio::kSupportedChannelPages);
VerifyOrExit(Radio::kChannelMin <= GetChannel() && GetChannel() <= Radio::kChannelMax);
ret = true;
@@ -208,7 +185,7 @@ void ChannelTlv::SetChannel(uint16_t aChannel)
#endif
SetChannelPage(channelPage);
- mChannel = HostSwap16(aChannel);
+ mChannel = BigEndian::HostSwap16(aChannel);
}
const char *StateTlv::StateToString(State aState)
diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp
index 3eca8dc35..c9c324e1b 100644
--- a/src/core/meshcop/meshcop_tlvs.hpp
+++ b/src/core/meshcop/meshcop_tlvs.hpp
@@ -59,11 +59,6 @@
namespace ot {
namespace MeshCoP {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-using ot::Encoding::BigEndian::ReadUint24;
-using ot::Encoding::BigEndian::WriteUint24;
-
/**
* Implements MeshCoP TLV generation and parsing.
*
@@ -126,6 +121,7 @@ public:
*/
static constexpr uint8_t kMaxProvisioningUrlLength = OT_PROVISIONING_URL_MAX_SIZE;
+ static constexpr uint8_t kMaxCommissionerIdLength = 64; ///< Max length of Commissioner ID TLV.
static constexpr uint8_t kMaxVendorNameLength = 32; ///< Max length of Vendor Name TLV.
static constexpr uint8_t kMaxVendorModelLength = 32; ///< Max length of Vendor Model TLV.
static constexpr uint8_t kMaxVendorSwVersionLength = 16; ///< Max length of Vendor SW Version TLV.
@@ -164,43 +160,6 @@ public:
const Tlv *GetNext(void) const { return As<Tlv>(ot::Tlv::GetNext()); }
/**
- * Reads the requested TLV out of @p aMessage.
- *
- * @param[in] aMessage A reference to the message.
- * @param[in] aType The Type value to search for.
- * @param[in] aMaxLength Maximum number of bytes to read.
- * @param[out] aTlv A reference to the TLV that will be copied to.
- *
- * @retval kErrorNone Successfully copied the TLV.
- * @retval kErrorNotFound Could not find the TLV with Type @p aType.
- *
- */
- 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);
- }
-
- /**
- * Reads the requested TLV out of @p aMessage.
- *
- * Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
- *
- * @tparam TlvType The TlvType to search for (must be a sub-class of `Tlv`).
- *
- * @param[in] aMessage A reference to the message.
- * @param[out] aTlv A reference to the TLV that will be copied to.
- *
- * @retval kErrorNone Successfully copied the TLV.
- * @retval kErrorNotFound Could not find the TLV with Type @p aType.
- *
- */
-
- template <typename TlvType> static Error FindTlv(const Message &aMessage, TlvType &aTlv)
- {
- return ot::Tlv::FindTlv(aMessage, aTlv);
- }
-
- /**
* Indicates whether a TLV appears to be well-formed.
*
* @param[in] aTlv A reference to the TLV.
@@ -210,63 +169,6 @@ public:
*/
static bool IsValid(const Tlv &aTlv);
- /**
- * Searches in a given sequence of TLVs to find the first TLV with a given template Type.
- *
- * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
- * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
- * @param[in] aType The TLV Type to search for.
- *
- * @returns A pointer to the TLV if found, or `nullptr` if not found.
- *
- */
- static Tlv *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType)
- {
- return AsNonConst(FindTlv(AsConst(aTlvsStart), aTlvsLength, aType));
- }
-
- /**
- * Searches in a given sequence of TLVs to find the first TLV with a given template Type.
- *
- * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
- * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
- * @param[in] aType The TLV Type to search for.
- *
- * @returns A pointer to the TLV if found, or `nullptr` if not found.
- *
- */
- static const Tlv *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType);
-
- /**
- * This static template method searches in a given sequence of TLVs to find the first TLV with a give template
- * `TlvType`.
- *
- * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
- * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
- *
- * @returns A pointer to the TLV if found, or `nullptr` if not found.
- *
- */
- template <typename TlvType> static TlvType *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength)
- {
- return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
- }
-
- /**
- * This static template method searches in a given sequence of TLVs to find the first TLV with a give template
- * `TlvType`.
- *
- * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within.
- * @param[in] aTlvsLength The length (number of bytes) in TLV sequence.
- *
- * @returns A pointer to the TLV if found, or `nullptr` if not found.
- *
- */
- template <typename TlvType> static const TlvType *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength)
- {
- return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
- }
-
} OT_TOOL_PACKED_END;
/**
@@ -343,6 +245,12 @@ typedef UintTlvInfo<Tlv::kPeriod, uint16_t> PeriodTlv;
typedef UintTlvInfo<Tlv::kScanDuration, uint16_t> ScanDurationTlv;
/**
+ * Defines Commissioner ID TLV constants and type.s
+ *
+ */
+typedef StringTlvInfo<Tlv::kCommissionerId, Tlv::kMaxCommissionerIdLength> CommissionerIdTlv;
+
+/**
* Implements Channel TLV generation and parsing.
*
*/
@@ -391,7 +299,7 @@ public:
* @returns The Channel value.
*
*/
- uint16_t GetChannel(void) const { return HostSwap16(mChannel); }
+ uint16_t GetChannel(void) const { return BigEndian::HostSwap16(mChannel); }
/**
* Sets the Channel value.
@@ -408,98 +316,16 @@ private:
} OT_TOOL_PACKED_END;
/**
- * Implements PAN ID TLV generation and parsing.
+ * Defines PAN ID TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class PanIdTlv : public Tlv, public UintTlvInfo<Tlv::kPanId, uint16_t>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kPanId);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the PAN ID value.
- *
- * @returns The PAN ID value.
- *
- */
- uint16_t GetPanId(void) const { return HostSwap16(mPanId); }
-
- /**
- * Sets the PAN ID value.
- *
- * @param[in] aPanId The PAN ID value.
- *
- */
- void SetPanId(uint16_t aPanId) { mPanId = HostSwap16(aPanId); }
-
-private:
- uint16_t mPanId;
-} OT_TOOL_PACKED_END;
+typedef UintTlvInfo<Tlv::kPanId, uint16_t> PanIdTlv;
/**
- * Implements Extended PAN ID TLV generation and parsing.
+ * Defines Extended PAN ID TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class ExtendedPanIdTlv : public Tlv, public SimpleTlvInfo<Tlv::kExtendedPanId, ExtendedPanId>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kExtendedPanId);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the Extended PAN ID value.
- *
- * @returns The Extended PAN ID value.
- *
- */
- const ExtendedPanId &GetExtendedPanId(void) const { return mExtendedPanId; }
-
- /**
- * Sets the Extended PAN ID value.
- *
- * @param[in] aExtendedPanId An Extended PAN ID value.
- *
- */
- void SetExtendedPanId(const ExtendedPanId &aExtendedPanId) { mExtendedPanId = aExtendedPanId; }
-
-private:
- ExtendedPanId mExtendedPanId;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kExtendedPanId, ExtendedPanId> ExtendedPanIdTlv;
/**
* Implements Network Name TLV generation and parsing.
@@ -549,200 +375,28 @@ private:
} OT_TOOL_PACKED_END;
/**
- * Implements PSKc TLV generation and parsing.
+ * Defines PSKc TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class PskcTlv : public Tlv, public SimpleTlvInfo<Tlv::kPskc, Pskc>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kPskc);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the PSKc value.
- *
- * @returns The PSKc value.
- *
- */
- const Pskc &GetPskc(void) const { return mPskc; }
-
- /**
- * Sets the PSKc value.
- *
- * @param[in] aPskc A pointer to the PSKc value.
- *
- */
- void SetPskc(const Pskc &aPskc) { mPskc = aPskc; }
-
-private:
- Pskc mPskc;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kPskc, Pskc> PskcTlv;
/**
- * Implements Network Network Key TLV generation and parsing.
+ * Defines Network Key TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class NetworkKeyTlv : public Tlv, public SimpleTlvInfo<Tlv::kNetworkKey, NetworkKey>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kNetworkKey);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the Network Network Key value.
- *
- * @returns The Network Network Key value.
- *
- */
- const NetworkKey &GetNetworkKey(void) const { return mNetworkKey; }
-
- /**
- * Sets the Network Network Key value.
- *
- * @param[in] aNetworkKey The Network Network Key.
- *
- */
- void SetNetworkKey(const NetworkKey &aNetworkKey) { mNetworkKey = aNetworkKey; }
-
-private:
- NetworkKey mNetworkKey;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kNetworkKey, NetworkKey> NetworkKeyTlv;
/**
- * Implements Network Key Sequence TLV generation and parsing.
+ * Defines Network Key Sequence TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class NetworkKeySequenceTlv : public Tlv, public UintTlvInfo<Tlv::kNetworkKeySequence, uint32_t>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kNetworkKeySequence);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the Network Key Sequence value.
- *
- * @returns The Network Key Sequence value.
- *
- */
- uint32_t GetNetworkKeySequence(void) const { return HostSwap32(mNetworkKeySequence); }
-
- /**
- * Sets the Network Key Sequence value.
- *
- * @param[in] aNetworkKeySequence The Network Key Sequence value.
- *
- */
- void SetNetworkKeySequence(uint32_t aNetworkKeySequence) { mNetworkKeySequence = HostSwap32(aNetworkKeySequence); }
-
-private:
- uint32_t mNetworkKeySequence;
-} OT_TOOL_PACKED_END;
+typedef UintTlvInfo<Tlv::kNetworkKeySequence, uint32_t> NetworkKeySequenceTlv;
/**
- * Implements Mesh Local Prefix TLV generation and parsing.
+ * Defines Mesh Local Prefix TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class MeshLocalPrefixTlv : public Tlv, public SimpleTlvInfo<Tlv::kMeshLocalPrefix, Ip6::NetworkPrefix>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kMeshLocalPrefix);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the size (in bytes) of the Mesh Local Prefix field.
- *
- * @returns The size (in bytes) of the Mesh Local Prefix field (8 bytes).
- *
- */
- uint8_t GetMeshLocalPrefixLength(void) const { return sizeof(mMeshLocalPrefix); }
-
- /**
- * Returns the Mesh Local Prefix value.
- *
- * @returns The Mesh Local Prefix value.
- *
- */
- const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
-
- /**
- * Sets the Mesh Local Prefix value.
- *
- * @param[in] aMeshLocalPrefix A pointer to the Mesh Local Prefix value.
- *
- */
- void SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix) { mMeshLocalPrefix = aMeshLocalPrefix; }
-
-private:
- Ip6::NetworkPrefix mMeshLocalPrefix;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kMeshLocalPrefix, Ip6::NetworkPrefix> MeshLocalPrefixTlv;
class SteeringData;
@@ -836,7 +490,7 @@ public:
* @returns The Border Agent Locator value.
*
*/
- uint16_t GetBorderAgentLocator(void) const { return HostSwap16(mLocator); }
+ uint16_t GetBorderAgentLocator(void) const { return BigEndian::HostSwap16(mLocator); }
/**
* Sets the Border Agent Locator value.
@@ -844,69 +498,13 @@ public:
* @param[in] aLocator The Border Agent Locator value.
*
*/
- void SetBorderAgentLocator(uint16_t aLocator) { mLocator = HostSwap16(aLocator); }
+ void SetBorderAgentLocator(uint16_t aLocator) { mLocator = BigEndian::HostSwap16(aLocator); }
private:
uint16_t mLocator;
} OT_TOOL_PACKED_END;
/**
- * Implements the Commissioner ID TLV generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class CommissionerIdTlv : public Tlv, public TlvInfo<Tlv::kCommissionerId>
-{
-public:
- static constexpr uint8_t kMaxLength = 64; ///< maximum length (bytes)
-
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kCommissionerId);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Returns the Commissioner ID length.
- *
- * @returns The Commissioner ID length.
- *
- */
- uint8_t GetCommissionerIdLength(void) const
- {
- return GetLength() <= sizeof(mCommissionerId) ? GetLength() : sizeof(mCommissionerId);
- }
-
- /**
- * Returns the Commissioner ID value.
- *
- * @returns The Commissioner ID value.
- *
- */
- const char *GetCommissionerId(void) const { return mCommissionerId; }
-
- /**
- * Sets the Commissioner ID value.
- *
- * @param[in] aCommissionerId A pointer to the Commissioner ID value.
- *
- */
- void SetCommissionerId(const char *aCommissionerId)
- {
- uint16_t length = StringLength(aCommissionerId, sizeof(mCommissionerId));
- memcpy(mCommissionerId, aCommissionerId, length);
- SetLength(static_cast<uint8_t>(length));
- }
-
-private:
- char mCommissionerId[kMaxLength];
-} OT_TOOL_PACKED_END;
-
-/**
* Implements Commissioner Session ID TLV generation and parsing.
*
*/
@@ -939,7 +537,7 @@ public:
* @returns The Commissioner Session ID value.
*
*/
- uint16_t GetCommissionerSessionId(void) const { return HostSwap16(mSessionId); }
+ uint16_t GetCommissionerSessionId(void) const { return BigEndian::HostSwap16(mSessionId); }
/**
* Sets the Commissioner Session ID value.
@@ -947,7 +545,7 @@ public:
* @param[in] aSessionId The Commissioner Session ID value.
*
*/
- void SetCommissionerSessionId(uint16_t aSessionId) { mSessionId = HostSwap16(aSessionId); }
+ void SetCommissionerSessionId(uint16_t aSessionId) { mSessionId = BigEndian::HostSwap16(aSessionId); }
private:
uint16_t mSessionId;
@@ -1000,8 +598,8 @@ private:
static constexpr uint8_t kThread11FlagsLength = 1; // The Thread 1.1 Security Policy Flags length.
static constexpr uint8_t kThread12FlagsLength = 2; // The Thread 1.2 Security Policy Flags length.
- void SetRotationTime(uint16_t aRotationTime) { mRotationTime = HostSwap16(aRotationTime); }
- uint16_t GetRotationTime(void) const { return HostSwap16(mRotationTime); }
+ void SetRotationTime(uint16_t aRotationTime) { mRotationTime = BigEndian::HostSwap16(aRotationTime); }
+ uint16_t GetRotationTime(void) const { return BigEndian::HostSwap16(mRotationTime); }
uint8_t GetFlagsLength(void) const { return GetLength() - sizeof(mRotationTime); }
uint16_t mRotationTime;
@@ -1013,60 +611,10 @@ private:
} OT_TOOL_PACKED_END;
/**
- * Implements Active Timestamp TLV generation and parsing.
+ * Defines Active Timestamp TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class ActiveTimestampTlv : public Tlv, public SimpleTlvInfo<Tlv::kActiveTimestamp, Timestamp>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kActiveTimestamp);
- SetLength(sizeof(*this) - sizeof(Tlv));
- mTimestamp.Clear();
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Gets the timestamp.
- *
- * @returns The timestamp.
- *
- */
- const Timestamp &GetTimestamp(void) const { return mTimestamp; }
-
- /**
- * Returns a reference to the timestamp.
- *
- * @returns A reference to the timestamp.
- *
- */
- Timestamp &GetTimestamp(void) { return mTimestamp; }
-
- /**
- * Sets the timestamp.
- *
- * @param[in] aTimestamp The new timestamp.
- *
- */
- void SetTimestamp(const Timestamp &aTimestamp) { mTimestamp = aTimestamp; }
-
-private:
- Timestamp mTimestamp;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kActiveTimestamp, Timestamp> ActiveTimestampTlv;
/**
* Implements State TLV generation and parsing.
@@ -1100,168 +648,22 @@ public:
};
/**
- * Implements Joiner UDP Port TLV generation and parsing.
+ * Defines Joiner UDP Port TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class JoinerUdpPortTlv : public Tlv, public UintTlvInfo<Tlv::kJoinerUdpPort, uint16_t>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kJoinerUdpPort);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the UDP Port value.
- *
- * @returns The UDP Port value.
- *
- */
- uint16_t GetUdpPort(void) const { return HostSwap16(mUdpPort); }
-
- /**
- * Sets the UDP Port value.
- *
- * @param[in] aUdpPort The UDP Port value.
- *
- */
- void SetUdpPort(uint16_t aUdpPort) { mUdpPort = HostSwap16(aUdpPort); }
-
-private:
- uint16_t mUdpPort;
-} OT_TOOL_PACKED_END;
+typedef UintTlvInfo<Tlv::kJoinerUdpPort, uint16_t> JoinerUdpPortTlv;
/**
- * Implements Pending Timestamp TLV generation and parsing.
+ * Defines Pending Timestamp TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class PendingTimestampTlv : public Tlv, public SimpleTlvInfo<Tlv::kPendingTimestamp, Timestamp>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kPendingTimestamp);
- SetLength(sizeof(*this) - sizeof(Tlv));
- mTimestamp.Clear();
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Gets the timestamp.
- *
- * @returns The timestamp.
- *
- */
- const Timestamp &GetTimestamp(void) const { return mTimestamp; }
-
- /**
- * Returns a reference to the timestamp.
- *
- * @returns A reference to the timestamp.
- *
- */
- Timestamp &GetTimestamp(void) { return mTimestamp; }
-
- /**
- * Sets the timestamp.
- *
- * @param[in] aTimestamp The new timestamp.
- *
- */
- void SetTimestamp(const Timestamp &aTimestamp) { mTimestamp = aTimestamp; }
-
-private:
- Timestamp mTimestamp;
-} OT_TOOL_PACKED_END;
+typedef SimpleTlvInfo<Tlv::kPendingTimestamp, Timestamp> PendingTimestampTlv;
/**
- * Implements Delay Timer TLV generation and parsing.
+ * Defines Delay Timer TLV constants and types.
*
*/
-OT_TOOL_PACKED_BEGIN
-class DelayTimerTlv : public Tlv, public UintTlvInfo<Tlv::kDelayTimer, uint32_t>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kDelayTimer);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the Delay Timer value.
- *
- * @returns The Delay Timer value.
- *
- */
- uint32_t GetDelayTimer(void) const { return HostSwap32(mDelayTimer); }
-
- /**
- * Sets the Delay Timer value.
- *
- * @param[in] aDelayTimer The Delay Timer value.
- *
- */
- void SetDelayTimer(uint32_t aDelayTimer) { mDelayTimer = HostSwap32(aDelayTimer); }
-
- static constexpr uint32_t kMaxDelayTimer = 259200; ///< Maximum delay timer value for a Pending Dataset in seconds
-
- /**
- * Minimum Delay Timer value for a Pending Operational Dataset (ms)
- *
- */
- static constexpr uint32_t kDelayTimerMinimal = OPENTHREAD_CONFIG_TMF_PENDING_DATASET_MINIMUM_DELAY;
-
- /**
- * Default Delay Timer value for a Pending Operational Dataset (ms)
- *
- */
- static constexpr uint32_t kDelayTimerDefault = OPENTHREAD_CONFIG_TMF_PENDING_DATASET_DEFAULT_DELAY;
-
-private:
- uint32_t mDelayTimer;
-} OT_TOOL_PACKED_END;
+typedef UintTlvInfo<Tlv::kDelayTimer, uint32_t> DelayTimerTlv;
// forward declare ChannelMaskTlv
class ChannelMaskTlv;
@@ -1407,7 +809,7 @@ public:
* @returns The Channel Mask value.
*
*/
- uint32_t GetMask(void) const { return Encoding::Reverse32(HostSwap32(mMask)); }
+ uint32_t GetMask(void) const { return Reverse32(BigEndian::HostSwap32(mMask)); }
/**
* Sets the Channel Mask value.
@@ -1415,7 +817,7 @@ public:
* @param[in] aMask The Channel Mask value.
*
*/
- void SetMask(uint32_t aMask) { mMask = HostSwap32(Encoding::Reverse32(aMask)); }
+ void SetMask(uint32_t aMask) { mMask = BigEndian::HostSwap32(Reverse32(aMask)); }
private:
uint32_t mMask;
@@ -1638,7 +1040,7 @@ public:
* @returns The Vendor Stack Vendor OUI value.
*
*/
- uint32_t GetOui(void) const { return ReadUint24(mOui); }
+ uint32_t GetOui(void) const { return BigEndian::ReadUint24(mOui); }
/**
* Returns the Stack Vendor OUI value.
@@ -1646,7 +1048,7 @@ public:
* @param[in] aOui The Vendor Stack Vendor OUI value.
*
*/
- void SetOui(uint32_t aOui) { WriteUint24(aOui, mOui); }
+ void SetOui(uint32_t aOui) { BigEndian::WriteUint24(aOui, mOui); }
/**
* Returns the Build value.
@@ -1654,7 +1056,7 @@ public:
* @returns The Build value.
*
*/
- uint16_t GetBuild(void) const { return (HostSwap16(mBuildRevision) & kBuildMask) >> kBuildOffset; }
+ uint16_t GetBuild(void) const { return (BigEndian::HostSwap16(mBuildRevision) & kBuildMask) >> kBuildOffset; }
/**
* Sets the Build value.
@@ -1664,8 +1066,8 @@ public:
*/
void SetBuild(uint16_t aBuild)
{
- mBuildRevision =
- HostSwap16((HostSwap16(mBuildRevision) & ~kBuildMask) | ((aBuild << kBuildOffset) & kBuildMask));
+ mBuildRevision = BigEndian::HostSwap16((BigEndian::HostSwap16(mBuildRevision) & ~kBuildMask) |
+ ((aBuild << kBuildOffset) & kBuildMask));
}
/**
@@ -1674,7 +1076,7 @@ public:
* @returns The Revision value.
*
*/
- uint8_t GetRevision(void) const { return (HostSwap16(mBuildRevision) & kRevMask) >> kRevOffset; }
+ uint8_t GetRevision(void) const { return (BigEndian::HostSwap16(mBuildRevision) & kRevMask) >> kRevOffset; }
/**
* Sets the Revision value.
@@ -1684,7 +1086,8 @@ public:
*/
void SetRevision(uint8_t aRevision)
{
- mBuildRevision = HostSwap16((HostSwap16(mBuildRevision) & ~kRevMask) | ((aRevision << kRevOffset) & kRevMask));
+ mBuildRevision = BigEndian::HostSwap16((BigEndian::HostSwap16(mBuildRevision) & ~kRevMask) |
+ ((aRevision << kRevOffset) & kRevMask));
}
/**
@@ -1763,7 +1166,7 @@ public:
* @returns The source port.
*
*/
- uint16_t GetSourcePort(void) const { return HostSwap16(mSourcePort); }
+ uint16_t GetSourcePort(void) const { return BigEndian::HostSwap16(mSourcePort); }
/**
* Updates the source port.
@@ -1771,7 +1174,7 @@ public:
* @param[in] aSourcePort The source port.
*
*/
- void SetSourcePort(uint16_t aSourcePort) { mSourcePort = HostSwap16(aSourcePort); }
+ void SetSourcePort(uint16_t aSourcePort) { mSourcePort = BigEndian::HostSwap16(aSourcePort); }
/**
* Returns the destination port.
@@ -1779,7 +1182,7 @@ public:
* @returns The destination port.
*
*/
- uint16_t GetDestinationPort(void) const { return HostSwap16(mDestinationPort); }
+ uint16_t GetDestinationPort(void) const { return BigEndian::HostSwap16(mDestinationPort); }
/**
* Updates the destination port.
@@ -1787,7 +1190,7 @@ public:
* @param[in] aDestinationPort The destination port.
*
*/
- void SetDestinationPort(uint16_t aDestinationPort) { mDestinationPort = HostSwap16(aDestinationPort); }
+ void SetDestinationPort(uint16_t aDestinationPort) { mDestinationPort = BigEndian::HostSwap16(aDestinationPort); }
private:
uint16_t mSourcePort;
@@ -1962,23 +1365,23 @@ public:
* @retval FALSE If the Commercial Commissioning Mode flag is not set.
*
*/
- bool IsCommercialCommissioningMode(void) const { return (mFlags & kCCMMask) != 0; }
+ bool IsCommercialCommissioningMode(void) const { return (mFlags & kCcmMask) != 0; }
/**
* Sets the Commercial Commissioning Mode flag.
*
- * @param[in] aCCM TRUE if set, FALSE otherwise.
+ * @param[in] aCcm TRUE if set, FALSE otherwise.
*
*/
- void SetCommercialCommissioningMode(bool aCCM)
+ void SetCommercialCommissioningMode(bool aCcm)
{
- if (aCCM)
+ if (aCcm)
{
- mFlags |= kCCMMask;
+ mFlags |= kCcmMask;
}
else
{
- mFlags &= ~kCCMMask;
+ mFlags &= ~kCcmMask;
}
}
@@ -1987,8 +1390,8 @@ private:
static constexpr uint8_t kVersionMask = 0xf << kVersionOffset;
static constexpr uint8_t kNativeOffset = 3;
static constexpr uint8_t kNativeMask = 1 << kNativeOffset;
- static constexpr uint8_t kCCMOffset = 2;
- static constexpr uint8_t kCCMMask = 1 << kCCMOffset;
+ static constexpr uint8_t kCcmOffset = 2;
+ static constexpr uint8_t kCcmMask = 1 << kCcmOffset;
uint8_t mFlags;
uint8_t mReserved;
@@ -2029,7 +1432,7 @@ public:
* @returns The Vendor OUI value.
*
*/
- uint32_t GetOui(void) const { return ReadUint24(mOui); }
+ uint32_t GetOui(void) const { return BigEndian::ReadUint24(mOui); }
/**
* Sets the Vendor OUI value.
@@ -2037,7 +1440,7 @@ public:
* @param[in] aOui The Vendor OUI value.
*
*/
- void SetOui(uint32_t aOui) { return WriteUint24(aOui, mOui); }
+ void SetOui(uint32_t aOui) { return BigEndian::WriteUint24(aOui, mOui); }
/**
* Returns the Adv Data length.
diff --git a/src/core/meshcop/panid_query_client.cpp b/src/core/meshcop/panid_query_client.cpp
index 8c6a004ef..431e8c2fa 100644
--- a/src/core/meshcop/panid_query_client.cpp
+++ b/src/core/meshcop/panid_query_client.cpp
@@ -39,9 +39,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/meshcop/timestamp.hpp b/src/core/meshcop/timestamp.hpp
index 5d7abb322..d4f8e471f 100644
--- a/src/core/meshcop/timestamp.hpp
+++ b/src/core/meshcop/timestamp.hpp
@@ -49,9 +49,6 @@
namespace ot {
namespace MeshCoP {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* Implements Timestamp generation and parsing.
*
@@ -80,7 +77,7 @@ public:
*/
uint64_t GetSeconds(void) const
{
- return (static_cast<uint64_t>(HostSwap16(mSeconds16)) << 32) + HostSwap32(mSeconds32);
+ return (static_cast<uint64_t>(BigEndian::HostSwap16(mSeconds16)) << 32) + BigEndian::HostSwap32(mSeconds32);
}
/**
@@ -91,8 +88,8 @@ public:
*/
void SetSeconds(uint64_t aSeconds)
{
- mSeconds16 = HostSwap16(static_cast<uint16_t>(aSeconds >> 32));
- mSeconds32 = HostSwap32(static_cast<uint32_t>(aSeconds & 0xffffffff));
+ mSeconds16 = BigEndian::HostSwap16(static_cast<uint16_t>(aSeconds >> 32));
+ mSeconds32 = BigEndian::HostSwap32(static_cast<uint32_t>(aSeconds & 0xffffffff));
}
/**
@@ -101,7 +98,7 @@ public:
* @returns The Ticks value.
*
*/
- uint16_t GetTicks(void) const { return HostSwap16(mTicks) >> kTicksOffset; }
+ uint16_t GetTicks(void) const { return BigEndian::HostSwap16(mTicks) >> kTicksOffset; }
/**
* Sets the Ticks value.
@@ -111,7 +108,8 @@ public:
*/
void SetTicks(uint16_t aTicks)
{
- mTicks = HostSwap16((HostSwap16(mTicks) & ~kTicksMask) | ((aTicks << kTicksOffset) & kTicksMask));
+ mTicks = BigEndian::HostSwap16((BigEndian::HostSwap16(mTicks) & ~kTicksMask) |
+ ((aTicks << kTicksOffset) & kTicksMask));
}
/**
@@ -120,7 +118,7 @@ public:
* @returns The Authoritative value.
*
*/
- bool GetAuthoritative(void) const { return (HostSwap16(mTicks) & kAuthoritativeMask) != 0; }
+ bool GetAuthoritative(void) const { return (BigEndian::HostSwap16(mTicks) & kAuthoritativeMask) != 0; }
/**
* Sets the Authoritative value.
@@ -130,8 +128,8 @@ public:
*/
void SetAuthoritative(bool aAuthoritative)
{
- mTicks = HostSwap16((HostSwap16(mTicks) & kTicksMask) |
- ((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask));
+ mTicks = BigEndian::HostSwap16((BigEndian::HostSwap16(mTicks) & kTicksMask) |
+ ((aAuthoritative << kAuthoritativeOffset) & kAuthoritativeMask));
}
/**
diff --git a/src/core/net/checksum.cpp b/src/core/net/checksum.cpp
index df761d429..c343fe54b 100644
--- a/src/core/net/checksum.cpp
+++ b/src/core/net/checksum.cpp
@@ -34,14 +34,18 @@
#include "checksum.hpp"
#include "common/code_utils.hpp"
+#include "common/log.hpp"
#include "common/message.hpp"
#include "net/icmp6.hpp"
#include "net/ip4_types.hpp"
+#include "net/ip6.hpp"
#include "net/tcp6.hpp"
#include "net/udp6.hpp"
namespace ot {
+RegisterLogModule("Ip6");
+
void Checksum::AddUint8(uint8_t aUint8)
{
uint16_t newValue = mValue;
@@ -85,7 +89,7 @@ void Checksum::WriteToMessage(uint16_t aOffset, Message &aMessage) const
checksum = ~checksum;
}
- checksum = Encoding::BigEndian::HostSwap16(checksum);
+ checksum = BigEndian::HostSwap16(checksum);
aMessage.Write(aOffset, checksum);
}
@@ -147,11 +151,18 @@ void Checksum::Calculate(const Ip4::Address &aSource,
Error Checksum::VerifyMessageChecksum(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, uint8_t aIpProto)
{
+ Error error = kErrorNone;
Checksum checksum;
checksum.Calculate(aMessageInfo.GetPeerAddr(), aMessageInfo.GetSockAddr(), aIpProto, aMessage);
- return (checksum.GetValue() == kValidRxChecksum) ? kErrorNone : kErrorDrop;
+ if (checksum.GetValue() != kValidRxChecksum)
+ {
+ LogNote("Bad %s checksum", Ip6::Ip6::IpProtoToString(aIpProto));
+ error = kErrorDrop;
+ }
+
+ return error;
}
void Checksum::UpdateMessageChecksum(Message &aMessage,
diff --git a/src/core/net/dhcp6.hpp b/src/core/net/dhcp6.hpp
index b2a0c187e..62a3d7b80 100644
--- a/src/core/net/dhcp6.hpp
+++ b/src/core/net/dhcp6.hpp
@@ -48,9 +48,6 @@
namespace ot {
namespace Dhcp6 {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-dhcp6
*
@@ -217,7 +214,7 @@ public:
* @returns The DHCPv6 option code.
*
*/
- Code GetCode(void) const { return static_cast<Code>(HostSwap16(mCode)); }
+ Code GetCode(void) const { return static_cast<Code>(BigEndian::HostSwap16(mCode)); }
/**
* Sets the DHCPv6 option code.
@@ -225,7 +222,7 @@ public:
* @param[in] aCode The DHCPv6 option code.
*
*/
- void SetCode(Code aCode) { mCode = HostSwap16(static_cast<uint16_t>(aCode)); }
+ void SetCode(Code aCode) { mCode = BigEndian::HostSwap16(static_cast<uint16_t>(aCode)); }
/**
* Returns the length of DHCPv6 option.
@@ -233,7 +230,7 @@ public:
* @returns The length of DHCPv6 option.
*
*/
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
+ uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
/**
* Sets the length of DHCPv6 option.
@@ -241,7 +238,7 @@ public:
* @param[in] aLength The length of DHCPv6 option.
*
*/
- void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
+ void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); }
private:
uint16_t mCode;
@@ -279,7 +276,7 @@ public:
* @returns The client DUID Type.
*
*/
- DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
+ DuidType GetDuidType(void) const { return static_cast<DuidType>(BigEndian::HostSwap16(mDuidType)); }
/**
* Sets the client DUID Type.
@@ -287,7 +284,7 @@ public:
* @param[in] aDuidType The client DUID Type.
*
*/
- void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
+ void SetDuidType(DuidType aDuidType) { mDuidType = BigEndian::HostSwap16(static_cast<uint16_t>(aDuidType)); }
/**
* Returns the client Duid HardwareType.
@@ -295,7 +292,7 @@ public:
* @returns The client Duid HardwareType.
*
*/
- uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
+ uint16_t GetDuidHardwareType(void) const { return BigEndian::HostSwap16(mDuidHardwareType); }
/**
* Sets the client Duid HardwareType.
@@ -303,7 +300,10 @@ public:
* @param[in] aDuidHardwareType The client Duid HardwareType.
*
*/
- void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
+ void SetDuidHardwareType(uint16_t aDuidHardwareType)
+ {
+ mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType);
+ }
/**
* Returns the client LinkLayerAddress.
@@ -350,7 +350,7 @@ public:
* @returns The server DUID Type.
*
*/
- DuidType GetDuidType(void) const { return static_cast<DuidType>(HostSwap16(mDuidType)); }
+ DuidType GetDuidType(void) const { return static_cast<DuidType>(BigEndian::HostSwap16(mDuidType)); }
/**
* Sets the server DUID Type.
@@ -358,7 +358,7 @@ public:
* @param[in] aDuidType The server DUID Type.
*
*/
- void SetDuidType(DuidType aDuidType) { mDuidType = HostSwap16(static_cast<uint16_t>(aDuidType)); }
+ void SetDuidType(DuidType aDuidType) { mDuidType = BigEndian::HostSwap16(static_cast<uint16_t>(aDuidType)); }
/**
* Returns the server DUID HardwareType.
@@ -366,7 +366,7 @@ public:
* @returns The server DUID HardwareType.
*
*/
- uint16_t GetDuidHardwareType(void) const { return HostSwap16(mDuidHardwareType); }
+ uint16_t GetDuidHardwareType(void) const { return BigEndian::HostSwap16(mDuidHardwareType); }
/**
* Sets the server DUID HardwareType.
@@ -374,7 +374,10 @@ public:
* @param[in] aDuidHardwareType The server DUID HardwareType.
*
*/
- void SetDuidHardwareType(uint16_t aDuidHardwareType) { mDuidHardwareType = HostSwap16(aDuidHardwareType); }
+ void SetDuidHardwareType(uint16_t aDuidHardwareType)
+ {
+ mDuidHardwareType = BigEndian::HostSwap16(aDuidHardwareType);
+ }
/**
* Returns the server LinkLayerAddress.
@@ -428,7 +431,7 @@ public:
* @returns The client IAID.
*
*/
- uint32_t GetIaid(void) const { return HostSwap32(mIaid); }
+ uint32_t GetIaid(void) const { return BigEndian::HostSwap32(mIaid); }
/**
* Sets the client IAID.
@@ -436,7 +439,7 @@ public:
* @param[in] aIaid The client IAID.
*
*/
- void SetIaid(uint32_t aIaid) { mIaid = HostSwap32(aIaid); }
+ void SetIaid(uint32_t aIaid) { mIaid = BigEndian::HostSwap32(aIaid); }
/**
* Returns T1.
@@ -444,7 +447,7 @@ public:
* @returns The value of T1.
*
*/
- uint32_t GetT1(void) const { return HostSwap32(mT1); }
+ uint32_t GetT1(void) const { return BigEndian::HostSwap32(mT1); }
/**
* Sets the value of T1.
@@ -452,7 +455,7 @@ public:
* @param[in] aT1 The value of T1.
*
*/
- void SetT1(uint32_t aT1) { mT1 = HostSwap32(aT1); }
+ void SetT1(uint32_t aT1) { mT1 = BigEndian::HostSwap32(aT1); }
/**
* Returns T2.
@@ -460,7 +463,7 @@ public:
* @returns The value of T2.
*
*/
- uint32_t GetT2(void) const { return HostSwap32(mT2); }
+ uint32_t GetT2(void) const { return BigEndian::HostSwap32(mT2); }
/**
* Sets the value of T2.
@@ -468,7 +471,7 @@ public:
* @param[in] aT2 The value of T2.
*
*/
- void SetT2(uint32_t aT2) { mT2 = HostSwap32(aT2); }
+ void SetT2(uint32_t aT2) { mT2 = BigEndian::HostSwap32(aT2); }
private:
uint32_t mIaid;
@@ -527,7 +530,7 @@ public:
* @returns The preferred lifetime of the IPv6 address.
*
*/
- uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
+ uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); }
/**
* Sets the preferred lifetime of the IPv6 address.
@@ -535,7 +538,10 @@ public:
* @param[in] aPreferredLifetime The preferred lifetime of the IPv6 address.
*
*/
- void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
+ void SetPreferredLifetime(uint32_t aPreferredLifetime)
+ {
+ mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime);
+ }
/**
* Returns the valid lifetime of the IPv6 address.
@@ -543,7 +549,7 @@ public:
* @returns The valid lifetime of the IPv6 address.
*
*/
- uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
+ uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); }
/**
* Sets the valid lifetime of the IPv6 address.
@@ -551,7 +557,7 @@ public:
* @param[in] aValidLifetime The valid lifetime of the IPv6 address.
*
*/
- void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
+ void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); }
private:
Ip6::Address mAddress;
@@ -583,7 +589,7 @@ public:
* @returns The elapsed time since solicit starts.
*
*/
- uint16_t GetElapsedTime(void) const { return HostSwap16(mElapsedTime); }
+ uint16_t GetElapsedTime(void) const { return BigEndian::HostSwap16(mElapsedTime); }
/**
* Sets the elapsed time since solicit starts.
@@ -591,7 +597,7 @@ public:
* @param[in] aElapsedTime The elapsed time since solicit starts.
*
*/
- void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = HostSwap16(aElapsedTime); }
+ void SetElapsedTime(uint16_t aElapsedTime) { mElapsedTime = BigEndian::HostSwap16(aElapsedTime); }
private:
uint16_t mElapsedTime;
@@ -639,7 +645,7 @@ public:
* @returns The status code.
*
*/
- Status GetStatusCode(void) const { return static_cast<Status>(HostSwap16(mStatus)); }
+ Status GetStatusCode(void) const { return static_cast<Status>(BigEndian::HostSwap16(mStatus)); }
/**
* Sets the status code.
@@ -647,7 +653,7 @@ public:
* @param[in] aStatus The status code.
*
*/
- void SetStatusCode(Status aStatus) { mStatus = HostSwap16(static_cast<uint16_t>(aStatus)); }
+ void SetStatusCode(Status aStatus) { mStatus = BigEndian::HostSwap16(static_cast<uint16_t>(aStatus)); }
private:
uint16_t mStatus;
diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp
index db671357a..680ea049e 100644
--- a/src/core/net/dhcp6_client.cpp
+++ b/src/core/net/dhcp6_client.cpp
@@ -38,9 +38,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "mac/mac.hpp"
#include "net/dhcp6.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp
index 826d5fefc..c268e1c6f 100644
--- a/src/core/net/dhcp6_server.cpp
+++ b/src/core/net/dhcp6_server.cpp
@@ -39,9 +39,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "thread/mle.hpp"
#include "thread/thread_netif.hpp"
@@ -485,21 +485,6 @@ Error Server::AppendRapidCommit(Message &aMessage)
return aMessage.Append(option);
}
-void Server::ApplyMeshLocalPrefix(void)
-{
- for (PrefixAgent &prefixAgent : mPrefixAgents)
- {
- if (prefixAgent.IsValid())
- {
- PrefixAgent *entry = &prefixAgent;
-
- Get<ThreadNetif>().RemoveUnicastAddress(entry->GetAloc());
- entry->GetAloc().GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(entry->GetAloc());
- }
- }
-}
-
} // namespace Dhcp6
} // namespace ot
diff --git a/src/core/net/dhcp6_server.hpp b/src/core/net/dhcp6_server.hpp
index d38c40edc..eba2d6c96 100644
--- a/src/core/net/dhcp6_server.hpp
+++ b/src/core/net/dhcp6_server.hpp
@@ -80,12 +80,6 @@ public:
*/
Error UpdateService(void);
- /**
- * Applies the Mesh Local Prefix.
- *
- */
- void ApplyMeshLocalPrefix(void);
-
private:
class PrefixAgent
{
@@ -173,6 +167,7 @@ private:
mAloc.InitAsThreadOrigin();
mAloc.GetAddress().SetToAnycastLocator(aMeshLocalPrefix, (Ip6::Address::kAloc16Mask << 8) + aContextId);
+ mAloc.mMeshLocal = true;
}
private:
diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp
index ef3fb3da2..366a657a4 100644
--- a/src/core/net/dns_client.cpp
+++ b/src/core/net/dns_client.cpp
@@ -34,9 +34,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "net/udp6.hpp"
#include "thread/network_data_types.hpp"
#include "thread/thread_netif.hpp"
@@ -49,11 +49,6 @@
namespace ot {
namespace Dns {
-#if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE
-using ot::Encoding::BigEndian::ReadUint16;
-using ot::Encoding::BigEndian::WriteUint16;
-#endif
-
RegisterLogModule("DnsClient");
//---------------------------------------------------------------------------------------------------------------------
@@ -1172,7 +1167,7 @@ Error Client::SendQuery(Query &aQuery, QueryInfo &aInfo, bool aUpdateTimer)
PrepareTcpMessage(*message);
break;
case kTcpConnectedSending:
- WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
+ BigEndian::WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
SuccessOrAssert(error = message->Read(message->GetOffset(),
(mSendBufferBytes + sizeof(uint16_t) + mSendLink.mLength), length));
IgnoreError(mEndpoint.SendByExtension(length + sizeof(uint16_t), /* aFlags */ 0));
@@ -1678,7 +1673,7 @@ void Client::PrepareTcpMessage(Message &aMessage)
uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
// Prepending the DNS query with length of the packet according to RFC1035.
- WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
+ BigEndian::WriteUint16(length, mSendBufferBytes + mSendLink.mLength);
SuccessOrAssert(
aMessage.Read(aMessage.GetOffset(), (mSendBufferBytes + sizeof(uint16_t) + mSendLink.mLength), length));
mSendLink.mLength += length + sizeof(uint16_t);
@@ -1788,7 +1783,7 @@ void Client::HandleTcpReceiveAvailable(otTcpEndpoint *aEndpoint,
SuccessOrExit(ReadFromLinkBuffer(data, offset, *message, sizeof(uint16_t)));
IgnoreError(message->Read(/* aOffset */ 0, length));
- length = HostSwap16(length);
+ length = BigEndian::HostSwap16(length);
// Try to read `length` bytes.
IgnoreError(message->SetLength(0));
diff --git a/src/core/net/dns_dso.cpp b/src/core/net/dns_dso.cpp
index 179e57cee..175afbcda 100644
--- a/src/core/net/dns_dso.cpp
+++ b/src/core/net/dns_dso.cpp
@@ -34,11 +34,11 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
/**
* @file
diff --git a/src/core/net/dns_dso.hpp b/src/core/net/dns_dso.hpp
index 447fa509a..fdaf991fb 100644
--- a/src/core/net/dns_dso.hpp
+++ b/src/core/net/dns_dso.hpp
@@ -60,9 +60,6 @@ struct otPlatDsoConnection
namespace ot {
namespace Dns {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
extern "C" otPlatDsoConnection *otPlatDsoAccept(otInstance *aInstance, const otSockAddr *aPeerSockAddr);
extern "C" void otPlatDsoHandleConnected(otPlatDsoConnection *aConnection);
@@ -149,8 +146,8 @@ public:
*/
void Init(Type aType, uint16_t aLength)
{
- mType = HostSwap16(aType);
- mLength = HostSwap16(aLength);
+ mType = BigEndian::HostSwap16(aType);
+ mLength = BigEndian::HostSwap16(aLength);
}
/**
@@ -159,7 +156,7 @@ public:
* @returns The TLV type.
*
*/
- Type GetType(void) const { return HostSwap16(mType); }
+ Type GetType(void) const { return BigEndian::HostSwap16(mType); }
/**
* Gets the TLV length.
@@ -167,7 +164,7 @@ public:
* @returns The TLV length (in bytes).
*
*/
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
+ uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
/**
* Returns the total size of the TLV (including the type and length fields).
@@ -911,11 +908,11 @@ private:
bool IsValid(void) const { return GetSize() >= sizeof(*this); }
- uint32_t GetInactivityTimeout(void) const { return HostSwap32(mInactivityTimeout); }
- void SetInactivityTimeout(uint32_t aTimeout) { mInactivityTimeout = HostSwap32(aTimeout); }
+ uint32_t GetInactivityTimeout(void) const { return BigEndian::HostSwap32(mInactivityTimeout); }
+ void SetInactivityTimeout(uint32_t aTimeout) { mInactivityTimeout = BigEndian::HostSwap32(aTimeout); }
- uint32_t GetKeepAliveInterval(void) const { return HostSwap32(mKeepAliveInterval); }
- void SetKeepAliveInterval(uint32_t aInterval) { mKeepAliveInterval = HostSwap32(aInterval); }
+ uint32_t GetKeepAliveInterval(void) const { return BigEndian::HostSwap32(mKeepAliveInterval); }
+ void SetKeepAliveInterval(uint32_t aInterval) { mKeepAliveInterval = BigEndian::HostSwap32(aInterval); }
private:
uint32_t mInactivityTimeout; // In msec
@@ -932,8 +929,8 @@ private:
bool IsValid(void) const { return GetSize() >= sizeof(*this); }
- uint32_t GetRetryDelay(void) const { return HostSwap32(mRetryDelay); }
- void SetRetryDelay(uint32_t aDelay) { mRetryDelay = HostSwap32(aDelay); }
+ uint32_t GetRetryDelay(void) const { return BigEndian::HostSwap32(mRetryDelay); }
+ void SetRetryDelay(uint32_t aDelay) { mRetryDelay = BigEndian::HostSwap32(aDelay); }
private:
uint32_t mRetryDelay;
diff --git a/src/core/net/dns_platform.cpp b/src/core/net/dns_platform.cpp
index ef48077b6..109f018e7 100644
--- a/src/core/net/dns_platform.cpp
+++ b/src/core/net/dns_platform.cpp
@@ -37,8 +37,8 @@
#include <openthread/platform/dns.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp
index ec640b294..aa19c73bf 100644
--- a/src/core/net/dns_types.cpp
+++ b/src/core/net/dns_types.cpp
@@ -35,16 +35,14 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
+#include "instance/instance.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));
@@ -244,7 +242,7 @@ Error Name::AppendPointerLabel(uint16_t aOffset, Message &aMessage)
OT_ASSERT(aOffset < kPointerLabelTypeUint16);
- value = HostSwap16(aOffset | kPointerLabelTypeUint16);
+ value = BigEndian::HostSwap16(aOffset | kPointerLabelTypeUint16);
ExitNow(error = aMessage.Append(value));
@@ -528,7 +526,7 @@ Error Name::LabelIterator::GetNextLabel(void)
// `mMessage.GetOffset()` must point to the start of the
// DNS header.
- nextLabelOffset = mMessage.GetOffset() + (HostSwap16(pointerValue) & kPointerLabelOffsetMask);
+ nextLabelOffset = mMessage.GetOffset() + (BigEndian::HostSwap16(pointerValue) & kPointerLabelOffsetMask);
VerifyOrExit(nextLabelOffset < mNextLabelOffset, error = kErrorParse);
mNextLabelOffset = nextLabelOffset;
@@ -953,7 +951,7 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry)
const char *cur;
char *keyBuffer = GetKeyBuffer();
- static_assert(sizeof(mChar) == TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length");
+ static_assert(sizeof(mChar) >= TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length");
VerifyOrExit(GetTxtData() != nullptr, error = kErrorParse);
@@ -985,9 +983,9 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry)
ExitNow();
}
- if (index >= kMaxKeyLength)
+ if (index >= sizeof(mChar) - 1)
{
- // The key is larger than recommended max key length.
+ // The key is larger than supported key string length.
// In this case, we return the full encoded string in
// `mValue` and `mValueLength` and set `mKey` to
// `nullptr`.
diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp
index 6c9caa4cb..9f8a93093 100644
--- a/src/core/net/dns_types.hpp
+++ b/src/core/net/dns_types.hpp
@@ -59,9 +59,6 @@ namespace ot {
*/
namespace Dns {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-dns
*
@@ -92,7 +89,7 @@ public:
* @returns The Message ID value.
*
*/
- uint16_t GetMessageId(void) const { return HostSwap16(mMessageId); }
+ uint16_t GetMessageId(void) const { return BigEndian::HostSwap16(mMessageId); }
/**
* Sets the Message ID.
@@ -100,7 +97,7 @@ public:
* @param[in] aMessageId The Message ID value.
*
*/
- void SetMessageId(uint16_t aMessageId) { mMessageId = HostSwap16(aMessageId); }
+ void SetMessageId(uint16_t aMessageId) { mMessageId = BigEndian::HostSwap16(aMessageId); }
/**
* Sets the Message ID to a crypto-secure randomly generated number.
@@ -331,7 +328,7 @@ public:
* @returns The number of entries in question section.
*
*/
- uint16_t GetQuestionCount(void) const { return HostSwap16(mQdCount); }
+ uint16_t GetQuestionCount(void) const { return BigEndian::HostSwap16(mQdCount); }
/**
* Sets the number of entries in question section.
@@ -339,7 +336,7 @@ public:
* @param[in] aCount The number of entries in question section.
*
*/
- void SetQuestionCount(uint16_t aCount) { mQdCount = HostSwap16(aCount); }
+ void SetQuestionCount(uint16_t aCount) { mQdCount = BigEndian::HostSwap16(aCount); }
/**
* Returns the number of entries in answer section.
@@ -347,7 +344,7 @@ public:
* @returns The number of entries in answer section.
*
*/
- uint16_t GetAnswerCount(void) const { return HostSwap16(mAnCount); }
+ uint16_t GetAnswerCount(void) const { return BigEndian::HostSwap16(mAnCount); }
/**
* Sets the number of entries in answer section.
@@ -355,7 +352,7 @@ public:
* @param[in] aCount The number of entries in answer section.
*
*/
- void SetAnswerCount(uint16_t aCount) { mAnCount = HostSwap16(aCount); }
+ void SetAnswerCount(uint16_t aCount) { mAnCount = BigEndian::HostSwap16(aCount); }
/**
* Returns the number of entries in authority records section.
@@ -363,7 +360,7 @@ public:
* @returns The number of entries in authority records section.
*
*/
- uint16_t GetAuthorityRecordCount(void) const { return HostSwap16(mNsCount); }
+ uint16_t GetAuthorityRecordCount(void) const { return BigEndian::HostSwap16(mNsCount); }
/**
* Sets the number of entries in authority records section.
@@ -371,7 +368,7 @@ public:
* @param[in] aCount The number of entries in authority records section.
*
*/
- void SetAuthorityRecordCount(uint16_t aCount) { mNsCount = HostSwap16(aCount); }
+ void SetAuthorityRecordCount(uint16_t aCount) { mNsCount = BigEndian::HostSwap16(aCount); }
/**
* Returns the number of entries in additional records section.
@@ -379,7 +376,7 @@ public:
* @returns The number of entries in additional records section.
*
*/
- uint16_t GetAdditionalRecordCount(void) const { return HostSwap16(mArCount); }
+ uint16_t GetAdditionalRecordCount(void) const { return BigEndian::HostSwap16(mArCount); }
/**
* Sets the number of entries in additional records section.
@@ -387,7 +384,7 @@ public:
* @param[in] aCount The number of entries in additional records section.
*
*/
- void SetAdditionalRecordCount(uint16_t aCount) { mArCount = HostSwap16(aCount); }
+ void SetAdditionalRecordCount(uint16_t aCount) { mArCount = BigEndian::HostSwap16(aCount); }
private:
// Protocol Constants (RFC 1035).
@@ -1057,6 +1054,14 @@ public:
static constexpr uint8_t kMaxKeyLength = OT_DNS_TXT_KEY_MAX_LENGTH;
/**
+ * Maximum length of TXT key string supported by `Iterator`.
+ *
+ * This is selected to be longer than recommended `kMaxKeyLength` to handle cases where longer keys are used.
+ *
+ */
+ static constexpr uint8_t kMaxIterKeyLength = OT_DNS_TXT_KEY_ITER_MAX_LENGTH;
+
+ /**
* Represents an iterator for TXT record entries (key/value pairs).
*
*/
@@ -1083,9 +1088,9 @@ public:
* 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`.
+ * If the parsed key string length is smaller than or equal to `kMaxIterKeyLength` the key string is returned
+ * in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to `nullptr` 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.
*
@@ -1245,7 +1250,7 @@ public:
*/
bool Matches(uint16_t aType, uint16_t aClass = kClassInternet) const
{
- return (mType == HostSwap16(aType)) && (mClass == HostSwap16(aClass));
+ return (mType == BigEndian::HostSwap16(aType)) && (mClass == BigEndian::HostSwap16(aClass));
}
/**
@@ -1254,7 +1259,7 @@ public:
* @returns The type of the resource record.
*
*/
- uint16_t GetType(void) const { return HostSwap16(mType); }
+ uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); }
/**
* Sets the type of the resource record.
@@ -1262,7 +1267,7 @@ public:
* @param[in] aType The type of the resource record.
*
*/
- void SetType(uint16_t aType) { mType = HostSwap16(aType); }
+ void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); }
/**
* Returns the class of the resource record.
@@ -1270,7 +1275,7 @@ public:
* @returns The class of the resource record.
*
*/
- uint16_t GetClass(void) const { return HostSwap16(mClass); }
+ uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); }
/**
* Sets the class of the resource record.
@@ -1278,7 +1283,7 @@ public:
* @param[in] aClass The class of the resource record.
*
*/
- void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
+ void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); }
/**
* Returns the time to live field of the resource record.
@@ -1286,7 +1291,7 @@ public:
* @returns The time to live field of the resource record.
*
*/
- uint32_t GetTtl(void) const { return HostSwap32(mTtl); }
+ uint32_t GetTtl(void) const { return BigEndian::HostSwap32(mTtl); }
/**
* Sets the time to live field of the resource record.
@@ -1294,7 +1299,7 @@ public:
* @param[in] aTtl The time to live field of the resource record.
*
*/
- void SetTtl(uint32_t aTtl) { mTtl = HostSwap32(aTtl); }
+ void SetTtl(uint32_t aTtl) { mTtl = BigEndian::HostSwap32(aTtl); }
/**
* Returns the length of the resource record data.
@@ -1302,7 +1307,7 @@ public:
* @returns The length of the resource record data.
*
*/
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
+ uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
/**
* Sets the length of the resource record data.
@@ -1310,7 +1315,7 @@ public:
* @param[in] aLength The length of the resource record data.
*
*/
- void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
+ void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); }
/**
* Returns the size of (number of bytes) in resource record and its data RDATA section (excluding the
@@ -1791,7 +1796,7 @@ public:
* @returns The priority value.
*
*/
- uint16_t GetPriority(void) const { return HostSwap16(mPriority); }
+ uint16_t GetPriority(void) const { return BigEndian::HostSwap16(mPriority); }
/**
* Sets the SRV record's priority value.
@@ -1799,7 +1804,7 @@ public:
* @param[in] aPriority The priority value.
*
*/
- void SetPriority(uint16_t aPriority) { mPriority = HostSwap16(aPriority); }
+ void SetPriority(uint16_t aPriority) { mPriority = BigEndian::HostSwap16(aPriority); }
/**
* Returns the SRV record's weight value.
@@ -1807,7 +1812,7 @@ public:
* @returns The weight value.
*
*/
- uint16_t GetWeight(void) const { return HostSwap16(mWeight); }
+ uint16_t GetWeight(void) const { return BigEndian::HostSwap16(mWeight); }
/**
* Sets the SRV record's weight value.
@@ -1815,7 +1820,7 @@ public:
* @param[in] aWeight The weight value.
*
*/
- void SetWeight(uint16_t aWeight) { mWeight = HostSwap16(aWeight); }
+ void SetWeight(uint16_t aWeight) { mWeight = BigEndian::HostSwap16(aWeight); }
/**
* Returns the SRV record's port number on the target host for this service.
@@ -1823,7 +1828,7 @@ public:
* @returns The port number.
*
*/
- uint16_t GetPort(void) const { return HostSwap16(mPort); }
+ uint16_t GetPort(void) const { return BigEndian::HostSwap16(mPort); }
/**
* Sets the SRV record's port number on the target host for this service.
@@ -1831,7 +1836,7 @@ public:
* @param[in] aPort The port number.
*
*/
- void SetPort(uint16_t aPort) { mPort = HostSwap16(aPort); }
+ void SetPort(uint16_t aPort) { mPort = BigEndian::HostSwap16(aPort); }
/**
* Parses and reads the SRV target host name from a message.
@@ -2123,7 +2128,7 @@ public:
* @returns The type-covered value.
*
*/
- uint16_t GetTypeCovered(void) const { return HostSwap16(mTypeCovered); }
+ uint16_t GetTypeCovered(void) const { return BigEndian::HostSwap16(mTypeCovered); }
/**
* Sets the SIG record's type-covered value.
@@ -2131,7 +2136,7 @@ public:
* @param[in] aTypeCovered The type-covered value.
*
*/
- void SetTypeCovered(uint8_t aTypeCovered) { mTypeCovered = HostSwap16(aTypeCovered); }
+ void SetTypeCovered(uint8_t aTypeCovered) { mTypeCovered = BigEndian::HostSwap16(aTypeCovered); }
/**
* Returns the SIG record's algorithm value.
@@ -2173,7 +2178,7 @@ public:
* @returns The original TTL value.
*
*/
- uint32_t GetOriginalTtl(void) const { return HostSwap32(mOriginalTtl); }
+ uint32_t GetOriginalTtl(void) const { return BigEndian::HostSwap32(mOriginalTtl); }
/**
* Sets the SIG record's original TTL value.
@@ -2181,7 +2186,7 @@ public:
* @param[in] aOriginalTtl The original TTL value.
*
*/
- void SetOriginalTtl(uint32_t aOriginalTtl) { mOriginalTtl = HostSwap32(aOriginalTtl); }
+ void SetOriginalTtl(uint32_t aOriginalTtl) { mOriginalTtl = BigEndian::HostSwap32(aOriginalTtl); }
/**
* Returns the SIG record's expiration time value.
@@ -2189,7 +2194,7 @@ public:
* @returns The expiration time value (seconds since Jan 1, 1970).
*
*/
- uint32_t GetExpiration(void) const { return HostSwap32(mExpiration); }
+ uint32_t GetExpiration(void) const { return BigEndian::HostSwap32(mExpiration); }
/**
* Sets the SIG record's expiration time value.
@@ -2197,7 +2202,7 @@ public:
* @param[in] aExpiration The expiration time value (seconds since Jan 1, 1970).
*
*/
- void SetExpiration(uint32_t aExpiration) { mExpiration = HostSwap32(aExpiration); }
+ void SetExpiration(uint32_t aExpiration) { mExpiration = BigEndian::HostSwap32(aExpiration); }
/**
* Returns the SIG record's inception time value.
@@ -2205,7 +2210,7 @@ public:
* @returns The inception time value (seconds since Jan 1, 1970).
*
*/
- uint32_t GetInception(void) const { return HostSwap32(mInception); }
+ uint32_t GetInception(void) const { return BigEndian::HostSwap32(mInception); }
/**
* Sets the SIG record's inception time value.
@@ -2213,7 +2218,7 @@ public:
* @param[in] aInception The inception time value (seconds since Jan 1, 1970).
*
*/
- void SetInception(uint32_t aInception) { mInception = HostSwap32(aInception); }
+ void SetInception(uint32_t aInception) { mInception = BigEndian::HostSwap32(aInception); }
/**
* Returns the SIG record's key tag value.
@@ -2221,7 +2226,7 @@ public:
* @returns The key tag value.
*
*/
- uint16_t GetKeyTag(void) const { return HostSwap16(mKeyTag); }
+ uint16_t GetKeyTag(void) const { return BigEndian::HostSwap16(mKeyTag); }
/**
* Sets the SIG record's key tag value.
@@ -2229,7 +2234,7 @@ public:
* @param[in] aKeyTag The key tag value.
*
*/
- void SetKeyTag(uint16_t aKeyTag) { mKeyTag = HostSwap16(aKeyTag); }
+ void SetKeyTag(uint16_t aKeyTag) { mKeyTag = BigEndian::HostSwap16(aKeyTag); }
/**
* Returns a pointer to the start of the record data fields.
@@ -2414,7 +2419,7 @@ public:
* @returns The option code value.
*
*/
- uint16_t GetOptionCode(void) const { return HostSwap16(mOptionCode); }
+ uint16_t GetOptionCode(void) const { return BigEndian::HostSwap16(mOptionCode); }
/**
* Sets the option code value.
@@ -2422,7 +2427,7 @@ public:
* @param[in] aOptionCode The option code value.
*
*/
- void SetOptionCode(uint16_t aOptionCode) { mOptionCode = HostSwap16(aOptionCode); }
+ void SetOptionCode(uint16_t aOptionCode) { mOptionCode = BigEndian::HostSwap16(aOptionCode); }
/**
* Returns the option length value.
@@ -2430,7 +2435,7 @@ public:
* @returns The option length (size of option data in bytes).
*
*/
- uint16_t GetOptionLength(void) const { return HostSwap16(mOptionLength); }
+ uint16_t GetOptionLength(void) const { return BigEndian::HostSwap16(mOptionLength); }
/**
* Sets the option length value.
@@ -2438,7 +2443,7 @@ public:
* @param[in] aOptionLength The option length (size of option data in bytes).
*
*/
- void SetOptionLength(uint16_t aOptionLength) { mOptionLength = HostSwap16(aOptionLength); }
+ void SetOptionLength(uint16_t aOptionLength) { mOptionLength = BigEndian::HostSwap16(aOptionLength); }
/**
* Returns the size of (number of bytes) in the Option and its data.
@@ -2511,7 +2516,7 @@ public:
* @returns The lease interval value (in seconds).
*
*/
- uint32_t GetLeaseInterval(void) const { return HostSwap32(mLeaseInterval); }
+ uint32_t GetLeaseInterval(void) const { return BigEndian::HostSwap32(mLeaseInterval); }
/**
* Returns the Update Lease OPT record's key lease interval value.
@@ -2523,7 +2528,7 @@ public:
*/
uint32_t GetKeyLeaseInterval(void) const
{
- return IsShortVariant() ? GetLeaseInterval() : HostSwap32(mKeyLeaseInterval);
+ return IsShortVariant() ? GetLeaseInterval() : BigEndian::HostSwap32(mKeyLeaseInterval);
}
/**
@@ -2547,8 +2552,11 @@ private:
static constexpr uint16_t kShortLength = sizeof(uint32_t); // lease only.
static constexpr uint16_t kLongLength = sizeof(uint32_t) + sizeof(uint32_t); // lease and key lease values
- void SetLeaseInterval(uint32_t aLeaseInterval) { mLeaseInterval = HostSwap32(aLeaseInterval); }
- void SetKeyLeaseInterval(uint32_t aKeyLeaseInterval) { mKeyLeaseInterval = HostSwap32(aKeyLeaseInterval); }
+ void SetLeaseInterval(uint32_t aLeaseInterval) { mLeaseInterval = BigEndian::HostSwap32(aLeaseInterval); }
+ void SetKeyLeaseInterval(uint32_t aKeyLeaseInterval)
+ {
+ mKeyLeaseInterval = BigEndian::HostSwap32(aKeyLeaseInterval);
+ }
uint32_t mLeaseInterval;
uint32_t mKeyLeaseInterval;
@@ -2584,7 +2592,7 @@ public:
* @returns The type of the question.
*
*/
- uint16_t GetType(void) const { return HostSwap16(mType); }
+ uint16_t GetType(void) const { return BigEndian::HostSwap16(mType); }
/**
* Sets the type of the question.
@@ -2592,7 +2600,7 @@ public:
* @param[in] aType The type of the question.
*
*/
- void SetType(uint16_t aType) { mType = HostSwap16(aType); }
+ void SetType(uint16_t aType) { mType = BigEndian::HostSwap16(aType); }
/**
* Returns the class of the question.
@@ -2600,7 +2608,7 @@ public:
* @returns The class of the question.
*
*/
- uint16_t GetClass(void) const { return HostSwap16(mClass); }
+ uint16_t GetClass(void) const { return BigEndian::HostSwap16(mClass); }
/**
* Sets the class of the question.
@@ -2608,7 +2616,7 @@ public:
* @param[in] aClass The class of the question.
*
*/
- void SetClass(uint16_t aClass) { mClass = HostSwap16(aClass); }
+ void SetClass(uint16_t aClass) { mClass = BigEndian::HostSwap16(aClass); }
private:
uint16_t mType; // The type of the data in question section.
diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp
index 3406c3d90..ea59c08d5 100644
--- a/src/core/net/dnssd_server.cpp
+++ b/src/core/net/dnssd_server.cpp
@@ -41,10 +41,10 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "net/srp_server.hpp"
#include "net/udp6.hpp"
diff --git a/src/core/net/icmp6.cpp b/src/core/net/icmp6.cpp
index 2f195b0ab..5bcea06c0 100644
--- a/src/core/net/icmp6.cpp
+++ b/src/core/net/icmp6.cpp
@@ -35,10 +35,10 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/ip6.hpp"
diff --git a/src/core/net/icmp6.hpp b/src/core/net/icmp6.hpp
index e24b9445c..ae5239a99 100644
--- a/src/core/net/icmp6.hpp
+++ b/src/core/net/icmp6.hpp
@@ -49,8 +49,6 @@
namespace ot {
namespace Ip6 {
-using ot::Encoding::BigEndian::HostSwap16;
-
/**
* @addtogroup core-ip6-icmp6
*
@@ -158,7 +156,7 @@ public:
* @returns The ICMPv6 message checksum.
*
*/
- uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
+ uint16_t GetChecksum(void) const { return BigEndian::HostSwap16(mChecksum); }
/**
* Sets the ICMPv6 message checksum.
@@ -166,7 +164,7 @@ public:
* @param[in] aChecksum The ICMPv6 message checksum.
*
*/
- void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+ void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); }
/**
* Returns the ICMPv6 message ID for Echo Requests and Replies.
@@ -174,7 +172,7 @@ public:
* @returns The ICMPv6 message ID.
*
*/
- uint16_t GetId(void) const { return HostSwap16(mData.m16[0]); }
+ uint16_t GetId(void) const { return BigEndian::HostSwap16(mData.m16[0]); }
/**
* Sets the ICMPv6 message ID for Echo Requests and Replies.
@@ -182,7 +180,7 @@ public:
* @param[in] aId The ICMPv6 message ID.
*
*/
- void SetId(uint16_t aId) { mData.m16[0] = HostSwap16(aId); }
+ void SetId(uint16_t aId) { mData.m16[0] = BigEndian::HostSwap16(aId); }
/**
* Returns the ICMPv6 message sequence for Echo Requests and Replies.
@@ -190,7 +188,7 @@ public:
* @returns The ICMPv6 message sequence.
*
*/
- uint16_t GetSequence(void) const { return HostSwap16(mData.m16[1]); }
+ uint16_t GetSequence(void) const { return BigEndian::HostSwap16(mData.m16[1]); }
/**
* Sets the ICMPv6 message sequence for Echo Requests and Replies.
@@ -198,7 +196,7 @@ public:
* @param[in] aSequence The ICMPv6 message sequence.
*
*/
- void SetSequence(uint16_t aSequence) { mData.m16[1] = HostSwap16(aSequence); }
+ void SetSequence(uint16_t aSequence) { mData.m16[1] = BigEndian::HostSwap16(aSequence); }
} OT_TOOL_PACKED_END;
/**
diff --git a/src/core/net/ip4_types.cpp b/src/core/net/ip4_types.cpp
index bbe80f198..7f03a3e0e 100644
--- a/src/core/net/ip4_types.cpp
+++ b/src/core/net/ip4_types.cpp
@@ -32,7 +32,9 @@
*/
#include "ip4_types.hpp"
-#include "ip6_address.hpp"
+
+#include "common/numeric_limits.hpp"
+#include "net/ip6_address.hpp"
namespace ot {
namespace Ip4 {
@@ -92,7 +94,7 @@ void Address::ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &a
OT_ASSERT(Ip6::Prefix::IsValidNat64PrefixLength(aPrefixLength));
- ip6Index = aPrefixLength / CHAR_BIT;
+ ip6Index = aPrefixLength / kBitsPerByte;
for (uint8_t &i : mFields.m8)
{
@@ -107,7 +109,7 @@ void Address::ExtractFromIp6Address(uint8_t aPrefixLength, const Ip6::Address &a
void Address::SynthesizeFromCidrAndHost(const Cidr &aCidr, const uint32_t aHost)
{
- mFields.m32 = (aCidr.mAddress.mFields.m32 & aCidr.SubnetMask()) | (HostSwap32(aHost) & aCidr.HostMask());
+ mFields.m32 = (aCidr.mAddress.mFields.m32 & aCidr.SubnetMask()) | (BigEndian::HostSwap32(aHost) & aCidr.HostMask());
}
void Address::ToString(StringWriter &aWriter) const
diff --git a/src/core/net/ip4_types.hpp b/src/core/net/ip4_types.hpp
index 86d908f40..8095a818a 100644
--- a/src/core/net/ip4_types.hpp
+++ b/src/core/net/ip4_types.hpp
@@ -65,9 +65,6 @@ class Address;
*/
namespace Ip4 {
-using Encoding::BigEndian::HostSwap16;
-using Encoding::BigEndian::HostSwap32;
-
using Ecn = Ip6::Ecn;
/**
@@ -279,7 +276,7 @@ private:
{
// Note: Using LL suffix to make it a uint64 since /32 is a valid CIDR, and right shifting 32 bits is undefined
// for uint32.
- return HostSwap32(0xffffffffLL >> mLength);
+ return BigEndian::HostSwap32(0xffffffffLL >> mLength);
}
uint32_t SubnetMask(void) const { return ~HostMask(); }
@@ -386,7 +383,7 @@ public:
* @returns The IPv4 Payload Length value.
*
*/
- uint16_t GetTotalLength(void) const { return HostSwap16(mTotalLength); }
+ uint16_t GetTotalLength(void) const { return BigEndian::HostSwap16(mTotalLength); }
/**
* Sets the IPv4 Payload Length value.
@@ -394,7 +391,7 @@ public:
* @param[in] aLength The IPv4 Payload Length value.
*
*/
- void SetTotalLength(uint16_t aLength) { mTotalLength = HostSwap16(aLength); }
+ void SetTotalLength(uint16_t aLength) { mTotalLength = BigEndian::HostSwap16(aLength); }
/**
* Returns the IPv4 payload protocol.
@@ -418,7 +415,7 @@ public:
* @returns The checksum field in the IPv4 header.
*
*/
- uint16_t GetChecksum(void) const { return HostSwap16(mHeaderChecksum); }
+ uint16_t GetChecksum(void) const { return BigEndian::HostSwap16(mHeaderChecksum); }
/**
* Sets the IPv4 header checksum, the checksum is in host endian.
@@ -426,7 +423,7 @@ public:
* @param[in] aChecksum The checksum for the IPv4 header.
*
*/
- void SetChecksum(uint16_t aChecksum) { mHeaderChecksum = HostSwap16(aChecksum); }
+ void SetChecksum(uint16_t aChecksum) { mHeaderChecksum = BigEndian::HostSwap16(aChecksum); }
/**
* Returns the IPv4 Identification value.
@@ -434,7 +431,7 @@ public:
* @returns The IPv4 Identification value.
*
*/
- uint16_t GetIdentification(void) const { return HostSwap16(mIdentification); }
+ uint16_t GetIdentification(void) const { return BigEndian::HostSwap16(mIdentification); }
/**
* Sets the IPv4 Identification value.
@@ -442,7 +439,7 @@ public:
* @param[in] aIdentification The IPv4 Identification value.
*
*/
- void SetIdentification(uint16_t aIdentification) { mIdentification = HostSwap16(aIdentification); }
+ void SetIdentification(uint16_t aIdentification) { mIdentification = BigEndian::HostSwap16(aIdentification); }
/**
* Returns the IPv4 Time-to-Live value.
@@ -527,7 +524,7 @@ public:
* @returns Whether don't fragment flag is set.
*
*/
- bool GetDf(void) const { return HostSwap16(mFlagsFragmentOffset) & kFlagsDf; }
+ bool GetDf(void) const { return BigEndian::HostSwap16(mFlagsFragmentOffset) & kFlagsDf; }
/**
* Returns the Mf flag in the IPv4 header.
@@ -535,7 +532,7 @@ public:
* @returns Whether more fragments flag is set.
*
*/
- bool GetMf(void) const { return HostSwap16(mFlagsFragmentOffset) & kFlagsMf; }
+ bool GetMf(void) const { return BigEndian::HostSwap16(mFlagsFragmentOffset) & kFlagsMf; }
/**
* Returns the fragment offset in the IPv4 header.
@@ -543,7 +540,7 @@ public:
* @returns The fragment offset of the IPv4 packet.
*
*/
- uint16_t GetFragmentOffset(void) const { return HostSwap16(mFlagsFragmentOffset) & kFragmentOffsetMask; }
+ uint16_t GetFragmentOffset(void) const { return BigEndian::HostSwap16(mFlagsFragmentOffset) & kFragmentOffsetMask; }
private:
// IPv4 header
@@ -660,7 +657,7 @@ public:
* @returns The checksum of the ICMP message.
*
*/
- uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
+ uint16_t GetChecksum(void) const { return BigEndian::HostSwap16(mChecksum); }
/**
* Sets the checksum field in the ICMP message.
@@ -668,7 +665,7 @@ public:
* @param[in] aChecksum The checksum of the ICMP message.
*
*/
- void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+ void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); }
/**
* Returns the rest of header field in the ICMP message.
diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp
index d55713ec6..d5ddeecad 100644
--- a/src/core/net/ip6.cpp
+++ b/src/core/net/ip6.cpp
@@ -38,11 +38,11 @@
#include "backbone_router/ndproxy_table.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/icmp6.hpp"
#include "net/ip6_address.hpp"
@@ -55,7 +55,7 @@
using IcmpType = ot::Ip6::Icmp::Header::Type;
-static const IcmpType sForwardICMPTypes[] = {
+static const IcmpType kForwardIcmpTypes[] = {
IcmpType::kTypeDstUnreach, IcmpType::kTypePacketToBig, IcmpType::kTypeTimeExceeded,
IcmpType::kTypeParameterProblem, IcmpType::kTypeEchoRequest, IcmpType::kTypeEchoReply,
};
@@ -200,12 +200,29 @@ exit:
return error;
}
-Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader)
+Error Ip6::PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader)
{
Error error = kErrorNone;
Header tunnelHeader;
const Address *source;
+#if OPENTHREAD_FTD
+ if (aHeader.GetDestination().IsMulticastLargerThanRealmLocal() &&
+ Get<ChildTable>().HasSleepyChildWithAddress(aHeader.GetDestination()))
+ {
+ Message *messageCopy = aMessage.Clone();
+
+ if (messageCopy != nullptr)
+ {
+ EnqueueDatagram(*messageCopy);
+ }
+ else
+ {
+ LogWarn("Failed to clone mcast message for indirect tx to sleepy children");
+ }
+ }
+#endif
+
// Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address.
tunnelHeader.InitVersionTrafficClassFlow();
tunnelHeader.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
@@ -280,25 +297,7 @@ Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader)
}
else
{
-#if OPENTHREAD_FTD
- if (aHeader.GetDestination().IsMulticastLargerThanRealmLocal() &&
- Get<ChildTable>().HasSleepyChildWithAddress(aHeader.GetDestination()))
- {
- Message *messageCopy = nullptr;
-
- if ((messageCopy = aMessage.Clone()) != nullptr)
- {
- IgnoreError(HandleDatagram(*messageCopy));
- LogInfo("Message copy for indirect transmission to sleepy children");
- }
- else
- {
- LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
- }
- }
-#endif
-
- SuccessOrExit(error = AddTunneledMplOption(aMessage, aHeader));
+ SuccessOrExit(error = PrepareMulticastToLargerThanRealmLocal(aMessage, aHeader));
}
exit:
@@ -469,24 +468,7 @@ Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI
if (aMessageInfo.GetPeerAddr().IsMulticastLargerThanRealmLocal())
{
-#if OPENTHREAD_FTD
- if (Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
- {
- Message *messageCopy = aMessage.Clone();
-
- if (messageCopy != nullptr)
- {
- LogInfo("Message copy for indirect transmission to sleepy children");
- EnqueueDatagram(*messageCopy);
- }
- else
- {
- LogWarn("No enough buffer for message copy for indirect transmission to sleepy children");
- }
- }
-#endif
-
- SuccessOrExit(error = AddTunneledMplOption(aMessage, header));
+ SuccessOrExit(error = PrepareMulticastToLargerThanRealmLocal(aMessage, header));
}
aMessage.SetMulticastLoop(aMessageInfo.GetMulticastLoop());
@@ -512,11 +494,11 @@ void Ip6::HandleSendQueue(void)
while ((message = mSendQueue.GetHead()) != nullptr)
{
mSendQueue.Dequeue(*message);
- IgnoreError(HandleDatagram(*message));
+ IgnoreError(HandleDatagram(OwnedPtr<Message>(message)));
}
}
-Error Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive)
+Error Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aReceive)
{
Error error = kErrorNone;
HopByHopHeader hbhHeader;
@@ -542,7 +524,7 @@ Error Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, b
if (option.GetType() == MplOption::kType)
{
- SuccessOrExit(error = mMpl.ProcessOption(aMessage, offset, aHeader.GetSource(), aIsOutbound, aReceive));
+ SuccessOrExit(error = mMpl.ProcessOption(aMessage, offset, aHeader.GetSource(), aReceive));
continue;
}
@@ -721,7 +703,8 @@ Error Ip6::HandleFragment(Message &aMessage, MessageInfo &aMessageInfo)
mReassemblyList.Dequeue(*message);
- IgnoreError(HandleDatagram(*message, aMessageInfo.mLinkInfo, /* aIsReassembled */ true));
+ IgnoreError(HandleDatagram(OwnedPtr<Message>(message), aMessageInfo.mLinkInfo,
+ /* aIsReassembled */ true));
}
exit:
@@ -823,34 +806,34 @@ exit:
}
#endif // OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
-Error Ip6::HandleExtensionHeaders(Message &aMessage,
- MessageInfo &aMessageInfo,
- Header &aHeader,
- uint8_t &aNextHeader,
- bool &aReceive)
+Error Ip6::HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr,
+ MessageInfo &aMessageInfo,
+ Header &aHeader,
+ uint8_t &aNextHeader,
+ bool &aReceive)
{
- Error error = kErrorNone;
- bool isOutbound = (aMessage.GetOrigin() != Message::kOriginThreadNetif);
+ Error error = kErrorNone;
+
ExtensionHeader extHeader;
while (aReceive || aNextHeader == kProtoHopOpts)
{
- SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), extHeader));
+ SuccessOrExit(error = aMessagePtr->Read(aMessagePtr->GetOffset(), extHeader));
switch (aNextHeader)
{
case kProtoHopOpts:
- SuccessOrExit(error = HandleOptions(aMessage, aHeader, isOutbound, aReceive));
+ SuccessOrExit(error = HandleOptions(*aMessagePtr, aHeader, aReceive));
break;
case kProtoFragment:
- IgnoreError(PassToHost(aMessage, aMessageInfo, aNextHeader,
+ IgnoreError(PassToHost(aMessagePtr, aMessageInfo, aNextHeader,
/* aApplyFilter */ false, aReceive, Message::kCopyToUse));
- SuccessOrExit(error = HandleFragment(aMessage, aMessageInfo));
+ SuccessOrExit(error = HandleFragment(*aMessagePtr, aMessageInfo));
break;
case kProtoDstOpts:
- SuccessOrExit(error = HandleOptions(aMessage, aHeader, isOutbound, aReceive));
+ SuccessOrExit(error = HandleOptions(*aMessagePtr, aHeader, aReceive));
break;
case kProtoIp6:
@@ -871,8 +854,26 @@ exit:
return error;
}
+Error Ip6::TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr,
+ OwnedPtr<Message> &aMessagePtr,
+ Message::Ownership aMessageOwnership)
+{
+ switch (aMessageOwnership)
+ {
+ case Message::kTakeCustody:
+ aTargetPtr = aMessagePtr.PassOwnership();
+ break;
+
+ case Message::kCopyToUse:
+ aTargetPtr.Reset(aMessagePtr->Clone());
+ break;
+ }
+
+ return (aTargetPtr != nullptr) ? kErrorNone : kErrorNoBufs;
+}
+
Error Ip6::HandlePayload(Header &aIp6Header,
- Message &aMessage,
+ OwnedPtr<Message> &aMessagePtr,
MessageInfo &aMessageInfo,
uint8_t aIpProto,
Message::Ownership aMessageOwnership)
@@ -881,8 +882,8 @@ Error Ip6::HandlePayload(Header &aIp6Header,
OT_UNUSED_VARIABLE(aIp6Header);
#endif
- Error error = kErrorNone;
- Message *message = (aMessageOwnership == Message::kTakeCustody) ? &aMessage : nullptr;
+ Error error = kErrorNone;
+ OwnedPtr<Message> messagePtr;
switch (aIpProto)
{
@@ -897,34 +898,21 @@ Error Ip6::HandlePayload(Header &aIp6Header,
ExitNow();
}
- if (aMessageOwnership == Message::kCopyToUse)
- {
- message = aMessage.Clone();
- }
-
- VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+ SuccessOrExit(error = TakeOrCopyMessagePtr(messagePtr, aMessagePtr, aMessageOwnership));
switch (aIpProto)
{
#if OPENTHREAD_CONFIG_TCP_ENABLE
case kProtoTcp:
- error = mTcp.HandleMessage(aIp6Header, *message, aMessageInfo);
- if (error == kErrorDrop)
- {
- LogNote("Error TCP Checksum");
- }
+ error = mTcp.HandleMessage(aIp6Header, *messagePtr, aMessageInfo);
break;
#endif
case kProtoUdp:
- error = mUdp.HandleMessage(*message, aMessageInfo);
- if (error == kErrorDrop)
- {
- LogNote("Error UDP Checksum");
- }
+ error = mUdp.HandleMessage(*messagePtr, aMessageInfo);
break;
case kProtoIcmp6:
- error = mIcmp.HandleMessage(*message, aMessageInfo);
+ error = mIcmp.HandleMessage(*messagePtr, aMessageInfo);
break;
default:
@@ -937,12 +925,10 @@ exit:
LogNote("Failed to handle payload: %s", ErrorToString(error));
}
- FreeMessage(message);
-
return error;
}
-Error Ip6::PassToHost(Message &aMessage,
+Error Ip6::PassToHost(OwnedPtr<Message> &aMessagePtr,
const MessageInfo &aMessageInfo,
uint8_t aIpProto,
bool aApplyFilter,
@@ -954,28 +940,15 @@ Error Ip6::PassToHost(Message &aMessage,
// may also perform translation and invoke IPv4 receive
// callback.
- Error error = kErrorNone;
- Message *message = nullptr;
-
- // `message` points to the `Message` instance we own in this
- // method. If we can take ownership of `aMessage`, we use it as
- // `message`. Otherwise, we may create a clone of it and use as
- // `message`. `message` variable will be set to `nullptr` if the
- // message ownership is transferred to an invoked callback. At
- // the end of this method we free `message` if it is not `nullptr`
- // indicating it was not passed to a callback.
+ Error error = kErrorNone;
+ OwnedPtr<Message> messagePtr;
- if (aMessageOwnership == Message::kTakeCustody)
- {
- message = &aMessage;
- }
-
- VerifyOrExit(aMessage.IsLoopbackToHostAllowed(), error = kErrorNoRoute);
+ VerifyOrExit(aMessagePtr->IsLoopbackToHostAllowed(), error = kErrorNoRoute);
VerifyOrExit(mReceiveIp6DatagramCallback.IsSet(), error = kErrorNoRoute);
// Do not pass IPv6 packets that exceed kMinimalMtu.
- VerifyOrExit(aMessage.GetLength() <= kMinimalMtu, error = kErrorDrop);
+ VerifyOrExit(aMessagePtr->GetLength() <= kMinimalMtu, error = kErrorDrop);
// If the sender used mesh-local address as source, do not pass to
// host unless this message is intended for this device itself.
@@ -1004,7 +977,7 @@ Error Ip6::PassToHost(Message &aMessage,
{
Icmp::Header icmp;
- IgnoreError(aMessage.Read(aMessage.GetOffset(), icmp));
+ IgnoreError(aMessagePtr->Read(aMessagePtr->GetOffset(), icmp));
VerifyOrExit(icmp.GetType() != Icmp::Header::kTypeEchoRequest, error = kErrorDrop);
}
@@ -1014,7 +987,7 @@ Error Ip6::PassToHost(Message &aMessage,
{
Udp::Header udp;
- IgnoreError(aMessage.Read(aMessage.GetOffset(), udp));
+ IgnoreError(aMessagePtr->Read(aMessagePtr->GetOffset(), udp));
VerifyOrExit(Get<Udp>().ShouldUsePlatformUdp(udp.GetDestinationPort()) &&
!Get<Udp>().IsPortInUse(udp.GetDestinationPort()),
error = kErrorNoRoute);
@@ -1034,27 +1007,12 @@ Error Ip6::PassToHost(Message &aMessage,
}
}
- switch (aMessageOwnership)
- {
- case Message::kTakeCustody:
- break;
-
- case Message::kCopyToUse:
- message = aMessage.Clone();
-
- if (message == nullptr)
- {
- LogWarn("No buff to clone msg (len: %d) to pass to host", aMessage.GetLength());
- ExitNow(error = kErrorNoBufs);
- }
-
- break;
- }
+ SuccessOrExit(error = TakeOrCopyMessagePtr(messagePtr, aMessagePtr, aMessageOwnership));
- IgnoreError(RemoveMplOption(*message));
+ IgnoreError(RemoveMplOption(*messagePtr));
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
- switch (Get<Nat64::Translator>().TranslateFromIp6(aMessage))
+ switch (Get<Nat64::Translator>().TranslateFromIp6(*messagePtr))
{
case Nat64::Translator::kNotTranslated:
break;
@@ -1065,37 +1023,33 @@ Error Ip6::PassToHost(Message &aMessage,
case Nat64::Translator::kForward:
VerifyOrExit(mReceiveIp4DatagramCallback.IsSet(), error = kErrorNoRoute);
// Pass message to callback transferring its ownership.
- mReceiveIp4DatagramCallback.Invoke(message);
- message = nullptr;
+ mReceiveIp4DatagramCallback.Invoke(messagePtr.Release());
ExitNow();
}
#endif
- // Pass message to callback transferring its ownership.
- mReceiveIp6DatagramCallback.Invoke(message);
- message = nullptr;
-
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
{
Header header;
- IgnoreError(header.ParseFrom(aMessage));
- UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ false);
+ IgnoreError(header.ParseFrom(*messagePtr));
+ UpdateBorderRoutingCounters(header, messagePtr->GetLength(), /* aIsInbound */ false);
}
#endif
+ // Pass message to callback transferring its ownership.
+ mReceiveIp6DatagramCallback.Invoke(messagePtr.Release());
+
exit:
- FreeMessage(message);
return error;
}
-Error Ip6::SendRaw(Message &aMessage)
+Error Ip6::SendRaw(OwnedPtr<Message> aMessagePtr)
{
Error error = kErrorNone;
Header header;
- bool freed = false;
- SuccessOrExit(error = header.ParseFrom(aMessage));
+ SuccessOrExit(error = header.ParseFrom(*aMessagePtr));
VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress);
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
@@ -1114,45 +1068,34 @@ Error Ip6::SendRaw(Message &aMessage)
if (header.GetDestination().IsMulticast())
{
- SuccessOrExit(error = InsertMplOption(aMessage, header));
+ SuccessOrExit(error = InsertMplOption(*aMessagePtr, header));
}
- error = HandleDatagram(aMessage);
- freed = true;
-
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
- UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ true);
+ UpdateBorderRoutingCounters(header, aMessagePtr->GetLength(), /* aIsInbound */ true);
#endif
-exit:
-
- if (!freed)
- {
- aMessage.Free();
- }
+ error = HandleDatagram(aMessagePtr.PassOwnership());
+exit:
return error;
}
-Error Ip6::HandleDatagram(Message &aMessage, const void *aLinkMessageInfo, bool aIsReassembled)
+Error Ip6::HandleDatagram(OwnedPtr<Message> aMessagePtr, const void *aLinkMessageInfo, bool aIsReassembled)
{
- Error error;
- MessageInfo messageInfo;
- Header header;
- bool receive;
- bool forwardThread;
- bool forwardHost;
- bool shouldFreeMessage;
- uint8_t nextHeader;
- Message::Origin origin = aMessage.GetOrigin();
-
-start:
- receive = false;
- forwardThread = false;
- forwardHost = false;
- shouldFreeMessage = true;
-
- SuccessOrExit(error = header.ParseFrom(aMessage));
+ Error error;
+ MessageInfo messageInfo;
+ Header header;
+ bool receive;
+ bool forwardThread;
+ bool forwardHost;
+ uint8_t nextHeader;
+
+ receive = false;
+ forwardThread = false;
+ forwardHost = false;
+
+ SuccessOrExit(error = header.ParseFrom(*aMessagePtr));
messageInfo.Clear();
messageInfo.SetPeerAddr(header.GetSource());
@@ -1168,10 +1111,10 @@ start:
{
// Destination is multicast
- forwardThread = (origin != Message::kOriginThreadNetif);
+ forwardThread = !aMessagePtr->IsOriginThreadNetif();
#if OPENTHREAD_FTD
- if ((origin == Message::kOriginThreadNetif) && header.GetDestination().IsMulticastLargerThanRealmLocal() &&
+ if (aMessagePtr->IsOriginThreadNetif() && header.GetDestination().IsMulticastLargerThanRealmLocal() &&
Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
{
forwardThread = true;
@@ -1180,7 +1123,7 @@ start:
forwardHost = header.GetDestination().IsMulticastLargerThanRealmLocal();
- if (((origin == Message::kOriginThreadNetif) || aMessage.GetMulticastLoop()) &&
+ if ((aMessagePtr->IsOriginThreadNetif() || aMessagePtr->GetMulticastLoop()) &&
Get<ThreadNetif>().IsMulticastSubscribed(header.GetDestination()))
{
receive = true;
@@ -1198,7 +1141,7 @@ start:
{
receive = true;
}
- else if ((origin != Message::kOriginThreadNetif) || !header.GetDestination().IsLinkLocal())
+ else if (!aMessagePtr->IsOriginThreadNetif() || !header.GetDestination().IsLinkLocal())
{
if (header.GetDestination().IsLinkLocal())
{
@@ -1207,7 +1150,7 @@ start:
else if (IsOnLink(header.GetDestination()))
{
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
- forwardThread = (!aMessage.IsLoopbackToHostAllowed() ||
+ forwardThread = (!aMessagePtr->IsLoopbackToHostAllowed() ||
!Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(header.GetDestination()));
#else
forwardThread = true;
@@ -1222,46 +1165,52 @@ start:
}
}
- aMessage.SetOffset(sizeof(header));
+ aMessagePtr->SetOffset(sizeof(header));
// Process IPv6 Extension Headers
nextHeader = static_cast<uint8_t>(header.GetNextHeader());
- SuccessOrExit(error = HandleExtensionHeaders(aMessage, messageInfo, header, nextHeader, receive));
+ SuccessOrExit(error = HandleExtensionHeaders(aMessagePtr, messageInfo, header, nextHeader, receive));
if (receive && (nextHeader == kProtoIp6))
{
- // Remove encapsulating header and start over.
- aMessage.RemoveHeader(aMessage.GetOffset());
- Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageReceive, aMessage);
- goto start;
+ // Process the embedded IPv6 message in an IPv6 tunnel message.
+ // If we need to `forwardThread` we create a copy by cloning
+ // the message, otherwise we take ownership of `aMessage`
+ // itself and use it directly. The encapsulating header is
+ // then removed before processing the embedded message.
+
+ OwnedPtr<Message> messagePtr;
+ bool multicastLoop = aMessagePtr->GetMulticastLoop();
+
+ SuccessOrExit(error = TakeOrCopyMessagePtr(messagePtr, aMessagePtr,
+ forwardThread ? Message::kCopyToUse : Message::kTakeCustody));
+ messagePtr->SetMulticastLoop(multicastLoop);
+ messagePtr->RemoveHeader(messagePtr->GetOffset());
+
+ Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageReceive, *messagePtr);
+
+ IgnoreError(HandleDatagram(messagePtr.PassOwnership(), aLinkMessageInfo, aIsReassembled));
+
+ receive = false;
+ forwardHost = false;
}
if ((forwardHost || receive) && !aIsReassembled)
{
- error = PassToHost(aMessage, messageInfo, nextHeader,
+ error = PassToHost(aMessagePtr, messageInfo, nextHeader,
/* aApplyFilter */ !forwardHost, receive,
(receive || forwardThread) ? Message::kCopyToUse : Message::kTakeCustody);
-
- // Need to free the message if we did not pass its
- // ownership in the call to `PassToHost()`
- shouldFreeMessage = (receive || forwardThread);
}
if (receive)
{
- error = HandlePayload(header, aMessage, messageInfo, nextHeader,
+ error = HandlePayload(header, aMessagePtr, messageInfo, nextHeader,
forwardThread ? Message::kCopyToUse : Message::kTakeCustody);
-
- // Need to free the message if we did not pass its
- // ownership in the call to `HandlePayload()`
- shouldFreeMessage = forwardThread;
}
if (forwardThread)
{
- uint8_t hopLimit;
-
- if (origin == Message::kOriginThreadNetif)
+ if (aMessagePtr->IsOriginThreadNetif())
{
VerifyOrExit(Get<Mle::Mle>().IsRouterOrLeader());
header.SetHopLimit(header.GetHopLimit() - 1);
@@ -1269,32 +1218,35 @@ start:
VerifyOrExit(header.GetHopLimit() > 0, error = kErrorDrop);
- hopLimit = header.GetHopLimit();
- aMessage.Write(Header::kHopLimitFieldOffset, hopLimit);
+ aMessagePtr->Write<uint8_t>(Header::kHopLimitFieldOffset, header.GetHopLimit());
if (nextHeader == kProtoIcmp6)
{
uint8_t icmpType;
- bool isAllowedType = false;
- SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), icmpType));
- for (IcmpType type : sForwardICMPTypes)
+ SuccessOrExit(error = aMessagePtr->Read(aMessagePtr->GetOffset(), icmpType));
+
+ error = kErrorDrop;
+
+ for (IcmpType type : kForwardIcmpTypes)
{
if (icmpType == type)
{
- isAllowedType = true;
+ error = kErrorNone;
break;
}
}
- VerifyOrExit(isAllowedType, error = kErrorDrop);
+
+ SuccessOrExit(error);
}
- if (aMessage.GetOrigin() == Message::kOriginHostUntrusted && nextHeader == kProtoUdp)
+ if (aMessagePtr->IsOriginHostUntrusted() && (nextHeader == kProtoUdp))
{
uint16_t destPort;
- SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
- destPort = HostSwap16(destPort);
+ SuccessOrExit(
+ error = aMessagePtr->Read(aMessagePtr->GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
+ destPort = BigEndian::HostSwap16(destPort);
if (destPort == Tmf::kUdpPort)
{
@@ -1304,12 +1256,13 @@ start:
}
#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- if ((origin == Message::kOriginHostTrusted && !aMessage.IsLoopbackToHostAllowed()) && (nextHeader == kProtoUdp))
+ if (aMessagePtr->IsOriginHostTrusted() && !aMessagePtr->IsLoopbackToHostAllowed() && (nextHeader == kProtoUdp))
{
uint16_t destPort;
- SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
- destPort = HostSwap16(destPort);
+ SuccessOrExit(
+ error = aMessagePtr->Read(aMessagePtr->GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
+ destPort = BigEndian::HostSwap16(destPort);
if (nextHeader == kProtoUdp)
{
@@ -1323,21 +1276,13 @@ start:
// type on the message to allow the radio type for tx to be
// selected later (based on the radios supported by the next
// hop).
- aMessage.ClearRadioType();
+ aMessagePtr->ClearRadioType();
#endif
- // `SendMessage()` takes custody of message in the success case
- SuccessOrExit(error = Get<MeshForwarder>().SendMessage(aMessage));
- shouldFreeMessage = false;
+ Get<MeshForwarder>().SendMessage(aMessagePtr.PassOwnership());
}
exit:
-
- if (shouldFreeMessage)
- {
- aMessage.Free();
- }
-
return error;
}
@@ -1421,11 +1366,19 @@ const Address *Ip6::SelectSourceAddress(const Address &aDestination) const
continue;
}
}
- else if (addr.mPreferred && !bestAddr->mPreferred)
+ else if (addr.mPreferred != bestAddr->mPreferred)
{
// Rule 3: Avoid deprecated addresses
- bestAddr = &addr;
- bestMatchLen = matchLen;
+
+ if (addr.mPreferred)
+ {
+ bestAddr = &addr;
+ bestMatchLen = matchLen;
+ }
+ else
+ {
+ continue;
+ }
}
else if (matchLen > bestMatchLen)
{
diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp
index ff5c1fd0c..1c700b590 100644
--- a/src/core/net/ip6.hpp
+++ b/src/core/net/ip6.hpp
@@ -49,6 +49,7 @@
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
+#include "common/owned_ptr.hpp"
#include "common/time_ticker.hpp"
#include "common/timer.hpp"
#include "net/icmp6.hpp"
@@ -72,9 +73,6 @@ namespace ot {
*/
namespace Ip6 {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-ipv6
*
@@ -194,10 +192,7 @@ public:
/**
* 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 `kErrorNone` is returned.
- *
- * @param[in] aMessage A reference to the message.
+ * @param[in] aMessage An owned pointer to a message (ownership is transferred to the method).
*
* @retval kErrorNone Successfully processed the message.
* @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules.
@@ -206,12 +201,12 @@ public:
* @retval kErrorParse Encountered a malformed header when processing the message.
*
*/
- Error SendRaw(Message &aMessage);
+ Error SendRaw(OwnedPtr<Message> aMessage);
/**
* Processes a received IPv6 datagram.
*
- * @param[in] aMessage A reference to the message.
+ * @param[in] aMessage An owned pointer to a message.
* @param[in] aLinkMessageInfo A pointer to link-specific message information.
*
* @retval kErrorNone Successfully processed the message.
@@ -221,7 +216,9 @@ public:
* @retval kErrorParse Encountered a malformed header when processing the message.
*
*/
- Error HandleDatagram(Message &aMessage, const void *aLinkMessageInfo = nullptr, bool aIsReassembled = false);
+ Error HandleDatagram(OwnedPtr<Message> aMessagePtr,
+ const void *aLinkMessageInfo = nullptr,
+ bool aIsReassembled = false);
/**
* Registers a callback to provide received raw IPv6 datagrams.
@@ -362,22 +359,24 @@ private:
static constexpr uint16_t kMinimalMtu = 1280;
- void HandleSendQueue(void);
-
static uint8_t PriorityToDscp(Message::Priority aPriority);
+ static Error TakeOrCopyMessagePtr(OwnedPtr<Message> &aTargetPtr,
+ OwnedPtr<Message> &aMessagePtr,
+ Message::Ownership aMessageOwnership);
void EnqueueDatagram(Message &aMessage);
- Error PassToHost(Message &aMessage,
+ void HandleSendQueue(void);
+ Error PassToHost(OwnedPtr<Message> &aMessagePtr,
const MessageInfo &aMessageInfo,
uint8_t aIpProto,
bool aApplyFilter,
bool aReceive,
Message::Ownership aMessageOwnership);
- Error HandleExtensionHeaders(Message &aMessage,
- MessageInfo &aMessageInfo,
- Header &aHeader,
- uint8_t &aNextHeader,
- bool &aReceive);
+ Error HandleExtensionHeaders(OwnedPtr<Message> &aMessagePtr,
+ MessageInfo &aMessageInfo,
+ Header &aHeader,
+ uint8_t &aNextHeader,
+ bool &aReceive);
Error FragmentDatagram(Message &aMessage, uint8_t aIpProto);
Error HandleFragment(Message &aMessage, MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE
@@ -387,12 +386,12 @@ private:
void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
#endif
Error AddMplOption(Message &aMessage, Header &aHeader);
- Error AddTunneledMplOption(Message &aMessage, Header &aHeader);
+ Error PrepareMulticastToLargerThanRealmLocal(Message &aMessage, const Header &aHeader);
Error InsertMplOption(Message &aMessage, Header &aHeader);
Error RemoveMplOption(Message &aMessage);
- Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
+ Error HandleOptions(Message &aMessage, Header &aHeader, bool &aReceive);
Error HandlePayload(Header &aIp6Header,
- Message &aMessage,
+ OwnedPtr<Message> &aMessagePtr,
MessageInfo &aMessageInfo,
uint8_t aIpProto,
Message::Ownership aMessageOwnership);
diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp
index e6d924296..4c092267e 100644
--- a/src/core/net/ip6_address.cpp
+++ b/src/core/net/ip6_address.cpp
@@ -39,15 +39,13 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "net/ip4_types.hpp"
#include "net/netif.hpp"
-using ot::Encoding::BigEndian::HostSwap32;
-
namespace ot {
namespace Ip6 {
@@ -72,7 +70,8 @@ void Prefix::Set(const uint8_t *aPrefix, uint8_t aLength)
bool Prefix::IsLinkLocal(void) const
{
- return (mLength >= 10) && ((mPrefix.mFields.m16[0] & HostSwap16(0xffc0)) == HostSwap16(0xfe80));
+ return (mLength >= 10) &&
+ ((mPrefix.mFields.m16[0] & BigEndian::HostSwap16(0xffc0)) == BigEndian::HostSwap16(0xfe80));
}
bool Prefix::IsMulticast(void) const { return (mLength >= 8) && (mPrefix.mFields.m8[0] == 0xff); }
@@ -132,7 +131,7 @@ bool Prefix::operator<(const Prefix &aOther) const
ExitNow();
}
- isSmaller = GetBytes()[matchedLength / CHAR_BIT] < aOther.GetBytes()[matchedLength / CHAR_BIT];
+ isSmaller = GetBytes()[matchedLength / kBitsPerByte] < aOther.GetBytes()[matchedLength / kBitsPerByte];
exit:
return isSmaller;
@@ -150,7 +149,7 @@ uint8_t Prefix::MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, ui
if (diff == 0)
{
- matchedLength += CHAR_BIT;
+ matchedLength += kBitsPerByte;
}
else
{
@@ -251,8 +250,8 @@ bool InterfaceIdentifier::IsReservedSubnetAnycast(void) const
// | 1111110111...111 | anycast ID |
// +------------------+------------+
- return (mFields.m32[0] == HostSwap32(0xfdffffff) && mFields.m16[2] == HostSwap16(0xffff) && mFields.m8[6] == 0xff &&
- mFields.m8[7] >= 0x80);
+ return (mFields.m32[0] == BigEndian::HostSwap32(0xfdffffff) && mFields.m16[2] == BigEndian::HostSwap16(0xffff) &&
+ mFields.m8[6] == 0xff && mFields.m8[7] >= 0x80);
}
void InterfaceIdentifier::GenerateRandom(void) { SuccessOrAssert(Random::Crypto::Fill(*this)); }
@@ -283,15 +282,15 @@ void InterfaceIdentifier::ConvertToMacAddress(Mac::Address &aMacAddress) const
void InterfaceIdentifier::SetToLocator(uint16_t aLocator)
{
// Locator IID pattern `0000:00ff:fe00:xxxx`
- mFields.m32[0] = HostSwap32(0x000000ff);
- mFields.m16[2] = HostSwap16(0xfe00);
- mFields.m16[3] = HostSwap16(aLocator);
+ mFields.m32[0] = BigEndian::HostSwap32(0x000000ff);
+ mFields.m16[2] = BigEndian::HostSwap16(0xfe00);
+ mFields.m16[3] = BigEndian::HostSwap16(aLocator);
}
bool InterfaceIdentifier::IsLocator(void) const
{
// Locator IID pattern 0000:00ff:fe00:xxxx
- return (mFields.m32[0] == HostSwap32(0x000000ff) && mFields.m16[2] == HostSwap16(0xfe00));
+ return (mFields.m32[0] == BigEndian::HostSwap32(0x000000ff) && mFields.m16[2] == BigEndian::HostSwap16(0xfe00));
}
bool InterfaceIdentifier::IsRoutingLocator(void) const
@@ -340,21 +339,25 @@ bool Address::IsUnspecified(void) const
bool Address::IsLoopback(void) const
{
- return (mFields.m32[0] == 0 && mFields.m32[1] == 0 && mFields.m32[2] == 0 && mFields.m32[3] == HostSwap32(1));
+ return (mFields.m32[0] == 0 && mFields.m32[1] == 0 && mFields.m32[2] == 0 &&
+ mFields.m32[3] == BigEndian::HostSwap32(1));
}
-bool Address::IsLinkLocal(void) const { return (mFields.m16[0] & HostSwap16(0xffc0)) == HostSwap16(0xfe80); }
+bool Address::IsLinkLocal(void) const
+{
+ return (mFields.m16[0] & BigEndian::HostSwap16(0xffc0)) == BigEndian::HostSwap16(0xfe80);
+}
void Address::SetToLinkLocalAddress(const Mac::ExtAddress &aExtAddress)
{
- mFields.m32[0] = HostSwap32(0xfe800000);
+ mFields.m32[0] = BigEndian::HostSwap32(0xfe800000);
mFields.m32[1] = 0;
GetIid().SetFromExtAddress(aExtAddress);
}
void Address::SetToLinkLocalAddress(const InterfaceIdentifier &aIid)
{
- mFields.m32[0] = HostSwap32(0xfe800000);
+ mFields.m32[0] = BigEndian::HostSwap32(0xfe800000);
mFields.m32[1] = 0;
SetIid(aIid);
}
@@ -405,8 +408,8 @@ void Address::CopyBits(uint8_t *aDst, const uint8_t *aSrc, uint8_t aNumBits)
// the case where `aNumBits` may not be a multiple of 8. It leaves the
// remaining bits beyond `aNumBits` in `aDst` unchanged.
- uint8_t numBytes = aNumBits / CHAR_BIT;
- uint8_t extraBits = aNumBits % CHAR_BIT;
+ uint8_t numBytes = aNumBits / kBitsPerByte;
+ uint8_t extraBits = aNumBits % kBitsPerByte;
memcpy(aDst, aSrc, numBytes);
@@ -520,7 +523,7 @@ void Address::SynthesizeFromIp4Address(const Prefix &aPrefix, const Ip4::Address
Clear();
SetPrefix(aPrefix);
- ip6Index = aPrefix.GetLength() / CHAR_BIT;
+ ip6Index = aPrefix.GetLength() / kBitsPerByte;
for (uint8_t i = 0; i < Ip4::Address::kSize; i++)
{
@@ -612,7 +615,7 @@ Error Address::ParseFrom(const char *aString, char aTerminatorChar)
VerifyOrExit((*aString == kColonChar) || (*aString == aTerminatorChar));
VerifyOrExit(index < endIndex);
- mFields.m16[index++] = HostSwap16(static_cast<uint16_t>(value));
+ mFields.m16[index++] = BigEndian::HostSwap16(static_cast<uint16_t>(value));
if (*aString == kColonChar)
{
@@ -685,7 +688,7 @@ void Address::AppendHexWords(StringWriter &aWriter, uint8_t aLength) const
aWriter.Append(":");
}
- aWriter.Append("%x", HostSwap16(mFields.m16[index]));
+ aWriter.Append("%x", BigEndian::HostSwap16(mFields.m16[index]));
}
}
diff --git a/src/core/net/ip6_address.hpp b/src/core/net/ip6_address.hpp
index 3e91551a5..b066557de 100644
--- a/src/core/net/ip6_address.hpp
+++ b/src/core/net/ip6_address.hpp
@@ -36,19 +36,17 @@
#include "openthread-core-config.h"
-#include <stdint.h>
-
#include <openthread/ip6.h>
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
+#include "common/num_utils.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
-using ot::Encoding::BigEndian::HostSwap16;
-
namespace ot {
namespace Ip4 {
@@ -73,8 +71,8 @@ OT_TOOL_PACKED_BEGIN
class NetworkPrefix : public otIp6NetworkPrefix, public Equatable<NetworkPrefix>, public Clearable<NetworkPrefix>
{
public:
- static constexpr uint8_t kSize = OT_IP6_PREFIX_SIZE; ///< Size in bytes.
- static constexpr uint8_t kLength = OT_IP6_PREFIX_SIZE * CHAR_BIT; ///< Length of Network Prefix in bits.
+ static constexpr uint8_t kSize = OT_IP6_PREFIX_SIZE; ///< Size in bytes.
+ static constexpr uint8_t kLength = kSize * kBitsPerByte; ///< Length of Network Prefix in bits.
/**
* Generates and sets the Network Prefix to a crypto-secure random Unique Local Address (ULA) based
@@ -96,8 +94,8 @@ OT_TOOL_PACKED_BEGIN
class Prefix : public otIp6Prefix, public Clearable<Prefix>, public Unequatable<Prefix>
{
public:
- static constexpr uint8_t kMaxLength = OT_IP6_ADDRESS_SIZE * CHAR_BIT; ///< Max length of a prefix in bits.
- static constexpr uint8_t kMaxSize = OT_IP6_ADDRESS_SIZE; ///< Max (byte) size of a prefix.
+ static constexpr uint8_t kMaxSize = OT_IP6_ADDRESS_SIZE; ///< Max (byte) size of a prefix.
+ static constexpr uint8_t kMaxLength = kMaxSize * kBitsPerByte; ///< Max length of a prefix in bits.
static constexpr uint16_t kInfoStringSize = OT_IP6_PREFIX_STRING_SIZE; ///< Info string size (`ToString()`).
@@ -121,7 +119,7 @@ public:
* @returns The 16-bit subnet ID.
*
*/
- uint16_t GetSubnetId(void) const { return HostSwap16(mPrefix.mFields.m16[3]); }
+ uint16_t GetSubnetId(void) const { return BigEndian::HostSwap16(mPrefix.mFields.m16[3]); }
/**
* Gets the prefix length (in bits).
@@ -162,7 +160,7 @@ public:
* @param[in] aSubnetId A 16-bit subnet ID.
*
*/
- void SetSubnetId(uint16_t aSubnetId) { mPrefix.mFields.m16[3] = HostSwap16(aSubnetId); }
+ void SetSubnetId(uint16_t aSubnetId) { mPrefix.mFields.m16[3] = BigEndian::HostSwap16(aSubnetId); }
/**
* Set the prefix length.
@@ -283,7 +281,7 @@ public:
* @returns The size (in bytes) of the prefix.
*
*/
- static uint8_t SizeForLength(uint8_t aLength) { return BitVectorBytes(aLength); }
+ static uint8_t SizeForLength(uint8_t aLength) { return BytesForBitSize(aLength); }
/**
* Returns the number of IPv6 prefix bits that match.
@@ -529,7 +527,7 @@ public:
* @returns The RLOC16 or ALOC16.
*
*/
- uint16_t GetLocator(void) const { return HostSwap16(mFields.m16[3]); }
+ uint16_t GetLocator(void) const { return BigEndian::HostSwap16(mFields.m16[3]); }
/**
* Sets the Interface Identifier (IID) address locator field.
@@ -540,7 +538,7 @@ public:
* @param[in] aLocator RLOC16 or ALOC16.
*
*/
- void SetLocator(uint16_t aLocator) { mFields.m16[3] = HostSwap16(aLocator); }
+ void SetLocator(uint16_t aLocator) { mFields.m16[3] = BigEndian::HostSwap16(aLocator); }
/**
* Applies a prefix to IID.
diff --git a/src/core/net/ip6_filter.cpp b/src/core/net/ip6_filter.cpp
index 0104fac81..1dae10c71 100644
--- a/src/core/net/ip6_filter.cpp
+++ b/src/core/net/ip6_filter.cpp
@@ -36,9 +36,9 @@
#include <stdio.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "net/ip6.hpp"
#include "net/tcp6.hpp"
diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp
index 2fc55c5aa..8289c53b0 100644
--- a/src/core/net/ip6_headers.hpp
+++ b/src/core/net/ip6_headers.hpp
@@ -57,9 +57,6 @@ namespace ot {
*/
namespace Ip6 {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-ipv6
*
@@ -133,7 +130,7 @@ public:
* @returns The Version, Traffic Class, and Flow fields as a 32-bit value.
*
*/
- uint32_t GetVerionTrafficClassFlow(void) const { return HostSwap32(mVerTcFlow.m32); }
+ uint32_t GetVerionTrafficClassFlow(void) const { return BigEndian::HostSwap32(mVerTcFlow.m32); }
/**
* Sets the combination of Version, Traffic Class, and Flow fields as a 32-bit value.
@@ -141,7 +138,7 @@ public:
* @param[in] aVerTcFlow The Version, Traffic Class, and Flow fields as a 32-bit value.
*
*/
- void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = HostSwap32(aVerTcFlow); }
+ void SetVerionTrafficClassFlow(uint32_t aVerTcFlow) { mVerTcFlow.m32 = BigEndian::HostSwap32(aVerTcFlow); }
/**
* Gets the Traffic Class field.
@@ -151,7 +148,8 @@ public:
*/
uint8_t GetTrafficClass(void) const
{
- return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >> kTrafficClassOffset);
+ return static_cast<uint8_t>((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & kTrafficClassMask) >>
+ kTrafficClassOffset);
}
/**
@@ -162,8 +160,9 @@ public:
*/
void SetTrafficClass(uint8_t aTc)
{
- mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) |
- ((static_cast<uint16_t>(aTc) << kTrafficClassOffset) & kTrafficClassMask));
+ mVerTcFlow.m16[0] =
+ BigEndian::HostSwap16((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & ~kTrafficClassMask) |
+ ((static_cast<uint16_t>(aTc) << kTrafficClassOffset) & kTrafficClassMask));
}
/**
@@ -174,7 +173,7 @@ public:
*/
uint8_t GetDscp(void) const
{
- return static_cast<uint8_t>((HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset);
+ return static_cast<uint8_t>((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & kDscpMask) >> kDscpOffset);
}
/**
@@ -185,8 +184,8 @@ public:
*/
void SetDscp(uint8_t aDscp)
{
- mVerTcFlow.m16[0] = HostSwap16((HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) |
- ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask));
+ mVerTcFlow.m16[0] = BigEndian::HostSwap16((BigEndian::HostSwap16(mVerTcFlow.m16[0]) & ~kDscpMask) |
+ ((static_cast<uint16_t>(aDscp) << kDscpOffset) & kDscpMask));
}
/**
@@ -211,7 +210,7 @@ public:
* @returns The Flow value.
*
*/
- uint32_t GetFlow(void) const { return HostSwap32(mVerTcFlow.m32) & kFlowMask; }
+ uint32_t GetFlow(void) const { return BigEndian::HostSwap32(mVerTcFlow.m32) & kFlowMask; }
/**
* Sets the 20-bit Flow field in IPv6 header.
@@ -221,7 +220,8 @@ public:
*/
void SetFlow(uint32_t aFlow)
{
- mVerTcFlow.m32 = HostSwap32((HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask));
+ mVerTcFlow.m32 =
+ BigEndian::HostSwap32((BigEndian::HostSwap32(mVerTcFlow.m32) & ~kFlowMask) | (aFlow & kFlowMask));
}
/**
@@ -230,7 +230,7 @@ public:
* @returns The IPv6 Payload Length value.
*
*/
- uint16_t GetPayloadLength(void) const { return HostSwap16(mPayloadLength); }
+ uint16_t GetPayloadLength(void) const { return BigEndian::HostSwap16(mPayloadLength); }
/**
* Sets the IPv6 Payload Length value.
@@ -238,7 +238,7 @@ public:
* @param[in] aLength The IPv6 Payload Length value.
*
*/
- void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); }
+ void SetPayloadLength(uint16_t aLength) { mPayloadLength = BigEndian::HostSwap16(aLength); }
/**
* Returns the IPv6 Next Header value.
@@ -639,7 +639,7 @@ public:
* @returns The Fragment Offset value.
*
*/
- uint16_t GetOffset(void) const { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; }
+ uint16_t GetOffset(void) const { return (BigEndian::HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; }
/**
* Sets the Fragment Offset value.
@@ -648,9 +648,9 @@ public:
*/
void SetOffset(uint16_t aOffset)
{
- uint16_t tmp = HostSwap16(mOffsetMore);
+ uint16_t tmp = BigEndian::HostSwap16(mOffsetMore);
tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask);
- mOffsetMore = HostSwap16(tmp);
+ mOffsetMore = BigEndian::HostSwap16(tmp);
}
/**
@@ -659,19 +659,19 @@ public:
* @returns The M flag value.
*
*/
- bool IsMoreFlagSet(void) const { return HostSwap16(mOffsetMore) & kMoreFlag; }
+ bool IsMoreFlagSet(void) const { return BigEndian::HostSwap16(mOffsetMore) & kMoreFlag; }
/**
* Clears the M flag value.
*
*/
- void ClearMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); }
+ void ClearMoreFlag(void) { mOffsetMore = BigEndian::HostSwap16(BigEndian::HostSwap16(mOffsetMore) & ~kMoreFlag); }
/**
* Sets the M flag value.
*
*/
- void SetMoreFlag(void) { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); }
+ void SetMoreFlag(void) { mOffsetMore = BigEndian::HostSwap16(BigEndian::HostSwap16(mOffsetMore) | kMoreFlag); }
/**
* Returns the frame identification.
diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp
index c5dd2d3e5..78922ef6f 100644
--- a/src/core/net/ip6_mpl.cpp
+++ b/src/core/net/ip6_mpl.cpp
@@ -35,11 +35,11 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
#include "common/serial_number.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
namespace ot {
@@ -90,7 +90,7 @@ void Mpl::InitOption(MplOption &aOption, const Address &aAddress)
aOption.SetSequence(mSequence++);
}
-Error Mpl::ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAddress, bool aIsOutbound, bool &aReceive)
+Error Mpl::ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAddress, bool &aReceive)
{
Error error;
MplOption option;
@@ -122,10 +122,10 @@ Error Mpl::ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAd
if (error == kErrorNone)
{
#if OPENTHREAD_FTD
- AddBufferedMessage(aMessage, option.GetSeedId(), option.GetSequence(), aIsOutbound);
+ AddBufferedMessage(aMessage, option.GetSeedId(), option.GetSequence());
#endif
}
- else if (aIsOutbound)
+ else if (!aMessage.IsOriginThreadNetif())
{
aReceive = false;
// In case MPL Data Message is generated locally, ignore potential error of the MPL Seed Set
@@ -311,9 +311,9 @@ void Mpl::HandleTimeTick(void)
#if OPENTHREAD_FTD
-uint8_t Mpl::GetTimerExpirations(void) const
+uint8_t Mpl::DetermineMaxRetransmissions(void) const
{
- uint8_t timerExpirations = 0;
+ uint8_t maxRetx = 0;
switch (Get<Mle::Mle>().GetRole())
{
@@ -322,19 +322,19 @@ uint8_t Mpl::GetTimerExpirations(void) const
break;
case Mle::kRoleChild:
- timerExpirations = kChildTimerExpirations;
+ maxRetx = kChildRetransmissions;
break;
case Mle::kRoleRouter:
case Mle::kRoleLeader:
- timerExpirations = kRouterTimerExpirations;
+ maxRetx = kRouterRetransmissions;
break;
}
- return timerExpirations;
+ return maxRetx;
}
-void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound)
+void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence)
{
Error error = kErrorNone;
Message *messageCopy = nullptr;
@@ -349,19 +349,26 @@ void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSeque
interval = kDataMessageInterval;
#endif
- VerifyOrExit(GetTimerExpirations() > 0);
+ VerifyOrExit(DetermineMaxRetransmissions() > 0);
VerifyOrExit((messageCopy = aMessage.Clone()) != nullptr, error = kErrorNoBufs);
- if (!aIsOutbound)
+ if (aMessage.IsOriginThreadNetif())
{
IgnoreError(aMessage.Read(Header::kHopLimitFieldOffset, hopLimit));
VerifyOrExit(hopLimit-- > 1, error = kErrorDrop);
messageCopy->Write(Header::kHopLimitFieldOffset, hopLimit);
}
+ // If the message originates from Thread Netif (i.e., it was
+ // received over Thread radio), set the `mTransmissionCount` to
+ // zero. Otherwise, the message originates from the host and will
+ // be forwarded by `Ip6` to the Thread mesh, so the message itself
+ // will be the first transmission and we set `mTransmissionCount`
+ // to one.
+
metadata.mSeedId = aSeedId;
metadata.mSequence = aSequence;
- metadata.mTransmissionCount = aIsOutbound ? 1 : 0;
+ metadata.mTransmissionCount = aMessage.IsOriginThreadNetif() ? 0 : 1;
metadata.mIntervalOffset = 0;
metadata.GenerateNextTransmissionTime(TimerMilli::GetNow(), interval);
@@ -378,66 +385,69 @@ void Mpl::HandleRetransmissionTimer(void)
{
TimeMilli now = TimerMilli::GetNow();
TimeMilli nextTime = now.GetDistantFuture();
- Metadata metadata;
for (Message &message : mBufferedMessageSet)
{
+ Metadata metadata;
+ Message *messageCopy;
+ uint8_t maxRetx;
+
metadata.ReadFrom(message);
if (now < metadata.mTransmissionTime)
{
nextTime = Min(nextTime, metadata.mTransmissionTime);
+ continue;
}
- else
+
+ metadata.mTransmissionCount++;
+
+ maxRetx = DetermineMaxRetransmissions();
+
+ if (metadata.mTransmissionCount > maxRetx)
{
- uint8_t timerExpirations = GetTimerExpirations();
+ // If the number of tx already exceeds the limit, remove
+ // the message. This situation can potentially happen on
+ // a device role change, which then updates the max MPL
+ // retx.
- // Update the number of transmission timer expirations.
- metadata.mTransmissionCount++;
+ mBufferedMessageSet.DequeueAndFree(message);
+ continue;
+ }
- if (metadata.mTransmissionCount < timerExpirations)
- {
- Message *messageCopy = message.Clone(message.GetLength() - sizeof(Metadata));
+ if (metadata.mTransmissionCount < maxRetx)
+ {
+ metadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
+ metadata.UpdateIn(message);
- if (messageCopy != nullptr)
- {
- if (metadata.mTransmissionCount > 1)
- {
- messageCopy->SetSubType(Message::kSubTypeMplRetransmission);
- }
+ nextTime = Min(nextTime, metadata.mTransmissionTime);
- messageCopy->SetLoopbackToHostAllowed(true);
- messageCopy->SetOrigin(Message::kOriginHostTrusted);
- Get<Ip6>().EnqueueDatagram(*messageCopy);
- }
+ messageCopy = message.Clone();
+ }
+ else
+ {
+ // This is the last retx of message, we can use the
+ // `message` directly.
- metadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
- metadata.UpdateIn(message);
+ mBufferedMessageSet.Dequeue(message);
+ messageCopy = &message;
+ }
- nextTime = Min(nextTime, metadata.mTransmissionTime);
- }
- else
+ if (messageCopy != nullptr)
+ {
+ if (metadata.mTransmissionCount > 1)
{
- mBufferedMessageSet.Dequeue(message);
-
- if (metadata.mTransmissionCount == timerExpirations)
- {
- if (metadata.mTransmissionCount > 1)
- {
- message.SetSubType(Message::kSubTypeMplRetransmission);
- }
-
- metadata.RemoveFrom(message);
- message.SetLoopbackToHostAllowed(true);
- message.SetOrigin(Message::kOriginHostTrusted);
- Get<Ip6>().EnqueueDatagram(message);
- }
- else
- {
- // Stop retransmitting if the number of timer expirations is already exceeded.
- message.Free();
- }
+ // Mark all transmissions after the first one as "MPL
+ // retx". This is used to decide whether to send this
+ // message to the device's sleepy children.
+
+ messageCopy->SetSubType(Message::kSubTypeMplRetransmission);
}
+
+ metadata.RemoveFrom(*messageCopy);
+ messageCopy->SetLoopbackToHostAllowed(true);
+ messageCopy->SetOrigin(Message::kOriginHostTrusted);
+ Get<Ip6>().EnqueueDatagram(*messageCopy);
}
}
diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp
index 65f5be40d..76fe15984 100644
--- a/src/core/net/ip6_mpl.hpp
+++ b/src/core/net/ip6_mpl.hpp
@@ -140,7 +140,7 @@ public:
* @returns The MPL Seed Id value.
*
*/
- uint16_t GetSeedId(void) const { return HostSwap16(mSeedId); }
+ uint16_t GetSeedId(void) const { return BigEndian::HostSwap16(mSeedId); }
/**
* Sets the MPL Seed Id value.
@@ -148,7 +148,7 @@ public:
* @param[in] aSeedId The MPL Seed Id value.
*
*/
- void SetSeedId(uint16_t aSeedId) { mSeedId = HostSwap16(aSeedId); }
+ void SetSeedId(uint16_t aSeedId) { mSeedId = BigEndian::HostSwap16(aSeedId); }
private:
static constexpr uint8_t kSeedIdLengthMask = 3 << 6;
@@ -194,7 +194,6 @@ public:
* @param[in] aMessage A reference to the message.
* @param[in] aOffset The offset in @p aMessage to read the MPL option.
* @param[in] aAddress A reference to the IPv6 Source Address.
- * @param[in] aIsOutbound TRUE if this message was locally generated, FALSE otherwise.
* @param[out] aReceive Set to FALSE if the MPL message is a duplicate and must not
* go through the receiving process again, untouched otherwise.
*
@@ -202,7 +201,7 @@ public:
* @retval kErrorDrop The MPL message is a duplicate and should be dropped.
*
*/
- Error ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAddress, bool aIsOutbound, bool &aReceive);
+ Error ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAddress, bool &aReceive);
#if OPENTHREAD_FTD
/**
@@ -234,8 +233,8 @@ private:
uint8_t mSequence;
#if OPENTHREAD_FTD
- static constexpr uint8_t kChildTimerExpirations = 0; // MPL retransmissions for Children.
- static constexpr uint8_t kRouterTimerExpirations = 2; // MPL retransmissions for Routers.
+ static constexpr uint8_t kChildRetransmissions = 0; // MPL retransmissions for Children.
+ static constexpr uint8_t kRouterRetransmissions = 2; // MPL retransmissions for Routers.
struct Metadata
{
@@ -252,9 +251,9 @@ private:
uint8_t mIntervalOffset;
};
- uint8_t GetTimerExpirations(void) const;
+ uint8_t DetermineMaxRetransmissions(void) const;
void HandleRetransmissionTimer(void);
- void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound);
+ void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence);
using RetxTimer = TimerMilliIn<Mpl, &Mpl::HandleRetransmissionTimer>;
diff --git a/src/core/net/nat64_translator.cpp b/src/core/net/nat64_translator.cpp
index 0415f909f..5afe9bfb0 100644
--- a/src/core/net/nat64_translator.cpp
+++ b/src/core/net/nat64_translator.cpp
@@ -99,7 +99,7 @@ Error Translator::SendMessage(Message &aMessage)
VerifyOrExit(result == kForward);
- error = Get<Ip6::Ip6>().SendRaw(aMessage);
+ error = Get<Ip6::Ip6>().SendRaw(OwnedPtr<Message>(&aMessage).PassOwnership());
freed = true;
exit:
diff --git a/src/core/net/nd6.hpp b/src/core/net/nd6.hpp
index bbf6a6ea7..f4a6d5a25 100644
--- a/src/core/net/nd6.hpp
+++ b/src/core/net/nd6.hpp
@@ -51,9 +51,6 @@
#include "net/ip6.hpp"
#include "thread/network_data_types.hpp"
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
namespace ot {
namespace Ip6 {
namespace Nd {
@@ -235,7 +232,7 @@ public:
* @param[in] aValidLifetime The valid lifetime in seconds.
*
*/
- void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = HostSwap32(aValidLifetime); }
+ void SetValidLifetime(uint32_t aValidLifetime) { mValidLifetime = BigEndian::HostSwap32(aValidLifetime); }
/**
* THis method gets the valid lifetime of the prefix in seconds.
@@ -243,7 +240,7 @@ public:
* @returns The valid lifetime in seconds.
*
*/
- uint32_t GetValidLifetime(void) const { return HostSwap32(mValidLifetime); }
+ uint32_t GetValidLifetime(void) const { return BigEndian::HostSwap32(mValidLifetime); }
/**
* Sets the preferred lifetime of the prefix in seconds.
@@ -251,7 +248,10 @@ public:
* @param[in] aPreferredLifetime The preferred lifetime in seconds.
*
*/
- void SetPreferredLifetime(uint32_t aPreferredLifetime) { mPreferredLifetime = HostSwap32(aPreferredLifetime); }
+ void SetPreferredLifetime(uint32_t aPreferredLifetime)
+ {
+ mPreferredLifetime = BigEndian::HostSwap32(aPreferredLifetime);
+ }
/**
* THis method returns the preferred lifetime of the prefix in seconds.
@@ -259,7 +259,7 @@ public:
* @returns The preferred lifetime in seconds.
*
*/
- uint32_t GetPreferredLifetime(void) const { return HostSwap32(mPreferredLifetime); }
+ uint32_t GetPreferredLifetime(void) const { return BigEndian::HostSwap32(mPreferredLifetime); }
/**
* Sets the prefix.
@@ -367,7 +367,7 @@ public:
* @param[in] aLifetime The lifetime of the route in seconds.
*
*/
- void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = HostSwap32(aLifetime); }
+ void SetRouteLifetime(uint32_t aLifetime) { mRouteLifetime = BigEndian::HostSwap32(aLifetime); }
/**
* Gets Route Lifetime in seconds.
@@ -375,7 +375,7 @@ public:
* @returns The Route Lifetime in seconds.
*
*/
- uint32_t GetRouteLifetime(void) const { return HostSwap32(mRouteLifetime); }
+ uint32_t GetRouteLifetime(void) const { return BigEndian::HostSwap32(mRouteLifetime); }
/**
* Sets the prefix and adjusts the option length based on the prefix length.
@@ -562,7 +562,7 @@ public:
* @param[in] aChecksum The checksum value.
*
*/
- void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+ void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); }
/**
* Sets the Router Lifetime in seconds.
@@ -570,7 +570,7 @@ public:
* @param[in] aRouterLifetime The router lifetime in seconds.
*
*/
- void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = HostSwap16(aRouterLifetime); }
+ void SetRouterLifetime(uint16_t aRouterLifetime) { mRouterLifetime = BigEndian::HostSwap16(aRouterLifetime); }
/**
* Gets the Router Lifetime (in seconds).
@@ -580,7 +580,7 @@ public:
* @returns The router lifetime in seconds.
*
*/
- uint16_t GetRouterLifetime(void) const { return HostSwap16(mRouterLifetime); }
+ uint16_t GetRouterLifetime(void) const { return BigEndian::HostSwap16(mRouterLifetime); }
/**
* Sets the default router preference.
@@ -734,6 +734,14 @@ public:
const Header &GetHeader(void) const { return *reinterpret_cast<const Header *>(mData.GetBytes()); }
/**
+ * Gets the RA message's header.
+ *
+ * @returns The RA message's header.
+ *
+ */
+ Header &GetHeader(void) { return *reinterpret_cast<Header *>(AsNonConst(mData.GetBytes())); }
+
+ /**
* Appends a Prefix Info Option to the RA message.
*
* The appended Prefix Info Option will have both on-link (L) and autonomous address-configuration (A) flags set.
diff --git a/src/core/net/nd_agent.cpp b/src/core/net/nd_agent.cpp
index 6f1760ab3..e05dd283f 100644
--- a/src/core/net/nd_agent.cpp
+++ b/src/core/net/nd_agent.cpp
@@ -105,6 +105,7 @@ void Agent::UpdateService(void)
mAloc.InitAsThreadOrigin();
mAloc.GetAddress().SetToAnycastLocator(Get<Mle::MleRouter>().GetMeshLocalPrefix(), rloc);
+ mAloc.mMeshLocal = true;
Get<ThreadNetif>().AddUnicastAddress(mAloc);
ExitNow();
}
@@ -114,18 +115,6 @@ exit:
return;
}
-void Agent::ApplyMeshLocalPrefix(void)
-{
- VerifyOrExit(IsAlocInUse());
-
- Get<ThreadNetif>().RemoveUnicastAddress(mAloc);
- mAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
- Get<ThreadNetif>().AddUnicastAddress(mAloc);
-
-exit:
- return;
-}
-
} // namespace NeighborDiscovery
} // namespace ot
diff --git a/src/core/net/nd_agent.hpp b/src/core/net/nd_agent.hpp
index 62125b678..01303a320 100644
--- a/src/core/net/nd_agent.hpp
+++ b/src/core/net/nd_agent.hpp
@@ -66,12 +66,6 @@ public:
*/
void UpdateService(void);
- /**
- * Updates the prefix of the Neighbor Discovery Agent Anycast Locator.
- *
- */
- void ApplyMeshLocalPrefix(void);
-
private:
void FreeAloc(void) { mAloc.mNext = &mAloc; }
bool IsAlocInUse(void) const { return mAloc.mNext != &mAloc; }
diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp
index b8a99a153..ff39891e7 100644
--- a/src/core/net/netif.cpp
+++ b/src/core/net/netif.cpp
@@ -35,9 +35,9 @@
#include "common/as_core_type.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
namespace ot {
@@ -365,6 +365,11 @@ void Netif::UnsubscribeAllExternalMulticastAddresses(void)
void Netif::AddUnicastAddress(UnicastAddress &aAddress)
{
+ if (aAddress.mMeshLocal)
+ {
+ aAddress.GetAddress().SetPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
+ }
+
SuccessOrExit(mUnicastAddresses.Add(aAddress));
SignalUnicastAddressChange(kAddressAdded, aAddress);
@@ -424,7 +429,7 @@ Error Netif::AddExternalUnicastAddress(const UnicastAddress &aAddress)
if (entry != nullptr)
{
- VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorAlready);
+ VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorInvalidArgs);
entry->mPrefixLength = aAddress.mPrefixLength;
entry->mAddressOrigin = aAddress.mAddressOrigin;
@@ -438,8 +443,10 @@ Error Netif::AddExternalUnicastAddress(const UnicastAddress &aAddress)
entry = mExtUnicastAddressPool.Allocate();
VerifyOrExit(entry != nullptr, error = kErrorNoBufs);
- *entry = aAddress;
- entry->mRloc = false;
+ *entry = aAddress;
+ entry->mRloc = false;
+ entry->mMeshLocal = false;
+
mUnicastAddresses.Push(*entry);
SignalUnicastAddressChange(kAddressAdded, *entry);
@@ -490,6 +497,29 @@ bool Netif::IsUnicastAddressExternal(const UnicastAddress &aAddress) const
return mExtUnicastAddressPool.IsPoolEntry(aAddress);
}
+void Netif::ApplyNewMeshLocalPrefix(void)
+{
+ for (UnicastAddress &address : mUnicastAddresses)
+ {
+ if (address.mMeshLocal)
+ {
+ SignalUnicastAddressChange(kAddressRemoved, address);
+ address.GetAddress().SetPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
+ SignalUnicastAddressChange(kAddressAdded, address);
+ }
+ }
+
+ for (MulticastAddress &address : mMulticastAddresses)
+ {
+ if (Get<Mle::Mle>().IsMulticastAddressMeshLocalPrefixBased(address))
+ {
+ SignalMulticastAddressChange(kAddressRemoved, address, kOriginThread);
+ address.GetAddress().SetMulticastNetworkPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
+ SignalMulticastAddressChange(kAddressAdded, address, kOriginThread);
+ }
+ }
+}
+
//---------------------------------------------------------------------------------------------------------------------
// Netif::UnicastAddress
@@ -502,10 +532,11 @@ void Netif::UnicastAddress::InitAsThreadOrigin(bool aPreferred)
mValid = true;
}
-void Netif::UnicastAddress::InitAsThreadOriginRealmLocalScope(void)
+void Netif::UnicastAddress::InitAsThreadOriginMeshLocal(void)
{
InitAsThreadOrigin();
SetScopeOverride(Address::kRealmLocalScope);
+ mMeshLocal = true;
}
void Netif::UnicastAddress::InitAsThreadOriginGlobalScope(void)
diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp
index be186b543..0e5057134 100644
--- a/src/core/net/netif.hpp
+++ b/src/core/net/netif.hpp
@@ -123,10 +123,10 @@ public:
/**
* Clears and initializes the unicast address as a valid (but not preferred), thread-origin,
- * realm-local scope (overridden) address with 64-bit prefix length.
+ * mesh-local address using the realm-local scope (overridden) address with 64-bit prefix length.
*
*/
- void InitAsThreadOriginRealmLocalScope(void);
+ void InitAsThreadOriginMeshLocal(void);
/**
* Clears and initializes the unicast address as a valid (but not preferred), thread-origin, global
@@ -215,6 +215,22 @@ public:
*/
AddressOrigin GetOrigin(void) const { return static_cast<AddressOrigin>(mAddressOrigin); }
+ /**
+ * Returns the next unicast address.
+ *
+ * @returns A pointer to the next unicast address.
+ *
+ */
+ const UnicastAddress *GetNext(void) const { return static_cast<const UnicastAddress *>(mNext); }
+
+ /**
+ * Returns the next unicast address.
+ *
+ * @returns A pointer to the next unicast address.
+ *
+ */
+ UnicastAddress *GetNext(void) { return static_cast<UnicastAddress *>(AsNonConst(mNext)); }
+
private:
bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; }
};
@@ -412,7 +428,7 @@ public:
*
* @param[in] aAddress A reference to the unicast address.
*
- * @retval TRUE If @p aAddress is assigned to the network interface,
+ * @retval TRUE If @p aAddress is assigned to the network interface.
* @retval FALSE If @p aAddress is not assigned to the network interface.
*
*/
@@ -423,7 +439,7 @@ public:
*
* @param[in] aAddress A reference to the unicast address.
*
- * @retval TRUE If @p aAddress is assigned to the network interface,
+ * @retval TRUE If @p aAddress is assigned to the network interface.
* @retval FALSE If @p aAddress is not assigned to the network interface.
*
*/
@@ -630,6 +646,14 @@ public:
*/
bool HasAnyExternalMulticastAddress(void) const { return !ExternalMulticastAddress::Iterator(*this).IsDone(); }
+ /**
+ * Applies the new mesh local prefix.
+ *
+ * Updates all mesh-local unicast addresses and prefix-based multicast addresses of the network interface.
+ *
+ */
+ void ApplyNewMeshLocalPrefix(void);
+
protected:
/**
* Subscribes the network interface to the realm-local all MPL forwarders, link-local, and realm-local
diff --git a/src/core/net/sntp_client.cpp b/src/core/net/sntp_client.cpp
index bc79e3d9b..5897a5f3b 100644
--- a/src/core/net/sntp_client.cpp
+++ b/src/core/net/sntp_client.cpp
@@ -34,9 +34,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "net/udp6.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/net/sntp_client.hpp b/src/core/net/sntp_client.hpp
index 3a513aa4e..d6d4dad3c 100644
--- a/src/core/net/sntp_client.hpp
+++ b/src/core/net/sntp_client.hpp
@@ -50,8 +50,6 @@
namespace ot {
namespace Sntp {
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* Implements SNTP client.
*
@@ -153,40 +151,70 @@ private:
uint8_t GetPrecision(void) const { return mPrecision; }
void SetPrecision(uint8_t aPrecision) { mPrecision = aPrecision; }
- uint32_t GetRootDelay(void) const { return HostSwap32(mRootDelay); }
- void SetRootDelay(uint32_t aRootDelay) { mRootDelay = HostSwap32(aRootDelay); }
+ uint32_t GetRootDelay(void) const { return BigEndian::HostSwap32(mRootDelay); }
+ void SetRootDelay(uint32_t aRootDelay) { mRootDelay = BigEndian::HostSwap32(aRootDelay); }
- uint32_t GetRootDispersion(void) const { return HostSwap32(mRootDispersion); }
- void SetRootDispersion(uint32_t aRootDispersion) { mRootDispersion = HostSwap32(aRootDispersion); }
+ uint32_t GetRootDispersion(void) const { return BigEndian::HostSwap32(mRootDispersion); }
+ void SetRootDispersion(uint32_t aRootDispersion) { mRootDispersion = BigEndian::HostSwap32(aRootDispersion); }
- uint32_t GetReferenceId(void) const { return HostSwap32(mReferenceId); }
- void SetReferenceId(uint32_t aReferenceId) { mReferenceId = HostSwap32(aReferenceId); }
+ uint32_t GetReferenceId(void) const { return BigEndian::HostSwap32(mReferenceId); }
+ void SetReferenceId(uint32_t aReferenceId) { mReferenceId = BigEndian::HostSwap32(aReferenceId); }
char *GetKissCode(void) { return reinterpret_cast<char *>(&mReferenceId); }
- uint32_t GetReferenceTimestampSeconds(void) const { return HostSwap32(mReferenceTimestampSeconds); }
- void SetReferenceTimestampSeconds(uint32_t aTimestamp) { mReferenceTimestampSeconds = HostSwap32(aTimestamp); }
+ uint32_t GetReferenceTimestampSeconds(void) const { return BigEndian::HostSwap32(mReferenceTimestampSeconds); }
+ void SetReferenceTimestampSeconds(uint32_t aTimestamp)
+ {
+ mReferenceTimestampSeconds = BigEndian::HostSwap32(aTimestamp);
+ }
- uint32_t GetReferenceTimestampFraction(void) const { return HostSwap32(mReferenceTimestampFraction); }
- void SetReferenceTimestampFraction(uint32_t aFraction) { mReferenceTimestampFraction = HostSwap32(aFraction); }
+ uint32_t GetReferenceTimestampFraction(void) const
+ {
+ return BigEndian::HostSwap32(mReferenceTimestampFraction);
+ }
+ void SetReferenceTimestampFraction(uint32_t aFraction)
+ {
+ mReferenceTimestampFraction = BigEndian::HostSwap32(aFraction);
+ }
- uint32_t GetOriginateTimestampSeconds(void) const { return HostSwap32(mOriginateTimestampSeconds); }
- void SetOriginateTimestampSeconds(uint32_t aTimestamp) { mOriginateTimestampSeconds = HostSwap32(aTimestamp); }
+ uint32_t GetOriginateTimestampSeconds(void) const { return BigEndian::HostSwap32(mOriginateTimestampSeconds); }
+ void SetOriginateTimestampSeconds(uint32_t aTimestamp)
+ {
+ mOriginateTimestampSeconds = BigEndian::HostSwap32(aTimestamp);
+ }
- uint32_t GetOriginateTimestampFraction(void) const { return HostSwap32(mOriginateTimestampFraction); }
- void SetOriginateTimestampFraction(uint32_t aFraction) { mOriginateTimestampFraction = HostSwap32(aFraction); }
+ uint32_t GetOriginateTimestampFraction(void) const
+ {
+ return BigEndian::HostSwap32(mOriginateTimestampFraction);
+ }
+ void SetOriginateTimestampFraction(uint32_t aFraction)
+ {
+ mOriginateTimestampFraction = BigEndian::HostSwap32(aFraction);
+ }
- uint32_t GetReceiveTimestampSeconds(void) const { return HostSwap32(mReceiveTimestampSeconds); }
- void SetReceiveTimestampSeconds(uint32_t aTimestamp) { mReceiveTimestampSeconds = HostSwap32(aTimestamp); }
+ uint32_t GetReceiveTimestampSeconds(void) const { return BigEndian::HostSwap32(mReceiveTimestampSeconds); }
+ void SetReceiveTimestampSeconds(uint32_t aTimestamp)
+ {
+ mReceiveTimestampSeconds = BigEndian::HostSwap32(aTimestamp);
+ }
- uint32_t GetReceiveTimestampFraction(void) const { return HostSwap32(mReceiveTimestampFraction); }
- void SetReceiveTimestampFraction(uint32_t aFraction) { mReceiveTimestampFraction = HostSwap32(aFraction); }
+ uint32_t GetReceiveTimestampFraction(void) const { return BigEndian::HostSwap32(mReceiveTimestampFraction); }
+ void SetReceiveTimestampFraction(uint32_t aFraction)
+ {
+ mReceiveTimestampFraction = BigEndian::HostSwap32(aFraction);
+ }
- uint32_t GetTransmitTimestampSeconds(void) const { return HostSwap32(mTransmitTimestampSeconds); }
- void SetTransmitTimestampSeconds(uint32_t aTimestamp) { mTransmitTimestampSeconds = HostSwap32(aTimestamp); }
+ uint32_t GetTransmitTimestampSeconds(void) const { return BigEndian::HostSwap32(mTransmitTimestampSeconds); }
+ void SetTransmitTimestampSeconds(uint32_t aTimestamp)
+ {
+ mTransmitTimestampSeconds = BigEndian::HostSwap32(aTimestamp);
+ }
- uint32_t GetTransmitTimestampFraction(void) const { return HostSwap32(mTransmitTimestampFraction); }
- void SetTransmitTimestampFraction(uint32_t aFraction) { mTransmitTimestampFraction = HostSwap32(aFraction); }
+ uint32_t GetTransmitTimestampFraction(void) const { return BigEndian::HostSwap32(mTransmitTimestampFraction); }
+ void SetTransmitTimestampFraction(uint32_t aFraction)
+ {
+ mTransmitTimestampFraction = BigEndian::HostSwap32(aFraction);
+ }
private:
static constexpr uint8_t kNtpVersion = 4; // Current NTP version.
diff --git a/src/core/net/srp_client.cpp b/src/core/net/srp_client.cpp
index eae23025c..617091ca1 100644
--- a/src/core/net/srp_client.cpp
+++ b/src/core/net/srp_client.cpp
@@ -33,12 +33,12 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
#include "common/settings.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
/**
* @file
@@ -1240,21 +1240,23 @@ Error Client::AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo)
if (mHostInfo.IsAutoAddressEnabled())
{
- // Append all addresses on Thread netif excluding link-local and
- // mesh-local addresses. If no address is appended, we include
- // the mesh local address.
+ // Append all preferred addresses on Thread netif excluding link-local
+ // and mesh-local addresses. If no address is appended, we include
+ // the mesh local EID.
mAutoHostAddressAddedMeshLocal = true;
for (const Ip6::Netif::UnicastAddress &unicastAddress : Get<ThreadNetif>().GetUnicastAddresses())
{
- if (unicastAddress.GetAddress().IsLinkLocal() ||
- Get<Mle::Mle>().IsMeshLocalAddress(unicastAddress.GetAddress()))
+ const Ip6::Address &address = unicastAddress.GetAddress();
+
+ if (address.IsLinkLocal() || Get<Mle::Mle>().IsMeshLocalAddress(address) || !unicastAddress.mPreferred ||
+ !unicastAddress.mValid)
{
continue;
}
- SuccessOrExit(error = AppendAaaaRecord(unicastAddress.GetAddress(), aMessage, aInfo));
+ SuccessOrExit(error = AppendAaaaRecord(address, aMessage, aInfo));
mAutoHostAddressAddedMeshLocal = false;
}
diff --git a/src/core/net/srp_server.cpp b/src/core/net/srp_server.cpp
index 2a57c9217..aaaaaa71f 100644
--- a/src/core/net/srp_server.cpp
+++ b/src/core/net/srp_server.cpp
@@ -37,13 +37,13 @@
#include "common/as_core_type.hpp"
#include "common/const_cast.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/new.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "net/dns_types.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/net/tcp6.cpp b/src/core/net/tcp6.cpp
index 74d598a82..d9712a3c6 100644
--- a/src/core/net/tcp6.cpp
+++ b/src/core/net/tcp6.cpp
@@ -40,11 +40,11 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/error.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
@@ -54,9 +54,6 @@
namespace ot {
namespace Ip6 {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
RegisterLogModule("Tcp");
static_assert(sizeof(struct tcpcb) == sizeof(Tcp::Endpoint::mTcb), "mTcb field in otTcpEndpoint is sized incorrectly");
@@ -133,7 +130,7 @@ const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const
static otSockAddr temp;
memcpy(&temp.mAddress, &tp.laddr, sizeof(temp.mAddress));
- temp.mPort = HostSwap16(tp.lport);
+ temp.mPort = BigEndian::HostSwap16(tp.lport);
return AsCoreType(&temp);
}
@@ -145,7 +142,7 @@ const SockAddr &Tcp::Endpoint::GetPeerAddress(void) const
static otSockAddr temp;
memcpy(&temp.mAddress, &tp.faddr, sizeof(temp.mAddress));
- temp.mPort = HostSwap16(tp.fport);
+ temp.mPort = BigEndian::HostSwap16(tp.fport);
return AsCoreType(&temp);
}
@@ -159,7 +156,7 @@ Error Tcp::Endpoint::Bind(const SockAddr &aSockName)
VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
memcpy(&tp.laddr, &aSockName.mAddress, sizeof(tp.laddr));
- tp.lport = HostSwap16(aSockName.mPort);
+ tp.lport = BigEndian::HostSwap16(aSockName.mPort);
error = kErrorNone;
exit:
@@ -179,7 +176,7 @@ Error Tcp::Endpoint::Connect(const SockAddr &aSockName, uint32_t aFlags)
tp.t_flags &= ~TF_FASTOPEN;
memcpy(&sin6p.sin6_addr, &aSockName.mAddress, sizeof(sin6p.sin6_addr));
- sin6p.sin6_port = HostSwap16(aSockName.mPort);
+ sin6p.sin6_port = BigEndian::HostSwap16(aSockName.mPort);
error = BsdErrorToOtError(tcp6_usr_connect(&tp, &sin6p));
}
else
@@ -188,7 +185,7 @@ Error Tcp::Endpoint::Connect(const SockAddr &aSockName, uint32_t aFlags)
/* Stash the destination address in tp. */
memcpy(&tp.faddr, &aSockName.mAddress, sizeof(tp.faddr));
- tp.fport = HostSwap16(aSockName.mPort);
+ tp.fport = BigEndian::HostSwap16(aSockName.mPort);
}
exit:
@@ -530,8 +527,8 @@ bool Tcp::Endpoint::Matches(const MessageInfo &aMessageInfo) const
const struct tcpcb *tp = &GetTcb();
VerifyOrExit(tp->t_state != TCP6S_CLOSED);
- VerifyOrExit(tp->lport == HostSwap16(aMessageInfo.GetSockPort()));
- VerifyOrExit(tp->fport == HostSwap16(aMessageInfo.GetPeerPort()));
+ VerifyOrExit(tp->lport == BigEndian::HostSwap16(aMessageInfo.GetSockPort()));
+ VerifyOrExit(tp->fport == BigEndian::HostSwap16(aMessageInfo.GetPeerPort()));
VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
VerifyOrExit(GetForeignIp6Address() == aMessageInfo.GetPeerAddr());
@@ -564,7 +561,7 @@ Instance &Tcp::Listener::GetInstance(void) const { return AsNonConst(AsCoreType(
Error Tcp::Listener::Listen(const SockAddr &aSockName)
{
Error error;
- uint16_t port = HostSwap16(aSockName.mPort);
+ uint16_t port = BigEndian::HostSwap16(aSockName.mPort);
struct tcpcb_listen *tpl = &GetTcbListen();
VerifyOrExit(Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
@@ -614,7 +611,7 @@ bool Tcp::Listener::Matches(const MessageInfo &aMessageInfo) const
const struct tcpcb_listen *tpl = &GetTcbListen();
VerifyOrExit(tpl->t_state == TCP6S_LISTEN);
- VerifyOrExit(tpl->lport == HostSwap16(aMessageInfo.GetSockPort()));
+ VerifyOrExit(tpl->lport == BigEndian::HostSwap16(aMessageInfo.GetSockPort()));
VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
matches = true;
@@ -662,8 +659,8 @@ Error Tcp::HandleMessage(ot::Ip6::Header &aIp6Header, Message &aMessage, Message
tcpHeader = reinterpret_cast<struct tcphdr *>(&header[0]);
tcp_fields_to_host(tcpHeader);
- aMessageInfo.mPeerPort = HostSwap16(tcpHeader->th_sport);
- aMessageInfo.mSockPort = HostSwap16(tcpHeader->th_dport);
+ aMessageInfo.mPeerPort = BigEndian::HostSwap16(tcpHeader->th_sport);
+ aMessageInfo.mSockPort = BigEndian::HostSwap16(tcpHeader->th_dport);
endpoint = mEndpoints.FindMatching(aMessageInfo, endpointPrev);
if (endpoint != nullptr)
@@ -781,7 +778,7 @@ Error Tcp::BsdErrorToOtError(int aBsdError)
bool Tcp::CanBind(const SockAddr &aSockName)
{
- uint16_t port = HostSwap16(aSockName.mPort);
+ uint16_t port = BigEndian::HostSwap16(aSockName.mPort);
bool allowed = false;
for (Endpoint &endpoint : mEndpoints)
@@ -1013,7 +1010,7 @@ struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *aTcbListen, struct in6
VerifyOrExit(listener.mAcceptReadyCallback != nullptr);
memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
- addr.mPort = HostSwap16(aPort);
+ addr.mPort = BigEndian::HostSwap16(aPort);
action = listener.mAcceptReadyCallback(&listener, &addr, &endpointPtr);
VerifyOrExit(tcp.IsInitialized(listener) && !listener.IsClosed());
@@ -1063,7 +1060,7 @@ bool tcplp_sys_accepted_connection(struct tcpcb_listen *aTcbListen,
otSockAddr addr;
memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
- addr.mPort = HostSwap16(aPort);
+ addr.mPort = BigEndian::HostSwap16(aPort);
listener.mAcceptDoneCallback(&listener, &endpoint, &addr);
if (!tcp.IsInitialized(endpoint) || endpoint.IsClosed())
@@ -1158,9 +1155,9 @@ uint32_t tcplp_sys_generate_isn()
return isn;
}
-uint16_t tcplp_sys_hostswap16(uint16_t aHostPort) { return HostSwap16(aHostPort); }
+uint16_t tcplp_sys_hostswap16(uint16_t aHostPort) { return BigEndian::HostSwap16(aHostPort); }
-uint32_t tcplp_sys_hostswap32(uint32_t aHostPort) { return HostSwap32(aHostPort); }
+uint32_t tcplp_sys_hostswap32(uint32_t aHostPort) { return BigEndian::HostSwap32(aHostPort); }
}
#endif // OPENTHREAD_CONFIG_TCP_ENABLE
diff --git a/src/core/net/tcp6.hpp b/src/core/net/tcp6.hpp
index 368120645..1ffe8ef4b 100644
--- a/src/core/net/tcp6.hpp
+++ b/src/core/net/tcp6.hpp
@@ -550,7 +550,7 @@ public:
* @returns The TCP Source Port.
*
*/
- uint16_t GetSourcePort(void) const { return HostSwap16(mSource); }
+ uint16_t GetSourcePort(void) const { return BigEndian::HostSwap16(mSource); }
/**
* Returns the TCP Destination Port.
@@ -558,7 +558,7 @@ public:
* @returns The TCP Destination Port.
*
*/
- uint16_t GetDestinationPort(void) const { return HostSwap16(mDestination); }
+ uint16_t GetDestinationPort(void) const { return BigEndian::HostSwap16(mDestination); }
/**
* Returns the TCP Sequence Number.
@@ -566,7 +566,7 @@ public:
* @returns The TCP Sequence Number.
*
*/
- uint32_t GetSequenceNumber(void) const { return HostSwap32(mSequenceNumber); }
+ uint32_t GetSequenceNumber(void) const { return BigEndian::HostSwap32(mSequenceNumber); }
/**
* Returns the TCP Acknowledgment Sequence Number.
@@ -574,7 +574,7 @@ public:
* @returns The TCP Acknowledgment Sequence Number.
*
*/
- uint32_t GetAcknowledgmentNumber(void) const { return HostSwap32(mAckNumber); }
+ uint32_t GetAcknowledgmentNumber(void) const { return BigEndian::HostSwap32(mAckNumber); }
/**
* Returns the TCP Flags.
@@ -582,7 +582,7 @@ public:
* @returns The TCP Flags.
*
*/
- uint16_t GetFlags(void) const { return HostSwap16(mFlags); }
+ uint16_t GetFlags(void) const { return BigEndian::HostSwap16(mFlags); }
/**
* Returns the TCP Window.
@@ -590,7 +590,7 @@ public:
* @returns The TCP Window.
*
*/
- uint16_t GetWindow(void) const { return HostSwap16(mWindow); }
+ uint16_t GetWindow(void) const { return BigEndian::HostSwap16(mWindow); }
/**
* Returns the TCP Checksum.
@@ -598,7 +598,7 @@ public:
* @returns The TCP Checksum.
*
*/
- uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
+ uint16_t GetChecksum(void) const { return BigEndian::HostSwap16(mChecksum); }
/**
* Returns the TCP Urgent Pointer.
@@ -606,7 +606,7 @@ public:
* @returns The TCP Urgent Pointer.
*
*/
- uint16_t GetUrgentPointer(void) const { return HostSwap16(mUrgentPointer); }
+ uint16_t GetUrgentPointer(void) const { return BigEndian::HostSwap16(mUrgentPointer); }
private:
uint16_t mSource;
diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp
index 3ddda61cd..71d0ea872 100644
--- a/src/core/net/udp6.cpp
+++ b/src/core/net/udp6.cpp
@@ -39,8 +39,8 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/ip6.hpp"
@@ -355,7 +355,7 @@ Error Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &a
else
#endif
{
- SuccessOrExit(error = SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
+ SuccessOrExit(error = SendDatagram(aMessage, messageInfoLocal));
}
exit:
@@ -427,7 +427,7 @@ Message *Udp::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
return Get<Ip6>().NewMessage(sizeof(Header) + aReserved, aSettings);
}
-Error Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto)
+Error Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo)
{
Error error = kErrorNone;
@@ -451,7 +451,7 @@ Error Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI
SuccessOrExit(error = aMessage.Prepend(udpHeader));
aMessage.SetOffset(0);
- error = Get<Ip6>().SendDatagram(aMessage, aMessageInfo, aIpProto);
+ error = Get<Ip6>().SendDatagram(aMessage, aMessageInfo, kProtoUdp);
}
exit:
diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp
index 8f7460a50..24e706607 100644
--- a/src/core/net/udp6.hpp
+++ b/src/core/net/udp6.hpp
@@ -373,7 +373,7 @@ public:
* @returns The UDP Source Port.
*
*/
- uint16_t GetSourcePort(void) const { return HostSwap16(mSourcePort); }
+ uint16_t GetSourcePort(void) const { return BigEndian::HostSwap16(mSourcePort); }
/**
* Sets the UDP Source Port.
@@ -381,7 +381,7 @@ public:
* @param[in] aPort The UDP Source Port.
*
*/
- void SetSourcePort(uint16_t aPort) { mSourcePort = HostSwap16(aPort); }
+ void SetSourcePort(uint16_t aPort) { mSourcePort = BigEndian::HostSwap16(aPort); }
/**
* Returns the UDP Destination Port.
@@ -389,7 +389,7 @@ public:
* @returns The UDP Destination Port.
*
*/
- uint16_t GetDestinationPort(void) const { return HostSwap16(mDestinationPort); }
+ uint16_t GetDestinationPort(void) const { return BigEndian::HostSwap16(mDestinationPort); }
/**
* Sets the UDP Destination Port.
@@ -397,7 +397,7 @@ public:
* @param[in] aPort The UDP Destination Port.
*
*/
- void SetDestinationPort(uint16_t aPort) { mDestinationPort = HostSwap16(aPort); }
+ void SetDestinationPort(uint16_t aPort) { mDestinationPort = BigEndian::HostSwap16(aPort); }
/**
* Returns the UDP Length.
@@ -405,7 +405,7 @@ public:
* @returns The UDP Length.
*
*/
- uint16_t GetLength(void) const { return HostSwap16(mLength); }
+ uint16_t GetLength(void) const { return BigEndian::HostSwap16(mLength); }
/**
* Sets the UDP Length.
@@ -413,7 +413,7 @@ public:
* @param[in] aLength The UDP Length.
*
*/
- void SetLength(uint16_t aLength) { mLength = HostSwap16(aLength); }
+ void SetLength(uint16_t aLength) { mLength = BigEndian::HostSwap16(aLength); }
/**
* Returns the UDP Checksum.
@@ -421,7 +421,7 @@ public:
* @returns The UDP Checksum.
*
*/
- uint16_t GetChecksum(void) const { return HostSwap16(mChecksum); }
+ uint16_t GetChecksum(void) const { return BigEndian::HostSwap16(mChecksum); }
/**
* Sets the UDP Checksum.
@@ -429,7 +429,7 @@ public:
* @param[in] aChecksum The UDP Checksum.
*
*/
- void SetChecksum(uint16_t aChecksum) { mChecksum = HostSwap16(aChecksum); }
+ void SetChecksum(uint16_t aChecksum) { mChecksum = BigEndian::HostSwap16(aChecksum); }
private:
uint16_t mSourcePort;
@@ -585,13 +585,12 @@ public:
*
* @param[in] aMessage A reference to the message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
- * @param[in] aIpProto The Internet Protocol value.
*
* @retval kErrorNone Successfully enqueued the message into an output interface.
* @retval kErrorNoBufs Insufficient available buffer to add the IPv6 headers.
*
*/
- Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto);
+ Error SendDatagram(Message &aMessage, MessageInfo &aMessageInfo);
/**
* Handles a received UDP message.
diff --git a/src/core/radio/radio.cpp b/src/core/radio/radio.cpp
index 9b3eb695e..bdc46bed3 100644
--- a/src/core/radio/radio.cpp
+++ b/src/core/radio/radio.cpp
@@ -61,6 +61,7 @@ void Radio::Init(void)
SetMacFrameCounter(0);
SetPromiscuous(false);
+ SetRxOnWhenIdle(true);
#endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
}
#endif // OPENTHREAD_RADIO
diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp
index 892e57919..3321abea4 100644
--- a/src/core/radio/radio.hpp
+++ b/src/core/radio/radio.hpp
@@ -435,6 +435,14 @@ public:
void SetPromiscuous(bool aEnable);
/**
+ * Indicates whether radio should stay in Receive or Sleep during idle periods.
+ *
+ * @param[in] aEnable TRUE to keep radio in Receive, FALSE to put to Sleep during idle periods.
+ *
+ */
+ void SetRxOnWhenIdle(bool aEnable);
+
+ /**
* Returns the current state of the radio.
*
* Is not required by OpenThread. It may be used for debugging and/or application-specific purposes.
@@ -833,6 +841,8 @@ inline bool Radio::GetPromiscuous(void) { return otPlatRadioGetPromiscuous(GetIn
inline void Radio::SetPromiscuous(bool aEnable) { otPlatRadioSetPromiscuous(GetInstancePtr(), aEnable); }
+inline void Radio::SetRxOnWhenIdle(bool aEnable) { otPlatRadioSetRxOnWhenIdle(GetInstancePtr(), aEnable); }
+
inline otRadioState Radio::GetState(void) { return otPlatRadioGetState(GetInstancePtr()); }
inline Error Radio::Enable(void)
@@ -974,6 +984,8 @@ inline bool Radio::GetPromiscuous(void) { return false; }
inline void Radio::SetPromiscuous(bool) {}
+inline void Radio::SetRxOnWhenIdle(bool) {}
+
inline otRadioState Radio::GetState(void) { return OT_RADIO_STATE_DISABLED; }
inline Error Radio::Enable(void) { return kErrorNone; }
diff --git a/src/core/radio/radio_callbacks.cpp b/src/core/radio/radio_callbacks.cpp
index ae85c7780..6a6131c19 100644
--- a/src/core/radio/radio_callbacks.cpp
+++ b/src/core/radio/radio_callbacks.cpp
@@ -33,8 +33,8 @@
#include "radio.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/radio/radio_platform.cpp b/src/core/radio/radio_platform.cpp
index 7840a867c..b71a0fb0e 100644
--- a/src/core/radio/radio_platform.cpp
+++ b/src/core/radio/radio_platform.cpp
@@ -35,7 +35,7 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "radio/radio.hpp"
using namespace ot;
@@ -314,3 +314,9 @@ OT_TOOL_WEAK otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChanne
return kErrorNotImplemented;
}
+
+OT_TOOL_WEAK void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnable)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aEnable);
+}
diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp
index 2f69c7d0a..d25347733 100644
--- a/src/core/radio/trel_interface.cpp
+++ b/src/core/radio/trel_interface.cpp
@@ -40,10 +40,10 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "net/dns_types.hpp"
namespace ot {
@@ -263,7 +263,7 @@ Error Interface::ParsePeerInfoTxtData(const Peer::Info &aInfo,
while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
{
// If the TXT data happens to have entries with key longer
- // than `kMaxKeyLength`, `mKey` would be `nullptr` and full
+ // than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full
// entry would be placed in `mValue`. We skip over such
// entries.
if (entry.mKey == nullptr)
diff --git a/src/core/radio/trel_link.cpp b/src/core/radio/trel_link.cpp
index 203e0dfeb..b97676549 100644
--- a/src/core/radio/trel_link.cpp
+++ b/src/core/radio/trel_link.cpp
@@ -36,9 +36,9 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Trel {
@@ -224,7 +224,7 @@ void Link::BeginTransmit(void)
}
// Prepare the ack frame (FCF followed by sequence number)
- Encoding::LittleEndian::WriteUint16(fcf, mAckFrameBuffer);
+ LittleEndian::WriteUint16(fcf, mAckFrameBuffer);
mAckFrameBuffer[sizeof(fcf)] = mTxFrame.GetSequence();
mRxFrame.mPsdu = mAckFrameBuffer;
diff --git a/src/core/radio/trel_packet.cpp b/src/core/radio/trel_packet.cpp
index 2847b6001..f28129f72 100644
--- a/src/core/radio/trel_packet.cpp
+++ b/src/core/radio/trel_packet.cpp
@@ -36,8 +36,8 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Trel {
diff --git a/src/core/radio/trel_packet.hpp b/src/core/radio/trel_packet.hpp
index 5b4caace6..3f2dd99d6 100644
--- a/src/core/radio/trel_packet.hpp
+++ b/src/core/radio/trel_packet.hpp
@@ -154,7 +154,7 @@ public:
* @returns The PAN Identifier field.
*
*/
- Mac::PanId GetPanId(void) const { return Encoding::BigEndian::HostSwap16(mPanId); }
+ Mac::PanId GetPanId(void) const { return BigEndian::HostSwap16(mPanId); }
/**
* Sets the PAN Identifier field in the header.
@@ -162,7 +162,7 @@ public:
* @param[in] aPanId A PAN Identifier.
*
*/
- void SetPanId(Mac::PanId aPanId) { mPanId = Encoding::BigEndian::HostSwap16(aPanId); }
+ void SetPanId(Mac::PanId aPanId) { mPanId = BigEndian::HostSwap16(aPanId); }
/**
* Gets the packet number field from the header.
@@ -170,7 +170,7 @@ public:
* @returns The packet number field.
*
*/
- uint32_t GetPacketNumber(void) const { return Encoding::BigEndian::HostSwap32(mPacketNumber); }
+ uint32_t GetPacketNumber(void) const { return BigEndian::HostSwap32(mPacketNumber); }
/**
* Sets the packet number field in the header.
@@ -178,7 +178,7 @@ public:
* @param[in] aPacketNumber The packet number.
*
*/
- void SetPacketNumber(uint32_t aPacketNumber) { mPacketNumber = Encoding::BigEndian::HostSwap32(aPacketNumber); }
+ void SetPacketNumber(uint32_t aPacketNumber) { mPacketNumber = BigEndian::HostSwap32(aPacketNumber); }
/**
* Gets the source MAC address field from the header.
diff --git a/src/core/thread/address_resolver.cpp b/src/core/thread/address_resolver.cpp
index 2337f8185..a779a1158 100644
--- a/src/core/thread/address_resolver.cpp
+++ b/src/core/thread/address_resolver.cpp
@@ -38,10 +38,10 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "thread/mesh_forwarder.hpp"
#include "thread/mle_router.hpp"
diff --git a/src/core/thread/announce_begin_server.cpp b/src/core/thread/announce_begin_server.cpp
index 1c904e358..4db912dd2 100644
--- a/src/core/thread/announce_begin_server.cpp
+++ b/src/core/thread/announce_begin_server.cpp
@@ -39,9 +39,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
#include "thread/uri_paths.hpp"
diff --git a/src/core/thread/announce_sender.cpp b/src/core/thread/announce_sender.cpp
index 810939e4c..4a8ece2c8 100644
--- a/src/core/thread/announce_sender.cpp
+++ b/src/core/thread/announce_sender.cpp
@@ -36,10 +36,10 @@
#include <openthread/platform/radio.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "radio/radio.hpp"
diff --git a/src/core/thread/anycast_locator.cpp b/src/core/thread/anycast_locator.cpp
index 88a02d4e1..14e0fd843 100644
--- a/src/core/thread/anycast_locator.cpp
+++ b/src/core/thread/anycast_locator.cpp
@@ -37,8 +37,8 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/uri_paths.hpp"
diff --git a/src/core/thread/child.cpp b/src/core/thread/child.cpp
index 7dbec0c40..008173b6d 100644
--- a/src/core/thread/child.cpp
+++ b/src/core/thread/child.cpp
@@ -36,9 +36,9 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/child_supervision.cpp b/src/core/thread/child_supervision.cpp
index 02ba64ada..80622ebb4 100644
--- a/src/core/thread/child_supervision.cpp
+++ b/src/core/thread/child_supervision.cpp
@@ -35,9 +35,9 @@
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "thread/thread_netif.hpp"
namespace ot {
@@ -67,13 +67,13 @@ exit:
void ChildSupervisor::SendMessage(Child &aChild)
{
- Message *message = nullptr;
- uint16_t childIndex;
+ OwnedPtr<Message> messagePtr;
+ uint16_t childIndex;
VerifyOrExit(aChild.GetIndirectMessageCount() == 0);
- message = Get<MessagePool>().Allocate(Message::kTypeSupervision, sizeof(uint8_t));
- VerifyOrExit(message != nullptr);
+ messagePtr.Reset(Get<MessagePool>().Allocate(Message::kTypeSupervision, sizeof(uint8_t)));
+ VerifyOrExit(messagePtr != nullptr);
// Supervision message is an empty payload 15.4 data frame.
// The child index is stored here in the message content to allow
@@ -81,15 +81,14 @@ void ChildSupervisor::SendMessage(Child &aChild)
// `ChildSupervisor::GetDestination(message)`.
childIndex = Get<ChildTable>().GetChildIndex(aChild);
- SuccessOrExit(message->Append(childIndex));
+ SuccessOrExit(messagePtr->Append(childIndex));
- SuccessOrExit(Get<MeshForwarder>().SendMessage(*message));
- message = nullptr;
+ Get<MeshForwarder>().SendMessage(messagePtr.PassOwnership());
LogInfo("Sending supervision message to child 0x%04x", aChild.GetRloc16());
exit:
- FreeMessage(message);
+ return;
}
void ChildSupervisor::UpdateOnSend(Child &aChild) { aChild.ResetSecondsSinceLastSupervision(); }
diff --git a/src/core/thread/child_table.cpp b/src/core/thread/child_table.cpp
index e5ec20936..cd9cb6549 100644
--- a/src/core/thread/child_table.cpp
+++ b/src/core/thread/child_table.cpp
@@ -36,8 +36,8 @@
#if OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/discover_scanner.cpp b/src/core/thread/discover_scanner.cpp
index 0fa311c90..2425e1e3a 100644
--- a/src/core/thread/discover_scanner.cpp
+++ b/src/core/thread/discover_scanner.cpp
@@ -35,8 +35,8 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "thread/mesh_forwarder.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"
diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp
index 934f33870..7d78879a3 100644
--- a/src/core/thread/dua_manager.cpp
+++ b/src/core/thread/dua_manager.cpp
@@ -37,10 +37,10 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/settings.hpp"
+#include "instance/instance.hpp"
#include "net/ip6_address.hpp"
#include "thread/mle_types.hpp"
#include "thread/thread_netif.hpp"
@@ -146,7 +146,7 @@ Error DuaManager::GenerateDomainUnicastAddressIid(void)
Error error;
uint8_t dadCounter = mDadCounter;
- if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, nullptr, 0, &dadCounter)) == kErrorNone)
+ if ((error = Get<Utils::Slaac>().GenerateIid(mDomainUnicastAddress, dadCounter)) == kErrorNone)
{
if (dadCounter != mDadCounter)
{
diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp
index c207ef9f3..c3901419c 100644
--- a/src/core/thread/energy_scan_server.cpp
+++ b/src/core/thread/energy_scan_server.cpp
@@ -37,9 +37,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
@@ -207,8 +207,10 @@ exit:
void EnergyScanServer::HandleNotifierEvents(Events aEvents)
{
+ uint16_t borderAgentRloc;
+
if (aEvents.Contains(kEventThreadNetdataChanged) && (mReportMessage != nullptr) &&
- Get<NetworkData::Leader>().GetCommissioningData() == nullptr)
+ Get<NetworkData::Leader>().FindBorderAgentRloc(borderAgentRloc) != kErrorNone)
{
mReportMessage->Free();
mReportMessage = nullptr;
diff --git a/src/core/thread/indirect_sender.cpp b/src/core/thread/indirect_sender.cpp
index 7549702ff..89e886917 100644
--- a/src/core/thread/indirect_sender.cpp
+++ b/src/core/thread/indirect_sender.cpp
@@ -36,9 +36,9 @@
#if OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "thread/child.hpp"
#include "thread/mesh_forwarder.hpp"
#include "thread/mle_tlvs.hpp"
diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp
index ddcbf74ef..4d734442a 100644
--- a/src/core/thread/key_manager.cpp
+++ b/src/core/thread/key_manager.cpp
@@ -35,12 +35,12 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/timer.hpp"
#include "crypto/hkdf_sha256.hpp"
#include "crypto/storage.hpp"
+#include "instance/instance.hpp"
#include "thread/mle_router.hpp"
#include "thread/thread_netif.hpp"
@@ -298,7 +298,7 @@ void KeyManager::ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys) const
hmac.Start(cryptoKey);
- Encoding::BigEndian::WriteUint32(aKeySequence, keySequenceBytes);
+ BigEndian::WriteUint32(aKeySequence, keySequenceBytes);
hmac.Update(keySequenceBytes);
hmac.Update(kThreadString);
@@ -318,7 +318,7 @@ void KeyManager::ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey) const
cryptoKey.Set(mNetworkKey.m8, NetworkKey::kSize);
#endif
- Encoding::BigEndian::WriteUint32(aKeySequence, salt);
+ BigEndian::WriteUint32(aKeySequence, salt);
memcpy(salt + sizeof(uint32_t), kHkdfExtractSaltString, sizeof(kHkdfExtractSaltString));
hkdf.Extract(salt, sizeof(salt), cryptoKey);
diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp
index 8e76990f7..9bf6e9a18 100644
--- a/src/core/thread/link_metrics.cpp
+++ b/src/core/thread/link_metrics.cpp
@@ -37,11 +37,11 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
+#include "instance/instance.hpp"
#include "mac/mac.hpp"
#include "thread/link_metrics_tlvs.hpp"
#include "thread/neighbor_table.hpp"
diff --git a/src/core/thread/link_metrics_tlvs.hpp b/src/core/thread/link_metrics_tlvs.hpp
index 46464c9b3..ddd0ae2a4 100644
--- a/src/core/thread/link_metrics_tlvs.hpp
+++ b/src/core/thread/link_metrics_tlvs.hpp
@@ -50,8 +50,6 @@
namespace ot {
namespace LinkMetrics {
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* Defines constants related to Link Metrics Sub-TLVs.
*
@@ -141,7 +139,7 @@ public:
* @returns The metric value.
*
*/
- uint32_t GetMetricsValue32(void) const { return HostSwap32(mMetricsValue.m32); }
+ uint32_t GetMetricsValue32(void) const { return BigEndian::HostSwap32(mMetricsValue.m32); }
/**
* Sets the metric value (8 bits).
@@ -163,7 +161,7 @@ public:
*/
void SetMetricsValue32(uint32_t aMetricsValue)
{
- mMetricsValue.m32 = HostSwap32(aMetricsValue);
+ mMetricsValue.m32 = BigEndian::HostSwap32(aMetricsValue);
SetLength(sizeof(*this) - sizeof(Tlv));
}
diff --git a/src/core/thread/link_quality.cpp b/src/core/thread/link_quality.cpp
index ed5bbb5bf..bf6b35b42 100644
--- a/src/core/thread/link_quality.cpp
+++ b/src/core/thread/link_quality.cpp
@@ -36,9 +36,9 @@
#include <stdio.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp
index a31519b3a..a3d0ef048 100644
--- a/src/core/thread/lowpan.cpp
+++ b/src/core/thread/lowpan.cpp
@@ -36,16 +36,14 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "common/numeric_limits.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#include "net/udp6.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/thread_netif.hpp"
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::ReadUint16;
-
namespace ot {
namespace Lowpan {
@@ -422,7 +420,7 @@ exit:
if (error == kErrorNone)
{
- aFrameBuilder.Write<uint16_t>(hcCtlOffset, HostSwap16(hcCtl));
+ aFrameBuilder.Write<uint16_t>(hcCtlOffset, BigEndian::HostSwap16(hcCtl));
}
else
{
@@ -722,7 +720,7 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header &aIp6Header,
{
if ((hcCtl & kHcSrcAddrContext) == 0)
{
- aIp6Header.GetSource().mFields.m16[0] = HostSwap16(0xfe80);
+ aIp6Header.GetSource().mFields.m16[0] = BigEndian::HostSwap16(0xfe80);
}
else
{
@@ -761,7 +759,7 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header &aIp6Header,
{
if ((hcCtl & kHcDstAddrModeMask) != 0)
{
- aIp6Header.GetDestination().mFields.m16[0] = HostSwap16(0xfe80);
+ aIp6Header.GetDestination().mFields.m16[0] = BigEndian::HostSwap16(0xfe80);
}
}
else
@@ -858,7 +856,7 @@ Error Lowpan::DecompressExtensionHeader(Message &aMessage, FrameData &aFrameData
}
// length
- hdr[1] = BitVectorBytes(sizeof(hdr) + len) - 1;
+ hdr[1] = BytesForBitSize(sizeof(hdr) + len) - 1;
SuccessOrExit(aMessage.AppendBytes(hdr, sizeof(hdr)));
aMessage.MoveOffset(sizeof(hdr));
@@ -1021,12 +1019,12 @@ Error Lowpan::Decompress(Message &aMessage,
if (aDatagramLength)
{
- ip6PayloadLength = HostSwap16(aDatagramLength - currentOffset - sizeof(Ip6::Header));
+ ip6PayloadLength = BigEndian::HostSwap16(aDatagramLength - currentOffset - sizeof(Ip6::Header));
}
else
{
ip6PayloadLength =
- HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aFrameData.GetLength());
+ BigEndian::HostSwap16(aMessage.GetOffset() - currentOffset - sizeof(Ip6::Header) + aFrameData.GetLength());
}
aMessage.Write(currentOffset + Ip6::Header::kPayloadLengthFieldOffset, ip6PayloadLength);
@@ -1044,7 +1042,7 @@ Ip6::Ecn Lowpan::DecompressEcn(const Message &aMessage, uint16_t aOffset) const
uint8_t byte;
SuccessOrExit(aMessage.Read(aOffset, hcCtl));
- hcCtl = HostSwap16(hcCtl);
+ hcCtl = BigEndian::HostSwap16(hcCtl);
VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch);
aOffset += sizeof(uint16_t);
@@ -1127,8 +1125,8 @@ Error MeshHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16
aHeaderLength = kMinHeaderLength;
}
- mSource = ReadUint16(aFrame);
- mDestination = ReadUint16(aFrame + 2);
+ mSource = BigEndian::ReadUint16(aFrame);
+ mDestination = BigEndian::ReadUint16(aFrame + 2);
error = kErrorNone;
@@ -1231,8 +1229,8 @@ Error FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, ui
VerifyOrExit(IsFragmentHeader(aFrame, aFrameLength));
- mSize = ReadUint16(aFrame + kSizeIndex) & kSizeMask;
- mTag = ReadUint16(aFrame + kTagIndex);
+ mSize = BigEndian::ReadUint16(aFrame + kSizeIndex) & kSizeMask;
+ mTag = BigEndian::ReadUint16(aFrame + kTagIndex);
if ((*aFrame & kOffsetFlag) == kOffsetFlag)
{
diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp
index e0b7a59dc..c83ba4a54 100644
--- a/src/core/thread/lowpan.hpp
+++ b/src/core/thread/lowpan.hpp
@@ -68,8 +68,6 @@ namespace ot {
*/
namespace Lowpan {
-using ot::Encoding::BigEndian::HostSwap16;
-
/**
* Represents a LOWPAN_IPHC Context.
*
@@ -475,8 +473,8 @@ public:
*/
void Init(uint16_t aSize, uint16_t aTag)
{
- mDispatchSize = HostSwap16(kFirstDispatch | (aSize & kSizeMask));
- mTag = HostSwap16(aTag);
+ mDispatchSize = BigEndian::HostSwap16(kFirstDispatch | (aSize & kSizeMask));
+ mTag = BigEndian::HostSwap16(aTag);
}
private:
@@ -506,8 +504,8 @@ public:
*/
void Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset)
{
- mDispatchSize = HostSwap16(kNextDispatch | (aSize & kSizeMask));
- mTag = HostSwap16(aTag);
+ mDispatchSize = BigEndian::HostSwap16(kNextDispatch | (aSize & kSizeMask));
+ mTag = BigEndian::HostSwap16(aTag);
mOffset = static_cast<uint8_t>(aOffset >> 3);
}
diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp
index 413321c28..4355447f2 100644
--- a/src/core/thread/mesh_forwarder.cpp
+++ b/src/core/thread/mesh_forwarder.cpp
@@ -36,11 +36,11 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
#include "common/time_ticker.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#include "net/ip6_filter.hpp"
#include "net/netif.hpp"
@@ -1157,7 +1157,11 @@ void MeshForwarder::UpdateNeighborLinkFailures(Neighbor &aNeighbor,
if (aAllowNeighborRemove && (Mle::IsActiveRouter(aNeighbor.GetRloc16())) &&
(aNeighbor.GetLinkFailures() >= aFailLimit))
{
+#if OPENTHREAD_FTD
Get<Mle::MleRouter>().RemoveRouterLink(static_cast<Router &>(aNeighbor));
+#else
+ IgnoreError(Get<Mle::Mle>().BecomeDetached());
+#endif
}
}
}
@@ -1419,31 +1423,26 @@ void MeshForwarder::HandleFragment(FrameData &aFrameData,
{
Neighbor *neighbor = Get<NeighborTable>().FindNeighbor(aMacAddrs.mSource, Neighbor::kInStateAnyExceptInvalid);
- if (neighbor != nullptr)
+ if ((neighbor != nullptr) && (fragmentHeader.GetDatagramOffset() == 0))
{
uint16_t tag = fragmentHeader.GetDatagramTag();
if (neighbor->IsLastRxFragmentTagSet())
{
VerifyOrExit(!neighbor->IsLastRxFragmentTagAfter(tag), error = kErrorDuplicated);
-
- if (neighbor->GetLastRxFragmentTag() == tag)
- {
- VerifyOrExit(fragmentHeader.GetDatagramOffset() != 0, error = kErrorDuplicated);
-
- // Duplication suppression for a "next fragment" is handled
- // by the code below where the the datagram offset is
- // checked against the offset of the corresponding message
- // (same datagram tag and size) in Reassembly List. Note
- // that if there is no matching message in the Reassembly
- // List (e.g., in case the message is already fully
- // assembled) the received "next fragment" frame would be
- // dropped.
- }
}
neighbor->SetLastRxFragmentTag(tag);
}
+
+ // Duplication suppression for a "next fragment" is handled
+ // by the code below where the the datagram offset is
+ // checked against the offset of the corresponding message
+ // (same datagram tag and size) in Reassembly List. Note
+ // that if there is no matching message in the Reassembly
+ // List (e.g., in case the message is already fully
+ // assembled) the received "next fragment" frame would be
+ // dropped.
}
#endif // OPENTHREAD_CONFIG_MULTI_RADIO
@@ -1666,7 +1665,7 @@ Error MeshForwarder::HandleDatagram(Message &aMessage, const ThreadLinkInfo &aLi
aMessage.SetLoopbackToHostAllowed(true);
aMessage.SetOrigin(Message::kOriginThreadNetif);
- return Get<Ip6::Ip6>().HandleDatagram(aMessage, &aLinkInfo);
+ return Get<Ip6::Ip6>().HandleDatagram(OwnedPtr<Message>(&aMessage), &aLinkInfo);
}
Error MeshForwarder::GetFramePriority(const FrameData &aFrameData,
@@ -1707,24 +1706,23 @@ exit:
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
Error MeshForwarder::SendEmptyMessage(void)
{
- Error error = kErrorNone;
- Message *message = nullptr;
+ Error error = kErrorNone;
+ OwnedPtr<Message> messagePtr;
VerifyOrExit(mEnabled && !Get<Mac::Mac>().GetRxOnWhenIdle() &&
Get<Mle::MleRouter>().GetParent().IsStateValidOrRestoring(),
error = kErrorInvalidState);
- message = Get<MessagePool>().Allocate(Message::kTypeMacEmptyData);
- VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+ messagePtr.Reset(Get<MessagePool>().Allocate(Message::kTypeMacEmptyData));
+ VerifyOrExit(messagePtr != nullptr, error = kErrorNoBufs);
- SuccessOrExit(error = SendMessage(*message));
+ SendMessage(messagePtr.PassOwnership());
exit:
- FreeMessageOnError(message, error);
LogDebg("Send empty message, error:%s", ErrorToString(error));
return error;
}
-#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
+#endif
bool MeshForwarder::CalcIePresent(const Message *aMessage)
{
diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp
index dfdc749fd..c27029d32 100644
--- a/src/core/thread/mesh_forwarder.hpp
+++ b/src/core/thread/mesh_forwarder.hpp
@@ -42,6 +42,7 @@
#include "common/locator.hpp"
#include "common/log.hpp"
#include "common/non_copyable.hpp"
+#include "common/owned_ptr.hpp"
#include "common/tasklet.hpp"
#include "common/time_ticker.hpp"
#include "mac/channel_mask.hpp"
@@ -196,14 +197,10 @@ public:
/**
* Submits a message to the mesh forwarder for forwarding.
*
- * @param[in] aMessage A reference to the message.
- *
- * @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.
+ * @param[in] aMessagePtr An owned pointer to a message (transfer ownership).
*
*/
- Error SendMessage(Message &aMessage);
+ void SendMessage(OwnedPtr<Message> aMessagePtr);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
/**
diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp
index 16eea50bc..4001bbeb5 100644
--- a/src/core/thread/mesh_forwarder_ftd.cpp
+++ b/src/core/thread/mesh_forwarder_ftd.cpp
@@ -46,76 +46,66 @@ namespace ot {
RegisterLogModule("MeshForwarder");
-Error MeshForwarder::SendMessage(Message &aMessage)
+void MeshForwarder::SendMessage(OwnedPtr<Message> aMessagePtr)
{
- Mle::MleRouter &mle = Get<Mle::MleRouter>();
- Error error = kErrorNone;
+ Message &message = *aMessagePtr.Release();
- aMessage.SetOffset(0);
- aMessage.SetDatagramTag(0);
- aMessage.SetTimestampToNow();
- mSendQueue.Enqueue(aMessage);
+ message.SetOffset(0);
+ message.SetDatagramTag(0);
+ message.SetTimestampToNow();
+ mSendQueue.Enqueue(message);
- switch (aMessage.GetType())
+ switch (message.GetType())
{
case Message::kTypeIp6:
{
- Ip6::Header ip6Header;
+ Ip6::Header ip6Header;
+ const Ip6::Address &destination = ip6Header.GetDestination();
- IgnoreError(aMessage.Read(0, ip6Header));
+ IgnoreError(message.Read(0, ip6Header));
- if (ip6Header.GetDestination().IsMulticast())
+ if (destination.IsMulticast())
{
// For traffic destined to multicast address larger than realm local, generally it uses IP-in-IP
// encapsulation (RFC2473), with outer destination as ALL_MPL_FORWARDERS. So here if the destination
// is multicast address larger than realm local, it should be for indirection transmission for the
// device's sleepy child, thus there should be no direct transmission.
- if (!ip6Header.GetDestination().IsMulticastLargerThanRealmLocal())
+ if (!destination.IsMulticastLargerThanRealmLocal())
{
- // schedule direct transmission
- aMessage.SetDirectTransmission();
+ message.SetDirectTransmission();
}
- if (aMessage.GetSubType() != Message::kSubTypeMplRetransmission)
+ if (message.GetSubType() != Message::kSubTypeMplRetransmission)
{
- if (ip6Header.GetDestination() == mle.GetLinkLocalAllThreadNodesAddress() ||
- ip6Header.GetDestination() == mle.GetRealmLocalAllThreadNodesAddress())
- {
- // destined for all sleepy children
- for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
- {
- if (!child.IsRxOnWhenIdle())
- {
- mIndirectSender.AddMessageForSleepyChild(aMessage, child);
- }
- }
- }
- else
+ // Check if we need to forward the multicast message
+ // to any sleepy child. This is skipped for MPL retx
+ // (only the first MPL transmission is forwarded to
+ // sleepy children).
+
+ bool destinedForAll = ((destination == Get<Mle::Mle>().GetLinkLocalAllThreadNodesAddress()) ||
+ (destination == Get<Mle::Mle>().GetRealmLocalAllThreadNodesAddress()));
+
+ for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
- // destined for some sleepy children which subscribed the multicast address.
- for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
+ if (!child.IsRxOnWhenIdle() && (destinedForAll || child.HasIp6Address(destination)))
{
- if (!child.IsRxOnWhenIdle() && child.HasIp6Address(ip6Header.GetDestination()))
- {
- mIndirectSender.AddMessageForSleepyChild(aMessage, child);
- }
+ mIndirectSender.AddMessageForSleepyChild(message, child);
}
}
}
}
else // Destination is unicast
{
- Neighbor *neighbor = Get<NeighborTable>().FindNeighbor(ip6Header.GetDestination());
+ Neighbor *neighbor = Get<NeighborTable>().FindNeighbor(destination);
- if ((neighbor != nullptr) && !neighbor->IsRxOnWhenIdle() && !aMessage.IsDirectTransmission() &&
+ if ((neighbor != nullptr) && !neighbor->IsRxOnWhenIdle() && !message.IsDirectTransmission() &&
Get<ChildTable>().Contains(*neighbor))
{
- // Destined for a sleepy child
- mIndirectSender.AddMessageForSleepyChild(aMessage, *static_cast<Child *>(neighbor));
+ mIndirectSender.AddMessageForSleepyChild(message, *static_cast<Child *>(neighbor));
}
else
{
- aMessage.SetDirectTransmission();
+ message.SetDirectTransmission();
}
}
@@ -124,33 +114,33 @@ Error MeshForwarder::SendMessage(Message &aMessage)
case Message::kTypeSupervision:
{
- Child *child = Get<ChildSupervisor>().GetDestination(aMessage);
+ Child *child = Get<ChildSupervisor>().GetDestination(message);
OT_ASSERT((child != nullptr) && !child->IsRxOnWhenIdle());
- mIndirectSender.AddMessageForSleepyChild(aMessage, *child);
+ mIndirectSender.AddMessageForSleepyChild(message, *child);
break;
}
default:
- aMessage.SetDirectTransmission();
+ message.SetDirectTransmission();
break;
}
// Ensure that the message is marked for direct tx and/or for indirect tx
// to a sleepy child. Otherwise, remove the message.
- if (RemoveMessageIfNoPendingTx(aMessage))
+ if (RemoveMessageIfNoPendingTx(message))
{
ExitNow();
}
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
- ApplyDirectTxQueueLimit(aMessage);
+ ApplyDirectTxQueueLimit(message);
#endif
mScheduleTransmissionTask.Post();
exit:
- return error;
+ return;
}
void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
@@ -196,7 +186,7 @@ void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
message.SetLoopbackToHostAllowed(true);
message.SetOrigin(Message::kOriginHostTrusted);
- IgnoreError(Get<Ip6::Ip6>().HandleDatagram(message));
+ IgnoreError(Get<Ip6::Ip6>().HandleDatagram(OwnedPtr<Message>(&message)));
continue;
}
#endif
@@ -521,7 +511,7 @@ Error MeshForwarder::UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &a
else if (mle.IsRoutingLocator(aIp6Header.GetDestination()))
{
uint16_t rloc16 = aIp6Header.GetDestination().GetIid().GetLocator();
- VerifyOrExit(mle.IsRouterIdValid(Mle::RouterIdFromRloc16(rloc16)), error = kErrorDrop);
+ VerifyOrExit(Mle::IsRouterIdValid(Mle::RouterIdFromRloc16(rloc16)), error = kErrorDrop);
mMeshDest = rloc16;
}
else if (mle.IsAnycastLocator(aIp6Header.GetDestination()))
@@ -544,7 +534,7 @@ Error MeshForwarder::UpdateIp6RouteFtd(const Ip6::Header &aIp6Header, Message &a
}
else if (aloc16 <= Mle::kAloc16CommissionerEnd)
{
- SuccessOrExit(error = MeshCoP::GetBorderAgentRloc(Get<ThreadNetif>(), mMeshDest));
+ SuccessOrExit(error = Get<NetworkData::Leader>().FindBorderAgentRloc(mMeshDest));
}
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
@@ -665,8 +655,7 @@ void MeshForwarder::SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::
void MeshForwarder::HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSource, const ThreadLinkInfo &aLinkInfo)
{
- Error error = kErrorNone;
- Message *message = nullptr;
+ Error error = kErrorNone;
Mac::Addresses meshAddrs;
Lowpan::MeshHeader meshHeader;
@@ -698,6 +687,7 @@ void MeshForwarder::HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSo
}
else if (meshHeader.GetHopsLeft() > 0)
{
+ OwnedPtr<Message> messagePtr;
Message::Priority priority = Message::kPriorityNormal;
Get<Mle::MleRouter>().ResolveRoutingLoops(aMacSource.GetShort(), meshAddrs.mDestination.GetShort());
@@ -707,32 +697,32 @@ void MeshForwarder::HandleMesh(FrameData &aFrameData, const Mac::Address &aMacSo
meshHeader.DecrementHopsLeft();
GetForwardFramePriority(aFrameData, meshAddrs, priority);
- message =
- Get<MessagePool>().Allocate(Message::kType6lowpan, /* aReserveHeader */ 0, Message::Settings(priority));
- VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+ messagePtr.Reset(
+ Get<MessagePool>().Allocate(Message::kType6lowpan, /* aReserveHeader */ 0, Message::Settings(priority)));
+ VerifyOrExit(messagePtr != nullptr, error = kErrorNoBufs);
- SuccessOrExit(error = meshHeader.AppendTo(*message));
- SuccessOrExit(error = message->AppendData(aFrameData));
+ SuccessOrExit(error = meshHeader.AppendTo(*messagePtr));
+ SuccessOrExit(error = messagePtr->AppendData(aFrameData));
- message->SetLinkInfo(aLinkInfo);
+ messagePtr->SetLinkInfo(aLinkInfo);
#if OPENTHREAD_CONFIG_MULTI_RADIO
// We set the received radio type on the message in order for it
// to be logged correctly from LogMessage().
- message->SetRadioType(static_cast<Mac::RadioType>(aLinkInfo.mRadioType));
+ messagePtr->SetRadioType(static_cast<Mac::RadioType>(aLinkInfo.mRadioType));
#endif
- LogMessage(kMessageReceive, *message, kErrorNone, &aMacSource);
+ LogMessage(kMessageReceive, *messagePtr, kErrorNone, &aMacSource);
#if OPENTHREAD_CONFIG_MULTI_RADIO
// Since the message will be forwarded, we clear the radio
// type on the message to allow the radio type for tx to be
// selected later (based on the radios supported by the next
// hop).
- message->ClearRadioType();
+ messagePtr->ClearRadioType();
#endif
- IgnoreError(SendMessage(*message));
+ SendMessage(messagePtr.PassOwnership());
}
exit:
@@ -741,7 +731,6 @@ exit:
{
LogInfo("Dropping rx mesh frame, error:%s, len:%d, src:%s, sec:%s", ErrorToString(error),
aFrameData.GetLength(), aMacSource.ToString().AsCString(), ToYesNo(aLinkInfo.IsLinkSecurityEnabled()));
- FreeMessage(message);
}
}
diff --git a/src/core/thread/mesh_forwarder_mtd.cpp b/src/core/thread/mesh_forwarder_mtd.cpp
index 5e697056b..b88c773cd 100644
--- a/src/core/thread/mesh_forwarder_mtd.cpp
+++ b/src/core/thread/mesh_forwarder_mtd.cpp
@@ -37,21 +37,21 @@
namespace ot {
-Error MeshForwarder::SendMessage(Message &aMessage)
+void MeshForwarder::SendMessage(OwnedPtr<Message> aMessagePtr)
{
- aMessage.SetDirectTransmission();
- aMessage.SetOffset(0);
- aMessage.SetDatagramTag(0);
- aMessage.SetTimestampToNow();
+ Message &message = *aMessagePtr.Release();
- mSendQueue.Enqueue(aMessage);
+ message.SetDirectTransmission();
+ message.SetOffset(0);
+ message.SetDatagramTag(0);
+ message.SetTimestampToNow();
+
+ mSendQueue.Enqueue(message);
mScheduleTransmissionTask.Post();
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
- ApplyDirectTxQueueLimit(aMessage);
+ ApplyDirectTxQueueLimit(message);
#endif
-
- return kErrorNone;
}
Error MeshForwarder::EvictMessage(Message::Priority aPriority)
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index fb5bcda08..cad9cacd3 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -41,12 +41,13 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "common/numeric_limits.hpp"
#include "common/random.hpp"
#include "common/serial_number.hpp"
#include "common/settings.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "net/netif.hpp"
@@ -59,8 +60,6 @@
#include "thread/time_sync_service.hpp"
#include "thread/version.hpp"
-using ot::Encoding::BigEndian::HostSwap16;
-
namespace ot {
namespace Mle {
@@ -124,27 +123,23 @@ Mle::Mle(Instance &aInstance)
mLinkLocal64.InitAsThreadOrigin(/* aPreferred */ true);
mLinkLocal64.GetAddress().SetToLinkLocalAddress(Get<Mac::Mac>().GetExtAddress());
- mLeaderAloc.InitAsThreadOriginRealmLocalScope();
-
- mMeshLocal64.InitAsThreadOriginRealmLocalScope();
+ mMeshLocal64.InitAsThreadOriginMeshLocal();
mMeshLocal64.GetAddress().GetIid().GenerateRandom();
- mMeshLocal16.InitAsThreadOriginRealmLocalScope();
+ mMeshLocal16.InitAsThreadOriginMeshLocal();
mMeshLocal16.GetAddress().GetIid().SetToLocator(0);
mMeshLocal16.mRloc = true;
mLinkLocalAllThreadNodes.Clear();
- mLinkLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff32);
- mLinkLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001);
+ mLinkLocalAllThreadNodes.GetAddress().mFields.m16[0] = BigEndian::HostSwap16(0xff32);
+ mLinkLocalAllThreadNodes.GetAddress().mFields.m16[7] = BigEndian::HostSwap16(0x0001);
mRealmLocalAllThreadNodes.Clear();
- mRealmLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff33);
- mRealmLocalAllThreadNodes.GetAddress().mFields.m16[7] = HostSwap16(0x0001);
+ mRealmLocalAllThreadNodes.GetAddress().mFields.m16[0] = BigEndian::HostSwap16(0xff33);
+ mRealmLocalAllThreadNodes.GetAddress().mFields.m16[7] = BigEndian::HostSwap16(0x0001);
+ mMeshLocalPrefix.Clear();
SetMeshLocalPrefix(AsCoreType(&kMeshLocalPrefixInit));
-
- // `SetMeshLocalPrefix()` also adds the Mesh-Local EID and subscribes
- // to the Link- and Realm-Local All Thread Nodes multicast addresses.
}
Error Mle::Enable(void)
@@ -195,7 +190,11 @@ Error Mle::Start(StartMode aMode)
SetStateDetached();
- ApplyMeshLocalPrefix();
+ Get<ThreadNetif>().AddUnicastAddress(mMeshLocal64);
+
+ Get<ThreadNetif>().SubscribeMulticast(mLinkLocalAllThreadNodes);
+ Get<ThreadNetif>().SubscribeMulticast(mRealmLocalAllThreadNodes);
+
SetRloc16(GetRloc16());
mAttachCounter = 0;
@@ -654,7 +653,7 @@ uint32_t Mle::GetAttachStartDelay(void) const
uint16_t counter = mAttachCounter - 1;
const uint32_t ratio = kAttachBackoffMaxInterval / kAttachBackoffMinInterval;
- if ((counter < sizeof(ratio) * CHAR_BIT) && ((1UL << counter) <= ratio))
+ if ((counter < BitSizeOf(ratio)) && ((1UL << counter) <= ratio))
{
delay = kAttachBackoffMinInterval;
delay <<= counter;
@@ -693,10 +692,12 @@ void Mle::SetStateDetached(void)
Get<BackboneRouter::Leader>().Reset();
#endif
+#if OPENTHREAD_FTD
if (IsLeader())
{
- Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
+ Get<ThreadNetif>().RemoveUnicastAddress(Get<MleRouter>().mLeaderAloc);
}
+#endif
SetRole(kRoleDetached);
SetAttachState(kAttachStateIdle);
@@ -719,10 +720,12 @@ void Mle::SetStateDetached(void)
void Mle::SetStateChild(uint16_t aRloc16)
{
+#if OPENTHREAD_FTD
if (IsLeader())
{
- Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
+ Get<ThreadNetif>().RemoveUnicastAddress(Get<MleRouter>().mLeaderAloc);
}
+#endif
SetRloc16(aRloc16);
SetRole(kRoleChild);
@@ -888,28 +891,40 @@ void Mle::UpdateLinkLocalAddress(void)
void Mle::SetMeshLocalPrefix(const Ip6::NetworkPrefix &aMeshLocalPrefix)
{
- VerifyOrExit(GetMeshLocalPrefix() != aMeshLocalPrefix,
- Get<Notifier>().SignalIfFirst(kEventThreadMeshLocalAddrChanged));
+ VerifyOrExit(mMeshLocalPrefix != aMeshLocalPrefix);
- if (Get<ThreadNetif>().IsUp())
- {
- Get<ThreadNetif>().RemoveUnicastAddress(mLeaderAloc);
+ mMeshLocalPrefix = aMeshLocalPrefix;
- // We must remove the old addresses before adding the new ones.
- Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal64);
- Get<ThreadNetif>().RemoveUnicastAddress(mMeshLocal16);
- Get<ThreadNetif>().UnsubscribeMulticast(mLinkLocalAllThreadNodes);
- Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
- }
+ // We ask `ThreadNetif` to apply the new mesh-local prefix which
+ // will then update all of its assigned unicast addresses that are
+ // marked as mesh-local, as well as all of the subscribed mesh-local
+ // prefix-based multicast addresses (such as link-local or
+ // realm-local All Thread Nodes addresses). It is important to call
+ // `ApplyNewMeshLocalPrefix()` first so that `ThreadNetif` can
+ // correctly signal the updates. It will first signal the removal
+ // of the previous address based on the old prefix, and then the
+ // addition of the new address with the new mesh-local prefix.
- mMeshLocal64.GetAddress().SetPrefix(aMeshLocalPrefix);
- mMeshLocal16.GetAddress().SetPrefix(aMeshLocalPrefix);
- mLeaderAloc.GetAddress().SetPrefix(aMeshLocalPrefix);
+ Get<ThreadNetif>().ApplyNewMeshLocalPrefix();
- // Just keep mesh local prefix if network interface is down
- VerifyOrExit(Get<ThreadNetif>().IsUp());
+ // Some of the addresses may already be updated from the
+ // `ApplyNewMeshLocalPrefix()` call, but we apply the new prefix to
+ // them in case they are not yet added to the `Netif`. This ensures
+ // that addresses are always updated and other modules can retrieve
+ // them using methods such as `GetMeshLocal16()`, `GetMeshLocal64()`
+ // or `GetLinkLocalAllThreadNodesAddress()`, even if they have not
+ // yet been added to the `Netif`.
+
+ mMeshLocal64.GetAddress().SetPrefix(mMeshLocalPrefix);
+ mMeshLocal16.GetAddress().SetPrefix(mMeshLocalPrefix);
+ mLinkLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(mMeshLocalPrefix);
+ mRealmLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(mMeshLocalPrefix);
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+ Get<BackboneRouter::Local>().ApplyNewMeshLocalPrefix();
+#endif
- ApplyMeshLocalPrefix();
+ Get<Notifier>().Signal(kEventThreadMeshLocalAddrChanged);
exit:
return;
@@ -928,71 +943,6 @@ exit:
}
#endif
-void Mle::ApplyMeshLocalPrefix(void)
-{
- mLinkLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(GetMeshLocalPrefix());
- mRealmLocalAllThreadNodes.GetAddress().SetMulticastNetworkPrefix(GetMeshLocalPrefix());
-
- VerifyOrExit(!IsDisabled());
-
- // Add the addresses back into the table.
- Get<ThreadNetif>().AddUnicastAddress(mMeshLocal64);
- Get<ThreadNetif>().SubscribeMulticast(mLinkLocalAllThreadNodes);
- Get<ThreadNetif>().SubscribeMulticast(mRealmLocalAllThreadNodes);
-
- if (IsAttached())
- {
- Get<ThreadNetif>().AddUnicastAddress(mMeshLocal16);
- }
-
- // update Leader ALOC
- if (IsLeader())
- {
- Get<ThreadNetif>().AddUnicastAddress(mLeaderAloc);
- }
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
- Get<MeshCoP::Commissioner>().ApplyMeshLocalPrefix();
-#endif
-
-#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
- Get<MeshCoP::BorderAgent>().ApplyMeshLocalPrefix();
-#endif
-
-#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
- Get<Dhcp6::Server>().ApplyMeshLocalPrefix();
-#endif
-
-#if OPENTHREAD_CONFIG_NEIGHBOR_DISCOVERY_AGENT_ENABLE
- Get<NeighborDiscovery::Agent>().ApplyMeshLocalPrefix();
-#endif
-
-#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
- for (ServiceAloc &serviceAloc : mServiceAlocs)
- {
- if (serviceAloc.IsInUse())
- {
- Get<ThreadNetif>().RemoveUnicastAddress(serviceAloc);
- }
-
- serviceAloc.ApplyMeshLocalPrefix(GetMeshLocalPrefix());
-
- if (serviceAloc.IsInUse())
- {
- Get<ThreadNetif>().AddUnicastAddress(serviceAloc);
- }
- }
-#endif
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- Get<BackboneRouter::Local>().ApplyMeshLocalPrefix();
-#endif
-
-exit:
- // Changing the prefix also causes the mesh local address to be different.
- Get<Notifier>().Signal(kEventThreadMeshLocalAddrChanged);
-}
-
void Mle::SetRloc16(uint16_t aRloc16)
{
uint16_t oldRloc16 = GetRloc16();
@@ -1051,7 +1001,7 @@ Error Mle::GetLeaderAddress(Ip6::Address &aAddress) const
VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
- aAddress.SetToRoutingLocator(GetMeshLocalPrefix(), Rloc16FromRouterId(mLeaderData.GetLeaderRouterId()));
+ aAddress.SetToRoutingLocator(mMeshLocalPrefix, Rloc16FromRouterId(mLeaderData.GetLeaderRouterId()));
exit:
return error;
@@ -1075,7 +1025,7 @@ Error Mle::GetServiceAloc(uint8_t aServiceId, Ip6::Address &aAddress) const
Error error = kErrorNone;
VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kErrorDetached);
- aAddress.SetToAnycastLocator(GetMeshLocalPrefix(), ServiceAlocFromId(aServiceId));
+ aAddress.SetToAnycastLocator(mMeshLocalPrefix, ServiceAlocFromId(aServiceId));
exit:
return error;
@@ -1271,7 +1221,7 @@ exit:
Mle::ServiceAloc::ServiceAloc(void)
{
- InitAsThreadOriginRealmLocalScope();
+ InitAsThreadOriginMeshLocal();
GetAddress().GetIid().SetToLocator(kNotInUse);
}
@@ -2145,7 +2095,7 @@ Error Mle::SendChildUpdateRequest(ChildUpdateRequestMode aMode)
destination.SetToLinkLocalAddress(mParent.GetExtAddress());
SuccessOrExit(error = message->SendTo(destination));
- Log(kMessageSend, kTypeChildUpdateRequestOfParent, destination);
+ Log(kMessageSend, kTypeChildUpdateRequestAsChild, destination);
if (!IsRxOnWhenIdle())
{
@@ -2166,12 +2116,13 @@ exit:
return error;
}
-Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge)
+Error Mle::SendChildUpdateResponse(const TlvList &aTlvList,
+ const RxChallenge &aChallenge,
+ const Ip6::Address &aDestination)
{
- Error error = kErrorNone;
- Ip6::Address destination;
- TxMessage *message;
- bool checkAddress = false;
+ Error error = kErrorNone;
+ TxMessage *message;
+ bool checkAddress = false;
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateResponse)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendSourceAddressTlv());
@@ -2230,10 +2181,9 @@ Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &a
}
}
- destination.SetToLinkLocalAddress(mParent.GetExtAddress());
- SuccessOrExit(error = message->SendTo(destination));
+ SuccessOrExit(error = message->SendTo(aDestination));
- Log(kMessageSend, kTypeChildUpdateResponseOfParent, destination);
+ Log(kMessageSend, kTypeChildUpdateResponseAsChild, aDestination);
if (checkAddress && HasUnregisteredAddress())
{
@@ -2257,7 +2207,6 @@ void Mle::SendAnnounce(uint8_t aChannel, AnnounceMode aMode)
void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, AnnounceMode aMode)
{
Error error = kErrorNone;
- ChannelTlv channelTlv;
MeshCoP::Timestamp activeTimestamp;
TxMessage *message = nullptr;
@@ -2266,10 +2215,7 @@ void Mle::SendAnnounce(uint8_t aChannel, const Ip6::Address &aDestination, Annou
message->SetLinkSecurityEnabled(true);
message->SetChannel(aChannel);
- channelTlv.Init();
- channelTlv.SetChannelPage(0);
- channelTlv.SetChannel(Get<Mac::Mac>().GetPanChannel());
- SuccessOrExit(error = channelTlv.AppendTo(*message));
+ SuccessOrExit(error = Tlv::Append<ChannelTlv>(*message, ChannelTlvValue(Get<Mac::Mac>().GetPanChannel())));
switch (aMode)
{
@@ -3521,7 +3467,7 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
// Source Address
SuccessOrExit(error = Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress));
- Log(kMessageReceive, kTypeChildUpdateRequestOfParent, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
+ Log(kMessageReceive, kTypeChildUpdateRequestAsChild, aRxInfo.mMessageInfo.GetPeerAddr(), sourceAddress);
// Challenge
switch (aRxInfo.mMessage.ReadChallengeTlv(challenge))
@@ -3602,10 +3548,11 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo)
}
#endif
- SuccessOrExit(error = SendChildUpdateResponse(tlvList, challenge));
+ // Send the response to the requester, regardless if it's this device's parent or not
+ SuccessOrExit(error = SendChildUpdateResponse(tlvList, challenge, aRxInfo.mMessageInfo.GetPeerAddr()));
exit:
- LogProcessError(kTypeChildUpdateRequestOfParent, error);
+ LogProcessError(kTypeChildUpdateRequestAsChild, error);
}
void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo)
@@ -3619,7 +3566,7 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo)
uint16_t sourceAddress;
uint32_t timeout;
- Log(kMessageReceive, kTypeChildUpdateResponseOfParent, aRxInfo.mMessageInfo.GetPeerAddr());
+ Log(kMessageReceive, kTypeChildUpdateResponseAsChild, aRxInfo.mMessageInfo.GetPeerAddr());
switch (aRxInfo.mMessage.ReadResponseTlv(response))
{
@@ -3760,13 +3707,13 @@ exit:
}
}
- LogProcessError(kTypeChildUpdateResponseOfParent, error);
+ LogProcessError(kTypeChildUpdateResponseAsChild, error);
}
void Mle::HandleAnnounce(RxInfo &aRxInfo)
{
Error error = kErrorNone;
- ChannelTlv channelTlv;
+ ChannelTlvValue channelTlvValue;
MeshCoP::Timestamp timestamp;
const MeshCoP::Timestamp *localTimestamp;
uint8_t channel;
@@ -3777,10 +3724,8 @@ void Mle::HandleAnnounce(RxInfo &aRxInfo)
Log(kMessageReceive, kTypeAnnounce, aRxInfo.mMessageInfo.GetPeerAddr());
- SuccessOrExit(error = Tlv::FindTlv(aRxInfo.mMessage, channelTlv));
- VerifyOrExit(channelTlv.IsValid(), error = kErrorParse);
-
- channel = static_cast<uint8_t>(channelTlv.GetChannel());
+ SuccessOrExit(error = Tlv::Find<ChannelTlv>(aRxInfo.mMessage, channelTlvValue));
+ channel = static_cast<uint8_t>(channelTlvValue.GetChannel());
SuccessOrExit(error = Tlv::Find<ActiveTimestampTlv>(aRxInfo.mMessage, timestamp));
SuccessOrExit(error = Tlv::Find<PanIdTlv>(aRxInfo.mMessage, panId));
@@ -3966,10 +3911,7 @@ bool Mle::IsAnycastLocator(const Ip6::Address &aAddress) const
return IsMeshLocalAddress(aAddress) && aAddress.GetIid().IsAnycastLocator();
}
-bool Mle::IsMeshLocalAddress(const Ip6::Address &aAddress) const
-{
- return (aAddress.GetPrefix() == GetMeshLocalPrefix());
-}
+bool Mle::IsMeshLocalAddress(const Ip6::Address &aAddress) const { return (aAddress.GetPrefix() == mMeshLocalPrefix); }
Error Mle::CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header)
{
@@ -4189,8 +4131,8 @@ const char *Mle::MessageTypeToString(MessageType aType)
"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
+ "Child Update Request", // (5) kTypeChildUpdateRequestAsChild
+ "Child Update Response", // (6) kTypeChildUpdateResponseAsChild
"Data Request", // (7) kTypeDataRequest
"Data Response", // (8) kTypeDataResponse
"Discovery Request", // (9) kTypeDiscoveryRequest
@@ -4229,8 +4171,8 @@ const char *Mle::MessageTypeToString(MessageType aType)
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(kTypeChildUpdateRequestAsChild == 5, "kTypeChildUpdateRequestAsChild value is incorrect");
+ static_assert(kTypeChildUpdateResponseAsChild == 6, "kTypeChildUpdateResponseAsChild 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");
@@ -4282,14 +4224,16 @@ const char *Mle::MessageTypeActionToSuffixString(MessageType aType, MessageActio
{
const char *str = "";
+ OT_UNUSED_VARIABLE(aAction); // Not currently used in non-FTD builds
+
switch (aType)
{
case kTypeChildIdRequestShort:
str = " - short";
break;
- case kTypeChildUpdateRequestOfParent:
- case kTypeChildUpdateResponseOfParent:
- str = (aAction == kMessageReceive) ? " from parent" : " to parent";
+ case kTypeChildUpdateRequestAsChild:
+ case kTypeChildUpdateResponseAsChild:
+ str = " as child";
break;
case kTypeParentRequestToRouters:
str = " to routers";
@@ -4856,16 +4800,10 @@ exit:
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
Error Mle::TxMessage::AppendCslChannelTlv(void)
{
- CslChannelTlv cslChannel;
-
// CSL channel value of zero indicates that the CSL channel is not
// specified. We can use this value in the TLV as well.
- cslChannel.Init();
- cslChannel.SetChannelPage(0);
- cslChannel.SetChannel(Get<Mac::Mac>().GetCslChannel());
-
- return Append(cslChannel);
+ return Tlv::Append<CslChannelTlv>(*this, ChannelTlvValue(Get<Mac::Mac>().GetCslChannel()));
}
Error Mle::TxMessage::AppendCslTimeoutTlv(void)
@@ -5015,6 +4953,28 @@ Error Mle::TxMessage::AppendPendingDatasetTlv(void)
return Get<MeshCoP::PendingDatasetManager>().AppendMleDatasetTlv(*this);
}
+Error Mle::TxMessage::AppendSteeringDataTlv(void)
+{
+ Error error = kErrorNone;
+ MeshCoP::SteeringData steeringData;
+
+#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
+ if (!Get<MleRouter>().mSteeringData.IsEmpty())
+ {
+ steeringData = Get<MleRouter>().mSteeringData;
+ }
+ else
+#endif
+ {
+ SuccessOrExit(Get<NetworkData::Leader>().FindSteeringData(steeringData));
+ }
+
+ error = Tlv::Append<MeshCoP::SteeringDataTlv>(*this, steeringData.GetData(), steeringData.GetLength());
+
+exit:
+ return error;
+}
+
#endif // OPENTHREAD_FTD
//---------------------------------------------------------------------------------------------------------------------
diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp
index 1ca1645ec..8f3e9eaa0 100644
--- a/src/core/thread/mle.hpp
+++ b/src/core/thread/mle.hpp
@@ -96,7 +96,9 @@ namespace Mle {
*
*/
+#if OPENTHREAD_FTD
class MleRouter;
+#endif
/**
* Implements MLE functionality required by the Thread EndDevices, Router, and Leader roles.
@@ -104,7 +106,9 @@ class MleRouter;
*/
class Mle : public InstanceLocator, private NonCopyable
{
+#if OPENTHREAD_FTD
friend class MleRouter;
+#endif
friend class DiscoverScanner;
friend class ot::Instance;
friend class ot::Notifier;
@@ -352,7 +356,7 @@ public:
* @returns A reference to the Mesh Local Prefix.
*
*/
- const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocal16.GetAddress().GetPrefix(); }
+ const Ip6::NetworkPrefix &GetMeshLocalPrefix(void) const { return mMeshLocalPrefix; }
/**
* Sets the Mesh Local Prefix.
@@ -378,12 +382,6 @@ public:
#endif
/**
- * Applies the Mesh Local Prefix.
- *
- */
- void ApplyMeshLocalPrefix(void);
-
- /**
* Returns a reference to the Thread link-local address.
*
* The Thread link local address is derived using IEEE802.15.4 Extended Address as Interface Identifier.
@@ -690,6 +688,31 @@ public:
*/
bool HasRestored(void) const { return mHasRestored; }
+ /**
+ * Indicates whether or not a given netif multicast address instance is a prefix-based address added by MLE and
+ * uses the mesh local prefix.
+ *
+ * @param[in] aAddress A `Netif::MulticastAddress` address instance.
+ *
+ * @retval TRUE If @p aAddress is a prefix-based address which uses the mesh local prefix.
+ * @retval FALSE If @p aAddress is not a prefix-based address which uses the mesh local prefix.
+ *
+ */
+ bool IsMulticastAddressMeshLocalPrefixBased(const Ip6::Netif::MulticastAddress &aAddress) const
+ {
+ return (&aAddress == &mLinkLocalAllThreadNodes) || (&aAddress == &mRealmLocalAllThreadNodes);
+ }
+
+ /**
+ * Determines the next hop towards an RLOC16 destination.
+ *
+ * @param[in] aDestination The RLOC16 of the destination.
+ *
+ * @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
+ *
+ */
+ uint16_t GetNextHop(uint16_t aDestination) const;
+
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
/**
* Gets the CSL timeout.
@@ -918,8 +941,8 @@ private:
kTypeChildIdRequest,
kTypeChildIdRequestShort,
kTypeChildIdResponse,
- kTypeChildUpdateRequestOfParent,
- kTypeChildUpdateResponseOfParent,
+ kTypeChildUpdateRequestAsChild,
+ kTypeChildUpdateResponseAsChild,
kTypeDataRequest,
kTypeDataResponse,
kTypeDiscoveryRequest,
@@ -1008,6 +1031,7 @@ private:
Error AppendActiveDatasetTlv(void);
Error AppendPendingDatasetTlv(void);
Error AppendConnectivityTlv(void);
+ Error AppendSteeringDataTlv(void);
Error AppendAddressRegistrationTlv(Child &aChild);
#endif
template <uint8_t kArrayLength> Error AppendTlvRequestTlv(const uint8_t (&aTlvArray)[kArrayLength])
@@ -1096,13 +1120,13 @@ private:
void InitSecurityControl(void) { mSecurityControl = kKeyIdMode2Mic32; }
bool IsSecurityControlValid(void) const { return (mSecurityControl == kKeyIdMode2Mic32); }
- uint32_t GetFrameCounter(void) const { return Encoding::LittleEndian::HostSwap32(mFrameCounter); }
- void SetFrameCounter(uint32_t aCounter) { mFrameCounter = Encoding::LittleEndian::HostSwap32(aCounter); }
+ uint32_t GetFrameCounter(void) const { return LittleEndian::HostSwap32(mFrameCounter); }
+ void SetFrameCounter(uint32_t aCounter) { mFrameCounter = LittleEndian::HostSwap32(aCounter); }
- uint32_t GetKeyId(void) const { return Encoding::BigEndian::HostSwap32(mKeySource); }
+ uint32_t GetKeyId(void) const { return BigEndian::HostSwap32(mKeySource); }
void SetKeyId(uint32_t aKeySequence)
{
- mKeySource = Encoding::BigEndian::HostSwap32(aKeySequence);
+ mKeySource = BigEndian::HostSwap32(aKeySequence);
mKeyIndex = (aKeySequence & 0x7f) + 1;
}
@@ -1151,7 +1175,6 @@ private:
void MarkAsNotInUse(void) { SetAloc16(kNotInUse); }
uint16_t GetAloc16(void) const { return GetAddress().GetIid().GetLocator(); }
void SetAloc16(uint16_t aAloc16) { GetAddress().GetIid().SetLocator(aAloc16); }
- void ApplyMeshLocalPrefix(const Ip6::NetworkPrefix &aPrefix) { GetAddress().SetPrefix(aPrefix); }
};
#endif
@@ -1210,7 +1233,6 @@ private:
void InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo);
void ClearParentCandidate(void) { mParentCandidate.Clear(); }
Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
- uint16_t GetNextHop(uint16_t aDestination) const;
Error SendDataRequest(const Ip6::Address &aDestination);
void HandleNotifierEvents(Events aEvents);
void SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata);
@@ -1221,7 +1243,9 @@ private:
Error SendChildUpdateRequest(ChildUpdateRequestMode aMode);
Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
Error SendChildUpdateRequest(void);
- Error SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge);
+ Error SendChildUpdateResponse(const TlvList &aTlvList,
+ const RxChallenge &aChallenge,
+ const Ip6::Address &aDestination);
void SetRloc16(uint16_t aRloc16);
void SetStateDetached(void);
void SetStateChild(uint16_t aRloc16);
@@ -1401,12 +1425,12 @@ private:
DelayTimer mDelayedResponseTimer;
MsgTxTimer mMessageTransmissionTimer;
DetachGracefullyTimer mDetachGracefullyTimer;
+ Ip6::NetworkPrefix mMeshLocalPrefix;
Ip6::Netif::UnicastAddress mLinkLocal64;
Ip6::Netif::UnicastAddress mMeshLocal64;
Ip6::Netif::UnicastAddress mMeshLocal16;
Ip6::Netif::MulticastAddress mLinkLocalAllThreadNodes;
Ip6::Netif::MulticastAddress mRealmLocalAllThreadNodes;
- Ip6::Netif::UnicastAddress mLeaderAloc;
};
} // namespace Mle
diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp
index 414bb7556..b97a7ec33 100644
--- a/src/core/thread/mle_router.cpp
+++ b/src/core/thread/mle_router.cpp
@@ -38,12 +38,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
#include "common/random.hpp"
#include "common/serial_number.hpp"
#include "common/settings.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop.hpp"
#include "net/icmp6.hpp"
@@ -96,6 +96,8 @@ MleRouter::MleRouter(Instance &aInstance)
mLeaderWeight = kDefaultLeaderWeight;
#endif
+ mLeaderAloc.InitAsThreadOriginMeshLocal();
+
SetRouterId(kInvalidRouterId);
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
@@ -2312,8 +2314,8 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
if (child->IsCslSynchronized())
{
- CslChannelTlv cslChannel;
- uint32_t cslTimeout;
+ ChannelTlvValue cslChannelTlvValue;
+ uint32_t cslTimeout;
switch (Tlv::Find<CslTimeoutTlv>(aRxInfo.mMessage, cslTimeout))
{
@@ -2328,13 +2330,11 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo)
ExitNow(error = kErrorNone);
}
- if (Tlv::FindTlv(aRxInfo.mMessage, cslChannel) == kErrorNone)
+ if (Tlv::Find<CslChannelTlv>(aRxInfo.mMessage, cslChannelTlvValue) == kErrorNone)
{
- VerifyOrExit(cslChannel.IsValid(), error = kErrorParse);
-
// Special value of zero is used to indicate that
// CSL channel is not specified.
- child->SetCslChannel(static_cast<uint8_t>(cslChannel.GetChannel()));
+ child->SetCslChannel(static_cast<uint8_t>(cslChannelTlvValue.GetChannel()));
}
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
@@ -2738,7 +2738,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
else // if steering data is not set out of band, fall back to network data
#endif
{
- VerifyOrExit(Get<NetworkData::Leader>().IsJoiningEnabled(), error = kErrorSecurity);
+ VerifyOrExit(Get<NetworkData::Leader>().IsJoiningAllowed(), error = kErrorSecurity);
}
}
}
@@ -2808,26 +2808,7 @@ Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const M
networkNameTlv.SetNetworkName(Get<MeshCoP::NetworkNameManager>().GetNetworkName().GetAsData());
SuccessOrExit(error = networkNameTlv.AppendTo(*message));
-#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
- // If steering data is set out of band, use that value.
- // Otherwise use the one from commissioning data.
- if (!mSteeringData.IsEmpty())
- {
- SuccessOrExit(error = Tlv::Append<MeshCoP::SteeringDataTlv>(*message, mSteeringData.GetData(),
- mSteeringData.GetLength()));
- }
- else
-#endif
- {
- const MeshCoP::Tlv *steeringData;
-
- steeringData = Get<NetworkData::Leader>().GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
-
- if (steeringData != nullptr)
- {
- SuccessOrExit(error = steeringData->AppendTo(*message));
- }
- }
+ SuccessOrExit(error = message->AppendSteeringDataTlv());
SuccessOrExit(
error = Tlv::Append<MeshCoP::JoinerUdpPortTlv>(*message, Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort()));
diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp
index 1a1025c33..65bfe114a 100644
--- a/src/core/thread/mle_router.hpp
+++ b/src/core/thread/mle_router.hpp
@@ -422,17 +422,6 @@ public:
void ResolveRoutingLoops(uint16_t aSourceMac, uint16_t aDestRloc16);
/**
- * Checks if a given Router ID has correct value.
- *
- * @param[in] aRouterId The Router ID value.
- *
- * @retval TRUE If @p aRouterId is in correct range [0..62].
- * @retval FALSE If @p aRouterId is not a valid Router ID.
- *
- */
- static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
-
- /**
* Fills an ConnectivityTlv.
*
* @param[out] aTlv A reference to the tlv to be filled.
@@ -769,6 +758,8 @@ private:
MeshCoP::SteeringData mSteeringData;
#endif
+ Ip6::Netif::UnicastAddress mLeaderAloc;
+
Callback<otThreadDiscoveryRequestCallback> mDiscoveryRequestCallback;
};
@@ -779,35 +770,9 @@ DeclareTmfHandler(MleRouter, kUriAddressRelease);
#if OPENTHREAD_MTD
-class MleRouter : public Mle
-{
- friend class Mle;
- friend class ot::Instance;
-
-public:
- explicit MleRouter(Instance &aInstance)
- : Mle(aInstance)
- {
- }
-
- bool IsSingleton(void) const { return false; }
-
- uint16_t GetNextHop(uint16_t aDestination) const { return Mle::GetNextHop(aDestination); }
+typedef Mle MleRouter;
- Error RemoveNeighbor(Neighbor &) { return BecomeDetached(); }
- void RemoveRouterLink(Router &) { IgnoreError(BecomeDetached()); }
-
- static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
-
- Error SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
-
- Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header)
- {
- return Mle::CheckReachability(aMeshDest, aIp6Header);
- }
-};
-
-#endif // OPENTHREAD_MTD
+#endif
} // namespace Mle
diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp
index 467622717..d4be8ff45 100644
--- a/src/core/thread/mle_tlvs.hpp
+++ b/src/core/thread/mle_tlvs.hpp
@@ -49,9 +49,6 @@ namespace ot {
namespace Mle {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-mle-tlvs
*
@@ -670,7 +667,7 @@ public:
*/
void Get(LeaderData &aLeaderData) const
{
- aLeaderData.SetPartitionId(HostSwap32(mPartitionId));
+ aLeaderData.SetPartitionId(BigEndian::HostSwap32(mPartitionId));
aLeaderData.SetWeighting(mWeighting);
aLeaderData.SetDataVersion(mDataVersion);
aLeaderData.SetStableDataVersion(mStableDataVersion);
@@ -685,7 +682,7 @@ public:
*/
void Set(const LeaderData &aLeaderData)
{
- mPartitionId = HostSwap32(aLeaderData.GetPartitionId());
+ mPartitionId = BigEndian::HostSwap32(aLeaderData.GetPartitionId());
mWeighting = aLeaderData.GetWeighting();
mDataVersion = aLeaderData.GetDataVersion(NetworkData::kFullSet);
mStableDataVersion = aLeaderData.GetDataVersion(NetworkData::kStableSubset);
@@ -906,7 +903,7 @@ public:
if (IsSedBufferingIncluded())
{
- buffersize = HostSwap16(mSedBufferSize);
+ buffersize = BigEndian::HostSwap16(mSedBufferSize);
}
return buffersize;
}
@@ -917,7 +914,7 @@ public:
* @param[in] aSedBufferSize The SED Buffer Size value.
*
*/
- void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = HostSwap16(aSedBufferSize); }
+ void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = BigEndian::HostSwap16(aSedBufferSize); }
/**
* Returns the SED Datagram Count value.
@@ -1028,31 +1025,44 @@ private:
};
/**
- * Implements Channel TLV generation and parsing.
+ * Implements Channel TLV value format.
+ *
+ * This is used by both Channel TLV and CSL Channel TLV.
*
*/
OT_TOOL_PACKED_BEGIN
-class ChannelTlv : public Tlv, public TlvInfo<Tlv::kChannel>
+class ChannelTlvValue
{
public:
/**
- * Initializes the TLV.
+ * Default constructor.
*
*/
- void Init(void)
+ ChannelTlvValue(void) = default;
+
+ /**
+ * Initializes the `ChannelTlvValue` with a given channel page and channel values.
+ *
+ * @param[in] aChannelPage The channel page.
+ * @param[in] aChannel The channel.
+ *
+ */
+ ChannelTlvValue(uint8_t aChannelPage, uint16_t aChannel)
+ : mChannelPage(aChannelPage)
+ , mChannel(BigEndian::HostSwap16(aChannel))
{
- SetType(kChannel);
- SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
- * Indicates whether or not the TLV appears to be well-formed.
+ * Initializes the `ChannelTlvValue` with zero channel page and a given channel value.
*
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
+ * @param[in] aChannel The channel.
*
*/
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
+ ChannelTlvValue(uint16_t aChannel)
+ : ChannelTlvValue(0, aChannel)
+ {
+ }
/**
* Returns the Channel Page value.
@@ -1076,7 +1086,7 @@ public:
* @returns The Channel value.
*
*/
- uint16_t GetChannel(void) const { return HostSwap16(mChannel); }
+ uint16_t GetChannel(void) const { return BigEndian::HostSwap16(mChannel); }
/**
* Sets the Channel value.
@@ -1084,13 +1094,25 @@ public:
* @param[in] aChannel The Channel value.
*
*/
- void SetChannel(uint16_t aChannel) { mChannel = HostSwap16(aChannel); }
+ void SetChannel(uint16_t aChannel) { mChannel = BigEndian::HostSwap16(aChannel); }
private:
uint8_t mChannelPage;
uint16_t mChannel;
} OT_TOOL_PACKED_END;
+/**
+ * Defines Channel TLV constants and types.
+ *
+ */
+typedef SimpleTlvInfo<Tlv::kChannel, ChannelTlvValue> ChannelTlv;
+
+/**
+ * Defines CSL Channel TLV constants and types.
+ *
+ */
+typedef SimpleTlvInfo<Tlv::kCslChannel, ChannelTlvValue> CslChannelTlv;
+
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
* Defines Time Request TLV constants and types.
@@ -1131,7 +1153,7 @@ public:
* @returns The time sync period.
*
*/
- uint16_t GetTimeSyncPeriod(void) const { return HostSwap16(mTimeSyncPeriod); }
+ uint16_t GetTimeSyncPeriod(void) const { return BigEndian::HostSwap16(mTimeSyncPeriod); }
/**
* Sets the time sync period.
@@ -1139,7 +1161,7 @@ public:
* @param[in] aTimeSyncPeriod The time sync period.
*
*/
- void SetTimeSyncPeriod(uint16_t aTimeSyncPeriod) { mTimeSyncPeriod = HostSwap16(aTimeSyncPeriod); }
+ void SetTimeSyncPeriod(uint16_t aTimeSyncPeriod) { mTimeSyncPeriod = BigEndian::HostSwap16(aTimeSyncPeriod); }
/**
* Returns the XTAL accuracy threshold.
@@ -1147,7 +1169,7 @@ public:
* @returns The XTAL accuracy threshold.
*
*/
- uint16_t GetXtalThreshold(void) const { return HostSwap16(mXtalThreshold); }
+ uint16_t GetXtalThreshold(void) const { return BigEndian::HostSwap16(mXtalThreshold); }
/**
* Sets the XTAL accuracy threshold.
@@ -1155,7 +1177,7 @@ public:
* @param[in] aXTALThreshold The XTAL accuracy threshold.
*
*/
- void SetXtalThreshold(uint16_t aXtalThreshold) { mXtalThreshold = HostSwap16(aXtalThreshold); }
+ void SetXtalThreshold(uint16_t aXtalThreshold) { mXtalThreshold = BigEndian::HostSwap16(aXtalThreshold); }
private:
uint16_t mTimeSyncPeriod;
@@ -1164,73 +1186,6 @@ private:
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
-#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
-/**
- * Implements CSL Channel TLV generation and parsing.
- *
- */
-OT_TOOL_PACKED_BEGIN
-class CslChannelTlv : public Tlv, public TlvInfo<Tlv::kCslChannel>
-{
-public:
- /**
- * Initializes the TLV.
- *
- */
- void Init(void)
- {
- SetType(kCslChannel);
- SetLength(sizeof(*this) - sizeof(Tlv));
- }
-
- /**
- * Indicates whether or not the TLV appears to be well-formed.
- *
- * @retval TRUE If the TLV appears to be well-formed.
- * @retval FALSE If the TLV does not appear to be well-formed.
- *
- */
- bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
-
- /**
- * Returns the Channel Page value.
- *
- * @returns The Channel Page value.
- *
- */
- uint8_t GetChannelPage(void) const { return mChannelPage; }
-
- /**
- * Sets the Channel Page value.
- *
- * @param[in] aChannelPage The Channel Page value.
- *
- */
- void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
-
- /**
- * Returns the Channel value.
- *
- * @returns The Channel value.
- *
- */
- uint16_t GetChannel(void) const { return HostSwap16(mChannel); }
-
- /**
- * Sets the Channel value.
- *
- * @param[in] aChannel The Channel value.
- *
- */
- void SetChannel(uint16_t aChannel) { mChannel = HostSwap16(aChannel); }
-
-private:
- uint8_t mChannelPage;
- uint16_t mChannel;
-} OT_TOOL_PACKED_END;
-
-#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE)
-
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
/**
* Implements CSL Clock Accuracy TLV generation and parsing.
diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp
index ae4dfdfa3..ffc6a4287 100644
--- a/src/core/thread/mle_types.hpp
+++ b/src/core/thread/mle_types.hpp
@@ -36,7 +36,6 @@
#include "openthread-core-config.h"
-#include <limits.h>
#include <stdint.h>
#include <string.h>
@@ -51,6 +50,7 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
+#include "common/numeric_limits.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/extended_panid.hpp"
@@ -481,7 +481,7 @@ public:
private:
static uint8_t MaskFor(uint8_t aRouterId) { return (0x80 >> (aRouterId % 8)); }
- uint8_t mRouterIdSet[BitVectorBytes(Mle::kMaxRouterId + 1)];
+ uint8_t mRouterIdSet[BytesForBitSize(Mle::kMaxRouterId + 1)];
} OT_TOOL_PACKED_END;
class TxChallenge;
@@ -617,6 +617,17 @@ inline uint16_t ChildIdFromRloc16(uint16_t aRloc16) { return aRloc16 & kMaxChild
inline uint8_t RouterIdFromRloc16(uint16_t aRloc16) { return aRloc16 >> kRouterIdOffset; }
/**
+ * Indicates whether or not a given Router ID is valid.
+ *
+ * @param[in] aRouterId The Router ID value to check.
+ *
+ * @retval TRUE If @p aRouterId is in correct range [0..62].
+ * @retval FALSE If @p aRouterId is not a valid Router ID.
+ *
+ */
+inline bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
+
+/**
* Returns whether the two RLOC16 have the same Router ID.
*
* @param[in] aRloc16A The first RLOC16 value.
diff --git a/src/core/thread/mlr_manager.cpp b/src/core/thread/mlr_manager.cpp
index 3d988a73e..dd25d7bea 100644
--- a/src/core/thread/mlr_manager.cpp
+++ b/src/core/thread/mlr_manager.cpp
@@ -37,9 +37,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "net/ip6_address.hpp"
#include "thread/thread_netif.hpp"
#include "thread/uri_paths.hpp"
@@ -54,8 +54,8 @@ MlrManager::MlrManager(Instance &aInstance)
, mReregistrationDelay(0)
, mSendDelay(0)
, mMlrPending(false)
-#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
- , mRegisterMulticastListenersPending(false)
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+ , mRegisterPending(false)
#endif
{
}
@@ -186,7 +186,7 @@ void MlrManager::ScheduleSend(uint16_t aDelay)
if (aDelay == 0)
{
mSendDelay = 0;
- SendMulticastListenerRegistration();
+ SendMlr();
}
else if (mSendDelay == 0 || mSendDelay > aDelay)
{
@@ -210,12 +210,11 @@ void MlrManager::UpdateTimeTickerRegistration(void)
}
}
-void MlrManager::SendMulticastListenerRegistration(void)
+void MlrManager::SendMlr(void)
{
Error error;
Mle::MleRouter &mle = Get<Mle::MleRouter>();
- Ip6::Address addresses[Ip6AddressesTlv::kMaxAddresses];
- uint8_t addressesNum = 0;
+ AddressArray addresses;
VerifyOrExit(!mMlrPending, error = kErrorBusy);
VerifyOrExit(mle.IsAttached(), error = kErrorInvalidState);
@@ -227,14 +226,14 @@ void MlrManager::SendMulticastListenerRegistration(void)
for (Ip6::Netif::ExternalMulticastAddress &addr :
Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
{
- if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
+ if (addresses.IsFull())
{
break;
}
if (addr.GetMlrState() == kMlrStateToRegister)
{
- AppendToUniqueAddressList(addresses, addressesNum, addr.GetAddress());
+ addresses.AddUnique(addr.GetAddress());
addr.SetMlrState(kMlrStateRegistering);
}
}
@@ -244,7 +243,7 @@ void MlrManager::SendMulticastListenerRegistration(void)
// Append Child multicast addresses
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValid))
{
- if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
+ if (addresses.IsFull())
{
break;
}
@@ -256,24 +255,23 @@ void MlrManager::SendMulticastListenerRegistration(void)
for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
{
- if (addressesNum >= Ip6AddressesTlv::kMaxAddresses)
+ if (addresses.IsFull())
{
break;
}
if (child.GetAddressMlrState(address) == kMlrStateToRegister)
{
- AppendToUniqueAddressList(addresses, addressesNum, address);
+ addresses.AddUnique(address);
child.SetAddressMlrState(address, kMlrStateRegistering);
}
}
}
#endif
- VerifyOrExit(addressesNum > 0, error = kErrorNotFound);
+ VerifyOrExit(!addresses.IsEmpty(), error = kErrorNotFound);
SuccessOrExit(
- error = SendMulticastListenerRegistrationMessage(
- addresses, addressesNum, nullptr, &MlrManager::HandleMulticastListenerRegistrationResponse, this));
+ error = SendMlrMessage(addresses.GetArrayBuffer(), addresses.GetLength(), nullptr, HandleMlrResponse, this));
mMlrPending = true;
@@ -300,12 +298,12 @@ exit:
CheckInvariants();
}
-#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-Error MlrManager::RegisterMulticastListeners(const otIp6Address *aAddresses,
- uint8_t aAddressNum,
- const uint32_t *aTimeout,
- otIp6RegisterMulticastListenersCallback aCallback,
- void *aContext)
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+Error MlrManager::RegisterMulticastListeners(const Ip6::Address *aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t *aTimeout,
+ MlrCallback aCallback,
+ void *aContext)
{
Error error;
@@ -322,55 +320,50 @@ Error MlrManager::RegisterMulticastListeners(const otIp6Address
#endif
// Only allow one outstanding registration if callback is specified.
- VerifyOrExit(!mRegisterMulticastListenersPending, error = kErrorBusy);
+ VerifyOrExit(!mRegisterPending, error = kErrorBusy);
- SuccessOrExit(error = SendMulticastListenerRegistrationMessage(
- aAddresses, aAddressNum, aTimeout, &MlrManager::HandleRegisterMulticastListenersResponse, this));
+ SuccessOrExit(error = SendMlrMessage(aAddresses, aAddressNum, aTimeout, HandleRegisterResponse, this));
- mRegisterMulticastListenersPending = true;
- mRegisterMulticastListenersCallback.Set(aCallback, aContext);
+ mRegisterPending = true;
+ mRegisterCallback.Set(aCallback, aContext);
exit:
return error;
}
-void MlrManager::HandleRegisterMulticastListenersResponse(void *aContext,
- otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- Error aResult)
+void MlrManager::HandleRegisterResponse(void *aContext,
+ otMessage *aMessage,
+ const otMessageInfo *aMessageInfo,
+ Error aResult)
{
- static_cast<MlrManager *>(aContext)->HandleRegisterMulticastListenersResponse(AsCoapMessagePtr(aMessage),
- AsCoreTypePtr(aMessageInfo), aResult);
+ static_cast<MlrManager *>(aContext)->HandleRegisterResponse(AsCoapMessagePtr(aMessage), AsCoreTypePtr(aMessageInfo),
+ aResult);
}
-void MlrManager::HandleRegisterMulticastListenersResponse(otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- Error aResult)
+void MlrManager::HandleRegisterResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
- uint8_t status;
- Error error;
- Ip6::Address failedAddresses[Ip6AddressesTlv::kMaxAddresses];
- uint8_t failedAddressNum = 0;
- Callback<otIp6RegisterMulticastListenersCallback> callbackCopy = mRegisterMulticastListenersCallback;
+ uint8_t status;
+ Error error;
+ AddressArray failedAddresses;
+ Callback<MlrCallback> callbackCopy = mRegisterCallback;
- mRegisterMulticastListenersPending = false;
- mRegisterMulticastListenersCallback.Clear();
+ mRegisterPending = false;
+ mRegisterCallback.Clear();
- error = ParseMulticastListenerRegistrationResponse(aResult, AsCoapMessagePtr(aMessage), status, failedAddresses,
- failedAddressNum);
+ error = ParseMlrResponse(aResult, AsCoapMessagePtr(aMessage), status, failedAddresses);
- callbackCopy.InvokeIfSet(error, status, failedAddresses, failedAddressNum);
+ callbackCopy.InvokeIfSet(error, status, failedAddresses.GetArrayBuffer(), failedAddresses.GetLength());
}
-#endif // (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-Error MlrManager::SendMulticastListenerRegistrationMessage(const otIp6Address *aAddresses,
- uint8_t aAddressNum,
- const uint32_t *aTimeout,
- Coap::ResponseHandler aResponseHandler,
- void *aResponseContext)
+Error MlrManager::SendMlrMessage(const Ip6::Address *aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t *aTimeout,
+ Coap::ResponseHandler aResponseHandler,
+ void *aResponseContext)
{
OT_UNUSED_VARIABLE(aTimeout);
@@ -390,7 +383,7 @@ Error MlrManager::SendMulticastListenerRegistrationMessage(const otIp6Address
SuccessOrExit(error = message->Append(addressesTlv));
SuccessOrExit(error = message->AppendBytes(aAddresses, sizeof(Ip6::Address) * aAddressNum));
-#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
if (Get<MeshCoP::Commissioner>().IsActive())
{
SuccessOrExit(
@@ -425,37 +418,33 @@ Error MlrManager::SendMulticastListenerRegistrationMessage(const otIp6Address
LogInfo("Sent MLR.req: addressNum=%d", aAddressNum);
exit:
- LogInfo("SendMulticastListenerRegistrationMessage(): %s", ErrorToString(error));
+ LogInfo("SendMlrMessage(): %s", ErrorToString(error));
FreeMessageOnError(message, error);
return error;
}
-void MlrManager::HandleMulticastListenerRegistrationResponse(void *aContext,
- otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- Error aResult)
+void MlrManager::HandleMlrResponse(void *aContext,
+ otMessage *aMessage,
+ const otMessageInfo *aMessageInfo,
+ Error aResult)
{
- static_cast<MlrManager *>(aContext)->HandleMulticastListenerRegistrationResponse(
- AsCoapMessagePtr(aMessage), AsCoreTypePtr(aMessageInfo), aResult);
+ static_cast<MlrManager *>(aContext)->HandleMlrResponse(AsCoapMessagePtr(aMessage), AsCoreTypePtr(aMessageInfo),
+ aResult);
}
-void MlrManager::HandleMulticastListenerRegistrationResponse(Coap::Message *aMessage,
- const Ip6::MessageInfo *aMessageInfo,
- Error aResult)
+void MlrManager::HandleMlrResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult)
{
OT_UNUSED_VARIABLE(aMessageInfo);
uint8_t status;
Error error;
- Ip6::Address failedAddresses[Ip6AddressesTlv::kMaxAddresses];
- uint8_t failedAddressNum = 0;
+ AddressArray failedAddresses;
- error = ParseMulticastListenerRegistrationResponse(aResult, aMessage, status, failedAddresses, failedAddressNum);
+ error = ParseMlrResponse(aResult, aMessage, status, failedAddresses);
- FinishMulticastListenerRegistration(error == kErrorNone && status == ThreadStatusTlv::MlrStatus::kMlrSuccess,
- failedAddresses, failedAddressNum);
+ FinishMlr(error == kErrorNone && status == ThreadStatusTlv::kMlrSuccess, failedAddresses);
- if (error == kErrorNone && status == ThreadStatusTlv::MlrStatus::kMlrSuccess)
+ if (error == kErrorNone && status == ThreadStatusTlv::kMlrSuccess)
{
// keep sending until all multicast addresses are registered.
ScheduleSend(0);
@@ -478,16 +467,15 @@ void MlrManager::HandleMulticastListenerRegistrationResponse(Coap::Message
}
}
-Error MlrManager::ParseMulticastListenerRegistrationResponse(Error aResult,
- Coap::Message *aMessage,
- uint8_t &aStatus,
- Ip6::Address *aFailedAddresses,
- uint8_t &aFailedAddressNum)
+Error MlrManager::ParseMlrResponse(Error aResult,
+ Coap::Message *aMessage,
+ uint8_t &aStatus,
+ AddressArray &aFailedAddresses)
{
Error error;
uint16_t addressesOffset, addressesLength;
- aStatus = ThreadStatusTlv::MlrStatus::kMlrGeneralFailure;
+ aStatus = ThreadStatusTlv::kMlrGeneralFailure;
VerifyOrExit(aResult == kErrorNone && aMessage != nullptr, error = kErrorParse);
VerifyOrExit(aMessage->GetCode() == Coap::kCodeChanged, error = kErrorParse);
@@ -502,15 +490,14 @@ Error MlrManager::ParseMulticastListenerRegistrationResponse(Error aRes
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
{
- IgnoreError(aMessage->Read(addressesOffset + offset, aFailedAddresses[aFailedAddressNum]));
- aFailedAddressNum++;
+ IgnoreError(aMessage->Read(addressesOffset + offset, *aFailedAddresses.PushBack()));
}
}
- VerifyOrExit(aFailedAddressNum == 0 || aStatus != ThreadStatusTlv::MlrStatus::kMlrSuccess, error = kErrorParse);
+ VerifyOrExit(aFailedAddresses.IsEmpty() || aStatus != ThreadStatusTlv::kMlrSuccess, error = kErrorParse);
exit:
- LogMlrResponse(aResult, error, aStatus, aFailedAddresses, aFailedAddressNum);
+ LogMlrResponse(aResult, error, aStatus, aFailedAddresses);
return aResult != kErrorNone ? aResult : error;
}
@@ -540,9 +527,7 @@ void MlrManager::SetMulticastAddressMlrState(MlrState aFromState, MlrState aToSt
#endif
}
-void MlrManager::FinishMulticastListenerRegistration(bool aSuccess,
- const Ip6::Address *aFailedAddresses,
- uint8_t aFailedAddressNum)
+void MlrManager::FinishMlr(bool aSuccess, const AddressArray &aFailedAddresses)
{
OT_ASSERT(mMlrPending);
@@ -554,7 +539,7 @@ void MlrManager::FinishMulticastListenerRegistration(bool aSucces
{
if (addr.GetMlrState() == kMlrStateRegistering)
{
- bool success = aSuccess || !AddressListContains(aFailedAddresses, aFailedAddressNum, addr.GetAddress());
+ bool success = aSuccess || !aFailedAddresses.IsEmptyOrContains(addr.GetAddress());
addr.SetMlrState(success ? kMlrStateRegistered : kMlrStateToRegister);
}
@@ -567,7 +552,7 @@ void MlrManager::FinishMulticastListenerRegistration(bool aSucces
{
if (child.GetAddressMlrState(address) == kMlrStateRegistering)
{
- bool success = aSuccess || !AddressListContains(aFailedAddresses, aFailedAddressNum, address);
+ bool success = aSuccess || !aFailedAddresses.IsEmptyOrContains(address);
child.SetAddressMlrState(address, success ? kMlrStateRegistered : kMlrStateToRegister);
}
@@ -583,7 +568,7 @@ void MlrManager::HandleTimeTick(void)
{
if (mSendDelay > 0 && --mSendDelay == 0)
{
- SendMulticastListenerRegistration();
+ SendMlr();
}
if (mReregistrationDelay > 0 && --mReregistrationDelay == 0)
@@ -678,74 +663,34 @@ void MlrManager::LogMulticastAddresses(void)
#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
}
-void MlrManager::AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses],
- uint8_t &aAddressNum,
- const Ip6::Address &aAddress)
+void MlrManager::AddressArray::AddUnique(const Ip6::Address &aAddress)
{
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
- for (uint8_t i = 0; i < aAddressNum; i++)
+ if (!Contains(aAddress))
{
- if (aAddresses[i] == aAddress)
- {
- ExitNow();
- }
+ IgnoreError(PushBack(aAddress));
}
-#endif
-
- aAddresses[aAddressNum++] = aAddress;
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
-exit:
-#endif
- return;
-}
-
-bool MlrManager::AddressListContains(const Ip6::Address *aAddressList,
- uint8_t aAddressListSize,
- const Ip6::Address &aAddress)
-{
- bool contains = false;
-
- // An empty address list is treated as if it contains all failed addresses.
- VerifyOrExit(aAddressListSize > 0, contains = true);
-
- for (uint8_t i = 0; i < aAddressListSize; i++)
- {
- if (aAddressList[i] == aAddress)
- {
- ExitNow(contains = true);
- }
- }
-
-exit:
- return contains;
}
-void MlrManager::LogMlrResponse(Error aResult,
- Error aError,
- uint8_t aStatus,
- const Ip6::Address *aFailedAddresses,
- uint8_t aFailedAddressNum)
+void MlrManager::LogMlrResponse(Error aResult, Error aError, uint8_t aStatus, const AddressArray &aFailedAddresses)
{
OT_UNUSED_VARIABLE(aResult);
OT_UNUSED_VARIABLE(aError);
OT_UNUSED_VARIABLE(aStatus);
OT_UNUSED_VARIABLE(aFailedAddresses);
- OT_UNUSED_VARIABLE(aFailedAddressNum);
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
- if (aResult == kErrorNone && aError == kErrorNone && aStatus == ThreadStatusTlv::MlrStatus::kMlrSuccess)
+ if (aResult == kErrorNone && aError == kErrorNone && aStatus == ThreadStatusTlv::kMlrSuccess)
{
LogInfo("Receive MLR.rsp OK");
}
else
{
LogWarn("Receive MLR.rsp: result=%s, error=%s, status=%d, failedAddressNum=%d", ErrorToString(aResult),
- ErrorToString(aError), aStatus, aFailedAddressNum);
+ ErrorToString(aError), aStatus, aFailedAddresses.GetLength());
- for (uint8_t i = 0; i < aFailedAddressNum; i++)
+ for (const Ip6::Address &address : aFailedAddresses)
{
- LogWarn("MA failed: %s", aFailedAddresses[i].ToString().AsCString());
+ LogWarn("MA failed: %s", address.ToString().AsCString());
}
}
#endif
diff --git a/src/core/thread/mlr_manager.hpp b/src/core/thread/mlr_manager.hpp
index 03ea44709..b1c1f63c0 100644
--- a/src/core/thread/mlr_manager.hpp
+++ b/src/core/thread/mlr_manager.hpp
@@ -44,6 +44,7 @@
#include "backbone_router/bbr_leader.hpp"
#include "coap/coap_message.hpp"
+#include "common/array.hpp"
#include "common/callback.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
@@ -80,6 +81,8 @@ class MlrManager : public InstanceLocator, private NonCopyable
friend class ot::TimeTicker;
public:
+ typedef otIp6RegisterMulticastListenersCallback MlrCallback;
+
/**
* Initializes the object.
*
@@ -135,44 +138,46 @@ public:
* @retval kErrorNoBufs If insufficient message buffers available.
*
*/
- Error RegisterMulticastListeners(const otIp6Address *aAddresses,
- uint8_t aAddressNum,
- const uint32_t *aTimeout,
- otIp6RegisterMulticastListenersCallback aCallback,
- void *aContext);
+ Error RegisterMulticastListeners(const Ip6::Address *aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t *aTimeout,
+ MlrCallback aCallback,
+ void *aContext);
#endif
private:
+ class AddressArray : public Array<Ip6::Address, Ip6AddressesTlv::kMaxAddresses>
+ {
+ public:
+ bool IsEmptyOrContains(const Ip6::Address &aAddress) const { return IsEmpty() || Contains(aAddress); }
+ void AddUnique(const Ip6::Address &aAddress);
+ };
+
void HandleNotifierEvents(Events aEvents);
- 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,
- 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);
+ void SendMlr(void);
+ Error SendMlrMessage(const Ip6::Address *aAddresses,
+ uint8_t aAddressNum,
+ const uint32_t *aTimeout,
+ Coap::ResponseHandler aResponseHandler,
+ void *aResponseContext);
+
+ static void HandleMlrResponse(void *aContext,
+ otMessage *aMessage,
+ const otMessageInfo *aMessageInfo,
+ Error aResult);
+ void HandleMlrResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
+ static Error ParseMlrResponse(Error aResult,
+ Coap::Message *aMessage,
+ uint8_t &aStatus,
+ AddressArray &aFailedAddresses);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
- static void HandleRegisterMulticastListenersResponse(void *aContext,
- otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- Error aResult);
- void HandleRegisterMulticastListenersResponse(otMessage *aMessage,
- const otMessageInfo *aMessageInfo,
- Error aResult);
+ static void HandleRegisterResponse(void *aContext,
+ otMessage *aMessage,
+ const otMessageInfo *aMessageInfo,
+ Error aResult);
+ void HandleRegisterResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult);
#endif
#if OPENTHREAD_CONFIG_MLR_ENABLE
@@ -189,16 +194,7 @@ private:
#endif
void SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState);
- void FinishMulticastListenerRegistration(bool aSuccess,
- const Ip6::Address *aFailedAddresses,
- uint8_t aFailedAddressNum);
-
- void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses],
- uint8_t &aAddressNum,
- const Ip6::Address &aAddress);
- static bool AddressListContains(const Ip6::Address *aAddressList,
- uint8_t aAddressListSize,
- const Ip6::Address &aAddress);
+ void FinishMlr(bool aSuccess, const AddressArray &aFailedAddresses);
void ScheduleSend(uint16_t aDelay);
void UpdateTimeTickerRegistration(void);
@@ -208,14 +204,10 @@ private:
void LogMulticastAddresses(void);
void CheckInvariants(void) const;
- static void LogMlrResponse(Error aResult,
- Error aError,
- uint8_t aStatus,
- const Ip6::Address *aFailedAddresses,
- uint8_t aFailedAddressNum);
+ static void LogMlrResponse(Error aResult, Error aError, uint8_t aStatus, const AddressArray &aFailedAddresses);
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
- Callback<otIp6RegisterMulticastListenersCallback> mRegisterMulticastListenersCallback;
+ Callback<MlrCallback> mRegisterCallback;
#endif
uint32_t mReregistrationDelay;
@@ -223,7 +215,7 @@ private:
bool mMlrPending : 1;
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
- bool mRegisterMulticastListenersPending : 1;
+ bool mRegisterPending : 1;
#endif
};
diff --git a/src/core/thread/neighbor.cpp b/src/core/thread/neighbor.cpp
index 868c762d5..d86956870 100644
--- a/src/core/thread/neighbor.cpp
+++ b/src/core/thread/neighbor.cpp
@@ -36,9 +36,9 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/neighbor_table.cpp b/src/core/thread/neighbor_table.cpp
index 39bd0663d..217414121 100644
--- a/src/core/thread/neighbor_table.cpp
+++ b/src/core/thread/neighbor_table.cpp
@@ -34,8 +34,8 @@
#include "neighbor_table.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "thread/dua_manager.hpp"
namespace ot {
diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp
index 009e67515..2599d653b 100644
--- a/src/core/thread/network_data.cpp
+++ b/src/core/thread/network_data.cpp
@@ -37,9 +37,9 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp
index 5171aa664..66a29a846 100644
--- a/src/core/thread/network_data_leader.cpp
+++ b/src/core/thread/network_data_leader.cpp
@@ -37,12 +37,12 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/logging.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "thread/lowpan.hpp"
#include "thread/mle_router.hpp"
@@ -55,18 +55,37 @@ namespace NetworkData {
RegisterLogModule("NetworkData");
-void LeaderBase::Reset(void)
+Leader::Leader(Instance &aInstance)
+ : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer))
+ , mMaxLength(0)
+#if OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
+ , mIsClone(false)
+#endif
+ , mWaitingForNetDataSync(false)
+ , mContextIds(aInstance)
+ , mTimer(aInstance)
+#endif
+{
+ Reset();
+}
+
+void Leader::Reset(void)
{
mVersion = Random::NonCrypto::GetUint8();
mStableVersion = Random::NonCrypto::GetUint8();
SetLength(0);
SignalNetDataChanged();
+
+#if OPENTHREAD_FTD
+ mContextIds.Clear();
+#endif
}
-Error LeaderBase::GetServiceId(uint32_t aEnterpriseNumber,
- const ServiceData &aServiceData,
- bool aServerStable,
- uint8_t &aServiceId) const
+Error Leader::GetServiceId(uint32_t aEnterpriseNumber,
+ const ServiceData &aServiceData,
+ bool aServerStable,
+ uint8_t &aServiceId) const
{
Error error = kErrorNotFound;
Iterator iterator = kIteratorInit;
@@ -89,7 +108,7 @@ exit:
return error;
}
-Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const
+Error Leader::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const
{
Error error = kErrorNotFound;
Iterator iterator = kIteratorInit;
@@ -113,7 +132,7 @@ Error LeaderBase::GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const
return error;
}
-const PrefixTlv *LeaderBase::FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
+const PrefixTlv *Leader::FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
{
// This method iterates over Prefix TLVs which match a given IPv6
// `aAddress`. If `aPrevTlv` is `nullptr` we start from the
@@ -135,7 +154,7 @@ const PrefixTlv *LeaderBase::FindNextMatchingPrefixTlv(const Ip6::Address &aAddr
return prefixTlv;
}
-Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
+Error Leader::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const
{
const PrefixTlv *prefixTlv = nullptr;
const ContextTlv *contextTlv;
@@ -168,7 +187,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon
return (aContext.mPrefix.GetLength() > 0) ? kErrorNone : kErrorNotFound;
}
-Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
+Error Leader::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
{
Error error = kErrorNotFound;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
@@ -200,7 +219,7 @@ exit:
return error;
}
-void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
+void Leader::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
{
aContext.mPrefix.Set(Get<Mle::MleRouter>().GetMeshLocalPrefix());
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
@@ -208,7 +227,7 @@ void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const
aContext.mIsValid = true;
}
-bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const
+bool Leader::IsOnMesh(const Ip6::Address &aAddress) const
{
const PrefixTlv *prefixTlv = nullptr;
bool isOnMesh = false;
@@ -237,7 +256,7 @@ exit:
return isOnMesh;
}
-Error LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint16_t &aRloc16) const
+Error Leader::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, uint16_t &aRloc16) const
{
Error error = kErrorNoRoute;
const PrefixTlv *prefixTlv = nullptr;
@@ -264,18 +283,17 @@ exit:
return error;
}
-template <typename EntryType>
-int LeaderBase::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const
+template <typename EntryType> int Leader::CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const
{
// `EntryType` can be `HasRouteEntry` or `BorderRouterEntry`.
return CompareRouteEntries(aFirst.GetPreference(), aFirst.GetRloc(), aSecond.GetPreference(), aSecond.GetRloc());
}
-int LeaderBase::CompareRouteEntries(int8_t aFirstPreference,
- uint16_t aFirstRloc,
- int8_t aSecondPreference,
- uint16_t aSecondRloc) const
+int Leader::CompareRouteEntries(int8_t aFirstPreference,
+ uint16_t aFirstRloc,
+ int8_t aSecondPreference,
+ uint16_t aSecondRloc) const
{
// Performs three-way comparison between two BR entries.
@@ -312,7 +330,7 @@ exit:
return result;
}
-Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const
+Error Leader::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, uint16_t &aRloc16) const
{
Error error = kErrorNoRoute;
const PrefixTlv *prefixTlv = nullptr;
@@ -359,7 +377,7 @@ Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDe
return error;
}
-Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const
+Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const
{
Error error = kErrorNoRoute;
TlvIterator subTlvIterator(aPrefix);
@@ -392,12 +410,12 @@ Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16
return error;
}
-Error LeaderBase::SetNetworkData(uint8_t aVersion,
- uint8_t aStableVersion,
- Type aType,
- const Message &aMessage,
- uint16_t aOffset,
- uint16_t aLength)
+Error Leader::SetNetworkData(uint8_t aVersion,
+ uint8_t aStableVersion,
+ Type aType,
+ const Message &aMessage,
+ uint16_t aOffset,
+ uint16_t aLength)
{
Error error = kErrorNone;
@@ -428,101 +446,126 @@ exit:
return error;
}
-Error LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
+const CommissioningDataTlv *Leader::FindCommissioningData(void) const
{
- Error error = kErrorNone;
- CommissioningDataTlv *commissioningDataTlv;
-
- RemoveCommissioningData();
-
- if (aValueLength > 0)
- {
- VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = kErrorNoBufs);
- commissioningDataTlv = As<CommissioningDataTlv>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
- VerifyOrExit(commissioningDataTlv != nullptr, error = kErrorNoBufs);
+ return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
+}
- commissioningDataTlv->Init();
- commissioningDataTlv->SetLength(aValueLength);
- memcpy(commissioningDataTlv->GetValue(), aValue, aValueLength);
- }
+const MeshCoP::Tlv *Leader::FindCommissioningDataSubTlv(uint8_t aType) const
+{
+ const MeshCoP::Tlv *subTlv = nullptr;
+ const NetworkDataTlv *dataTlv = FindCommissioningData();
- mVersion++;
- SignalNetDataChanged();
+ VerifyOrExit(dataTlv != nullptr);
+ subTlv = As<MeshCoP::Tlv>(Tlv::FindTlv(dataTlv->GetValue(), dataTlv->GetLength(), aType));
exit:
- return error;
+ return subTlv;
}
-const CommissioningDataTlv *LeaderBase::GetCommissioningData(void) const
+Error Leader::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const
{
- return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
-}
-
-const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const
-{
- const MeshCoP::Tlv *rval = nullptr;
- const NetworkDataTlv *commissioningDataTlv;
-
- commissioningDataTlv = GetCommissioningData();
- VerifyOrExit(commissioningDataTlv != nullptr);
+ Error error = kErrorNone;
+ const MeshCoP::Tlv *subTlv = FindCommissioningDataSubTlv(aType);
- rval = MeshCoP::Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType);
+ VerifyOrExit(subTlv != nullptr, error = kErrorNotFound);
+ VerifyOrExit(subTlv->GetLength() >= sizeof(uint16_t), error = kErrorParse);
+ aValue = BigEndian::ReadUint16(subTlv->GetValue());
exit:
- return rval;
+ return error;
}
-bool LeaderBase::IsJoiningEnabled(void) const
+void Leader::GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) const
{
- const MeshCoP::Tlv *steeringData;
- bool rval = false;
+ const CommissioningDataTlv *dataTlv = FindCommissioningData();
+ const MeshCoP::Tlv *subTlv;
+ const MeshCoP::Tlv *endTlv;
+
+ aDataset.Clear();
+
+ VerifyOrExit(dataTlv != nullptr);
- VerifyOrExit(GetCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator) != nullptr);
+ aDataset.mIsLocatorSet = (FindBorderAgentRloc(aDataset.mLocator) == kErrorNone);
+ aDataset.mIsSessionIdSet = (FindCommissioningSessionId(aDataset.mSessionId) == kErrorNone);
+ aDataset.mIsJoinerUdpPortSet = (FindJoinerUdpPort(aDataset.mJoinerUdpPort) == kErrorNone);
+ aDataset.mIsSteeringDataSet = (FindSteeringData(AsCoreType(&aDataset.mSteeringData)) == kErrorNone);
- steeringData = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
- VerifyOrExit(steeringData != nullptr);
+ // Determine if the Commissioning data has any extra unknown TLVs
- for (int i = 0; i < steeringData->GetLength(); i++)
+ subTlv = reinterpret_cast<const MeshCoP::Tlv *>(dataTlv->GetValue());
+ endTlv = reinterpret_cast<const MeshCoP::Tlv *>(dataTlv->GetValue() + dataTlv->GetLength());
+
+ for (; subTlv < endTlv; subTlv = subTlv->GetNext())
{
- if (steeringData->GetValue()[i] != 0)
+ switch (subTlv->GetType())
{
- ExitNow(rval = true);
+ case MeshCoP::Tlv::kBorderAgentLocator:
+ case MeshCoP::Tlv::kSteeringData:
+ case MeshCoP::Tlv::kJoinerUdpPort:
+ case MeshCoP::Tlv::kCommissionerSessionId:
+ break;
+ default:
+ ExitNow(aDataset.mHasExtraTlv = true);
}
}
exit:
- return rval;
+ return;
+}
+
+Error Leader::FindBorderAgentRloc(uint16_t &aRloc16) const
+{
+ return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16);
+}
+
+Error Leader::FindCommissioningSessionId(uint16_t &aSessionId) const
+{
+ return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kCommissionerSessionId, aSessionId);
+}
+
+Error Leader::FindJoinerUdpPort(uint16_t &aPort) const
+{
+ return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kJoinerUdpPort, aPort);
}
-void LeaderBase::RemoveCommissioningData(void)
+Error Leader::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const
{
- CommissioningDataTlv *tlv = GetCommissioningData();
+ Error error = kErrorNone;
+ const MeshCoP::SteeringDataTlv *steeringDataTlv = FindInCommissioningData<MeshCoP::SteeringDataTlv>();
- VerifyOrExit(tlv != nullptr);
- RemoveTlv(tlv);
+ VerifyOrExit(steeringDataTlv != nullptr, error = kErrorNotFound);
+ steeringDataTlv->CopyTo(aSteeringData);
exit:
- return;
+ return error;
}
-Error LeaderBase::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
+bool Leader::IsJoiningAllowed(void) const
{
- Error error = kErrorNone;
- const MeshCoP::Tlv *steeringDataTlv;
+ bool isAllowed = false;
MeshCoP::SteeringData steeringData;
- steeringDataTlv = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
- VerifyOrExit(steeringDataTlv != nullptr, error = kErrorInvalidState);
+ SuccessOrExit(FindSteeringData(steeringData));
+ isAllowed = !steeringData.IsEmpty();
- As<MeshCoP::SteeringDataTlv>(steeringDataTlv)->CopyTo(steeringData);
+exit:
+ return isAllowed;
+}
+
+Error Leader::SteeringDataCheck(const FilterIndexes &aFilterIndexes) const
+{
+ Error error = kErrorInvalidState;
+ MeshCoP::SteeringData steeringData;
- VerifyOrExit(steeringData.Contains(aFilterIndexes), error = kErrorNotFound);
+ SuccessOrExit(FindSteeringData(steeringData));
+ error = steeringData.Contains(aFilterIndexes) ? kErrorNone : kErrorNotFound;
exit:
return error;
}
-Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
+Error Leader::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
{
FilterIndexes filterIndexes;
Mac::ExtAddress joinerId;
@@ -533,7 +576,7 @@ Error LeaderBase::SteeringDataCheckJoiner(const Mac::ExtAddress &aEui64) const
return SteeringDataCheck(filterIndexes);
}
-Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
+Error Leader::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDiscerner) const
{
FilterIndexes filterIndexes;
@@ -542,7 +585,7 @@ Error LeaderBase::SteeringDataCheckJoiner(const MeshCoP::JoinerDiscerner &aDisce
return SteeringDataCheck(filterIndexes);
}
-void LeaderBase::SignalNetDataChanged(void)
+void Leader::SignalNetDataChanged(void)
{
mMaxLength = Max(mMaxLength, GetLength());
Get<ot::Notifier>().Signal(kEventThreadNetdataChanged);
diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp
index a696b5588..4ad1a99f0 100644
--- a/src/core/thread/network_data_leader.hpp
+++ b/src/core/thread/network_data_leader.hpp
@@ -40,10 +40,13 @@
#include "coap/coap.hpp"
#include "common/const_cast.hpp"
+#include "common/non_copyable.hpp"
+#include "common/numeric_limits.hpp"
#include "common/timer.hpp"
#include "net/ip6_address.hpp"
#include "thread/mle_router.hpp"
#include "thread/network_data.hpp"
+#include "thread/tmf.hpp"
namespace ot {
@@ -63,8 +66,11 @@ namespace NetworkData {
* Implements the Thread Network Data maintained by the Leader.
*
*/
-class LeaderBase : public MutableNetworkData
+class Leader : public MutableNetworkData, private NonCopyable
{
+ friend class Tmf::Agent;
+ friend class Notifier;
+
public:
/**
* Initializes the object.
@@ -72,12 +78,7 @@ public:
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
- explicit LeaderBase(Instance &aInstance)
- : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer))
- , mMaxLength(0)
- {
- Reset();
- }
+ explicit Leader(Instance &aInstance);
/**
* Reset the Thread Network Data.
@@ -182,65 +183,96 @@ public:
uint16_t aLength);
/**
- * Returns a pointer to the Commissioning Data.
+ * Gets the Commissioning Dataset from Network Data.
*
- * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
+ * @param[out] aDataset A reference to a `MeshCoP::CommissioningDataset` to populate.
*
*/
- CommissioningDataTlv *GetCommissioningData(void) { return AsNonConst(AsConst(this)->GetCommissioningData()); }
+ void GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) const;
/**
- * Returns a pointer to the Commissioning Data.
+ * Searches for given sub-TLV in Commissioning Data TLV.
+ *
+ * @tparam SubTlvType The sub-TLV type to search for.
*
- * @returns A pointer to the Commissioning Data or `nullptr` if no Commissioning Data exists.
+ * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists.
*
*/
- const CommissioningDataTlv *GetCommissioningData(void) const;
+ template <typename SubTlvType> const SubTlvType *FindInCommissioningData(void) const
+ {
+ return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
+ }
/**
- * Returns a pointer to the Commissioning Data Sub-TLV.
+ * Searches for given sub-TLV in Commissioning Data TLV.
*
- * @param[in] aType The TLV type value.
+ * @tparam SubTlvType The sub-TLV type to search for.
*
- * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
+ * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists.
*
*/
- MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
+ template <typename SubTlvType> SubTlvType *FindInCommissioningData(void)
{
- return AsNonConst(AsConst(this)->GetCommissioningDataSubTlv(aType));
+ return As<SubTlvType>(FindCommissioningDataSubTlv(SubTlvType::kType));
}
/**
- * Returns a pointer to the Commissioning Data Sub-TLV.
+ * Finds and reads the Commissioning Session ID in Commissioning Data TLV.
*
- * @param[in] aType The TLV type value.
+ * @param[out] aSessionId A reference to return the read session ID.
*
- * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no Sub-TLV exists.
+ * @retval kErrorNone Successfully read the session ID, @p aSessionId is updated.
+ * @retval kErrorNotFound Did not find Session ID sub-TLV.
+ * @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
*
*/
- const MeshCoP::Tlv *GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const;
+ Error FindCommissioningSessionId(uint16_t &aSessionId) const;
/**
- * Indicates whether or not the Commissioning Data TLV indicates Joining is enabled.
+ * Finds and reads the Border Agent RLOC16 in Commissioning Data TLV.
*
- * Joining is enabled if a Border Agent Locator TLV exist and the Steering Data TLV is non-zero.
+ * @param[out] aRloc16 A reference to return the read RLOC16.
*
- * @returns TRUE if the Commissioning Data TLV says Joining is enabled, FALSE otherwise.
+ * @retval kErrorNone Successfully read the Border Agent RLOC16, @p aRloc16 is updated.
+ * @retval kErrorNotFound Did not find Border Agent RLOC16 sub-TLV.
+ * @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
*
*/
- bool IsJoiningEnabled(void) const;
+ Error FindBorderAgentRloc(uint16_t &aRloc16) const;
/**
- * Adds Commissioning Data to the Thread Network Data.
+ * Finds and reads the Joiner UDP Port in Commissioning Data TLV.
*
- * @param[in] aValue A pointer to the Commissioning Data value.
- * @param[in] aValueLength The length of @p aValue.
+ * @param[out] aPort A reference to return the read port number.
*
- * @retval kErrorNone Successfully added the Commissioning Data.
- * @retval kErrorNoBufs Insufficient space to add the Commissioning Data.
+ * @retval kErrorNone Successfully read the Joiner UDP port, @p aPort is updated.
+ * @retval kErrorNotFound Did not find Joiner UDP Port sub-TLV.
+ * @retval kErrorParse Failed to parse Commissioning Data TLV (invalid format).
+ *
+ */
+ Error FindJoinerUdpPort(uint16_t &aPort) const;
+
+ /**
+ * Finds and read the Steering Data in Commissioning Data TLV.
+ *
+ * @param[out] aSteeringData A reference to return the read Steering Data.
+ *
+ * @retval kErrorNone Successfully read the Steering Data, @p aSteeringData is updated.
+ * @retval kErrorNotFound Did not find Steering Data sub-TLV.
*
*/
- Error SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength);
+ Error FindSteeringData(MeshCoP::SteeringData &aSteeringData) const;
+
+ /**
+ * Indicates whether or not the Commissioning Data TLV indicates Joining is allowed.
+ *
+ * Joining is allowed if a Border Agent Locator TLV exist and the Steering Data TLV is non-zero.
+ *
+ * @retval TRUE If joining is allowed.
+ * @retval FALSE If joining is not allowed.
+ *
+ */
+ bool IsJoiningAllowed(void) const;
/**
* Checks if the steering data includes a Joiner.
@@ -297,19 +329,118 @@ public:
*/
Error GetPreferredNat64Prefix(ExternalRouteConfig &aConfig) const;
-protected:
- void SignalNetDataChanged(void);
+#if OPENTHREAD_FTD
+ /**
+ * Defines the match mode constants to compare two RLOC16 values.
+ *
+ */
+ enum MatchMode : uint8_t
+ {
+ kMatchModeRloc16, ///< Perform exact RLOC16 match.
+ kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children).
+ };
- uint8_t mStableVersion;
- uint8_t mVersion;
+ /**
+ * Starts the Leader services.
+ *
+ * The start mode indicates whether device is starting normally as leader or restoring its role as leader after
+ * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for
+ * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data
+ * before allowing new Network Data registrations.
+ *
+ * @param[in] aStartMode The start mode.
+ *
+ */
+ void Start(Mle::LeaderStartMode aStartMode);
+
+ /**
+ * Increments the Thread Network Data version.
+ *
+ */
+ void IncrementVersion(void);
+
+ /**
+ * Increments both the Thread Network Data version and stable version.
+ *
+ */
+ void IncrementVersionAndStableVersion(void);
+
+ /**
+ * Returns CONTEXT_ID_RESUSE_DELAY value.
+ *
+ * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds).
+ *
+ */
+ uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); }
+
+ /**
+ * Sets CONTEXT_ID_RESUSE_DELAY value.
+ *
+ * @warning This method should only be used for testing.
+ *
+ * @param[in] aDelay The CONTEXT_ID_REUSE_DELAY value (in seconds).
+ *
+ */
+ void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); }
+
+ /**
+ * Removes Network Data entries matching with a given RLOC16.
+ *
+ * @param[in] aRloc16 A RLOC16 value.
+ * @param[in] aMatchMode A match mode (@sa MatchMode).
+ *
+ */
+ void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode);
+
+ /**
+ * Updates Commissioning Data in Network Data.
+ *
+ * @param[in] aData A pointer to the Commissioning Data.
+ * @param[in] aDataLength The length of @p aData.
+ *
+ * @retval kErrorNone Successfully updated the Commissioning Data.
+ * @retval kErrorNoBufs Insufficient space to add the Commissioning Data.
+ *
+ */
+ Error SetCommissioningData(const void *aData, uint8_t aDataLength);
+
+ /**
+ * Synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data.
+ *
+ * Note that this method should be called only by the Leader once after reset.
+ *
+ */
+ void HandleNetworkDataRestoredAfterReset(void);
+
+ /**
+ * Scans network data for given Service ID and returns pointer to the respective TLV, if present.
+ *
+ * @param aServiceId Service ID to look for.
+ * @return Pointer to the Service TLV for given Service ID, or nullptr if not present.
+ *
+ */
+ const ServiceTlv *FindServiceById(uint8_t aServiceId) const;
+
+#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ /**
+ * Indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data.
+ *
+ * @param[in] aPrefix The OMR prefix to check.
+ *
+ * @retval TRUE If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix.
+ * @retval FALSE Otherwise.
+ *
+ */
+ bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix);
+#endif
+
+#endif // OPENTHREAD_FTD
private:
using FilterIndexes = MeshCoP::SteeringData::HashBitIndexes;
const PrefixTlv *FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const;
- void RemoveCommissioningData(void);
-
template <typename EntryType> int CompareRouteEntries(const EntryType &aFirst, const EntryType &aSecond) const;
int CompareRouteEntries(int8_t aFirstPreference,
uint16_t aFirstRloc,
@@ -320,11 +451,202 @@ private:
Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) const;
Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const;
void GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const;
+ Error ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const;
+ void SignalNetDataChanged(void);
+ const CommissioningDataTlv *FindCommissioningData(void) const;
+ CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); }
+ const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const;
+ MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType)
+ {
+ return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType));
+ }
+
+#if OPENTHREAD_FTD
+ static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec.
+ static constexpr uint8_t kMinServiceId = 0x00;
+ static constexpr uint8_t kMaxServiceId = 0x0f;
+
+ class ChangedFlags
+ {
+ public:
+ ChangedFlags(void)
+ : mChanged(false)
+ , mStableChanged(false)
+ {
+ }
+
+ void Update(const NetworkDataTlv &aTlv)
+ {
+ mChanged = true;
+ mStableChanged = (mStableChanged || aTlv.IsStable());
+ }
+
+ bool DidChange(void) const { return mChanged; }
+ bool DidStableChange(void) const { return mStableChanged; }
+
+ private:
+ bool mChanged; // Any (stable or not) network data change (add/remove).
+ bool mStableChanged; // Stable network data change (add/remove).
+ };
+
+ enum UpdateStatus : uint8_t
+ {
+ kTlvRemoved, // TLV contained no sub TLVs and therefore is removed.
+ kTlvUpdated, // TLV stable flag is updated based on its sub TLVs.
+ };
+
+ class ContextIds : public InstanceLocator
+ {
+ public:
+ // This class tracks Context IDs. A Context ID can be in one
+ // of the 3 states: It is unallocated, or it is allocated
+ // and in-use, or it scheduled to be removed (after reuse delay
+ // interval is passed).
+
+ static constexpr uint8_t kInvalidId = NumericLimits<uint8_t>::kMax;
+
+ explicit ContextIds(Instance &aInstance);
+
+ void Clear(void);
+ Error GetUnallocatedId(uint8_t &aId);
+ void MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); }
+ void ScheduleToRemove(uint8_t aId);
+ uint32_t GetReuseDelay(void) const { return mReuseDelay; }
+ void SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; }
+ void HandleTimer(void);
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
+ void MarkAsClone(void) { mIsClone = true; }
+#endif
+
+ private:
+ static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds).
+
+ static constexpr uint8_t kMinId = 1;
+ static constexpr uint8_t kMaxId = 15;
+
+ // The `mRemoveTimes[id]` is used to track the state of a
+ // Context ID and its remove time. Two specific values
+ // `kUnallocated` and `kInUse` are used to indicate ID is in
+ // unallocated or in-use states. Other values indicate we
+ // are in remove state waiting to remove it at `mRemoveTime`.
+ static constexpr uint32_t kUnallocated = 0;
+ static constexpr uint32_t kInUse = 1;
+
+ bool IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; }
+ bool IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; }
+ TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; }
+ void SetRemoveTime(uint8_t aId, TimeMilli aTime);
+ void MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); }
+
+ TimeMilli mRemoveTimes[kMaxId - kMinId + 1];
+ uint32_t mReuseDelay;
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
+ bool mIsClone;
+#endif
+ };
+
+ template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+
+ void HandleTimer(void);
+
+ void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData);
+
+ 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);
+
+ Error AllocateServiceId(uint8_t &aServiceId) const;
+
+ void RemoveContext(uint8_t aContextId);
+ void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
+
+ void RemoveCommissioningData(void);
+
+ void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags);
+ void RemoveRloc(uint16_t aRloc16,
+ MatchMode aMatchMode,
+ const NetworkData &aExcludeNetworkData,
+ ChangedFlags &aChangedFlags);
+ void RemoveRlocInPrefix(PrefixTlv &aPrefix,
+ uint16_t aRloc16,
+ MatchMode aMatchMode,
+ const PrefixTlv *aExcludePrefix,
+ ChangedFlags &aChangedFlags);
+ void RemoveRlocInService(ServiceTlv &aService,
+ uint16_t aRloc16,
+ MatchMode aMatchMode,
+ const ServiceTlv *aExcludeService,
+ ChangedFlags &aChangedFlags);
+ void RemoveRlocInHasRoute(PrefixTlv &aPrefix,
+ HasRouteTlv &aHasRoute,
+ uint16_t aRloc16,
+ MatchMode aMatchMode,
+ const PrefixTlv *aExcludePrefix,
+ ChangedFlags &aChangedFlags);
+ void RemoveRlocInBorderRouter(PrefixTlv &aPrefix,
+ BorderRouterTlv &aBorderRouter,
+ uint16_t aRloc16,
+ MatchMode aMatchMode,
+ const PrefixTlv *aExcludePrefix,
+ ChangedFlags &aChangedFlags);
+
+ static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode);
+
+ static Error Validate(const NetworkData &aNetworkData, 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);
+ static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry);
+ static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry);
+ static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer);
+
+ UpdateStatus UpdatePrefix(PrefixTlv &aPrefix);
+ UpdateStatus UpdateService(ServiceTlv &aService);
+ UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs);
+
+ Error UpdateCommissioningData(uint16_t aDataLength, CommissioningDataTlv *&aDataTlv);
+ Error SetCommissioningData(const Message &aMessage);
+
+ void SendCommissioningSetResponse(const Coap::Message &aRequest,
+ const Ip6::MessageInfo &aMessageInfo,
+ MeshCoP::StateTlv::State aState);
+ void IncrementVersions(bool aIncludeStable);
+ void IncrementVersions(const ChangedFlags &aFlags);
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
+ void CheckForNetDataGettingFull(const NetworkData &aNetworkData, uint16_t aOldRloc16);
+ void MarkAsClone(void);
+#endif
+
+ using UpdateTimer = TimerMilliIn<Leader, &Leader::HandleTimer>;
+#endif // OPENTHREAD_FTD
+
+ uint8_t mStableVersion;
+ uint8_t mVersion;
uint8_t mTlvBuffer[kMaxSize];
uint8_t mMaxLength;
+
+#if OPENTHREAD_FTD
+#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
+ bool mIsClone;
+#endif
+ bool mWaitingForNetDataSync;
+ ContextIds mContextIds;
+ UpdateTimer mTimer;
+#endif
};
+#if OPENTHREAD_FTD
+DeclareTmfHandler(Leader, kUriServerData);
+DeclareTmfHandler(Leader, kUriCommissionerGet);
+DeclareTmfHandler(Leader, kUriCommissionerSet);
+#endif
+
/**
* @}
*/
@@ -332,20 +654,4 @@ private:
} // namespace NetworkData
} // namespace ot
-#if OPENTHREAD_MTD
-namespace ot {
-namespace NetworkData {
-class Leader : public LeaderBase
-{
-public:
- using LeaderBase::LeaderBase;
-};
-} // namespace NetworkData
-} // namespace ot
-#elif OPENTHREAD_FTD
-#include "network_data_leader_ftd.hpp"
-#else
-#error "Please define OPENTHREAD_MTD=1 or OPENTHREAD_FTD=1"
-#endif
-
#endif // NETWORK_DATA_LEADER_HPP_
diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp
index c3f219a9c..fe423ef4f 100644
--- a/src/core/thread/network_data_leader_ftd.cpp
+++ b/src/core/thread/network_data_leader_ftd.cpp
@@ -40,11 +40,11 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/message.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop.hpp"
#include "thread/lowpan.hpp"
@@ -58,25 +58,6 @@ namespace NetworkData {
RegisterLogModule("NetworkData");
-Leader::Leader(Instance &aInstance)
- : LeaderBase(aInstance)
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
- , mIsClone(false)
-#endif
- , mWaitingForNetDataSync(false)
- , mContextIds(aInstance)
- , mTimer(aInstance)
-{
- Reset();
-}
-
-void Leader::Reset(void)
-{
- LeaderBase::Reset();
-
- mContextIds.Clear();
-}
-
void Leader::Start(Mle::LeaderStartMode aStartMode)
{
#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
@@ -186,96 +167,37 @@ exit:
template <> void Leader::HandleTmf<kUriCommissionerSet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- uint16_t offset = aMessage.GetOffset();
- uint16_t length = aMessage.GetLength() - aMessage.GetOffset();
- uint8_t tlvs[NetworkData::kMaxSize];
- MeshCoP::StateTlv::State state = MeshCoP::StateTlv::kReject;
- bool hasSessionId = false;
- bool hasValidTlv = false;
- uint16_t sessionId = 0;
- CommissioningDataTlv *commDataTlv;
-
- MeshCoP::Tlv *cur;
- MeshCoP::Tlv *end;
+ MeshCoP::StateTlv::State state = MeshCoP::StateTlv::kReject;
+ uint16_t borderAgentRloc;
+ uint16_t sessionId;
+ uint16_t localSessionId;
VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync);
- VerifyOrExit(length <= sizeof(tlvs));
+ // Validate that there is no Border Agent Locator TLV. This also
+ // validates that all included TLVs are properly formatted.
- aMessage.ReadBytes(offset, tlvs, length);
+ VerifyOrExit(Tlv::Find<MeshCoP::BorderAgentLocatorTlv>(aMessage, borderAgentRloc) == kErrorNotFound);
- // Session Id and Border Router Locator MUST NOT be set, but accept including unexpected or
- // unknown TLV as long as there is at least one valid TLV.
- cur = reinterpret_cast<MeshCoP::Tlv *>(tlvs);
- end = reinterpret_cast<MeshCoP::Tlv *>(tlvs + length);
+ SuccessOrExit(Tlv::Find<MeshCoP::CommissionerSessionIdTlv>(aMessage, sessionId));
- while (cur < end)
+ if (FindCommissioningSessionId(localSessionId) == kErrorNone)
{
- MeshCoP::Tlv::Type type;
-
- VerifyOrExit(((cur + 1) <= end) && !cur->IsExtended() && (cur->GetNext() <= end));
-
- type = cur->GetType();
-
- if (type == MeshCoP::Tlv::kJoinerUdpPort || type == MeshCoP::Tlv::kSteeringData)
- {
- hasValidTlv = true;
- }
- else if (type == MeshCoP::Tlv::kBorderAgentLocator)
- {
- ExitNow();
- }
- else if (type == MeshCoP::Tlv::kCommissionerSessionId)
- {
- MeshCoP::CommissionerSessionIdTlv *tlv = As<MeshCoP::CommissionerSessionIdTlv>(cur);
-
- VerifyOrExit(tlv->IsValid());
- sessionId = tlv->GetCommissionerSessionId();
- hasSessionId = true;
- }
- else
- {
- // do nothing for unexpected or unknown TLV
- }
-
- cur = cur->GetNext();
+ VerifyOrExit(sessionId == localSessionId);
}
- // verify whether or not commissioner session id TLV is included
- VerifyOrExit(hasSessionId);
+ // Add the Border Agent RLOC TLV from Network Data.
- // verify whether or not MGMT_COMM_SET.req includes at least one valid TLV
- VerifyOrExit(hasValidTlv);
-
- // Find Commissioning Data TLV
- commDataTlv = GetCommissioningData();
-
- if (commDataTlv != nullptr)
+ if (FindBorderAgentRloc(borderAgentRloc) == kErrorNone)
{
- // Iterate over MeshCoP TLVs and extract desired data
- for (cur = reinterpret_cast<MeshCoP::Tlv *>(commDataTlv->GetValue());
- cur < reinterpret_cast<MeshCoP::Tlv *>(commDataTlv->GetValue() + commDataTlv->GetLength());
- cur = cur->GetNext())
- {
- if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
- {
- VerifyOrExit(sessionId == As<MeshCoP::CommissionerSessionIdTlv>(cur)->GetCommissionerSessionId());
- }
- else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
- {
- VerifyOrExit(length + cur->GetSize() <= sizeof(tlvs));
- memcpy(tlvs + length, reinterpret_cast<uint8_t *>(cur), cur->GetSize());
- length += cur->GetSize();
- }
- }
+ SuccessOrExit(Tlv::Append<MeshCoP::BorderAgentLocatorTlv>(aMessage, borderAgentRloc));
}
- IgnoreError(SetCommissioningData(tlvs, static_cast<uint8_t>(length)));
+ SuccessOrExit(SetCommissioningData(aMessage));
state = MeshCoP::StateTlv::kAccept;
exit:
-
if (Get<Mle::MleRouter>().IsLeader())
{
SendCommissioningSetResponse(aMessage, aMessageInfo, state);
@@ -284,94 +206,71 @@ exit:
template <> void Leader::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
- uint16_t length = 0;
- uint16_t offset;
+ uint16_t length;
+ uint16_t offset;
+ Coap::Message *response = nullptr;
VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync);
- SuccessOrExit(Tlv::FindTlvValueOffset(aMessage, MeshCoP::Tlv::kGet, offset, length));
- aMessage.SetOffset(offset);
+ response = Get<Tmf::Agent>().NewPriorityResponseMessage(aMessage);
+ VerifyOrExit(response != nullptr);
-exit:
- if (Get<Mle::MleRouter>().IsLeader())
+ if (Tlv::FindTlvValueOffset(aMessage, MeshCoP::Tlv::kGet, offset, length) == kErrorNone)
{
- SendCommissioningGetResponse(aMessage, length, aMessageInfo);
- }
-}
+ // Append the requested sub-TLV types given in Get TLV.
-void Leader::SendCommissioningGetResponse(const Coap::Message &aRequest,
- uint16_t aLength,
- const Ip6::MessageInfo &aMessageInfo)
-{
- Error error = kErrorNone;
- Coap::Message *message;
- CommissioningDataTlv *commDataTlv;
- uint8_t *data = nullptr;
- uint8_t length = 0;
-
- message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
- VerifyOrExit(message != nullptr, error = kErrorNoBufs);
-
- commDataTlv = GetCommissioningData();
+ for (; length > 0; offset++, length--)
+ {
+ uint8_t type;
+ const MeshCoP::Tlv *subTlv;
- if (commDataTlv != nullptr)
- {
- data = commDataTlv->GetValue();
- length = commDataTlv->GetLength();
- }
+ IgnoreError(aMessage.Read(offset, type));
- VerifyOrExit(data && length, error = kErrorDrop);
+ subTlv = FindCommissioningDataSubTlv(type);
- if (aLength == 0)
- {
- SuccessOrExit(error = message->AppendBytes(data, length));
+ if (subTlv != nullptr)
+ {
+ SuccessOrExit(subTlv->AppendTo(*response));
+ }
+ }
}
else
{
- for (uint16_t index = 0; index < aLength; index++)
- {
- uint8_t type;
+ // Append all sub-TLVs in the Commissioning Data.
- IgnoreError(aRequest.Read(aRequest.GetOffset() + index, type));
+ CommissioningDataTlv *dataTlv = FindCommissioningData();
- for (MeshCoP::Tlv *cur = reinterpret_cast<MeshCoP::Tlv *>(data);
- cur < reinterpret_cast<MeshCoP::Tlv *>(data + length); cur = cur->GetNext())
- {
- if (cur->GetType() == type)
- {
- SuccessOrExit(error = cur->AppendTo(*message));
- break;
- }
- }
+ if (dataTlv != nullptr)
+ {
+ SuccessOrExit(response->AppendBytes(dataTlv->GetValue(), dataTlv->GetLength()));
}
}
- SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
+ SuccessOrExit(Get<Tmf::Agent>().SendMessage(*response, aMessageInfo));
+ response = nullptr; // `SendMessage` takes ownership on success
LogInfo("Sent %s response", UriToString<kUriCommissionerGet>());
exit:
- FreeMessageOnError(message, error);
+ FreeMessage(response);
}
void Leader::SendCommissioningSetResponse(const Coap::Message &aRequest,
const Ip6::MessageInfo &aMessageInfo,
MeshCoP::StateTlv::State aState)
{
- Error error = kErrorNone;
- Coap::Message *message;
-
- message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
- VerifyOrExit(message != nullptr, error = kErrorNoBufs);
+ Coap::Message *message = Get<Tmf::Agent>().NewPriorityResponseMessage(aRequest);
- SuccessOrExit(error = Tlv::Append<MeshCoP::StateTlv>(*message, aState));
+ VerifyOrExit(message != nullptr);
+ SuccessOrExit(Tlv::Append<MeshCoP::StateTlv>(*message, aState));
- SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
+ SuccessOrExit(Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
+ message = nullptr; // `SendMessage` takes ownership on success
- LogInfo("sent %s response", UriToString<kUriCommissionerSet>());
+ LogInfo("Sent %s response", UriToString<kUriCommissionerSet>());
exit:
- FreeMessageOnError(message, error);
+ FreeMessage(message);
}
bool Leader::RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode)
@@ -1322,6 +1221,7 @@ void Leader::HandleNetworkDataRestoredAfterReset(void)
Iterator iterator = kIteratorInit;
ChangedFlags flags;
uint16_t rloc16;
+ uint16_t sessionId;
mWaitingForNetDataSync = false;
@@ -1366,6 +1266,89 @@ void Leader::HandleNetworkDataRestoredAfterReset(void)
mContextIds.ScheduleToRemove(context->GetContextId());
}
}
+
+ // Update Commissioning Data. We adopt the same session ID
+ // (if any) and resign active commissioner (if any) by
+ // clearing the Commissioning Data.
+
+ if (FindCommissioningSessionId(sessionId) == kErrorNone)
+ {
+ Get<MeshCoP::Leader>().SetSessionId(sessionId);
+ }
+
+ if (FindBorderAgentRloc(rloc16) == kErrorNone)
+ {
+ Get<MeshCoP::Leader>().SetEmptyCommissionerData();
+ }
+}
+
+Error Leader::UpdateCommissioningData(uint16_t aDataLength, CommissioningDataTlv *&aDataTlv)
+{
+ // First determine whether or not we can add Commissioning Data
+ // TLV with the given `aDataLength`, taking into account that we
+ // would remove the current Commissioning Data TLV. Then remove
+ // the current TLV and append a new TLV with proper size which is
+ // returned in `aDataTlv`.
+
+ Error error = kErrorNone;
+ CommissioningDataTlv *dataTlv = FindCommissioningData();
+ uint16_t insertLength;
+
+ if (dataTlv != nullptr)
+ {
+ insertLength = (aDataLength <= dataTlv->GetLength()) ? 0 : aDataLength - dataTlv->GetLength();
+ }
+ else
+ {
+ insertLength = sizeof(CommissioningDataTlv) + aDataLength;
+ }
+
+ VerifyOrExit(CanInsert(insertLength), error = kErrorNoBufs);
+
+ if (dataTlv != nullptr)
+ {
+ RemoveTlv(dataTlv);
+ }
+
+ aDataTlv = As<CommissioningDataTlv>(AppendTlv(sizeof(CommissioningDataTlv) + aDataLength));
+
+ OT_ASSERT(aDataTlv != nullptr);
+
+ aDataTlv->Init();
+ aDataTlv->SetLength(static_cast<uint8_t>(aDataLength));
+
+ // The caller would fill the `aDataTlv` value.
+
+ mVersion++;
+ SignalNetDataChanged();
+
+exit:
+ return error;
+}
+
+Error Leader::SetCommissioningData(const void *aData, uint8_t aDataLength)
+{
+ Error error = kErrorNone;
+ CommissioningDataTlv *dataTlv;
+
+ SuccessOrExit(error = UpdateCommissioningData(aDataLength, dataTlv));
+ memcpy(dataTlv->GetValue(), aData, aDataLength);
+
+exit:
+ return error;
+}
+
+Error Leader::SetCommissioningData(const Message &aMessage)
+{
+ Error error = kErrorNone;
+ uint16_t dataLength = aMessage.GetLength() - aMessage.GetOffset();
+ CommissioningDataTlv *dataTlv;
+
+ SuccessOrExit(error = UpdateCommissioningData(dataLength, dataTlv));
+ aMessage.ReadBytes(aMessage.GetOffset(), dataTlv->GetValue(), dataLength);
+
+exit:
+ return error;
}
void Leader::HandleTimer(void)
diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp
deleted file mode 100644
index de91ec1c6..000000000
--- a/src/core/thread/network_data_leader_ftd.hpp
+++ /dev/null
@@ -1,369 +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 includes definitions for manipulating Thread Network Data managed by the Thread Leader.
- */
-
-#ifndef NETWORK_DATA_LEADER_FTD_HPP_
-#define NETWORK_DATA_LEADER_FTD_HPP_
-
-#include "openthread-core-config.h"
-
-#if OPENTHREAD_FTD
-
-#include <stdint.h>
-
-#include "common/non_copyable.hpp"
-#include "common/numeric_limits.hpp"
-#include "common/timer.hpp"
-#include "net/ip6_address.hpp"
-#include "thread/mle_router.hpp"
-#include "thread/network_data.hpp"
-#include "thread/tmf.hpp"
-
-namespace ot {
-
-namespace NetworkData {
-
-class Notifier;
-
-/**
- * @addtogroup core-netdata-leader
- *
- * @brief
- * This module includes definitions for manipulating Thread Network Data managed by the Thread Leader.
- *
- * @{
- *
- */
-
-/**
- * Implements the Thread Network Data maintained by the Leader.
- *
- */
-class Leader : public LeaderBase, private NonCopyable
-{
- friend class Tmf::Agent;
- friend class Notifier;
-
-public:
- /**
- * Defines the match mode constants to compare two RLOC16 values.
- *
- */
- enum MatchMode : uint8_t
- {
- kMatchModeRloc16, ///< Perform exact RLOC16 match.
- kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children).
- };
-
- /**
- * Initializes the object.
- *
- * @param[in] aInstance A reference to the OpenThread instance.
- *
- */
- explicit Leader(Instance &aInstance);
-
- /**
- * Reset the Thread Network Data.
- *
- */
- void Reset(void);
-
- /**
- * Starts the Leader services.
- *
- * The start mode indicates whether device is starting normally as leader or restoring its role as leader after
- * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for
- * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data
- * before allowing new Network Data registrations.
- *
- * @param[in] aStartMode The start mode.
- *
- */
- void Start(Mle::LeaderStartMode aStartMode);
-
- /**
- * Increments the Thread Network Data version.
- *
- */
- void IncrementVersion(void);
-
- /**
- * Increments both the Thread Network Data version and stable version.
- *
- */
- void IncrementVersionAndStableVersion(void);
-
- /**
- * Returns CONTEXT_ID_RESUSE_DELAY value.
- *
- * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds).
- *
- */
- uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); }
-
- /**
- * Sets CONTEXT_ID_RESUSE_DELAY value.
- *
- * @warning This method should only be used for testing.
- *
- * @param[in] aDelay The CONTEXT_ID_REUSE_DELAY value (in seconds).
- *
- */
- void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); }
-
- /**
- * Removes Network Data entries matching with a given RLOC16.
- *
- * @param[in] aRloc16 A RLOC16 value.
- * @param[in] aMatchMode A match mode (@sa MatchMode).
- *
- */
- void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode);
-
- /**
- * Synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data.
- *
- * Note that this method should be called only by the Leader once after reset.
- *
- */
- void HandleNetworkDataRestoredAfterReset(void);
-
- /**
- * Scans network data for given Service ID and returns pointer to the respective TLV, if present.
- *
- * @param aServiceId Service ID to look for.
- * @return Pointer to the Service TLV for given Service ID, or nullptr if not present.
- *
- */
- const ServiceTlv *FindServiceById(uint8_t aServiceId) const;
-
-#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- /**
- * Indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data.
- *
- * @param[in] aPrefix The OMR prefix to check.
- *
- * @retval TRUE If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix.
- * @retval FALSE Otherwise.
- *
- */
- bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix);
-#endif
-
-private:
- static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec.
-
- static constexpr uint8_t kMinServiceId = 0x00;
- static constexpr uint8_t kMaxServiceId = 0x0f;
-
- class ChangedFlags
- {
- public:
- ChangedFlags(void)
- : mChanged(false)
- , mStableChanged(false)
- {
- }
-
- void Update(const NetworkDataTlv &aTlv)
- {
- mChanged = true;
- mStableChanged = (mStableChanged || aTlv.IsStable());
- }
-
- bool DidChange(void) const { return mChanged; }
- bool DidStableChange(void) const { return mStableChanged; }
-
- private:
- bool mChanged; // Any (stable or not) network data change (add/remove).
- bool mStableChanged; // Stable network data change (add/remove).
- };
-
- enum UpdateStatus : uint8_t
- {
- kTlvRemoved, // TLV contained no sub TLVs and therefore is removed.
- kTlvUpdated, // TLV stable flag is updated based on its sub TLVs.
- };
-
- class ContextIds : public InstanceLocator
- {
- public:
- // This class tracks Context IDs. A Context ID can be in one
- // of the 3 states: It is unallocated, or it is allocated
- // and in-use, or it scheduled to be removed (after reuse delay
- // interval is passed).
-
- static constexpr uint8_t kInvalidId = NumericLimits<uint8_t>::kMax;
-
- explicit ContextIds(Instance &aInstance);
-
- void Clear(void);
- Error GetUnallocatedId(uint8_t &aId);
- void MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); }
- void ScheduleToRemove(uint8_t aId);
- uint32_t GetReuseDelay(void) const { return mReuseDelay; }
- void SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; }
- void HandleTimer(void);
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
- void MarkAsClone(void) { mIsClone = true; }
-#endif
-
- private:
- static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds).
-
- static constexpr uint8_t kMinId = 1;
- static constexpr uint8_t kMaxId = 15;
-
- // The `mRemoveTimes[id]` is used to track the state of a
- // Context ID and its remove time. Two specific values
- // `kUnallocated` and `kInUse` are used to indicate ID is in
- // unallocated or in-use states. Other values indicate we
- // are in remove state waiting to remove it at `mRemoveTime`.
-
- static constexpr uint32_t kUnallocated = 0;
- static constexpr uint32_t kInUse = 1;
-
- bool IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; }
- bool IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; }
- TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; }
- void SetRemoveTime(uint8_t aId, TimeMilli aTime);
- void MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); }
-
- TimeMilli mRemoveTimes[kMaxId - kMinId + 1];
- uint32_t mReuseDelay;
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
- bool mIsClone;
-#endif
- };
-
- template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
-
- void HandleTimer(void);
-
- void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData);
-
- 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);
-
- Error AllocateServiceId(uint8_t &aServiceId) const;
-
- void RemoveContext(uint8_t aContextId);
- void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
-
- void RemoveCommissioningData(void);
-
- void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags);
- void RemoveRloc(uint16_t aRloc16,
- MatchMode aMatchMode,
- const NetworkData &aExcludeNetworkData,
- ChangedFlags &aChangedFlags);
- void RemoveRlocInPrefix(PrefixTlv &aPrefix,
- uint16_t aRloc16,
- MatchMode aMatchMode,
- const PrefixTlv *aExcludePrefix,
- ChangedFlags &aChangedFlags);
- void RemoveRlocInService(ServiceTlv &aService,
- uint16_t aRloc16,
- MatchMode aMatchMode,
- const ServiceTlv *aExcludeService,
- ChangedFlags &aChangedFlags);
- void RemoveRlocInHasRoute(PrefixTlv &aPrefix,
- HasRouteTlv &aHasRoute,
- uint16_t aRloc16,
- MatchMode aMatchMode,
- const PrefixTlv *aExcludePrefix,
- ChangedFlags &aChangedFlags);
- void RemoveRlocInBorderRouter(PrefixTlv &aPrefix,
- BorderRouterTlv &aBorderRouter,
- uint16_t aRloc16,
- MatchMode aMatchMode,
- const PrefixTlv *aExcludePrefix,
- ChangedFlags &aChangedFlags);
-
- static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode);
-
- static Error Validate(const NetworkData &aNetworkData, 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);
- static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry);
- static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry);
- static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer);
-
- UpdateStatus UpdatePrefix(PrefixTlv &aPrefix);
- UpdateStatus UpdateService(ServiceTlv &aService);
- UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs);
-
- void SendCommissioningGetResponse(const Coap::Message &aRequest,
- uint16_t aLength,
- const Ip6::MessageInfo &aMessageInfo);
- void SendCommissioningSetResponse(const Coap::Message &aRequest,
- const Ip6::MessageInfo &aMessageInfo,
- MeshCoP::StateTlv::State aState);
- void IncrementVersions(bool aIncludeStable);
- void IncrementVersions(const ChangedFlags &aFlags);
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
- void CheckForNetDataGettingFull(const NetworkData &aNetworkData, uint16_t aOldRloc16);
- void MarkAsClone(void);
-#endif
-
- using UpdateTimer = TimerMilliIn<Leader, &Leader::HandleTimer>;
-
-#if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
- bool mIsClone;
-#endif
- bool mWaitingForNetDataSync;
- ContextIds mContextIds;
- UpdateTimer mTimer;
-};
-
-DeclareTmfHandler(Leader, kUriServerData);
-DeclareTmfHandler(Leader, kUriCommissionerGet);
-DeclareTmfHandler(Leader, kUriCommissionerSet);
-
-/**
- * @}
- */
-
-} // namespace NetworkData
-} // namespace ot
-
-#endif // OPENTHREAD_FTD
-
-#endif // NETWORK_DATA_LEADER_FTD_HPP_
diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp
index b99900fd5..1e92266c2 100644
--- a/src/core/thread/network_data_local.cpp
+++ b/src/core/thread/network_data_local.cpp
@@ -37,9 +37,9 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "thread/mle_types.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp
index 657c0e3b5..750b3799b 100644
--- a/src/core/thread/network_data_notifier.cpp
+++ b/src/core/thread/network_data_notifier.cpp
@@ -36,9 +36,9 @@
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/network_data_local.hpp"
#include "thread/tmf.hpp"
diff --git a/src/core/thread/network_data_publisher.cpp b/src/core/thread/network_data_publisher.cpp
index 056765cb9..6094eddef 100644
--- a/src/core/thread/network_data_publisher.cpp
+++ b/src/core/thread/network_data_publisher.cpp
@@ -39,10 +39,10 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/const_cast.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/network_data_local.hpp"
#include "thread/network_data_service.hpp"
diff --git a/src/core/thread/network_data_service.cpp b/src/core/thread/network_data_service.cpp
index 1d2e90dba..77ff48597 100644
--- a/src/core/thread/network_data_service.cpp
+++ b/src/core/thread/network_data_service.cpp
@@ -35,8 +35,8 @@
#include "network_data_service.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
#include "thread/network_data_local.hpp"
namespace ot {
@@ -299,7 +299,7 @@ Error Manager::GetNextDnsSrpUnicastInfo(Iterator &aIterator, DnsSrpUnicast::Info
// IPv6 address.
aInfo.mSockAddr.GetAddress().SetToRoutingLocator(Get<Mle::Mle>().GetMeshLocalPrefix(),
aIterator.mServerSubTlv->GetServer16());
- aInfo.mSockAddr.SetPort(Encoding::BigEndian::ReadUint16(data.GetBytes()));
+ aInfo.mSockAddr.SetPort(BigEndian::ReadUint16(data.GetBytes()));
aInfo.mOrigin = DnsSrpUnicast::kFromServerData;
aInfo.mRloc16 = aIterator.mServerSubTlv->GetServer16();
ExitNow();
diff --git a/src/core/thread/network_data_service.hpp b/src/core/thread/network_data_service.hpp
index aea859a97..6fca444aa 100644
--- a/src/core/thread/network_data_service.hpp
+++ b/src/core/thread/network_data_service.hpp
@@ -50,9 +50,6 @@ namespace ot {
namespace NetworkData {
namespace Service {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
const uint32_t kThreadEnterpriseNumber = ServiceTlv::kThreadEnterpriseNumber; ///< Thread enterprise number.
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
@@ -111,7 +108,7 @@ public:
* @returns The BBR Registration Delay (in seconds) of Backbone Router.
*
*/
- uint16_t GetReregistrationDelay(void) const { return HostSwap16(mReregistrationDelay); }
+ uint16_t GetReregistrationDelay(void) const { return BigEndian::HostSwap16(mReregistrationDelay); }
/**
* Sets the Registration Delay (in seconds) of Backbone Router.
@@ -121,7 +118,7 @@ public:
*/
void SetReregistrationDelay(uint16_t aReregistrationDelay)
{
- mReregistrationDelay = HostSwap16(aReregistrationDelay);
+ mReregistrationDelay = BigEndian::HostSwap16(aReregistrationDelay);
}
/**
@@ -130,7 +127,7 @@ public:
* @returns The multicast listener report timeout (in seconds) of Backbone Router.
*
*/
- uint32_t GetMlrTimeout(void) const { return HostSwap32(mMlrTimeout); }
+ uint32_t GetMlrTimeout(void) const { return BigEndian::HostSwap32(mMlrTimeout); }
/**
* Sets multicast listener report timeout (in seconds) of Backbone Router.
@@ -138,7 +135,7 @@ public:
* @param[in] aMlrTimeout The multicast listener report timeout (in seconds) of Backbone Router.
*
*/
- void SetMlrTimeout(uint32_t aMlrTimeout) { mMlrTimeout = HostSwap32(aMlrTimeout); }
+ void SetMlrTimeout(uint32_t aMlrTimeout) { mMlrTimeout = BigEndian::HostSwap32(aMlrTimeout); }
private:
uint8_t mSequenceNumber;
@@ -279,7 +276,7 @@ public:
explicit ServiceData(const Ip6::Address &aAddress, uint16_t aPort)
: mServiceNumber(kServiceNumber)
, mAddress(aAddress)
- , mPort(HostSwap16(aPort))
+ , mPort(BigEndian::HostSwap16(aPort))
{
OT_UNUSED_VARIABLE(mServiceNumber);
}
@@ -306,7 +303,7 @@ public:
* @returns The port number.
*
*/
- uint16_t GetPort(void) const { return HostSwap16(mPort); }
+ uint16_t GetPort(void) const { return BigEndian::HostSwap16(mPort); }
private:
uint8_t mServiceNumber;
@@ -331,7 +328,7 @@ public:
*/
ServerData(const Ip6::Address &aAddress, uint16_t aPort)
: mAddress(aAddress)
- , mPort(HostSwap16(aPort))
+ , mPort(BigEndian::HostSwap16(aPort))
{
}
@@ -357,7 +354,7 @@ public:
* @returns The port number.
*
*/
- uint16_t GetPort(void) const { return HostSwap16(mPort); }
+ uint16_t GetPort(void) const { return BigEndian::HostSwap16(mPort); }
private:
Ip6::Address mAddress;
diff --git a/src/core/thread/network_data_tlvs.cpp b/src/core/thread/network_data_tlvs.cpp
index e81ec2d93..8a4330a03 100644
--- a/src/core/thread/network_data_tlvs.cpp
+++ b/src/core/thread/network_data_tlvs.cpp
@@ -101,7 +101,7 @@ void ServiceTlv::Init(uint8_t aServiceId, uint32_t aEnterpriseNumber, const Serv
if (aEnterpriseNumber != kThreadEnterpriseNumber)
{
- mShared.mEnterpriseNumber = HostSwap32(aEnterpriseNumber);
+ mShared.mEnterpriseNumber = BigEndian::HostSwap32(aEnterpriseNumber);
mServiceDataLength = aServiceData.GetLength();
aServiceData.CopyBytesTo(&mServiceDataLength + sizeof(uint8_t));
}
diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp
index 3c128be87..7b15fb275 100644
--- a/src/core/thread/network_data_tlvs.hpp
+++ b/src/core/thread/network_data_tlvs.hpp
@@ -48,9 +48,6 @@
namespace ot {
namespace NetworkData {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* @addtogroup core-netdata-tlvs
*
@@ -424,7 +421,7 @@ public:
*
* @returns The RLOC16 value.
*/
- uint16_t GetRloc(void) const { return HostSwap16(mRloc); }
+ uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
/**
* Sets the RLOC16 value.
@@ -432,7 +429,7 @@ public:
* @param[in] aRloc16 The RLOC16 value.
*
*/
- void SetRloc(uint16_t aRloc16) { mRloc = HostSwap16(aRloc16); }
+ void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
/**
* Returns the Preference value.
@@ -935,7 +932,7 @@ public:
*
* @returns The RLOC16 value.
*/
- uint16_t GetRloc(void) const { return HostSwap16(mRloc); }
+ uint16_t GetRloc(void) const { return BigEndian::HostSwap16(mRloc); }
/**
* Sets the RLOC16 value.
@@ -943,7 +940,7 @@ public:
* @param[in] aRloc16 The RLOC16 value.
*
*/
- void SetRloc(uint16_t aRloc16) { mRloc = HostSwap16(aRloc16); }
+ void SetRloc(uint16_t aRloc16) { mRloc = BigEndian::HostSwap16(aRloc16); }
/**
* Returns the Flags value.
@@ -951,7 +948,7 @@ public:
* @returns The Flags value.
*
*/
- uint16_t GetFlags(void) const { return HostSwap16(mFlags); }
+ uint16_t GetFlags(void) const { return BigEndian::HostSwap16(mFlags); }
/**
* Sets the Flags value.
@@ -959,7 +956,7 @@ public:
* @param[in] aFlags The Flags value.
*
*/
- void SetFlags(uint16_t aFlags) { mFlags = HostSwap16(aFlags); }
+ void SetFlags(uint16_t aFlags) { mFlags = BigEndian::HostSwap16(aFlags); }
/**
* Returns the Preference value.
@@ -976,7 +973,7 @@ public:
* @retval FALSE If the Preferred flag is not set.
*
*/
- bool IsPreferred(void) const { return (HostSwap16(mFlags) & kPreferredFlag) != 0; }
+ bool IsPreferred(void) const { return (BigEndian::HostSwap16(mFlags) & kPreferredFlag) != 0; }
/**
* Indicates whether or not the SLAAC flag is set.
@@ -985,7 +982,7 @@ public:
* @retval FALSE If the SLAAC flag is not set.
*
*/
- bool IsSlaac(void) const { return (HostSwap16(mFlags) & kSlaacFlag) != 0; }
+ bool IsSlaac(void) const { return (BigEndian::HostSwap16(mFlags) & kSlaacFlag) != 0; }
/**
* Indicates whether or not the DHCP flag is set.
@@ -994,7 +991,7 @@ public:
* @retval FALSE If the DHCP flag is not set.
*
*/
- bool IsDhcp(void) const { return (HostSwap16(mFlags) & kDhcpFlag) != 0; }
+ bool IsDhcp(void) const { return (BigEndian::HostSwap16(mFlags) & kDhcpFlag) != 0; }
/**
* Indicates whether or not the Configure flag is set.
@@ -1003,7 +1000,7 @@ public:
* @retval FALSE If the Configure flag is not set.
*
*/
- bool IsConfigure(void) const { return (HostSwap16(mFlags) & kConfigureFlag) != 0; }
+ bool IsConfigure(void) const { return (BigEndian::HostSwap16(mFlags) & kConfigureFlag) != 0; }
/**
* Indicates whether or not the Default Route flag is set.
@@ -1012,7 +1009,7 @@ public:
* @retval FALSE If the Default Route flag is not set.
*
*/
- bool IsDefaultRoute(void) const { return (HostSwap16(mFlags) & kDefaultRouteFlag) != 0; }
+ bool IsDefaultRoute(void) const { return (BigEndian::HostSwap16(mFlags) & kDefaultRouteFlag) != 0; }
/**
* Indicates whether or not the On-Mesh flag is set.
@@ -1021,7 +1018,7 @@ public:
* @retval FALSE If the On-Mesh flag is not set.
*
*/
- bool IsOnMesh(void) const { return (HostSwap16(mFlags) & kOnMeshFlag) != 0; }
+ bool IsOnMesh(void) const { return (BigEndian::HostSwap16(mFlags) & kOnMeshFlag) != 0; }
/**
* Indicates whether or not the Nd-Dns flag is set.
@@ -1030,7 +1027,7 @@ public:
* @retval FALSE If the Nd-Dns flag is not set.
*
*/
- bool IsNdDns(void) const { return (HostSwap16(mFlags) & kNdDnsFlag) != 0; }
+ bool IsNdDns(void) const { return (BigEndian::HostSwap16(mFlags) & kNdDnsFlag) != 0; }
/**
* Indicates whether or not the Domain Prefix flag is set.
@@ -1039,7 +1036,7 @@ public:
* @retval FALSE If the Domain Prefix flag is not set.
*
*/
- bool IsDp(void) const { return (HostSwap16(mFlags) & kDpFlag) != 0; }
+ bool IsDp(void) const { return (BigEndian::HostSwap16(mFlags) & kDpFlag) != 0; }
/**
* Returns a pointer to the next BorderRouterEntry
@@ -1349,7 +1346,7 @@ public:
uint32_t GetEnterpriseNumber(void) const
{
return IsThreadEnterprise() ? static_cast<uint32_t>(kThreadEnterpriseNumber)
- : HostSwap32(mShared.mEnterpriseNumber);
+ : BigEndian::HostSwap32(mShared.mEnterpriseNumber);
}
/**
@@ -1505,7 +1502,7 @@ public:
* @returns The Server16 value.
*
*/
- uint16_t GetServer16(void) const { return HostSwap16(mServer16); }
+ uint16_t GetServer16(void) const { return BigEndian::HostSwap16(mServer16); }
/*
* Sets the Server16 value.
@@ -1513,7 +1510,7 @@ public:
* @param[in] aServer16 The Server16 value.
*
*/
- void SetServer16(uint16_t aServer16) { mServer16 = HostSwap16(aServer16); }
+ void SetServer16(uint16_t aServer16) { mServer16 = BigEndian::HostSwap16(aServer16); }
/**
* Gets the Server Data.
diff --git a/src/core/thread/network_data_types.cpp b/src/core/thread/network_data_types.cpp
index 1793f2b4c..be349ab90 100644
--- a/src/core/thread/network_data_types.cpp
+++ b/src/core/thread/network_data_types.cpp
@@ -33,7 +33,7 @@
#include "network_data_types.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "thread/network_data_tlvs.hpp"
namespace ot {
diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp
index 97926091d..634574bc2 100644
--- a/src/core/thread/network_diagnostic.cpp
+++ b/src/core/thread/network_diagnostic.cpp
@@ -39,10 +39,11 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "common/numeric_limits.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "mac/mac.hpp"
#include "net/netif.hpp"
#include "thread/mesh_forwarder.hpp"
@@ -82,39 +83,20 @@ Server::Server(Instance &aInstance)
Error Server::SetVendorName(const char *aVendorName)
{
- return SetVendorString(mVendorName, sizeof(mVendorName), aVendorName);
+ return StringCopy(mVendorName, aVendorName, kStringCheckUtf8Encoding);
}
Error Server::SetVendorModel(const char *aVendorModel)
{
- return SetVendorString(mVendorModel, sizeof(mVendorModel), aVendorModel);
+ return StringCopy(mVendorModel, aVendorModel, kStringCheckUtf8Encoding);
}
Error Server::SetVendorSwVersion(const char *aVendorSwVersion)
{
- return SetVendorString(mVendorSwVersion, sizeof(mVendorSwVersion), aVendorSwVersion);
+ return StringCopy(mVendorSwVersion, aVendorSwVersion, kStringCheckUtf8Encoding);
}
-Error Server::SetVendorString(char *aDestString, uint16_t kMaxSize, const char *aSrcString)
-{
- Error error = kErrorInvalidArgs;
- uint16_t length;
-
- VerifyOrExit(aSrcString != nullptr);
-
- length = StringLength(aSrcString, kMaxSize);
- VerifyOrExit(length < kMaxSize);
-
- VerifyOrExit(IsValidUtf8String(aSrcString));
-
- memcpy(aDestString, aSrcString, length + 1);
- error = kErrorNone;
-
-exit:
- return error;
-}
-
-#endif // OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
+#endif
void Server::PrepareMessageInfoForDest(const Ip6::Address &aDestination, Tmf::MessageInfo &aMessageInfo) const
{
@@ -340,7 +322,7 @@ Error Server::AppendDiagTlv(uint8_t aTlvType, Message &aMessage)
tlv.Init();
- for (uint8_t page = 0; page < static_cast<uint8_t>(sizeof(Radio::kSupportedChannelPages) * CHAR_BIT); page++)
+ for (uint8_t page = 0; page < static_cast<uint8_t>(BitSizeOf(Radio::kSupportedChannelPages)); page++)
{
if (Radio::kSupportedChannelPages & (1 << page))
{
diff --git a/src/core/thread/network_diagnostic.hpp b/src/core/thread/network_diagnostic.hpp
index f610f2bb0..de16b7c70 100644
--- a/src/core/thread/network_diagnostic.hpp
+++ b/src/core/thread/network_diagnostic.hpp
@@ -208,8 +208,6 @@ private:
template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE
- Error SetVendorString(char *aDestString, uint16_t kMaxSize, const char *aSrcString);
-
VendorNameTlv::StringType mVendorName;
VendorModelTlv::StringType mVendorModel;
VendorSwVersionTlv::StringType mVendorSwVersion;
diff --git a/src/core/thread/network_diagnostic_tlvs.cpp b/src/core/thread/network_diagnostic_tlvs.cpp
index 941b0ccef..715730f2d 100644
--- a/src/core/thread/network_diagnostic_tlvs.cpp
+++ b/src/core/thread/network_diagnostic_tlvs.cpp
@@ -38,10 +38,6 @@
namespace ot {
namespace NetworkDiagnostic {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-using ot::Encoding::BigEndian::HostSwap64;
-
#if OPENTHREAD_FTD
void ChildTlv::InitFrom(const Child &aChild)
@@ -56,24 +52,24 @@ void ChildTlv::InitFrom(const Child &aChild)
mFlags |= (aChild.GetNetworkDataType() == NetworkData::kFullSet) ? kFlagsFullNetdta : 0;
mFlags |= kFlagsTrackErrRate;
- mRloc16 = HostSwap16(aChild.GetRloc16());
+ mRloc16 = BigEndian::HostSwap16(aChild.GetRloc16());
mExtAddress = aChild.GetExtAddress();
- mVersion = HostSwap16(aChild.GetVersion());
- mTimeout = HostSwap32(aChild.GetTimeout());
- mAge = HostSwap32(Time::MsecToSec(TimerMilli::GetNow() - aChild.GetLastHeard()));
- mConnectionTime = HostSwap32(aChild.GetConnectionTime());
- mSupervisionInterval = HostSwap16(aChild.GetSupervisionInterval());
+ mVersion = BigEndian::HostSwap16(aChild.GetVersion());
+ mTimeout = BigEndian::HostSwap32(aChild.GetTimeout());
+ mAge = BigEndian::HostSwap32(Time::MsecToSec(TimerMilli::GetNow() - aChild.GetLastHeard()));
+ mConnectionTime = BigEndian::HostSwap32(aChild.GetConnectionTime());
+ mSupervisionInterval = BigEndian::HostSwap16(aChild.GetSupervisionInterval());
mLinkMargin = aChild.GetLinkInfo().GetLinkMargin();
mAverageRssi = aChild.GetLinkInfo().GetAverageRss();
mLastRssi = aChild.GetLinkInfo().GetLastRss();
- mFrameErrorRate = HostSwap16(aChild.GetLinkInfo().GetFrameErrorRate());
- mMessageErrorRate = HostSwap16(aChild.GetLinkInfo().GetMessageErrorRate());
- mQueuedMessageCount = HostSwap16(aChild.GetIndirectMessageCount());
+ mFrameErrorRate = BigEndian::HostSwap16(aChild.GetLinkInfo().GetFrameErrorRate());
+ mMessageErrorRate = BigEndian::HostSwap16(aChild.GetLinkInfo().GetMessageErrorRate());
+ mQueuedMessageCount = BigEndian::HostSwap16(aChild.GetIndirectMessageCount());
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
mFlags |= aChild.IsCslSynchronized() ? kFlagsCslSync : 0;
- mCslPeriod = HostSwap16(aChild.GetCslPeriod());
- mCslTimeout = HostSwap32(aChild.GetCslTimeout());
+ mCslPeriod = BigEndian::HostSwap16(aChild.GetCslPeriod());
+ mCslTimeout = BigEndian::HostSwap32(aChild.GetCslTimeout());
mCslChannel = aChild.GetCslChannel();
#endif
}
@@ -86,15 +82,15 @@ void RouterNeighborTlv::InitFrom(const Router &aRouter)
SetLength(sizeof(*this) - sizeof(Tlv));
mFlags |= kFlagsTrackErrRate;
- mRloc16 = HostSwap16(aRouter.GetRloc16());
+ mRloc16 = BigEndian::HostSwap16(aRouter.GetRloc16());
mExtAddress = aRouter.GetExtAddress();
- mVersion = HostSwap16(aRouter.GetVersion());
- mConnectionTime = HostSwap32(aRouter.GetConnectionTime());
+ mVersion = BigEndian::HostSwap16(aRouter.GetVersion());
+ mConnectionTime = BigEndian::HostSwap32(aRouter.GetConnectionTime());
mLinkMargin = aRouter.GetLinkInfo().GetLinkMargin();
mAverageRssi = aRouter.GetLinkInfo().GetAverageRss();
mLastRssi = aRouter.GetLinkInfo().GetLastRss();
- mFrameErrorRate = HostSwap16(aRouter.GetLinkInfo().GetFrameErrorRate());
- mMessageErrorRate = HostSwap16(aRouter.GetLinkInfo().GetMessageErrorRate());
+ mFrameErrorRate = BigEndian::HostSwap16(aRouter.GetLinkInfo().GetFrameErrorRate());
+ mMessageErrorRate = BigEndian::HostSwap16(aRouter.GetLinkInfo().GetMessageErrorRate());
}
#endif // OPENTHREAD_FTD
@@ -112,40 +108,40 @@ void MleCountersTlv::Init(const Mle::Counters &aMleCounters)
SetType(kMleCounters);
SetLength(sizeof(*this) - sizeof(Tlv));
- mDisabledRole = HostSwap16(aMleCounters.mDisabledRole);
- mDetachedRole = HostSwap16(aMleCounters.mDetachedRole);
- mChildRole = HostSwap16(aMleCounters.mChildRole);
- mRouterRole = HostSwap16(aMleCounters.mRouterRole);
- mLeaderRole = HostSwap16(aMleCounters.mLeaderRole);
- mAttachAttempts = HostSwap16(aMleCounters.mAttachAttempts);
- mPartitionIdChanges = HostSwap16(aMleCounters.mPartitionIdChanges);
- mBetterPartitionAttachAttempts = HostSwap16(aMleCounters.mBetterPartitionAttachAttempts);
- mParentChanges = HostSwap16(aMleCounters.mParentChanges);
- mTrackedTime = HostSwap64(aMleCounters.mTrackedTime);
- mDisabledTime = HostSwap64(aMleCounters.mDisabledTime);
- mDetachedTime = HostSwap64(aMleCounters.mDetachedTime);
- mChildTime = HostSwap64(aMleCounters.mChildTime);
- mRouterTime = HostSwap64(aMleCounters.mRouterTime);
- mLeaderTime = HostSwap64(aMleCounters.mLeaderTime);
+ mDisabledRole = BigEndian::HostSwap16(aMleCounters.mDisabledRole);
+ mDetachedRole = BigEndian::HostSwap16(aMleCounters.mDetachedRole);
+ mChildRole = BigEndian::HostSwap16(aMleCounters.mChildRole);
+ mRouterRole = BigEndian::HostSwap16(aMleCounters.mRouterRole);
+ mLeaderRole = BigEndian::HostSwap16(aMleCounters.mLeaderRole);
+ mAttachAttempts = BigEndian::HostSwap16(aMleCounters.mAttachAttempts);
+ mPartitionIdChanges = BigEndian::HostSwap16(aMleCounters.mPartitionIdChanges);
+ mBetterPartitionAttachAttempts = BigEndian::HostSwap16(aMleCounters.mBetterPartitionAttachAttempts);
+ mParentChanges = BigEndian::HostSwap16(aMleCounters.mParentChanges);
+ mTrackedTime = BigEndian::HostSwap64(aMleCounters.mTrackedTime);
+ mDisabledTime = BigEndian::HostSwap64(aMleCounters.mDisabledTime);
+ mDetachedTime = BigEndian::HostSwap64(aMleCounters.mDetachedTime);
+ mChildTime = BigEndian::HostSwap64(aMleCounters.mChildTime);
+ mRouterTime = BigEndian::HostSwap64(aMleCounters.mRouterTime);
+ mLeaderTime = BigEndian::HostSwap64(aMleCounters.mLeaderTime);
}
void MleCountersTlv::Read(MleCounters &aDiagMleCounters) const
{
- aDiagMleCounters.mDisabledRole = HostSwap16(mDisabledRole);
- aDiagMleCounters.mDetachedRole = HostSwap16(mDetachedRole);
- aDiagMleCounters.mChildRole = HostSwap16(mChildRole);
- aDiagMleCounters.mRouterRole = HostSwap16(mRouterRole);
- aDiagMleCounters.mLeaderRole = HostSwap16(mLeaderRole);
- aDiagMleCounters.mAttachAttempts = HostSwap16(mAttachAttempts);
- aDiagMleCounters.mPartitionIdChanges = HostSwap16(mPartitionIdChanges);
- aDiagMleCounters.mBetterPartitionAttachAttempts = HostSwap16(mBetterPartitionAttachAttempts);
- aDiagMleCounters.mParentChanges = HostSwap16(mParentChanges);
- aDiagMleCounters.mTrackedTime = HostSwap64(mTrackedTime);
- aDiagMleCounters.mDisabledTime = HostSwap64(mDisabledTime);
- aDiagMleCounters.mDetachedTime = HostSwap64(mDetachedTime);
- aDiagMleCounters.mChildTime = HostSwap64(mChildTime);
- aDiagMleCounters.mRouterTime = HostSwap64(mRouterTime);
- aDiagMleCounters.mLeaderTime = HostSwap64(mLeaderTime);
+ aDiagMleCounters.mDisabledRole = BigEndian::HostSwap16(mDisabledRole);
+ aDiagMleCounters.mDetachedRole = BigEndian::HostSwap16(mDetachedRole);
+ aDiagMleCounters.mChildRole = BigEndian::HostSwap16(mChildRole);
+ aDiagMleCounters.mRouterRole = BigEndian::HostSwap16(mRouterRole);
+ aDiagMleCounters.mLeaderRole = BigEndian::HostSwap16(mLeaderRole);
+ aDiagMleCounters.mAttachAttempts = BigEndian::HostSwap16(mAttachAttempts);
+ aDiagMleCounters.mPartitionIdChanges = BigEndian::HostSwap16(mPartitionIdChanges);
+ aDiagMleCounters.mBetterPartitionAttachAttempts = BigEndian::HostSwap16(mBetterPartitionAttachAttempts);
+ aDiagMleCounters.mParentChanges = BigEndian::HostSwap16(mParentChanges);
+ aDiagMleCounters.mTrackedTime = BigEndian::HostSwap64(mTrackedTime);
+ aDiagMleCounters.mDisabledTime = BigEndian::HostSwap64(mDisabledTime);
+ aDiagMleCounters.mDetachedTime = BigEndian::HostSwap64(mDetachedTime);
+ aDiagMleCounters.mChildTime = BigEndian::HostSwap64(mChildTime);
+ aDiagMleCounters.mRouterTime = BigEndian::HostSwap64(mRouterTime);
+ aDiagMleCounters.mLeaderTime = BigEndian::HostSwap64(mLeaderTime);
}
} // namespace NetworkDiagnostic
diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp
index 5bdb8df0f..e867e0fa0 100644
--- a/src/core/thread/network_diagnostic_tlvs.hpp
+++ b/src/core/thread/network_diagnostic_tlvs.hpp
@@ -54,9 +54,6 @@
namespace ot {
namespace NetworkDiagnostic {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* Implements Network Diagnostic TLV generation and parsing.
*
@@ -362,7 +359,7 @@ public:
* @returns The IfInUnknownProtos counter
*
*/
- uint32_t GetIfInUnknownProtos(void) const { return HostSwap32(mIfInUnknownProtos); }
+ uint32_t GetIfInUnknownProtos(void) const { return BigEndian::HostSwap32(mIfInUnknownProtos); }
/**
* Sets the IfInUnknownProtos counter.
@@ -372,7 +369,7 @@ public:
*/
void SetIfInUnknownProtos(const uint32_t aIfInUnknownProtos)
{
- mIfInUnknownProtos = HostSwap32(aIfInUnknownProtos);
+ mIfInUnknownProtos = BigEndian::HostSwap32(aIfInUnknownProtos);
}
/**
@@ -381,7 +378,7 @@ public:
* @returns The IfInErrors counter
*
*/
- uint32_t GetIfInErrors(void) const { return HostSwap32(mIfInErrors); }
+ uint32_t GetIfInErrors(void) const { return BigEndian::HostSwap32(mIfInErrors); }
/**
* Sets the IfInErrors counter.
@@ -389,7 +386,7 @@ public:
* @param[in] aIfInErrors The IfInErrors counter
*
*/
- void SetIfInErrors(const uint32_t aIfInErrors) { mIfInErrors = HostSwap32(aIfInErrors); }
+ void SetIfInErrors(const uint32_t aIfInErrors) { mIfInErrors = BigEndian::HostSwap32(aIfInErrors); }
/**
* Returns the IfOutErrors counter.
@@ -397,7 +394,7 @@ public:
* @returns The IfOutErrors counter
*
*/
- uint32_t GetIfOutErrors(void) const { return HostSwap32(mIfOutErrors); }
+ uint32_t GetIfOutErrors(void) const { return BigEndian::HostSwap32(mIfOutErrors); }
/**
* Sets the IfOutErrors counter.
@@ -405,7 +402,7 @@ public:
* @param[in] aIfOutErrors The IfOutErrors counter.
*
*/
- void SetIfOutErrors(const uint32_t aIfOutErrors) { mIfOutErrors = HostSwap32(aIfOutErrors); }
+ void SetIfOutErrors(const uint32_t aIfOutErrors) { mIfOutErrors = BigEndian::HostSwap32(aIfOutErrors); }
/**
* Returns the IfInUcastPkts counter.
@@ -413,7 +410,7 @@ public:
* @returns The IfInUcastPkts counter
*
*/
- uint32_t GetIfInUcastPkts(void) const { return HostSwap32(mIfInUcastPkts); }
+ uint32_t GetIfInUcastPkts(void) const { return BigEndian::HostSwap32(mIfInUcastPkts); }
/**
* Sets the IfInUcastPkts counter.
@@ -421,14 +418,14 @@ public:
* @param[in] aIfInUcastPkts The IfInUcastPkts counter.
*
*/
- void SetIfInUcastPkts(const uint32_t aIfInUcastPkts) { mIfInUcastPkts = HostSwap32(aIfInUcastPkts); }
+ void SetIfInUcastPkts(const uint32_t aIfInUcastPkts) { mIfInUcastPkts = BigEndian::HostSwap32(aIfInUcastPkts); }
/**
* Returns the IfInBroadcastPkts counter.
*
* @returns The IfInBroadcastPkts counter
*
*/
- uint32_t GetIfInBroadcastPkts(void) const { return HostSwap32(mIfInBroadcastPkts); }
+ uint32_t GetIfInBroadcastPkts(void) const { return BigEndian::HostSwap32(mIfInBroadcastPkts); }
/**
* Sets the IfInBroadcastPkts counter.
@@ -438,7 +435,7 @@ public:
*/
void SetIfInBroadcastPkts(const uint32_t aIfInBroadcastPkts)
{
- mIfInBroadcastPkts = HostSwap32(aIfInBroadcastPkts);
+ mIfInBroadcastPkts = BigEndian::HostSwap32(aIfInBroadcastPkts);
}
/**
@@ -447,7 +444,7 @@ public:
* @returns The IfInDiscards counter
*
*/
- uint32_t GetIfInDiscards(void) const { return HostSwap32(mIfInDiscards); }
+ uint32_t GetIfInDiscards(void) const { return BigEndian::HostSwap32(mIfInDiscards); }
/**
* Sets the IfInDiscards counter.
@@ -455,7 +452,7 @@ public:
* @param[in] aIfInDiscards The IfInDiscards counter.
*
*/
- void SetIfInDiscards(const uint32_t aIfInDiscards) { mIfInDiscards = HostSwap32(aIfInDiscards); }
+ void SetIfInDiscards(const uint32_t aIfInDiscards) { mIfInDiscards = BigEndian::HostSwap32(aIfInDiscards); }
/**
* Returns the IfOutUcastPkts counter.
@@ -463,7 +460,7 @@ public:
* @returns The IfOutUcastPkts counter
*
*/
- uint32_t GetIfOutUcastPkts(void) const { return HostSwap32(mIfOutUcastPkts); }
+ uint32_t GetIfOutUcastPkts(void) const { return BigEndian::HostSwap32(mIfOutUcastPkts); }
/**
* Sets the IfOutUcastPkts counter.
@@ -471,7 +468,7 @@ public:
* @param[in] aIfOutUcastPkts The IfOutUcastPkts counter.
*
*/
- void SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts) { mIfOutUcastPkts = HostSwap32(aIfOutUcastPkts); }
+ void SetIfOutUcastPkts(const uint32_t aIfOutUcastPkts) { mIfOutUcastPkts = BigEndian::HostSwap32(aIfOutUcastPkts); }
/**
* Returns the IfOutBroadcastPkts counter.
@@ -479,7 +476,7 @@ public:
* @returns The IfOutBroadcastPkts counter
*
*/
- uint32_t GetIfOutBroadcastPkts(void) const { return HostSwap32(mIfOutBroadcastPkts); }
+ uint32_t GetIfOutBroadcastPkts(void) const { return BigEndian::HostSwap32(mIfOutBroadcastPkts); }
/**
* Sets the IfOutBroadcastPkts counter.
@@ -489,7 +486,7 @@ public:
*/
void SetIfOutBroadcastPkts(const uint32_t aIfOutBroadcastPkts)
{
- mIfOutBroadcastPkts = HostSwap32(aIfOutBroadcastPkts);
+ mIfOutBroadcastPkts = BigEndian::HostSwap32(aIfOutBroadcastPkts);
}
/**
@@ -498,7 +495,7 @@ public:
* @returns The IfOutDiscards counter
*
*/
- uint32_t GetIfOutDiscards(void) const { return HostSwap32(mIfOutDiscards); }
+ uint32_t GetIfOutDiscards(void) const { return BigEndian::HostSwap32(mIfOutDiscards); }
/**
* Sets the IfOutDiscards counter.
@@ -506,7 +503,7 @@ public:
* @param[in] aIfOutDiscards The IfOutDiscards counter.
*
*/
- void SetIfOutDiscards(const uint32_t aIfOutDiscards) { mIfOutDiscards = HostSwap32(aIfOutDiscards); }
+ void SetIfOutDiscards(const uint32_t aIfOutDiscards) { mIfOutDiscards = BigEndian::HostSwap32(aIfOutDiscards); }
private:
uint32_t mIfInUnknownProtos;
@@ -618,8 +615,8 @@ private:
static constexpr uint16_t kLqiMask = 0x3 << kLqiOffset;
static constexpr uint16_t kChildIdMask = 0x1ff << kChildIdOffset;
- uint16_t GetTimeoutChildId(void) const { return HostSwap16(mTimeoutChildId); }
- void SetTimeoutChildId(uint16_t aTimeoutChildIf) { mTimeoutChildId = HostSwap16(aTimeoutChildIf); }
+ uint16_t GetTimeoutChildId(void) const { return BigEndian::HostSwap16(mTimeoutChildId); }
+ void SetTimeoutChildId(uint16_t aTimeoutChildIf) { mTimeoutChildId = BigEndian::HostSwap16(aTimeoutChildIf); }
uint16_t mTimeoutChildId;
uint8_t mMode;
@@ -735,7 +732,7 @@ public:
* @returns The RLOC16 of the child.
*
*/
- uint16_t GetRloc16(void) const { return HostSwap16(mRloc16); }
+ uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
/**
* Returns the Extended Address.
@@ -751,7 +748,7 @@ public:
* @returns The Version of the child.
*
*/
- uint16_t GetVersion(void) const { return HostSwap16(mVersion); }
+ uint16_t GetVersion(void) const { return BigEndian::HostSwap16(mVersion); }
/**
* Returns the Timeout field
@@ -759,7 +756,7 @@ public:
* @returns The Timeout value in seconds.
*
*/
- uint32_t GetTimeout(void) const { return HostSwap32(mTimeout); }
+ uint32_t GetTimeout(void) const { return BigEndian::HostSwap32(mTimeout); }
/**
* Returns the Age field.
@@ -767,7 +764,7 @@ public:
* @returns The Age field (seconds since last heard from the child).
*
*/
- uint32_t GetAge(void) const { return HostSwap32(mAge); }
+ uint32_t GetAge(void) const { return BigEndian::HostSwap32(mAge); }
/**
* Returns the Connection Time field.
@@ -775,7 +772,7 @@ public:
* @returns The Connection Time field (seconds since attach).
*
*/
- uint32_t GetConnectionTime(void) const { return HostSwap32(mConnectionTime); }
+ uint32_t GetConnectionTime(void) const { return BigEndian::HostSwap32(mConnectionTime); }
/**
* Returns the Supervision Interval field
@@ -783,7 +780,7 @@ public:
* @returns The Supervision Interval in seconds. Zero indicates not used.
*
*/
- uint16_t GetSupervisionInterval(void) const { return HostSwap16(mSupervisionInterval); }
+ uint16_t GetSupervisionInterval(void) const { return BigEndian::HostSwap16(mSupervisionInterval); }
/**
* Returns the Link Margin field.
@@ -818,7 +815,7 @@ public:
* @returns The Frame Error Rate (0x0000->0%, 0xffff->100%).
*
*/
- uint16_t GetFrameErrorRate(void) const { return HostSwap16(mFrameErrorRate); }
+ uint16_t GetFrameErrorRate(void) const { return BigEndian::HostSwap16(mFrameErrorRate); }
/**
* Returns the Message Error Rate field.
@@ -829,7 +826,7 @@ public:
* @returns The Message Error Rate (0x0000->0%, 0xffff->100%).
*
*/
- uint16_t GetMessageErrorRate(void) const { return HostSwap16(mMessageErrorRate); }
+ uint16_t GetMessageErrorRate(void) const { return BigEndian::HostSwap16(mMessageErrorRate); }
/**
* Returns the Queued Message Count field.
@@ -837,7 +834,7 @@ public:
* @returns The Queued Message Count (number of queued messages for indirect tx to child).
*
*/
- uint16_t GetQueuedMessageCount(void) const { return HostSwap16(mQueuedMessageCount); }
+ uint16_t GetQueuedMessageCount(void) const { return BigEndian::HostSwap16(mQueuedMessageCount); }
/**
* Returns the CSL Period in unit of 10 symbols.
@@ -845,7 +842,7 @@ public:
* @returns The CSL Period in unit of 10-symbols-time. Zero if CSL is not supported.
*
*/
- uint16_t GetCslPeriod(void) const { return HostSwap16(mCslPeriod); }
+ uint16_t GetCslPeriod(void) const { return BigEndian::HostSwap16(mCslPeriod); }
/**
* Returns the CSL Timeout in seconds.
@@ -853,7 +850,7 @@ public:
* @returns The CSL Timeout in seconds. Zero if unknown on parent of if CSL Is not supported.
*
*/
- uint32_t GetCslTimeout(void) const { return HostSwap32(mCslTimeout); }
+ uint32_t GetCslTimeout(void) const { return BigEndian::HostSwap32(mCslTimeout); }
/**
* Returns the CSL Channel.
@@ -899,7 +896,7 @@ public:
* @returns The RLOC16 of the child.
*
*/
- uint16_t GetRloc16(void) const { return HostSwap16(mRloc16); }
+ uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
/**
* Sets the RLOC16.
@@ -907,7 +904,7 @@ public:
* @param[in] aRloc16 The RLOC16 value.
*
*/
- void SetRloc16(uint16_t aRloc16) { mRloc16 = HostSwap16(aRloc16); }
+ void SetRloc16(uint16_t aRloc16) { mRloc16 = BigEndian::HostSwap16(aRloc16); }
private:
uint16_t mRloc16;
@@ -957,7 +954,7 @@ public:
* @returns The RLOC16 of the router.
*
*/
- uint16_t GetRloc16(void) const { return HostSwap16(mRloc16); }
+ uint16_t GetRloc16(void) const { return BigEndian::HostSwap16(mRloc16); }
/**
* Returns the Extended Address.
@@ -973,7 +970,7 @@ public:
* @returns The Version of the router.
*
*/
- uint16_t GetVersion(void) const { return HostSwap16(mVersion); }
+ uint16_t GetVersion(void) const { return BigEndian::HostSwap16(mVersion); }
/**
* Returns the Connection Time field.
@@ -981,7 +978,7 @@ public:
* @returns The Connection Time field (seconds since link establishment).
*
*/
- uint32_t GetConnectionTime(void) const { return HostSwap32(mConnectionTime); }
+ uint32_t GetConnectionTime(void) const { return BigEndian::HostSwap32(mConnectionTime); }
/**
* Returns the Link Margin field.
@@ -1016,7 +1013,7 @@ public:
* @returns The Frame Error Rate (0x0000->0%, 0xffff->100%).
*
*/
- uint16_t GetFrameErrorRate(void) const { return HostSwap16(mFrameErrorRate); }
+ uint16_t GetFrameErrorRate(void) const { return BigEndian::HostSwap16(mFrameErrorRate); }
/**
* Returns the Message Error Rate field.
@@ -1027,7 +1024,7 @@ public:
* @returns The Message Error Rate (0x0000->0%, 0xffff->100%).
*
*/
- uint16_t GetMessageErrorRate(void) const { return HostSwap16(mMessageErrorRate); }
+ uint16_t GetMessageErrorRate(void) const { return BigEndian::HostSwap16(mMessageErrorRate); }
private:
uint8_t mFlags; // Flags (`kFlags*` constants).
@@ -1082,8 +1079,8 @@ private:
static constexpr uint16_t kIsLastFlag = 1 << 15;
static constexpr uint16_t kIndexMask = 0x7f;
- uint16_t GetFlagsIndex(void) const { return HostSwap16(mFlagsIndex); }
- void SetFlagsIndex(uint16_t aFlagsIndex) { mFlagsIndex = HostSwap16(aFlagsIndex); }
+ uint16_t GetFlagsIndex(void) const { return BigEndian::HostSwap16(mFlagsIndex); }
+ void SetFlagsIndex(uint16_t aFlagsIndex) { mFlagsIndex = BigEndian::HostSwap16(aFlagsIndex); }
uint16_t mFlagsIndex;
} OT_TOOL_PACKED_END;
diff --git a/src/core/thread/panid_query_server.cpp b/src/core/thread/panid_query_server.cpp
index 01df10af8..19c40c40c 100644
--- a/src/core/thread/panid_query_server.cpp
+++ b/src/core/thread/panid_query_server.cpp
@@ -37,9 +37,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "meshcop/meshcop.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "thread/thread_netif.hpp"
diff --git a/src/core/thread/radio_selector.cpp b/src/core/thread/radio_selector.cpp
index 965734a0c..ea7ea74de 100644
--- a/src/core/thread/radio_selector.cpp
+++ b/src/core/thread/radio_selector.cpp
@@ -36,10 +36,10 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/router.cpp b/src/core/thread/router.cpp
index c99fec132..d16d635e5 100644
--- a/src/core/thread/router.cpp
+++ b/src/core/thread/router.cpp
@@ -36,9 +36,9 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp
index b462c69ea..1302ce788 100644
--- a/src/core/thread/router_table.cpp
+++ b/src/core/thread/router_table.cpp
@@ -31,10 +31,10 @@
#if OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"
#include "thread/network_data_leader.hpp"
diff --git a/src/core/thread/src_match_controller.cpp b/src/core/thread/src_match_controller.cpp
index 2d73ce923..b53db1114 100644
--- a/src/core/thread/src_match_controller.cpp
+++ b/src/core/thread/src_match_controller.cpp
@@ -37,9 +37,9 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "radio/radio.hpp"
#include "thread/child.hpp"
diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp
index e01d19218..bba16dec6 100644
--- a/src/core/thread/thread_netif.cpp
+++ b/src/core/thread/thread_netif.cpp
@@ -35,9 +35,9 @@
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
diff --git a/src/core/thread/thread_tlvs.hpp b/src/core/thread/thread_tlvs.hpp
index 5b3bdb24a..db971fe40 100644
--- a/src/core/thread/thread_tlvs.hpp
+++ b/src/core/thread/thread_tlvs.hpp
@@ -46,9 +46,6 @@
namespace ot {
-using ot::Encoding::BigEndian::HostSwap16;
-using ot::Encoding::BigEndian::HostSwap32;
-
/**
* Implements Network Layer TLV generation and parsing.
*
diff --git a/src/core/thread/time_sync_service.cpp b/src/core/thread/time_sync_service.cpp
index 138c1aa74..77e3dd383 100644
--- a/src/core/thread/time_sync_service.cpp
+++ b/src/core/thread/time_sync_service.cpp
@@ -41,9 +41,9 @@
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/time.h>
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
#define ABS(value) (((value) >= 0) ? (value) : -(value))
diff --git a/src/core/utils/channel_manager.cpp b/src/core/utils/channel_manager.cpp
index 1303509f7..7ed7df486 100644
--- a/src/core/utils/channel_manager.cpp
+++ b/src/core/utils/channel_manager.cpp
@@ -37,11 +37,11 @@
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "meshcop/dataset_updater.hpp"
#include "radio/radio.hpp"
diff --git a/src/core/utils/flash.cpp b/src/core/utils/flash.cpp
index 243d7d505..f49e5f6ee 100644
--- a/src/core/utils/flash.cpp
+++ b/src/core/utils/flash.cpp
@@ -35,7 +35,7 @@
#include <openthread/platform/flash.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
namespace ot {
diff --git a/src/core/utils/history_tracker.cpp b/src/core/utils/history_tracker.cpp
index 2bcda12fd..74d8cfb85 100644
--- a/src/core/utils/history_tracker.cpp
+++ b/src/core/utils/history_tracker.cpp
@@ -38,11 +38,11 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/num_utils.hpp"
#include "common/string.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
diff --git a/src/core/utils/jam_detector.cpp b/src/core/utils/jam_detector.cpp
index a628fed6c..af55ba824 100644
--- a/src/core/utils/jam_detector.cpp
+++ b/src/core/utils/jam_detector.cpp
@@ -36,10 +36,10 @@
#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "thread/thread_netif.hpp"
namespace ot {
diff --git a/src/core/utils/link_metrics_manager.cpp b/src/core/utils/link_metrics_manager.cpp
index bbdac1b5d..ecb990ddc 100644
--- a/src/core/utils/link_metrics_manager.cpp
+++ b/src/core/utils/link_metrics_manager.cpp
@@ -85,6 +85,7 @@ Error LinkMetricsManager::GetLinkMetricsValueByExtAddr(const Mac::ExtAddress
subject = mSubjectList.FindMatching(aExtAddress);
VerifyOrExit(subject != nullptr, error = kErrorNotFound);
+ VerifyOrExit(subject->mState == kActive || subject->mState == kRenewing, error = kErrorInvalidState);
aMetricsValues.mLinkMarginValue = subject->mData.mLinkMargin;
aMetricsValues.mRssiValue = subject->mData.mRssi;
diff --git a/src/core/utils/link_metrics_manager.hpp b/src/core/utils/link_metrics_manager.hpp
index 9ab9ab331..098865e31 100644
--- a/src/core/utils/link_metrics_manager.hpp
+++ b/src/core/utils/link_metrics_manager.hpp
@@ -35,7 +35,7 @@
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE == 0
#error \
- "OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE can only be used when OPENTHREAD_CONFIG_LINK_METRICS_INITIATOR_ENABLE is true"
+ "OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE can only be used when OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE is true"
#endif
#include <openthread/link_metrics.h>
diff --git a/src/core/utils/mesh_diag.cpp b/src/core/utils/mesh_diag.cpp
index 60d78f15c..e21cb184c 100644
--- a/src/core/utils/mesh_diag.cpp
+++ b/src/core/utils/mesh_diag.cpp
@@ -38,9 +38,9 @@
#include "common/as_core_type.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Utils {
diff --git a/src/core/utils/ping_sender.cpp b/src/core/utils/ping_sender.cpp
index d1565ef78..b5fc75f4f 100644
--- a/src/core/utils/ping_sender.cpp
+++ b/src/core/utils/ping_sender.cpp
@@ -44,8 +44,6 @@
namespace ot {
namespace Utils {
-using Encoding::BigEndian::HostSwap32;
-
void PingSender::Config::SetUnspecifiedToDefault(void)
{
if (mSize == 0)
@@ -134,11 +132,12 @@ void PingSender::SendPing(void)
messageInfo.SetPeerAddr(mConfig.GetDestination());
messageInfo.mHopLimit = mConfig.mHopLimit;
messageInfo.mAllowZeroHopLimit = mConfig.mAllowZeroHopLimit;
+ messageInfo.mMulticastLoop = mConfig.mMulticastLoop;
message = Get<Ip6::Icmp>().NewMessage();
VerifyOrExit(message != nullptr);
- SuccessOrExit(message->Append(HostSwap32(now.GetValue())));
+ SuccessOrExit(message->Append(BigEndian::HostSwap32(now.GetValue())));
if (mConfig.mSize > message->GetLength())
{
@@ -202,7 +201,7 @@ void PingSender::HandleIcmpReceive(const Message &aMessage,
VerifyOrExit(aIcmpHeader.GetId() == mIdentifier);
SuccessOrExit(aMessage.Read(aMessage.GetOffset(), timestamp));
- timestamp = HostSwap32(timestamp);
+ timestamp = BigEndian::HostSwap32(timestamp);
reply.mSenderAddress = aMessageInfo.GetPeerAddr();
reply.mRoundTripTime = ClampToUint16(TimerMilli::GetNow() - TimeMilli(timestamp));
diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp
index ade19541c..7420bdf1a 100644
--- a/src/core/utils/slaac_address.cpp
+++ b/src/core/utils/slaac_address.cpp
@@ -37,12 +37,13 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"
+#include "common/numeric_limits.hpp"
#include "common/random.hpp"
#include "common/settings.hpp"
#include "crypto/sha256.hpp"
+#include "instance/instance.hpp"
#include "net/ip6_address.hpp"
namespace ot {
@@ -62,9 +63,10 @@ void Slaac::Enable(void)
{
VerifyOrExit(!mEnabled);
- LogInfo("Enabling");
mEnabled = true;
- Update(kModeAdd);
+ LogInfo("Enabled");
+
+ AddAddresses();
exit:
return;
@@ -74,15 +76,15 @@ void Slaac::Disable(void)
{
VerifyOrExit(mEnabled);
- LogInfo("Disabling");
+ RemoveAllAddresses();
+ LogInfo("Disabled");
mEnabled = false;
- Update(kModeRemove);
exit:
return;
}
-void Slaac::SetFilter(otIp6SlaacPrefixFilter aFilter)
+void Slaac::SetFilter(PrefixFilter aFilter)
{
VerifyOrExit(aFilter != mFilter);
@@ -90,26 +92,40 @@ void Slaac::SetFilter(otIp6SlaacPrefixFilter aFilter)
LogInfo("Filter %s", (mFilter != nullptr) ? "updated" : "disabled");
VerifyOrExit(mEnabled);
- Update(kModeAdd | kModeRemove);
+ RemoveAddresses();
+ AddAddresses();
exit:
return;
}
-bool Slaac::ShouldFilter(const Ip6::Prefix &aPrefix) const
+bool Slaac::ShouldUseForSlaac(const NetworkData::OnMeshPrefixConfig &aConfig) const
{
- return (mFilter != nullptr) && mFilter(&GetInstance(), &aPrefix);
+ bool shouldUse = false;
+
+ VerifyOrExit(aConfig.mSlaac && !aConfig.mDp);
+ VerifyOrExit(aConfig.GetPrefix().GetLength() == Ip6::NetworkPrefix::kLength);
+
+ if (mFilter != nullptr)
+ {
+ VerifyOrExit(!mFilter(&GetInstance(), &aConfig.GetPrefix()));
+ }
+
+ shouldUse = true;
+
+exit:
+ return shouldUse;
}
void Slaac::HandleNotifierEvents(Events aEvents)
{
- UpdateMode mode = kModeNone;
-
VerifyOrExit(mEnabled);
if (aEvents.Contains(kEventThreadNetdataChanged))
{
- mode |= kModeAdd | kModeRemove;
+ RemoveAddresses();
+ AddAddresses();
+ ExitNow();
}
if (aEvents.Contains(kEventIp6AddressRemoved))
@@ -123,12 +139,7 @@ void Slaac::HandleNotifierEvents(Events aEvents)
// prefix. So on IPv6 address removal event, we check if SLAAC module need
// to add any addresses.
- mode |= kModeAdd;
- }
-
- if (mode != kModeNone)
- {
- Update(mode);
+ AddAddresses();
}
exit:
@@ -143,122 +154,126 @@ bool Slaac::DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aCon
(aAddr.GetAddress().MatchesPrefix(aConfig.GetPrefix())));
}
-void Slaac::Update(UpdateMode aMode)
+void Slaac::RemoveAddresses(void)
{
- NetworkData::Iterator iterator;
- NetworkData::OnMeshPrefixConfig config;
- bool found;
+ // Remove any SLAAC addresses with no matching on-mesh prefix.
- if (aMode & kModeRemove)
+ for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
{
- // If enabled, remove any SLAAC addresses with no matching on-mesh prefix,
- // otherwise (when disabled) remove all previously added SLAAC addresses.
+ NetworkData::Iterator iterator;
+ NetworkData::OnMeshPrefixConfig config;
+ bool found = false;
- for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
+ if (!slaacAddr.mValid)
{
- if (!slaacAddr.mValid)
- {
- continue;
- }
+ continue;
+ }
- found = false;
+ iterator = NetworkData::kIteratorInit;
- if (mEnabled)
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
+ {
+ if (ShouldUseForSlaac(config) && DoesConfigMatchNetifAddr(config, slaacAddr))
{
- iterator = NetworkData::kIteratorInit;
-
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
- {
- if (config.mDp)
- {
- // Skip domain prefix which is processed in MLE.
- continue;
- }
-
- if (config.mSlaac && !ShouldFilter(config.GetPrefix()) &&
- DoesConfigMatchNetifAddr(config, slaacAddr))
- {
- found = true;
- break;
- }
- }
+ found = true;
+ break;
}
+ }
- if (!found)
- {
- LogInfo("Removing address %s", slaacAddr.GetAddress().ToString().AsCString());
-
- Get<ThreadNetif>().RemoveUnicastAddress(slaacAddr);
- slaacAddr.mValid = false;
- }
+ if (!found)
+ {
+ RemoveAddress(slaacAddr);
}
}
+}
- if ((aMode & kModeAdd) && mEnabled)
+void Slaac::RemoveAllAddresses(void)
+{
+ for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
{
- // Generate and add SLAAC addresses for any newly added on-mesh prefixes.
+ if (slaacAddr.mValid)
+ {
+ RemoveAddress(slaacAddr);
+ }
+ }
+}
- iterator = NetworkData::kIteratorInit;
+void Slaac::RemoveAddress(Ip6::Netif::UnicastAddress &aAddress)
+{
+ LogInfo("Removing %s", aAddress.GetAddress().ToString().AsCString());
- while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
- {
- Ip6::Prefix &prefix = config.GetPrefix();
+ Get<ThreadNetif>().RemoveUnicastAddress(aAddress);
+ aAddress.mValid = false;
+}
- if (config.mDp || !config.mSlaac || (prefix.GetLength() != Ip6::NetworkPrefix::kLength) ||
- ShouldFilter(prefix))
- {
- continue;
- }
+void Slaac::AddAddresses(void)
+{
+ NetworkData::Iterator iterator;
+ NetworkData::OnMeshPrefixConfig config;
+
+ // Generate and add SLAAC addresses for any newly added on-mesh prefixes.
- found = false;
+ iterator = NetworkData::kIteratorInit;
- for (const Ip6::Netif::UnicastAddress &netifAddr : Get<ThreadNetif>().GetUnicastAddresses())
+ while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
+ {
+ bool found = false;
+
+ if (!ShouldUseForSlaac(config))
+ {
+ continue;
+ }
+
+ for (const Ip6::Netif::UnicastAddress &netifAddr : Get<ThreadNetif>().GetUnicastAddresses())
+ {
+ if (DoesConfigMatchNetifAddr(config, netifAddr))
{
- if (DoesConfigMatchNetifAddr(config, netifAddr))
- {
- found = true;
- break;
- }
+ found = true;
+ break;
}
+ }
- if (!found)
- {
- bool added = false;
+ if (!found)
+ {
+ AddAddressFor(config);
+ }
+ }
+}
- for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
- {
- if (slaacAddr.mValid)
- {
- continue;
- }
+void Slaac::AddAddressFor(const NetworkData::OnMeshPrefixConfig &aConfig)
+{
+ Ip6::Netif::UnicastAddress *newAddress = nullptr;
+ uint8_t dadCounter = 0;
- slaacAddr.InitAsSlaacOrigin(config.mOnMesh ? prefix.mLength : 128, config.mPreferred);
- slaacAddr.GetAddress().SetPrefix(prefix);
+ for (Ip6::Netif::UnicastAddress &slaacAddr : mAddresses)
+ {
+ if (!slaacAddr.mValid)
+ {
+ newAddress = &slaacAddr;
+ break;
+ }
+ }
- IgnoreError(GenerateIid(slaacAddr));
+ if (newAddress == nullptr)
+ {
+ LogWarn("Failed to add - already have max %u addresses", kNumAddresses);
+ ExitNow();
+ }
- LogInfo("Adding address %s", slaacAddr.GetAddress().ToString().AsCString());
+ newAddress->InitAsSlaacOrigin(aConfig.mOnMesh ? aConfig.GetPrefix().mLength : 128, aConfig.mPreferred);
+ newAddress->GetAddress().SetPrefix(aConfig.GetPrefix());
- Get<ThreadNetif>().AddUnicastAddress(slaacAddr);
+ IgnoreError(GenerateIid(*newAddress, dadCounter));
- added = true;
- break;
- }
+ LogInfo("Adding address %s", newAddress->GetAddress().ToString().AsCString());
- if (!added)
- {
- LogWarn("Failed to add - max %d addresses supported and already in use",
- GetArrayLength(mAddresses));
- }
- }
- }
- }
+ Get<ThreadNetif>().AddUnicastAddress(*newAddress);
+
+exit:
+ return;
}
-Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
- uint8_t *aNetworkId,
- uint8_t aNetworkIdLength,
- uint8_t *aDadCounter) const
+Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress, uint8_t &aDadCounter) const
{
/*
* This method generates a semantically opaque IID per RFC 7217.
@@ -268,7 +283,7 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
* - RID is random (but stable) Identifier.
* - For pseudo-random function `F()` SHA-256 is used in this method.
* - `Net_Iface` is set to constant string "wpan".
- * - `Network_ID` is not used if `aNetworkId` is `nullptr` (optional per RF-7217).
+ * - `Network_ID` is not used (optional per RFC 7217).
* - The `secret_key` is randomly generated on first use (using true
* random number generator) and saved in non-volatile settings for
* future use.
@@ -277,7 +292,6 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
Error error = kErrorFailed;
const uint8_t netIface[] = {'w', 'p', 'a', 'n'};
- uint8_t dadCounter = aDadCounter ? *aDadCounter : 0;
IidSecretKey secretKey;
Crypto::Sha256 sha256;
Crypto::Sha256::Hash hash;
@@ -287,18 +301,13 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
GetIidSecretKey(secretKey);
- for (uint16_t count = 0; count < kMaxIidCreationAttempts; count++, dadCounter++)
+ for (uint16_t count = 0; count < kMaxIidCreationAttempts; count++, aDadCounter++)
{
sha256.Start();
- sha256.Update(aAddress.mAddress.mFields.m8, BitVectorBytes(aAddress.mPrefixLength));
-
- if (aNetworkId)
- {
- sha256.Update(aNetworkId, aNetworkIdLength);
- }
+ sha256.Update(aAddress.mAddress.mFields.m8, BytesForBitSize(aAddress.mPrefixLength));
sha256.Update(netIface);
- sha256.Update(dadCounter);
+ sha256.Update(aDadCounter);
sha256.Update(secretKey);
sha256.Finish(hash);
@@ -310,11 +319,6 @@ Error Slaac::GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
continue;
}
- if (aDadCounter)
- {
- *aDadCounter = dadCounter;
- }
-
// Exit and return the address if the IID is not reserved,
ExitNow(error = kErrorNone);
}
diff --git a/src/core/utils/slaac_address.hpp b/src/core/utils/slaac_address.hpp
index 3e73f1920..99feca2fc 100644
--- a/src/core/utils/slaac_address.hpp
+++ b/src/core/utils/slaac_address.hpp
@@ -65,6 +65,8 @@ class Slaac : public InstanceLocator, private NonCopyable
friend class ot::Notifier;
public:
+ typedef otIp6SlaacPrefixFilter PrefixFilter; ///< Prefix filter function pointer.
+
/**
* Represents the secret key used for generating semantically opaque IID (per RFC 7217).
*
@@ -120,8 +122,10 @@ public:
*
* The filter can be set to `nullptr` to disable filtering (i.e., allow SLAAC addresses for all prefixes).
*
+ * @param[in] aFilter The filter to use.
+ *
*/
- void SetFilter(otIp6SlaacPrefixFilter aFilter);
+ void SetFilter(PrefixFilter aFilter);
/**
* Generates the IID of an IPv6 address.
@@ -129,45 +133,34 @@ public:
* @param[in,out] aAddress A reference to the address that will be filled with the IID generated.
* Note the prefix of the address must already be filled and will be used
* to generate the IID.
- * @param[in] aNetworkId A pointer to a byte array of Network_ID to generate IID.
- * @param[in] aNetworkIdLength The size of array @p aNetworkId.
- * @param[in,out] aDadCounter A pointer to the DAD_Counter that is employed to resolve Duplicate
- * Address Detection conflicts.
+ * @param[in,out] aDadCounter The DAD_Counter that is employed to resolve Duplicate Address Detection
+ * conflicts.
*
* @retval kErrorNone If successfully generated the IID.
* @retval kErrorFailed If no valid IID was generated.
*
*/
- Error GenerateIid(Ip6::Netif::UnicastAddress &aAddress,
- uint8_t *aNetworkId = nullptr,
- uint8_t aNetworkIdLength = 0,
- uint8_t *aDadCounter = nullptr) const;
+ Error GenerateIid(Ip6::Netif::UnicastAddress &aAddress, uint8_t &aDadCounter) const;
private:
- static constexpr uint16_t kMaxIidCreationAttempts = 256; // Maximum number of attempts when generating IID.
-
- typedef uint8_t UpdateMode;
+ static constexpr uint16_t kNumAddresses = OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES;
- // Values for `UpdateMode` input parameter in `Update()`.
-
- static constexpr UpdateMode kModeNone = 0x0; // No action.
- static constexpr UpdateMode kModeAdd = 1 << 0; // Add new SLAAC addresses for new prefixes in network data.
-
- // Remove SLAAC addresses.
- // - When SLAAC is enabled, remove addresses with no matching prefix in network data,
- // - When SLAAC is disabled, remove all previously added addresses.
- static constexpr UpdateMode kModeRemove = 1 << 1;
+ static constexpr uint16_t kMaxIidCreationAttempts = 256; // Maximum number of attempts when generating IID.
- bool ShouldFilter(const Ip6::Prefix &aPrefix) const;
- void Update(UpdateMode aMode);
+ bool ShouldUseForSlaac(const NetworkData::OnMeshPrefixConfig &aConfig) const;
+ void RemoveAddresses(void);
+ void RemoveAllAddresses(void);
+ void AddAddresses(void);
+ void RemoveAddress(Ip6::Netif::UnicastAddress &aAddress);
+ void AddAddressFor(const NetworkData::OnMeshPrefixConfig &aConfig);
void GetIidSecretKey(IidSecretKey &aKey) const;
void HandleNotifierEvents(Events aEvents);
static bool DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aConfig,
const Ip6::Netif::UnicastAddress &aAddr);
bool mEnabled;
- otIp6SlaacPrefixFilter mFilter;
- Ip6::Netif::UnicastAddress mAddresses[OPENTHREAD_CONFIG_IP6_SLAAC_NUM_ADDRESSES];
+ PrefixFilter mFilter;
+ Ip6::Netif::UnicastAddress mAddresses[kNumAddresses];
};
/**
diff --git a/src/core/utils/srp_client_buffers.cpp b/src/core/utils/srp_client_buffers.cpp
index cfead0ac2..098e7ea54 100644
--- a/src/core/utils/srp_client_buffers.cpp
+++ b/src/core/utils/srp_client_buffers.cpp
@@ -38,8 +38,8 @@
#include <string.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/locator_getters.hpp"
+#include "instance/instance.hpp"
namespace ot {
namespace Utils {
diff --git a/src/lib/platform/BUILD.gn b/src/lib/platform/BUILD.gn
index c46831e0b..49525340f 100644
--- a/src/lib/platform/BUILD.gn
+++ b/src/lib/platform/BUILD.gn
@@ -38,5 +38,6 @@ config("platform_config") {
static_library("libopenthread-platform") {
sources = platform_sources
+ public_deps = [ "../../core:libopenthread_core_headers" ]
public_configs = [ ":platform_config" ]
}
diff --git a/src/lib/platform/exit_code.h b/src/lib/platform/exit_code.h
index 4aef8bdd2..ee9e7d237 100644
--- a/src/lib/platform/exit_code.h
+++ b/src/lib/platform/exit_code.h
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <string.h>
+#include <openthread/logging.h>
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/src/lib/spinel/CMakeLists.txt b/src/lib/spinel/CMakeLists.txt
index de68fc25a..e6cf16f58 100644
--- a/src/lib/spinel/CMakeLists.txt
+++ b/src/lib/spinel/CMakeLists.txt
@@ -26,27 +26,22 @@
# POSSIBILITY OF SUCH DAMAGE.
#
+add_library(openthread-radio-spinel)
add_library(openthread-spinel-ncp)
add_library(openthread-spinel-rcp)
target_compile_definitions(openthread-spinel-ncp PRIVATE
- OPENTHREAD_FTD=1
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
-if (OT_NCP_SPI)
- target_compile_definitions(openthread-spinel-ncp PRIVATE OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=0)
- target_compile_definitions(openthread-spinel-rcp PRIVATE OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=0)
-else()
- target_compile_definitions(openthread-spinel-ncp PRIVATE OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1)
- target_compile_definitions(openthread-spinel-rcp PRIVATE OPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1)
-endif()
-
target_compile_definitions(openthread-spinel-rcp PRIVATE
- OPENTHREAD_RADIO=1
PUBLIC OPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=0
)
+target_compile_options(openthread-radio-spinel PRIVATE
+ ${OT_CFLAGS}
+)
+
target_compile_options(openthread-spinel-ncp PRIVATE
${OT_CFLAGS}
)
@@ -61,19 +56,25 @@ set(COMMON_INCLUDES
)
set(COMMON_SOURCES
- radio_spinel.cpp
spinel.c
spinel_buffer.cpp
spinel_decoder.cpp
spinel_encoder.cpp
)
+target_include_directories(openthread-radio-spinel PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
target_include_directories(openthread-spinel-ncp PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
target_include_directories(openthread-spinel-rcp PUBLIC ${OT_PUBLIC_INCLUDES} PRIVATE ${COMMON_INCLUDES})
+target_sources(openthread-radio-spinel PRIVATE radio_spinel.cpp)
target_sources(openthread-spinel-ncp PRIVATE ${COMMON_SOURCES})
target_sources(openthread-spinel-rcp PRIVATE ${COMMON_SOURCES})
+target_link_libraries(openthread-radio-spinel
+ PRIVATE
+ ot-config
+)
+
target_link_libraries(openthread-spinel-ncp
PRIVATE
ot-config-ftd
diff --git a/src/lib/spinel/multi_frame_buffer.hpp b/src/lib/spinel/multi_frame_buffer.hpp
index 2c90d9069..ab1ef835b 100644
--- a/src/lib/spinel/multi_frame_buffer.hpp
+++ b/src/lib/spinel/multi_frame_buffer.hpp
@@ -267,7 +267,7 @@ public:
if (mWriteFrameStart + kHeaderSize + aSkipLength <= GetArrayEnd(mBuffer))
{
- Encoding::LittleEndian::WriteUint16(aSkipLength, mWriteFrameStart + kHeaderSkipLengthOffset);
+ LittleEndian::WriteUint16(aSkipLength, mWriteFrameStart + kHeaderSkipLengthOffset);
mWritePointer = GetFrame();
mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer);
error = OT_ERROR_NONE;
@@ -282,10 +282,7 @@ public:
* @returns The length (number of bytes) of the reserved buffer.
*
*/
- uint16_t GetSkipLength(void) const
- {
- return Encoding::LittleEndian::ReadUint16(mWriteFrameStart + kHeaderSkipLengthOffset);
- }
+ uint16_t GetSkipLength(void) const { return LittleEndian::ReadUint16(mWriteFrameStart + kHeaderSkipLengthOffset); }
/**
* Gets a pointer to the start of the current frame.
@@ -323,8 +320,7 @@ public:
}
else
{
- Encoding::LittleEndian::WriteUint16(GetSkipLength() + GetLength(),
- mWriteFrameStart + kHeaderTotalLengthOffset);
+ LittleEndian::WriteUint16(GetSkipLength() + GetLength(), mWriteFrameStart + kHeaderTotalLengthOffset);
mWriteFrameStart = mWritePointer;
IgnoreError(SetSkipLength(0));
}
@@ -377,8 +373,8 @@ public:
if (aFrame != mWriteFrameStart)
{
- uint16_t totalLength = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderTotalLengthOffset);
- uint16_t skipLength = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderSkipLengthOffset);
+ uint16_t totalLength = LittleEndian::ReadUint16(aFrame + kHeaderTotalLengthOffset);
+ uint16_t skipLength = LittleEndian::ReadUint16(aFrame + kHeaderSkipLengthOffset);
aLength = totalLength - skipLength;
aFrame += kHeaderSize + skipLength;
diff --git a/src/lib/spinel/openthread-spinel-config.h b/src/lib/spinel/openthread-spinel-config.h
index 086a75842..6b3316ac1 100644
--- a/src/lib/spinel/openthread-spinel-config.h
+++ b/src/lib/spinel/openthread-spinel-config.h
@@ -78,4 +78,15 @@
#ifndef OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL
#define OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL (60 * 1000 * 1000)
#endif
+
+/**
+ * @def OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID
+ *
+ * Define broadcast IID for spinel frames dedicated to all hosts in multipan configuration.
+ *
+ */
+#ifndef OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID
+#define OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID SPINEL_HEADER_IID_3
+#endif
+
#endif // OPENTHREAD_SPINEL_CONFIG_H_
diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp
index e933874e7..2cd1deaff 100644
--- a/src/lib/spinel/radio_spinel.cpp
+++ b/src/lib/spinel/radio_spinel.cpp
@@ -51,6 +51,35 @@
namespace ot {
namespace Spinel {
+char RadioSpinel::sVersion[kVersionStringSize] = "";
+
+otExtAddress RadioSpinel::sIeeeEui64;
+
+bool RadioSpinel::sIsReady = false; ///< NCP ready.
+
+bool RadioSpinel::sSupportsLogStream =
+ false; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
+
+bool RadioSpinel::sSupportsResetToBootloader = false; ///< RCP supports resetting into bootloader mode.
+
+otRadioCaps RadioSpinel::sRadioCaps = OT_RADIO_CAPS_NONE;
+
+inline bool RadioSpinel::IsFrameForUs(spinel_iid_t aIid)
+{
+ bool found = false;
+
+ for (spinel_iid_t iid : mIidList)
+ {
+ if (aIid == iid)
+ {
+ ExitNow(found = true);
+ }
+ }
+
+exit:
+ return found;
+}
+
RadioSpinel::RadioSpinel(void)
: mInstance(nullptr)
, mSpinelInterface(nullptr)
@@ -62,19 +91,19 @@ RadioSpinel::RadioSpinel(void)
, mPropertyFormat(nullptr)
, mExpectedCommand(0)
, mError(OT_ERROR_NONE)
+ , mIid(SPINEL_HEADER_INVALID_IID)
, mTransmitFrame(nullptr)
, mShortAddress(0)
, mPanId(0xffff)
- , mRadioCaps(0)
, mChannel(0)
, mRxSensitivity(0)
, mState(kStateDisabled)
, mIsPromiscuous(false)
- , mIsReady(false)
- , mSupportsLogStream(false)
+ , mRxOnWhenIdle(true)
, mIsTimeSynced(false)
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
, mRcpFailureCount(0)
+ , mRcpFailure(kRcpFailureNone)
, mSrcMatchShortEntryCount(0)
, mSrcMatchExtEntryCount(0)
, mMacKeySet(false)
@@ -82,7 +111,6 @@ RadioSpinel::RadioSpinel(void)
, mTransmitPowerSet(false)
, mCoexEnabledSet(false)
, mFemLnaGainSet(false)
- , mRcpFailed(false)
, mEnergyScanning(false)
, mMacFrameCounterSet(false)
#endif
@@ -95,11 +123,16 @@ RadioSpinel::RadioSpinel(void)
, mRadioTimeRecalcStart(UINT64_MAX)
, mRadioTimeOffset(UINT64_MAX)
{
- mVersion[0] = '\0';
+ memset(mIidList, SPINEL_HEADER_INVALID_IID, sizeof(mIidList));
memset(&mRadioSpinelMetrics, 0, sizeof(mRadioSpinelMetrics));
+ memset(&mCallbacks, 0, sizeof(mCallbacks));
}
-void RadioSpinel::Init(SpinelInterface &aSpinelInterface, bool aResetRadio, bool aSkipRcpCompatibilityCheck)
+void RadioSpinel::Init(SpinelInterface &aSpinelInterface,
+ bool aResetRadio,
+ bool aSkipRcpCompatibilityCheck,
+ const spinel_iid_t *aIidList,
+ uint8_t aIidListLength)
{
otError error = OT_ERROR_NONE;
bool supportsRcpApiVersion;
@@ -112,10 +145,16 @@ void RadioSpinel::Init(SpinelInterface &aSpinelInterface, bool aResetRadio, bool
mSpinelInterface = &aSpinelInterface;
SuccessOrDie(mSpinelInterface->Init(HandleReceivedFrame, this, mRxFrameBuffer));
+ VerifyOrDie(aIidList != nullptr, OT_EXIT_INVALID_ARGUMENTS);
+ VerifyOrDie(aIidListLength != 0 && aIidListLength <= OT_ARRAY_LENGTH(mIidList), OT_EXIT_INVALID_ARGUMENTS);
+ mIid = aIidList[0];
+ memset(mIidList, SPINEL_HEADER_INVALID_IID, sizeof(mIidList));
+ memcpy(mIidList, aIidList, aIidListLength * sizeof(spinel_iid_t));
+
ResetRcp(aResetRadio);
SuccessOrExit(error = CheckSpinelVersion());
- SuccessOrExit(error = Get(SPINEL_PROP_NCP_VERSION, SPINEL_DATATYPE_UTF8_S, mVersion, sizeof(mVersion)));
- SuccessOrExit(error = Get(SPINEL_PROP_HWADDR, SPINEL_DATATYPE_EUI64_S, mIeeeEui64.m8));
+ SuccessOrExit(error = Get(SPINEL_PROP_NCP_VERSION, SPINEL_DATATYPE_UTF8_S, sVersion, sizeof(sVersion)));
+ SuccessOrExit(error = Get(SPINEL_PROP_HWADDR, SPINEL_DATATYPE_EUI64_S, sIeeeEui64.m8));
VerifyOrDie(IsRcp(supportsRcpApiVersion, supportsRcpMinHostApiVersion), OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
@@ -133,17 +172,35 @@ exit:
SuccessOrDie(error);
}
+void RadioSpinel::SetCallbacks(const struct RadioSpinelCallbacks &aCallbacks)
+{
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+ assert(aCallbacks.mDiagReceiveDone != nullptr);
+ assert(aCallbacks.mDiagTransmitDone != nullptr);
+#endif
+ assert(aCallbacks.mEnergyScanDone != nullptr);
+ assert(aCallbacks.mReceiveDone != nullptr);
+ assert(aCallbacks.mTransmitDone != nullptr);
+ assert(aCallbacks.mTxStarted != nullptr);
+
+ mCallbacks = aCallbacks;
+}
+
void RadioSpinel::ResetRcp(bool aResetRadio)
{
bool hardwareReset;
bool resetDone = false;
- mIsReady = false;
+ // Avoid resetting the device twice in a row in Multipan RCP architecture
+ VerifyOrExit(!sIsReady, resetDone = true);
+
mWaitingKey = SPINEL_PROP_LAST_STATUS;
- if (aResetRadio && (SendReset(SPINEL_RESET_STACK) == OT_ERROR_NONE) && (WaitResponse(false) == OT_ERROR_NONE))
+ if (aResetRadio && (SendReset(SPINEL_RESET_STACK) == OT_ERROR_NONE) && (!sIsReady) &&
+ (WaitResponse(false) == OT_ERROR_NONE))
{
- otLogInfoPlat("Software reset RCP successfully");
+ VerifyOrExit(sIsReady, resetDone = false);
+ LogInfo("Software reset RCP successfully");
ExitNow(resetDone = true);
}
@@ -158,17 +215,17 @@ void RadioSpinel::ResetRcp(bool aResetRadio)
if (hardwareReset)
{
- otLogInfoPlat("Hardware reset RCP successfully");
+ LogInfo("Hardware reset RCP successfully");
}
else
{
- otLogInfoPlat("RCP self reset successfully");
+ LogInfo("RCP self reset successfully");
}
exit:
if (!resetDone)
{
- otLogCritPlat("Failed to reset RCP!");
+ LogCrit("Failed to reset RCP!");
DieNow(OT_EXIT_FAILURE);
}
}
@@ -186,8 +243,8 @@ otError RadioSpinel::CheckSpinelVersion(void)
if ((versionMajor != SPINEL_PROTOCOL_VERSION_THREAD_MAJOR) ||
(versionMinor != SPINEL_PROTOCOL_VERSION_THREAD_MINOR))
{
- otLogCritPlat("Spinel version mismatch - Posix:%d.%d, RCP:%d.%d", SPINEL_PROTOCOL_VERSION_THREAD_MAJOR,
- SPINEL_PROTOCOL_VERSION_THREAD_MINOR, versionMajor, versionMinor);
+ LogCrit("Spinel version mismatch - Posix:%d.%d, RCP:%d.%d", SPINEL_PROTOCOL_VERSION_THREAD_MAJOR,
+ SPINEL_PROTOCOL_VERSION_THREAD_MINOR, versionMajor, versionMinor);
DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
}
@@ -228,7 +285,7 @@ bool RadioSpinel::IsRcp(bool &aSupportsRcpApiVersion, bool &aSupportsRcpMinHostA
if (capability == SPINEL_CAP_OPENTHREAD_LOG_METADATA)
{
- mSupportsLogStream = true;
+ sSupportsLogStream = true;
}
if (capability == SPINEL_CAP_RCP_API_VERSION)
@@ -236,6 +293,11 @@ bool RadioSpinel::IsRcp(bool &aSupportsRcpApiVersion, bool &aSupportsRcpMinHostA
aSupportsRcpApiVersion = true;
}
+ if (capability == SPINEL_CAP_RCP_RESET_TO_BOOTLOADER)
+ {
+ sSupportsResetToBootloader = true;
+ }
+
if (capability == SPINEL_PROP_RCP_MIN_HOST_API_VERSION)
{
aSupportsRcpMinHostApiVersion = true;
@@ -247,7 +309,7 @@ bool RadioSpinel::IsRcp(bool &aSupportsRcpApiVersion, bool &aSupportsRcpMinHostA
if (!supportsRawRadio && isRcp)
{
- otLogCritPlat("RCP capability list does not include support for radio/raw mode");
+ LogCrit("RCP capability list does not include support for radio/raw mode");
DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
}
@@ -266,22 +328,22 @@ otError RadioSpinel::CheckRadioCapabilities(void)
unsigned int radioCaps;
SuccessOrExit(error = Get(SPINEL_PROP_RADIO_CAPS, SPINEL_DATATYPE_UINT_PACKED_S, &radioCaps));
- mRadioCaps = static_cast<otRadioCaps>(radioCaps);
+ sRadioCaps = static_cast<otRadioCaps>(radioCaps);
- if ((mRadioCaps & kRequiredRadioCaps) != kRequiredRadioCaps)
+ if ((sRadioCaps & kRequiredRadioCaps) != kRequiredRadioCaps)
{
- otRadioCaps missingCaps = (mRadioCaps & kRequiredRadioCaps) ^ kRequiredRadioCaps;
+ otRadioCaps missingCaps = (sRadioCaps & kRequiredRadioCaps) ^ kRequiredRadioCaps;
- // missingCaps may be an unused variable when otLogCritPlat is blank
+ // missingCaps may be an unused variable when LogCrit is blank
// avoid compiler warning in that case
OT_UNUSED_VARIABLE(missingCaps);
- otLogCritPlat("RCP is missing required capabilities: %s%s%s%s%s",
- (missingCaps & OT_RADIO_CAPS_ACK_TIMEOUT) ? "ack-timeout " : "",
- (missingCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) ? "tx-retries " : "",
- (missingCaps & OT_RADIO_CAPS_CSMA_BACKOFF) ? "CSMA-backoff " : "",
- (missingCaps & OT_RADIO_CAPS_TRANSMIT_SEC) ? "tx-security " : "",
- (missingCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) ? "tx-timing " : "");
+ LogCrit("RCP is missing required capabilities: %s%s%s%s%s",
+ (missingCaps & OT_RADIO_CAPS_ACK_TIMEOUT) ? "ack-timeout " : "",
+ (missingCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) ? "tx-retries " : "",
+ (missingCaps & OT_RADIO_CAPS_CSMA_BACKOFF) ? "CSMA-backoff " : "",
+ (missingCaps & OT_RADIO_CAPS_TRANSMIT_SEC) ? "tx-security " : "",
+ (missingCaps & OT_RADIO_CAPS_TRANSMIT_TIMING) ? "tx-timing " : "");
DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
}
@@ -308,9 +370,9 @@ otError RadioSpinel::CheckRcpApiVersion(bool aSupportsRcpApiVersion, bool aSuppo
if (rcpApiVersion < SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION)
{
- otLogCritPlat("RCP and host are using incompatible API versions");
- otLogCritPlat("RCP API Version %u is older than min required by host %u", rcpApiVersion,
- SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION);
+ LogCrit("RCP and host are using incompatible API versions");
+ LogCrit("RCP API Version %u is older than min required by host %u", rcpApiVersion,
+ SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION);
DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
}
}
@@ -328,9 +390,9 @@ otError RadioSpinel::CheckRcpApiVersion(bool aSupportsRcpApiVersion, bool aSuppo
if (SPINEL_RCP_API_VERSION < minHostRcpApiVersion)
{
- otLogCritPlat("RCP and host are using incompatible API versions");
- otLogCritPlat("RCP requires min host API version %u but host is older and at version %u",
- minHostRcpApiVersion, SPINEL_RCP_API_VERSION);
+ LogCrit("RCP and host are using incompatible API versions");
+ LogCrit("RCP requires min host API version %u but host is older and at version %u", minHostRcpApiVersion,
+ SPINEL_RCP_API_VERSION);
DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE);
}
}
@@ -348,6 +410,7 @@ void RadioSpinel::Deinit(void)
}
// This allows implementing pseudo reset.
+ sIsReady = false;
new (this) RadioSpinel();
}
@@ -362,9 +425,16 @@ void RadioSpinel::HandleReceivedFrame(void)
LogSpinelFrame(mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetLength(), false);
unpacked = spinel_datatype_unpack(mRxFrameBuffer.GetFrame(), mRxFrameBuffer.GetLength(), "C", &header);
- VerifyOrExit(unpacked > 0 && (header & SPINEL_HEADER_FLAG) == SPINEL_HEADER_FLAG &&
- SPINEL_HEADER_GET_IID(header) == 0,
- error = OT_ERROR_PARSE);
+ // Accept spinel messages with the correct IID or broadcast IID.
+ spinel_iid_t iid = SPINEL_HEADER_GET_IID(header);
+
+ if (!IsFrameForUs(iid))
+ {
+ mRxFrameBuffer.DiscardFrame();
+ ExitNow();
+ }
+
+ VerifyOrExit(unpacked > 0 && (header & SPINEL_HEADER_FLAG) == SPINEL_HEADER_FLAG, error = OT_ERROR_PARSE);
if (SPINEL_HEADER_GET_TID(header) == 0)
{
@@ -380,7 +450,7 @@ exit:
if (error != OT_ERROR_NONE)
{
mRxFrameBuffer.DiscardFrame();
- otLogWarnPlat("Error handling hdlc frame: %s", otThreadErrorToString(error));
+ LogWarn("Error handling hdlc frame: %s", otThreadErrorToString(error));
}
UpdateParseErrorCount(error);
@@ -419,7 +489,7 @@ void RadioSpinel::HandleNotification(SpinelInterface::RxFrameBuffer &aFrameBuffe
case SPINEL_CMD_PROP_VALUE_INSERTED:
case SPINEL_CMD_PROP_VALUE_REMOVED:
- otLogInfoPlat("Ignored command %lu", ToUlong(cmd));
+ LogInfo("Ignored command %lu", ToUlong(cmd));
break;
default:
@@ -433,7 +503,7 @@ exit:
if (shouldSaveFrame)
{
- otLogCritPlat("RX Spinel buffer full, dropped incoming frame");
+ LogCrit("RX Spinel buffer full, dropped incoming frame");
}
}
@@ -494,7 +564,7 @@ void RadioSpinel::HandleResponse(const uint8_t *aBuffer, uint16_t aLength)
}
else
{
- otLogWarnPlat("Unexpected Spinel transaction message: %u", SPINEL_HEADER_GET_TID(header));
+ LogWarn("Unexpected Spinel transaction message: %u", SPINEL_HEADER_GET_TID(header));
error = OT_ERROR_DROP;
}
@@ -596,12 +666,19 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
ExitNow();
}
- otLogInfoPlat("RCP reset: %s", spinel_status_to_cstr(status));
- mIsReady = true;
+ LogInfo("RCP reset: %s", spinel_status_to_cstr(status));
+ sIsReady = true;
+ }
+ else if (status == SPINEL_STATUS_SWITCHOVER_DONE || status == SPINEL_STATUS_SWITCHOVER_FAILED)
+ {
+ if (mCallbacks.mSwitchoverDone != nullptr)
+ {
+ mCallbacks.mSwitchoverDone(mInstance, status == SPINEL_STATUS_SWITCHOVER_DONE);
+ }
}
else
{
- otLogInfoPlat("RCP last status: %s", spinel_status_to_cstr(status));
+ LogInfo("RCP last status: %s", spinel_status_to_cstr(status));
}
}
else if (aKey == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT)
@@ -617,7 +694,7 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
mEnergyScanning = false;
#endif
- otPlatRadioEnergyScanDone(mInstance, maxRssi);
+ mCallbacks.mEnergyScanDone(mInstance, maxRssi);
}
else if (aKey == SPINEL_PROP_STREAM_DEBUG)
{
@@ -628,9 +705,9 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
assert(len < sizeof(logStream));
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
logStream[len] = '\0';
- otLogDebgPlat("RCP => %s", logStream);
+ LogDebg("RCP => %s", logStream);
}
- else if ((aKey == SPINEL_PROP_STREAM_LOG) && mSupportsLogStream)
+ else if ((aKey == SPINEL_PROP_STREAM_LOG) && sSupportsLogStream)
{
const char *logString;
uint8_t logLevel;
@@ -648,25 +725,25 @@ void RadioSpinel::HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer,
case SPINEL_NCP_LOG_LEVEL_EMERG:
case SPINEL_NCP_LOG_LEVEL_ALERT:
case SPINEL_NCP_LOG_LEVEL_CRIT:
- otLogCritPlat("RCP => %s", logString);
+ LogCrit("RCP => %s", logString);
break;
case SPINEL_NCP_LOG_LEVEL_ERR:
case SPINEL_NCP_LOG_LEVEL_WARN:
- otLogWarnPlat("RCP => %s", logString);
+ LogWarn("RCP => %s", logString);
break;
case SPINEL_NCP_LOG_LEVEL_NOTICE:
- otLogNotePlat("RCP => %s", logString);
+ LogNote("RCP => %s", logString);
break;
case SPINEL_NCP_LOG_LEVEL_INFO:
- otLogInfoPlat("RCP => %s", logString);
+ LogInfo("RCP => %s", logString);
break;
case SPINEL_NCP_LOG_LEVEL_DEBUG:
default:
- otLogDebgPlat("RCP => %s", logString);
+ LogDebg("RCP => %s", logString);
break;
}
}
@@ -712,7 +789,7 @@ otError RadioSpinel::ParseRadioFrame(otRadioFrame &aFrame,
aBuffer += unpacked;
aLength -= static_cast<uint16_t>(unpacked);
- if (mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC)
+ if (sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC)
{
unpacked =
spinel_datatype_unpack_in_place(aBuffer, aLength,
@@ -789,14 +866,13 @@ void RadioSpinel::RadioReceive(void)
#if OPENTHREAD_CONFIG_DIAG_ENABLE
if (otPlatDiagModeGet())
{
- otPlatDiagRadioReceiveDone(mInstance, &mRxRadioFrame, OT_ERROR_NONE);
+ mCallbacks.mDiagReceiveDone(mInstance, &mRxRadioFrame, OT_ERROR_NONE);
}
else
#endif
{
- otPlatRadioReceiveDone(mInstance, &mRxRadioFrame, OT_ERROR_NONE);
+ mCallbacks.mReceiveDone(mInstance, &mRxRadioFrame, OT_ERROR_NONE);
}
-
exit:
return;
}
@@ -806,12 +882,12 @@ void RadioSpinel::TransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, ot
#if OPENTHREAD_CONFIG_DIAG_ENABLE
if (otPlatDiagModeGet())
{
- otPlatDiagRadioTransmitDone(mInstance, aFrame, aError);
+ mCallbacks.mDiagTransmitDone(mInstance, aFrame, aError);
}
else
#endif
{
- otPlatRadioTxDone(mInstance, aFrame, aAckFrame, aError);
+ mCallbacks.mTransmitDone(mInstance, aFrame, aAckFrame, aError);
}
}
@@ -827,7 +903,7 @@ void RadioSpinel::ProcessRadioStateMachine(void)
else if (mState == kStateTransmitting && otPlatTimeGet() >= mTxRadioEndUs)
{
// Frame has been successfully passed to radio, but no `TransmitDone` event received within kTxWaitUs.
- otLogWarnPlat("radio tx timeout");
+ LogWarn("radio tx timeout");
HandleRcpTimeout();
}
}
@@ -866,6 +942,18 @@ exit:
return error;
}
+otError RadioSpinel::SetRxOnWhenIdle(bool aEnable)
+{
+ otError error = OT_ERROR_NONE;
+
+ VerifyOrExit(mRxOnWhenIdle != aEnable);
+ SuccessOrExit(error = Set(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, SPINEL_DATATYPE_BOOL_S, aEnable));
+ mRxOnWhenIdle = aEnable;
+
+exit:
+ return error;
+}
+
otError RadioSpinel::SetShortAddress(uint16_t aAddress)
{
otError error = OT_ERROR_NONE;
@@ -878,41 +966,76 @@ exit:
return error;
}
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
+otError RadioSpinel::ReadMacKey(const otMacKeyMaterial &aKeyMaterial, otMacKey &aKey)
+{
+ size_t keySize;
+ otError error = otPlatCryptoExportKey(aKeyMaterial.mKeyMaterial.mKeyRef, aKey.m8, sizeof(aKey), &keySize);
+
+ SuccessOrExit(error);
+ VerifyOrExit(keySize == sizeof(otMacKey), error = OT_ERROR_FAILED);
+
+exit:
+ return error;
+}
+
otError RadioSpinel::SetMacKey(uint8_t aKeyIdMode,
uint8_t aKeyId,
const otMacKeyMaterial *aPrevKey,
const otMacKeyMaterial *aCurrKey,
const otMacKeyMaterial *aNextKey)
{
- otError error;
- size_t aKeySize;
+ otError error;
+ otMacKey prevKey;
+ otMacKey currKey;
+ otMacKey nextKey;
- VerifyOrExit((aPrevKey != nullptr) && (aCurrKey != nullptr) && (aNextKey != nullptr), error = kErrorInvalidArgs);
+ SuccessOrExit(error = ReadMacKey(*aPrevKey, prevKey));
+ SuccessOrExit(error = ReadMacKey(*aCurrKey, currKey));
+ SuccessOrExit(error = ReadMacKey(*aNextKey, nextKey));
+ error = SetMacKey(aKeyIdMode, aKeyId, prevKey, currKey, nextKey);
+
+exit:
+ return error;
+}
-#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
- SuccessOrExit(error = otPlatCryptoExportKey(aPrevKey->mKeyMaterial.mKeyRef, aPrevKey->mKeyMaterial.mKey.m8,
- sizeof(aPrevKey->mKeyMaterial.mKey.m8), &aKeySize));
- SuccessOrExit(error = otPlatCryptoExportKey(aCurrKey->mKeyMaterial.mKeyRef, aCurrKey->mKeyMaterial.mKey.m8,
- sizeof(aCurrKey->mKeyMaterial.mKey.m8), &aKeySize));
- SuccessOrExit(error = otPlatCryptoExportKey(aNextKey->mKeyMaterial.mKeyRef, aNextKey->mKeyMaterial.mKey.m8,
- sizeof(aNextKey->mKeyMaterial.mKey.m8), &aKeySize));
#else
- OT_UNUSED_VARIABLE(aKeySize);
-#endif
+
+otError RadioSpinel::SetMacKey(uint8_t aKeyIdMode,
+ uint8_t aKeyId,
+ const otMacKeyMaterial *aPrevKey,
+ const otMacKeyMaterial *aCurrKey,
+ const otMacKeyMaterial *aNextKey)
+{
+ return SetMacKey(aKeyIdMode, aKeyId, aPrevKey->mKeyMaterial.mKey, aCurrKey->mKeyMaterial.mKey,
+ aNextKey->mKeyMaterial.mKey);
+}
+
+#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
+otError RadioSpinel::SetMacKey(uint8_t aKeyIdMode,
+ uint8_t aKeyId,
+ const otMacKey &aPrevKey,
+ const otMacKey &aCurrKey,
+ const otMacKey &aNextKey)
+{
+ otError error;
SuccessOrExit(error = Set(SPINEL_PROP_RCP_MAC_KEY,
SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_UINT8_S SPINEL_DATATYPE_DATA_WLEN_S
SPINEL_DATATYPE_DATA_WLEN_S SPINEL_DATATYPE_DATA_WLEN_S,
- aKeyIdMode, aKeyId, aPrevKey->mKeyMaterial.mKey.m8, sizeof(otMacKey),
- aCurrKey->mKeyMaterial.mKey.m8, sizeof(otMacKey), aNextKey->mKeyMaterial.mKey.m8,
- sizeof(otMacKey)));
+ aKeyIdMode, aKeyId, aPrevKey.m8, sizeof(aPrevKey), aCurrKey.m8, sizeof(aCurrKey),
+ aNextKey.m8, sizeof(aNextKey)));
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
mKeyIdMode = aKeyIdMode;
mKeyId = aKeyId;
- memcpy(mPrevKey.m8, aPrevKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE);
- memcpy(mCurrKey.m8, aCurrKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE);
- memcpy(mNextKey.m8, aNextKey->mKeyMaterial.mKey.m8, OT_MAC_KEY_SIZE);
+
+ mPrevKey = aPrevKey;
+ mCurrKey = aCurrKey;
+ mNextKey = aNextKey;
+
mMacKeySet = true;
#endif
@@ -937,7 +1060,7 @@ exit:
otError RadioSpinel::GetIeeeEui64(uint8_t *aIeeeEui64)
{
- memcpy(aIeeeEui64, mIeeeEui64.m8, sizeof(mIeeeEui64.m8));
+ memcpy(aIeeeEui64, sIeeeEui64.m8, sizeof(sIeeeEui64.m8));
return OT_ERROR_NONE;
}
@@ -1242,7 +1365,7 @@ otError RadioSpinel::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration)
{
otError error;
- VerifyOrExit(mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN, error = OT_ERROR_NOT_CAPABLE);
+ VerifyOrExit(sRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN, error = OT_ERROR_NOT_CAPABLE);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
mScanChannel = aScanChannel;
@@ -1275,7 +1398,7 @@ otError RadioSpinel::Get(spinel_prop_key_t aKey, const char *aFormat, ...)
error = RequestWithPropertyFormatV(aFormat, SPINEL_CMD_PROP_VALUE_GET, aKey, nullptr, mPropertyArgs);
va_end(mPropertyArgs);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- } while (mRcpFailed);
+ } while (mRcpFailure != kRcpFailureNone);
#endif
return error;
@@ -1302,7 +1425,7 @@ otError RadioSpinel::GetWithParam(spinel_prop_key_t aKey,
aParamSize);
va_end(mPropertyArgs);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- } while (mRcpFailed);
+ } while (mRcpFailure != kRcpFailureNone);
#endif
return error;
@@ -1324,7 +1447,7 @@ otError RadioSpinel::Set(spinel_prop_key_t aKey, const char *aFormat, ...)
mPropertyArgs);
va_end(mPropertyArgs);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- } while (mRcpFailed);
+ } while (mRcpFailure != kRcpFailureNone);
#endif
return error;
@@ -1346,7 +1469,7 @@ otError RadioSpinel::Insert(spinel_prop_key_t aKey, const char *aFormat, ...)
mPropertyArgs);
va_end(mPropertyArgs);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- } while (mRcpFailed);
+ } while (mRcpFailure != kRcpFailureNone);
#endif
return error;
@@ -1368,7 +1491,7 @@ otError RadioSpinel::Remove(spinel_prop_key_t aKey, const char *aFormat, ...)
mPropertyArgs);
va_end(mPropertyArgs);
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- } while (mRcpFailed);
+ } while (mRcpFailure != kRcpFailureNone);
#endif
return error;
@@ -1378,7 +1501,7 @@ otError RadioSpinel::WaitResponse(bool aHandleRcpTimeout)
{
uint64_t end = otPlatTimeGet() + kMaxWaitTime * kUsPerMs;
- otLogDebgPlat("Wait response: tid=%u key=%lu", mWaitingTid, ToUlong(mWaitingKey));
+ LogDebg("Wait response: tid=%u key=%lu", mWaitingTid, ToUlong(mWaitingKey));
do
{
@@ -1387,14 +1510,14 @@ otError RadioSpinel::WaitResponse(bool aHandleRcpTimeout)
now = otPlatTimeGet();
if ((end <= now) || (mSpinelInterface->WaitForFrame(end - now) != OT_ERROR_NONE))
{
- otLogWarnPlat("Wait for response timeout");
+ LogWarn("Wait for response timeout");
if (aHandleRcpTimeout)
{
HandleRcpTimeout();
}
ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT);
}
- } while (mWaitingTid || !mIsReady);
+ } while (mWaitingTid || !sIsReady);
LogIfFail("Error waiting response", mError);
// This indicates end of waiting response.
@@ -1434,9 +1557,14 @@ otError RadioSpinel::SendReset(uint8_t aResetType)
uint8_t buffer[kMaxSpinelFrame];
spinel_ssize_t packed;
+ if ((aResetType == SPINEL_RESET_BOOTLOADER) && !sSupportsResetToBootloader)
+ {
+ ExitNow(error = OT_ERROR_NOT_CAPABLE);
+ }
+
// Pack the header, command and key
packed = spinel_datatype_pack(buffer, sizeof(buffer), SPINEL_DATATYPE_COMMAND_S SPINEL_DATATYPE_UINT8_S,
- SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_RESET, aResetType);
+ SPINEL_HEADER_FLAG | SPINEL_HEADER_IID(mIid), SPINEL_CMD_RESET, aResetType);
VerifyOrExit(packed > 0 && static_cast<size_t>(packed) <= sizeof(buffer), error = OT_ERROR_NO_BUFS);
@@ -1459,7 +1587,7 @@ otError RadioSpinel::SendCommand(uint32_t aCommand,
uint16_t offset;
// Pack the header, command and key
- packed = spinel_datatype_pack(buffer, sizeof(buffer), "Cii", SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | tid,
+ packed = spinel_datatype_pack(buffer, sizeof(buffer), "Cii", SPINEL_HEADER_FLAG | SPINEL_HEADER_IID(mIid) | tid,
aCommand, aKey);
VerifyOrExit(packed > 0 && static_cast<size_t>(packed) <= sizeof(buffer), error = OT_ERROR_NO_BUFS);
@@ -1609,7 +1737,7 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand,
static_cast<Mac::TxFrame *>(mTransmitFrame)->SetIsHeaderUpdated(headerUpdated);
- if ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && headerUpdated &&
+ if ((sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && headerUpdated &&
static_cast<Mac::TxFrame *>(mTransmitFrame)->GetSecurityEnabled())
{
uint8_t keyId;
@@ -1639,12 +1767,12 @@ otError RadioSpinel::Transmit(otRadioFrame &aFrame)
{
otError error = OT_ERROR_INVALID_STATE;
- VerifyOrExit(mState == kStateReceive || (mState == kStateSleep && (mRadioCaps & OT_RADIO_CAPS_SLEEP_TO_TX)));
+ VerifyOrExit(mState == kStateReceive || (mState == kStateSleep && (sRadioCaps & OT_RADIO_CAPS_SLEEP_TO_TX)));
mTransmitFrame = &aFrame;
// `otPlatRadioTxStarted()` is triggered immediately for now, which may be earlier than real started time.
- otPlatRadioTxStarted(mInstance, mTransmitFrame);
+ mCallbacks.mTxStarted(mInstance, mTransmitFrame);
error = Request(SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_STREAM_RAW,
SPINEL_DATATYPE_DATA_WLEN_S // Frame data
@@ -1751,7 +1879,7 @@ otError RadioSpinel::Enable(otInstance *aInstance)
exit:
if (error != OT_ERROR_NONE)
{
- otLogWarnPlat("RadioSpinel enable: %s", otThreadErrorToString(error));
+ LogWarn("RadioSpinel enable: %s", otThreadErrorToString(error));
error = OT_ERROR_FAILED;
}
@@ -1870,7 +1998,7 @@ void RadioSpinel::CalcRcpTimeOffset(void)
VerifyOrExit(!mIsTimeSynced || (otPlatTimeGet() >= GetNextRadioTimeRecalcStart()));
- otLogDebgPlat("Trying to get RCP time offset");
+ LogDebg("Trying to get RCP time offset");
packed = spinel_datatype_pack(buffer, sizeof(buffer), SPINEL_DATATYPE_UINT64_S, remoteTimestamp);
VerifyOrExit(packed > 0 && static_cast<size_t>(packed) <= sizeof(buffer), error = OT_ERROR_NO_BUFS);
@@ -1903,10 +2031,10 @@ void RadioSpinel::HandleRcpUnexpectedReset(spinel_status_t aStatus)
OT_UNUSED_VARIABLE(aStatus);
mRadioSpinelMetrics.mRcpUnexpectedResetCount++;
- otLogCritPlat("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus));
+ LogCrit("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus));
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- mRcpFailed = true;
+ mRcpFailure = kRcpFailureUnexpectedReset;
#elif OPENTHREAD_SPINEL_CONFIG_ABORT_ON_UNEXPECTED_RCP_RESET_ENABLE
abort();
#else
@@ -1919,14 +2047,14 @@ void RadioSpinel::HandleRcpTimeout(void)
mRadioSpinelMetrics.mRcpTimeoutCount++;
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- mRcpFailed = true;
+ mRcpFailure = kRcpFailureTimeout;
#else
- if (!mIsReady)
+ if (!sIsReady)
{
- otLogCritPlat("Failed to communicate with RCP - no response from RCP during initialization");
- otLogCritPlat("This is not a bug and typically due a config error (wrong URL parameters) or bad RCP image:");
- otLogCritPlat("- Make sure RCP is running the correct firmware");
- otLogCritPlat("- Double check the config parameters passed as `RadioURL` input");
+ LogCrit("Failed to communicate with RCP - no response from RCP during initialization");
+ LogCrit("This is not a bug and typically due a config error (wrong URL parameters) or bad RCP image:");
+ LogCrit("- Make sure RCP is running the correct firmware");
+ LogCrit("- Double check the config parameters passed as `RadioURL` input");
}
DieNow(OT_EXIT_RADIO_SPINEL_NO_RESPONSE);
@@ -1938,24 +2066,30 @@ void RadioSpinel::RecoverFromRcpFailure(void)
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
constexpr int16_t kMaxFailureCount = OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT;
State recoveringState = mState;
+ bool skipReset = false;
- if (!mRcpFailed)
+ if (mRcpFailure == kRcpFailureNone)
{
ExitNow();
}
- mRcpFailed = false;
- otLogWarnPlat("RCP failure detected");
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ skipReset = (mRcpFailure == kRcpFailureUnexpectedReset);
+#endif
+
+ mRcpFailure = kRcpFailureNone;
+
+ LogWarn("RCP failure detected");
++mRadioSpinelMetrics.mRcpRestorationCount;
++mRcpFailureCount;
if (mRcpFailureCount > kMaxFailureCount)
{
- otLogCritPlat("Too many rcp failures, exiting");
+ LogCrit("Too many rcp failures, exiting");
DieNow(OT_EXIT_FAILURE);
}
- otLogWarnPlat("Trying to recover (%d/%d)", mRcpFailureCount, kMaxFailureCount);
+ LogWarn("Trying to recover (%d/%d)", mRcpFailureCount, kMaxFailureCount);
mState = kStateDisabled;
mRxFrameBuffer.Clear();
@@ -1966,7 +2100,15 @@ void RadioSpinel::RecoverFromRcpFailure(void)
mError = OT_ERROR_NONE;
mIsTimeSynced = false;
- ResetRcp(mResetRadioOnStartup);
+ if (skipReset)
+ {
+ sIsReady = true;
+ }
+ else
+ {
+ ResetRcp(mResetRadioOnStartup);
+ }
+
SuccessOrDie(Set(SPINEL_PROP_PHY_ENABLED, SPINEL_DATATYPE_BOOL_S, true));
mState = kStateSleep;
@@ -1997,7 +2139,7 @@ void RadioSpinel::RecoverFromRcpFailure(void)
}
--mRcpFailureCount;
- otLogNotePlat("RCP recovery is done");
+ LogNote("RCP recovery is done");
exit:
return;
@@ -2089,10 +2231,41 @@ void RadioSpinel::RestoreProperties(void)
}
#endif // OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
+ if ((sRadioCaps & OT_RADIO_CAPS_RX_ON_WHEN_IDLE) != 0)
+ {
+ SuccessOrDie(Set(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, SPINEL_DATATYPE_BOOL_S, mRxOnWhenIdle));
+ }
+
CalcRcpTimeOffset();
}
#endif // OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
+otError RadioSpinel::GetMultipanActiveInterface(spinel_iid_t *aIid)
+{
+ otError error = Get(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE, SPINEL_DATATYPE_UINT8_S, aIid);
+ LogIfFail("Get GetMultipanActiveInterface failed", error);
+ return error;
+}
+
+otError RadioSpinel::SetMultipanActiveInterface(spinel_iid_t aIid, bool aCompletePending)
+{
+ otError error;
+ uint8_t value;
+
+ VerifyOrExit(aIid == (aIid & SPINEL_MULTIPAN_INTERFACE_ID_MASK), error = OT_ERROR_INVALID_ARGS);
+
+ value = static_cast<uint8_t>(aIid);
+ if (aCompletePending)
+ {
+ value |= (1 << SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_SHIFT);
+ }
+
+ error = Set(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE, SPINEL_DATATYPE_UINT8_S, value);
+
+exit:
+ return error;
+}
+
otError RadioSpinel::SetChannelMaxTransmitPower(uint8_t aChannel, int8_t aMaxPower)
{
otError error = OT_ERROR_NONE;
@@ -2112,13 +2285,13 @@ otError RadioSpinel::SetRadioRegion(uint16_t aRegionCode)
if (error == OT_ERROR_NONE)
{
- otLogNotePlat("Set region code \"%c%c\" successfully", static_cast<char>(aRegionCode >> 8),
- static_cast<char>(aRegionCode));
+ LogNote("Set region code \"%c%c\" successfully", static_cast<char>(aRegionCode >> 8),
+ static_cast<char>(aRegionCode));
}
else
{
- otLogWarnPlat("Failed to set region code \"%c%c\": %s", static_cast<char>(aRegionCode >> 8),
- static_cast<char>(aRegionCode), otThreadErrorToString(error));
+ LogWarn("Failed to set region code \"%c%c\": %s", static_cast<char>(aRegionCode >> 8),
+ static_cast<char>(aRegionCode), otThreadErrorToString(error));
}
return error;
@@ -2256,8 +2429,9 @@ void RadioSpinel::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool a
unpacked = spinel_datatype_unpack(aFrame, aLength, "CiiD", &header, &cmd, &key, &data, &len);
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
- start += Snprintf(start, static_cast<uint32_t>(end - start), "%s, flg:0x%x, tid:%u, cmd:%s", prefix,
- SPINEL_HEADER_GET_FLAG(header), SPINEL_HEADER_GET_TID(header), spinel_command_to_cstr(cmd));
+ start += Snprintf(start, static_cast<uint32_t>(end - start), "%s, flg:0x%x, iid:%d, tid:%u, cmd:%s", prefix,
+ SPINEL_HEADER_GET_FLAG(header), SPINEL_HEADER_GET_IID(header), SPINEL_HEADER_GET_TID(header),
+ spinel_command_to_cstr(cmd));
VerifyOrExit(cmd != SPINEL_CMD_RESET);
start += Snprintf(start, static_cast<uint32_t>(end - start), ", key:%s", spinel_prop_key_to_cstr(key));
@@ -2571,7 +2745,7 @@ void RadioSpinel::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool a
start += Snprintf(start, static_cast<uint32_t>(end - start), ", len:%u, rssi:%d ...", frame.mLength,
frame.mInfo.mRxInfo.mRssi);
OT_UNUSED_VARIABLE(start); // Avoid static analysis error
- otLogDebgPlat("%s", buf);
+ LogDebg("%s", buf);
start = buf;
start += Snprintf(start, static_cast<uint32_t>(end - start),
@@ -2607,7 +2781,7 @@ void RadioSpinel::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool a
", len:%u, channel:%u, maxbackoffs:%u, maxretries:%u ...", frame.mLength, frame.mChannel,
frame.mInfo.mTxInfo.mMaxCsmaBackoffs, frame.mInfo.mTxInfo.mMaxFrameRetries);
OT_UNUSED_VARIABLE(start); // Avoid static analysis error
- otLogDebgPlat("%s", buf);
+ LogDebg("%s", buf);
start = buf;
start += Snprintf(start, static_cast<uint32_t>(end - start),
@@ -2757,25 +2931,25 @@ void RadioSpinel::LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool a
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
- otLogDebgPlat("%s ...", buf);
- otLogDebgPlat(" txRequest:%lu", ToUlong(metrics.mNumTxRequest));
- otLogDebgPlat(" txGrantImmediate:%lu", ToUlong(metrics.mNumTxGrantImmediate));
- otLogDebgPlat(" txGrantWait:%lu", ToUlong(metrics.mNumTxGrantWait));
- otLogDebgPlat(" txGrantWaitActivated:%lu", ToUlong(metrics.mNumTxGrantWaitActivated));
- otLogDebgPlat(" txGrantWaitTimeout:%lu", ToUlong(metrics.mNumTxGrantWaitTimeout));
- otLogDebgPlat(" txGrantDeactivatedDuringRequest:%lu", ToUlong(metrics.mNumTxGrantDeactivatedDuringRequest));
- otLogDebgPlat(" txDelayedGrant:%lu", ToUlong(metrics.mNumTxDelayedGrant));
- otLogDebgPlat(" avgTxRequestToGrantTime:%lu", ToUlong(metrics.mAvgTxRequestToGrantTime));
- otLogDebgPlat(" rxRequest:%lu", ToUlong(metrics.mNumRxRequest));
- otLogDebgPlat(" rxGrantImmediate:%lu", ToUlong(metrics.mNumRxGrantImmediate));
- otLogDebgPlat(" rxGrantWait:%lu", ToUlong(metrics.mNumRxGrantWait));
- otLogDebgPlat(" rxGrantWaitActivated:%lu", ToUlong(metrics.mNumRxGrantWaitActivated));
- otLogDebgPlat(" rxGrantWaitTimeout:%lu", ToUlong(metrics.mNumRxGrantWaitTimeout));
- otLogDebgPlat(" rxGrantDeactivatedDuringRequest:%lu", ToUlong(metrics.mNumRxGrantDeactivatedDuringRequest));
- otLogDebgPlat(" rxDelayedGrant:%lu", ToUlong(metrics.mNumRxDelayedGrant));
- otLogDebgPlat(" avgRxRequestToGrantTime:%lu", ToUlong(metrics.mAvgRxRequestToGrantTime));
- otLogDebgPlat(" rxGrantNone:%lu", ToUlong(metrics.mNumRxGrantNone));
- otLogDebgPlat(" stopped:%u", metrics.mStopped);
+ LogDebg("%s ...", buf);
+ LogDebg(" txRequest:%lu", ToUlong(metrics.mNumTxRequest));
+ LogDebg(" txGrantImmediate:%lu", ToUlong(metrics.mNumTxGrantImmediate));
+ LogDebg(" txGrantWait:%lu", ToUlong(metrics.mNumTxGrantWait));
+ LogDebg(" txGrantWaitActivated:%lu", ToUlong(metrics.mNumTxGrantWaitActivated));
+ LogDebg(" txGrantWaitTimeout:%lu", ToUlong(metrics.mNumTxGrantWaitTimeout));
+ LogDebg(" txGrantDeactivatedDuringRequest:%lu", ToUlong(metrics.mNumTxGrantDeactivatedDuringRequest));
+ LogDebg(" txDelayedGrant:%lu", ToUlong(metrics.mNumTxDelayedGrant));
+ LogDebg(" avgTxRequestToGrantTime:%lu", ToUlong(metrics.mAvgTxRequestToGrantTime));
+ LogDebg(" rxRequest:%lu", ToUlong(metrics.mNumRxRequest));
+ LogDebg(" rxGrantImmediate:%lu", ToUlong(metrics.mNumRxGrantImmediate));
+ LogDebg(" rxGrantWait:%lu", ToUlong(metrics.mNumRxGrantWait));
+ LogDebg(" rxGrantWaitActivated:%lu", ToUlong(metrics.mNumRxGrantWaitActivated));
+ LogDebg(" rxGrantWaitTimeout:%lu", ToUlong(metrics.mNumRxGrantWaitTimeout));
+ LogDebg(" rxGrantDeactivatedDuringRequest:%lu", ToUlong(metrics.mNumRxGrantDeactivatedDuringRequest));
+ LogDebg(" rxDelayedGrant:%lu", ToUlong(metrics.mNumRxDelayedGrant));
+ LogDebg(" avgRxRequestToGrantTime:%lu", ToUlong(metrics.mAvgRxRequestToGrantTime));
+ LogDebg(" rxGrantNone:%lu", ToUlong(metrics.mNumRxGrantNone));
+ LogDebg(" stopped:%u", metrics.mStopped);
start = buf;
start += Snprintf(start, static_cast<uint32_t>(end - start), " grantGlitch:%u", metrics.mNumGrantGlitch);
@@ -2856,11 +3030,11 @@ exit:
OT_UNUSED_VARIABLE(start); // Avoid static analysis error
if (error == OT_ERROR_NONE)
{
- otLogDebgPlat("%s", buf);
+ LogDebg("%s", buf);
}
else if (prefix != nullptr)
{
- otLogDebgPlat("%s, failed to parse spinel frame !", prefix);
+ LogDebg("%s, failed to parse spinel frame !", prefix);
}
}
@@ -2947,9 +3121,56 @@ void RadioSpinel::LogIfFail(const char *aText, otError aError)
if (aError != OT_ERROR_NONE && aError != OT_ERROR_NO_ACK)
{
- otLogWarnPlat("%s: %s", aText, otThreadErrorToString(aError));
+ LogWarn("%s: %s", aText, otThreadErrorToString(aError));
}
}
+static const char kModuleName[] = "RadioSpinel";
+
+void RadioSpinel::LogCrit(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(OT_LOG_LEVEL_CRIT, kModuleName, aFormat, args);
+ va_end(args);
+}
+
+void RadioSpinel::LogWarn(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(OT_LOG_LEVEL_WARN, kModuleName, aFormat, args);
+ va_end(args);
+}
+
+void RadioSpinel::LogNote(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(OT_LOG_LEVEL_NOTE, kModuleName, aFormat, args);
+ va_end(args);
+}
+
+void RadioSpinel::LogInfo(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(OT_LOG_LEVEL_INFO, kModuleName, aFormat, args);
+ va_end(args);
+}
+
+void RadioSpinel::LogDebg(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+ otLogPlatArgs(OT_LOG_LEVEL_DEBG, kModuleName, aFormat, args);
+ va_end(args);
+}
+
} // namespace Spinel
} // namespace ot
diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp
index dac40d5c0..da0b6521d 100644
--- a/src/lib/spinel/radio_spinel.hpp
+++ b/src/lib/spinel/radio_spinel.hpp
@@ -47,6 +47,103 @@ namespace ot {
namespace Spinel {
/**
+ * Maximum number of Spinel Interface IDs.
+ *
+ */
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+static constexpr uint8_t kSpinelHeaderMaxNumIid = 4;
+#else
+static constexpr uint8_t kSpinelHeaderMaxNumIid = 1;
+#endif
+
+struct RadioSpinelCallbacks
+{
+ /**
+ * This callback notifies user of `RadioSpinel` of a received frame.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aFrame A pointer to the received frame or nullptr if the receive operation failed.
+ * @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 (*mReceiveDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError);
+
+ /**
+ * The callback notifies user of `RadioSpinel` that the transmit operation has completed, providing, if
+ * applicable, the received ACK frame.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aFrame The transmitted frame.
+ * @param[in] aAckFrame A pointer to the ACK frame, nullptr if no ACK was received.
+ * @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 (*mTransmitDone)(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, Error aError);
+
+ /**
+ * This callback notifies user of `RadioSpinel` that energy scan is complete.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aMaxRssi Maximum RSSI seen on the channel, or `SubMac::kInvalidRssiValue` if failed.
+ *
+ */
+ void (*mEnergyScanDone)(otInstance *aInstance, int8_t aMaxRssi);
+
+ /**
+ * This callback notifies user of `RadioSpinel` that the transmission has started.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance structure.
+ * @param[in] aFrame A pointer to the frame that is being transmitted.
+ *
+ */
+ void (*mTxStarted)(otInstance *aInstance, otRadioFrame *aFrame);
+
+ /**
+ * This callback notifies user of `RadioSpinel` that the radio interface switchover has completed.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance structure.
+ * @param[in] aSuccess A value indicating if the switchover was successful or not.
+ *
+ */
+ void (*mSwitchoverDone)(otInstance *aInstance, bool aSuccess);
+
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+ /**
+ * This callback notifies diagnostics module using `RadioSpinel` of a received frame.
+ *
+ * This callback is used when diagnostics is enabled.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aFrame A pointer to the received frame or NULL 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.
+ *
+ */
+ void (*mDiagReceiveDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError);
+
+ /**
+ * This callback notifies diagnostics module using `RadioSpinel` that the transmission has completed.
+ *
+ * This callback is used when diagnostics is enabled.
+ *
+ * @param[in] aInstance The OpenThread instance structure.
+ * @param[in] aFrame A pointer to the frame that was transmitted.
+ * @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 the
+ * channel, OT_ERROR_ABORT when transmission was aborted for other reasons.
+ *
+ */
+ void (*mDiagTransmitDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError);
+#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
+};
+
+/**
* The class for providing a OpenThread radio interface by talking with a radio-only
* co-processor(RCP).
*
@@ -72,9 +169,24 @@ public:
* @param[in] aSpinelInterface A reference to the Spinel interface.
* @param[in] aResetRadio TRUE to reset on init, FALSE to not reset on init.
* @param[in] aSkipRcpCompatibilityCheck TRUE to skip RCP compatibility check, FALSE to perform the check.
+ * @param[in] aIidList A Pointer to the list of IIDs to receive spinel frame from.
+ * First entry must be the IID of the Host Application.
+ * @param[in] aIidListLength The Length of the @p aIidList.
*
*/
- void Init(SpinelInterface &aSpinelInterface, bool aResetRadio, bool aSkipRcpCompatibilityCheck);
+ void Init(SpinelInterface &aSpinelInterface,
+ bool aResetRadio,
+ bool aSkipRcpCompatibilityCheck,
+ const spinel_iid_t *aIidList,
+ uint8_t aIidListLength);
+
+ /**
+ * This method sets the notification callbacks.
+ *
+ * @param[in] aCallbacks A pointer to structure with notification callbacks.
+ *
+ */
+ void SetCallbacks(const struct RadioSpinelCallbacks &aCallbacks);
/**
* Deinitialize this radio transceiver.
@@ -104,6 +216,18 @@ public:
otError SetPromiscuous(bool aEnable);
/**
+ * Sets the status of RxOnWhenIdle mode.
+ *
+ * @param[in] aEnable Whether to enable or disable RxOnWhenIdle mode.
+ *
+ * @retval OT_ERROR_NONE Succeeded.
+ * @retval OT_ERROR_BUSY Failed due to another operation is on going.
+ * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver.
+ *
+ */
+ otError SetRxOnWhenIdle(bool aEnable);
+
+ /**
* Sets the Short Address for address filtering.
*
* @param[in] aShortAddress The IEEE 802.15.4 Short Address.
@@ -230,7 +354,7 @@ public:
* @returns A pointer to the radio version string.
*
*/
- const char *GetVersion(void) const { return mVersion; }
+ const char *GetVersion(void) const { return sVersion; }
/**
* Returns the radio capabilities.
@@ -238,7 +362,7 @@ public:
* @returns The radio capability bit vector.
*
*/
- otRadioCaps GetRadioCaps(void) const { return mRadioCaps; }
+ otRadioCaps GetRadioCaps(void) const { return sRadioCaps; }
/**
* Gets the most recent RSSI measurement.
@@ -311,6 +435,44 @@ public:
#endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
/**
+ * Get currently active interface.
+ *
+ * @param[out] aIid IID of the interface that owns the radio.
+ *
+ * @retval OT_ERROR_NONE Successfully got the property.
+ * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver.
+ * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to lack of the support in radio
+ * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously.
+ * (i.e. no active/inactive interface concept in the platform level)
+ *
+ */
+ otError GetMultipanActiveInterface(spinel_iid_t *aIid);
+
+ /**
+ * Sets specified radio interface active
+ *
+ * This function allows selecting currently active radio interface on platforms that do not support parallel
+ * communication on multiple interfaces. I.e. if more than one interface is in receive state calling
+ * SetMultipanActiveInterface guarantees that specified interface will not be losing frames. This function
+ * returns if the request was received properly. After interface switching is complete SwitchoverDone callback is
+ * Invoked. Switching interfaces may take longer if aCompletePending is set true.
+ *
+ * @param[in] aIid IID of the interface to set active.
+ * @param[in] aCompletePending Set true if pending radio operation should complete first(Soft switch) or false if
+ * ongoing operations should be interrupted (Force switch).
+ *
+ * @retval OT_ERROR_NONE Successfully requested interface switch.
+ * @retval OT_ERROR_BUSY Failed due to another operation on going.
+ * @retval OT_ERROR_RESPONSE_TIMEOUT Failed due to no response received from the transceiver.
+ * @retval OT_ERROR_NOT_IMPLEMENTED Failed due to lack of support in radio for the given interface id or
+ * @retval OT_ERROR_INVALID_COMMAND Platform supports all interfaces simultaneously
+ * (i.e. no active/inactive interface concept in the platform level)
+ * @retval OT_ERROR_ALREADY Given interface is already active.
+ *
+ */
+ otError SetMultipanActiveInterface(spinel_iid_t aIid, bool aCompletePending);
+
+ /**
* Returns a reference to the transmit buffer.
*
* The caller forms the IEEE 802.15.4 frame in this buffer then calls otPlatRadioTransmit() to request transmission.
@@ -808,10 +970,11 @@ public:
/**
* Tries to reset the co-processor.
*
- * @prarm[in] aResetType The reset type, SPINEL_RESET_PLATFORM or SPINEL_RESET_STACK.
+ * @prarm[in] aResetType The reset type, SPINEL_RESET_PLATFORM, SPINEL_RESET_STACK, or SPINEL_RESET_BOOTLOADER.
*
* @retval OT_ERROR_NONE Successfully removed item from the property.
* @retval OT_ERROR_BUSY Failed due to another operation is on going.
+ * @retval OT_ERROR_NOT_CAPABLE Requested reset type is not supported by the co-processor
*
*/
otError SendReset(uint8_t aResetType);
@@ -895,6 +1058,14 @@ public:
*/
static otError SpinelStatusToOtError(spinel_status_t aStatus);
+#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
+ /**
+ * Restore the properties of Radio Co-processor (RCP).
+ *
+ */
+ void RestoreProperties(void);
+#endif
+
private:
enum
{
@@ -914,11 +1085,9 @@ private:
kStateTransmitDone, ///< Radio indicated frame transmission is done.
};
- enum
- {
- kUsPerMs = 1000, ///< Microseconds per millisecond.
- kTxWaitUs = 5000000, ///< Maximum time of waiting for `TransmitDone` event, in microseconds.
- };
+ static constexpr uint32_t kUsPerMs = 1000; ///< Microseconds per millisecond.
+ static constexpr uint64_t kTxWaitUs =
+ 5000000; ///< Maximum time of waiting for `TransmitDone` event, in microseconds.
typedef otError (RadioSpinel::*ResponseHandler)(const uint8_t *aBuffer, uint16_t aLength);
@@ -985,6 +1154,17 @@ private:
return !(aKey == SPINEL_PROP_STREAM_RAW || aKey == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT);
}
+ /**
+ * Checks whether given interface ID is part of list of IIDs to be allowed.
+ *
+ * @param[in] aIid Spinel Interface ID.
+ *
+ * @retval TRUE Given IID present in allow list.
+ * @retval FALSE Otherwise.
+ *
+ */
+ inline bool IsFrameForUs(spinel_iid_t aIid);
+
void HandleNotification(SpinelInterface::RxFrameBuffer &aFrameBuffer);
void HandleNotification(const uint8_t *aFrame, uint16_t aLength);
void HandleValueIs(spinel_prop_key_t aKey, const uint8_t *aBuffer, uint16_t aLength);
@@ -1003,24 +1183,38 @@ private:
void HandleRcpTimeout(void);
void RecoverFromRcpFailure(void);
-#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
- void RestoreProperties(void);
-#endif
void UpdateParseErrorCount(otError aError)
{
mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0;
}
+ otError SetMacKey(uint8_t aKeyIdMode,
+ uint8_t aKeyId,
+ const otMacKey &aPrevKey,
+ const otMacKey &aCurrKey,
+ const otMacKey &NextKey);
+#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+ static otError ReadMacKey(const otMacKeyMaterial &aKeyMaterial, otMacKey &aKey);
+#endif
+
+ static void LogIfFail(const char *aText, otError aError);
+
+ static void LogCrit(const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
+ static void LogWarn(const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
+ static void LogNote(const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
+ static void LogInfo(const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
+ static void LogDebg(const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(1, 2);
+
uint32_t Snprintf(char *aDest, uint32_t aSize, const char *aFormat, ...);
void LogSpinelFrame(const uint8_t *aFrame, uint16_t aLength, bool aTx);
- void LogIfFail(const char *aText, otError aError);
-
otInstance *mInstance;
SpinelInterface::RxFrameBuffer mRxFrameBuffer;
SpinelInterface *mSpinelInterface;
+ RadioSpinelCallbacks mCallbacks; ///< Callbacks for notifications of higher layer.
+
uint16_t mCmdTidsInUse; ///< Used transaction ids.
spinel_tid_t mCmdNextTid; ///< Next available transaction id.
spinel_tid_t mTxRadioTid; ///< The transaction id used to send a radio frame.
@@ -1030,6 +1224,8 @@ private:
va_list mPropertyArgs; ///< The arguments pack or unpack spinel property of current transaction.
uint32_t mExpectedCommand; ///< Expected response command of current transaction.
otError mError; ///< The result of current transaction.
+ spinel_iid_t mIid; ///< The spinel interface id used by this process.
+ spinel_iid_t mIidList[kSpinelHeaderMaxNumIid]; ///< Array of interface ids to accept the incoming spinel frames.
uint8_t mRxPsdu[OT_RADIO_FRAME_MAX_SIZE];
uint8_t mTxPsdu[OT_RADIO_FRAME_MAX_SIZE];
@@ -1039,26 +1235,37 @@ private:
otRadioFrame mAckRadioFrame;
otRadioFrame *mTransmitFrame; ///< Points to the frame to send
- otExtAddress mExtendedAddress;
- uint16_t mShortAddress;
- uint16_t mPanId;
- otRadioCaps mRadioCaps;
- uint8_t mChannel;
- int8_t mRxSensitivity;
- otError mTxError;
- char mVersion[kVersionStringSize];
- otExtAddress mIeeeEui64;
+ otExtAddress mExtendedAddress;
+ uint16_t mShortAddress;
+ uint16_t mPanId;
+ uint8_t mChannel;
+ int8_t mRxSensitivity;
+ otError mTxError;
+ static char sVersion[kVersionStringSize];
+ static otExtAddress sIeeeEui64;
+ static otRadioCaps sRadioCaps;
State mState;
- bool mIsPromiscuous : 1; ///< Promiscuous mode.
- bool mIsReady : 1; ///< NCP ready.
- bool mSupportsLogStream : 1; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
- bool mIsTimeSynced : 1; ///< Host has calculated the time difference between host and RCP.
+ bool mIsPromiscuous : 1; ///< Promiscuous mode.
+ bool mRxOnWhenIdle : 1; ///< RxOnWhenIdle mode.
+ bool mIsTimeSynced : 1; ///< Host has calculated the time difference between host and RCP.
+
+ static bool sIsReady; ///< NCP ready.
+ static bool sSupportsLogStream; ///< RCP supports `LOG_STREAM` property with OpenThread log meta-data format.
+ static bool sSupportsResetToBootloader; ///< RCP supports resetting into bootloader mode.
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
+ enum
+ {
+ kRcpFailureNone,
+ kRcpFailureTimeout,
+ kRcpFailureUnexpectedReset,
+ };
+
bool mResetRadioOnStartup : 1; ///< Whether should send reset command when init.
int16_t mRcpFailureCount; ///< Count of consecutive RCP failures.
+ uint8_t mRcpFailure : 2; ///< RCP failure reason, should recover and retry operation.
// Properties set by core.
uint8_t mKeyIdMode;
@@ -1083,7 +1290,6 @@ private:
bool mTransmitPowerSet : 1; ///< Whether transmit power has been set.
bool mCoexEnabledSet : 1; ///< Whether coex enabled has been set.
bool mFemLnaGainSet : 1; ///< Whether FEM LNA gain has been set.
- bool mRcpFailed : 1; ///< RCP failure happened, should recover and retry operation.
bool mEnergyScanning : 1; ///< If fails while scanning, restarts scanning.
bool mMacFrameCounterSet : 1; ///< Whether the MAC frame counter has been set.
diff --git a/src/lib/spinel/spi_frame.hpp b/src/lib/spinel/spi_frame.hpp
index a606c0896..bb5403040 100644
--- a/src/lib/spinel/spi_frame.hpp
+++ b/src/lib/spinel/spi_frame.hpp
@@ -195,10 +195,7 @@ public:
* @param[in] aAcceptLen The accept length in bytes.
*
*/
- void SetHeaderAcceptLen(uint16_t aAcceptLen)
- {
- Encoding::LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen);
- }
+ void SetHeaderAcceptLen(uint16_t aAcceptLen) { LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen); }
/**
* Gets the "accept len" field in the SPI frame header.
@@ -206,7 +203,7 @@ public:
* @returns The accept length in bytes.
*
*/
- uint16_t GetHeaderAcceptLen(void) const { return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen); }
+ uint16_t GetHeaderAcceptLen(void) const { return LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen); }
/**
* Sets the "data len" field in the SPI frame header.
@@ -216,7 +213,7 @@ public:
* @param[in] aDataLen The data length in bytes.
*
*/
- void SetHeaderDataLen(uint16_t aDataLen) { Encoding::LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen); }
+ void SetHeaderDataLen(uint16_t aDataLen) { LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen); }
/**
* Gets the "data len" field in the SPI frame header.
@@ -224,7 +221,7 @@ public:
* @returns The data length in bytes.
*
*/
- uint16_t GetHeaderDataLen(void) const { return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexDataLen); }
+ uint16_t GetHeaderDataLen(void) const { return LittleEndian::ReadUint16(mBuffer + kIndexDataLen); }
private:
enum
diff --git a/src/lib/spinel/spinel.c b/src/lib/spinel/spinel.c
index 5cf3836b7..82ea55556 100644
--- a/src/lib/spinel/spinel.c
+++ b/src/lib/spinel/spinel.c
@@ -46,7 +46,6 @@
#include "spinel.h"
#include <errno.h>
-#include <limits.h>
#ifndef SPINEL_PLATFORM_HEADER
/* These are all already included in the spinel platform header
@@ -241,7 +240,7 @@ spinel_ssize_t spinel_packed_uint_decode(const uint8_t *bytes, spinel_size_t len
do
{
- if ((len < sizeof(uint8_t)) || (i >= sizeof(unsigned int) * CHAR_BIT))
+ if ((len < sizeof(uint8_t)) || (i >= sizeof(unsigned int) * SPINEL_BITS_PER_BYTE))
{
ret = -1;
break;
@@ -1263,6 +1262,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
{SPINEL_PROP_MAC_PROMISCUOUS_MODE, "MAC_PROMISCUOUS_MODE"},
{SPINEL_PROP_MAC_ENERGY_SCAN_RESULT, "MAC_ENERGY_SCAN_RESULT"},
{SPINEL_PROP_MAC_DATA_POLL_PERIOD, "MAC_DATA_POLL_PERIOD"},
+ {SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE, "MAC_RX_ON_WHEN_IDLE_MODE"},
{SPINEL_PROP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
{SPINEL_PROP_MAC_ALLOWLIST_ENABLED, "MAC_ALLOWLIST_ENABLED"},
{SPINEL_PROP_MAC_EXTENDED_ADDR, "MAC_EXTENDED_ADDR"},
@@ -1548,6 +1548,8 @@ const char *spinel_status_to_cstr(spinel_status_t status)
{SPINEL_STATUS_ITEM_NOT_FOUND, "ITEM_NOT_FOUND"},
{SPINEL_STATUS_INVALID_COMMAND_FOR_PROP, "INVALID_COMMAND_FOR_PROP"},
{SPINEL_STATUS_RESPONSE_TIMEOUT, "RESPONSE_TIMEOUT"},
+ {SPINEL_STATUS_SWITCHOVER_DONE, "SWITCHOVER_DONE"},
+ {SPINEL_STATUS_SWITCHOVER_FAILED, "SWITCHOVER_FAILED"},
{SPINEL_STATUS_JOIN_FAILURE, "JOIN_FAILURE"},
{SPINEL_STATUS_JOIN_SECURITY, "JOIN_SECURITY"},
{SPINEL_STATUS_JOIN_NO_PEERS, "JOIN_NO_PEERS"},
@@ -1606,6 +1608,8 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability)
{SPINEL_CAP_NET_THREAD_1_1, "NET_THREAD_1_1"},
{SPINEL_CAP_NET_THREAD_1_2, "NET_THREAD_1_2"},
{SPINEL_CAP_RCP_API_VERSION, "RCP_API_VERSION"},
+ {SPINEL_CAP_RCP_MIN_HOST_API_VERSION, "RCP_MIN_HOST_API_VERSION"},
+ {SPINEL_CAP_RCP_RESET_TO_BOOTLOADER, "RCP_RESET_TO_BOOTLOADER"},
{SPINEL_CAP_MAC_ALLOWLIST, "MAC_ALLOWLIST"},
{SPINEL_CAP_MAC_RAW, "MAC_RAW"},
{SPINEL_CAP_OOB_STEERING_DATA, "OOB_STEERING_DATA"},
diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h
index ffa370786..5d8094db4 100644
--- a/src/lib/spinel/spinel.h
+++ b/src/lib/spinel/spinel.h
@@ -78,16 +78,16 @@
*
* The Interface Identifier (IID) is a number between 0 and 3, which
* is associated by the OS with a specific NCP. This allows the protocol
- * to support up to 4 NCPs under same connection.
+ * to support multiple networks under same connection.
*
* The least significant bits of the header represent the Transaction
* Identifier (TID). The TID is used for correlating responses to the
* commands which generated them.
*
* When a command is sent from the host, any reply to that command sent
- * by the NCP will use the same value for the TID. When the host
- * receives a frame that matches the TID of the command it sent, it can
- * easily recognize that frame as the actual response to that command.
+ * by the NCP will use the same value for the IID and TID. When the host
+ * receives a frame that matches the IID and TID of the command it sent, it
+ * can easily recognize that frame as the actual response to that command.
*
* The TID value of zero (0) is used for commands to which a correlated
* response is not expected or needed, such as for unsolicited update
@@ -420,7 +420,7 @@
* Please see section "Spinel definition compatibility guideline" for more details.
*
*/
-#define SPINEL_RCP_API_VERSION 9
+#define SPINEL_RCP_API_VERSION 10
/**
* @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION
@@ -479,6 +479,8 @@
/// Macro for generating bit masks using bit index from the spec
#define SPINEL_BIT_MASK(bit_index, field_bit_count) ((1 << ((field_bit_count)-1)) >> (bit_index))
+#define SPINEL_BITS_PER_BYTE 8 // Number of bits in a byte
+
// ----------------------------------------------------------------------------
#if defined(__cplusplus)
@@ -512,6 +514,9 @@ enum
SPINEL_STATUS_UNKNOWN_NEIGHBOR = 22, ///< The neighbor is unknown.
SPINEL_STATUS_NOT_CAPABLE = 23, ///< The target is not capable of handling requested operation.
SPINEL_STATUS_RESPONSE_TIMEOUT = 24, ///< No response received from remote node
+ SPINEL_STATUS_SWITCHOVER_DONE =
+ 25, ///< Radio interface switch completed successfully (SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE)
+ SPINEL_STATUS_SWITCHOVER_FAILED = 26, ///< Radio interface switch failed (SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE)
SPINEL_STATUS_JOIN__BEGIN = 104,
@@ -883,6 +888,7 @@ typedef struct
typedef int spinel_ssize_t;
typedef unsigned int spinel_size_t;
+typedef uint8_t spinel_iid_t;
typedef uint8_t spinel_tid_t;
enum
@@ -897,8 +903,9 @@ enum
enum
{
- SPINEL_RESET_PLATFORM = 1,
- SPINEL_RESET_STACK = 2,
+ SPINEL_RESET_PLATFORM = 1,
+ SPINEL_RESET_STACK = 2,
+ SPINEL_RESET_BOOTLOADER = 3,
};
enum
@@ -928,8 +935,10 @@ enum
* `PROP_LAST_STATUS` has been set to `STATUS_RESET_SOFTWARE`.
*
* The optional command payload specifies the reset type, can be
- * `SPINEL_RESET_PLATFORM` or `SPINEL_RESET_STACK`. Defaults to stack
- * reset if unspecified.
+ * `SPINEL_RESET_PLATFORM`, `SPINEL_RESET_STACK`, or
+ * `SPINEL_RESET_BOOTLOADER`.
+ *
+ * Defaults to stack reset if unspecified.
*
* If an error occurs, the value of `PROP_LAST_STATUS` will be emitted
* instead with the value set to the generated status code for the error.
@@ -1284,6 +1293,7 @@ enum
SPINEL_CAP_RCP__BEGIN = 64,
SPINEL_CAP_RCP_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 0),
SPINEL_CAP_RCP_MIN_HOST_API_VERSION = (SPINEL_CAP_RCP__BEGIN + 1),
+ SPINEL_CAP_RCP_RESET_TO_BOOTLOADER = (SPINEL_CAP_RCP__BEGIN + 2),
SPINEL_CAP_RCP__END = 80,
SPINEL_CAP_OPENTHREAD__BEGIN = 512,
@@ -1445,8 +1455,6 @@ enum
*
* Provides number of interfaces.
*
- * Currently always reads as 1.
- *
*/
SPINEL_PROP_INTERFACE_COUNT = 6,
@@ -2124,6 +2132,17 @@ enum
*/
SPINEL_PROP_MAC_DATA_POLL_PERIOD = SPINEL_PROP_MAC__BEGIN + 10,
+ /// MAC RxOnWhenIdle mode
+ /** Format: `b`
+ *
+ * Set to true to enable RxOnWhenIdle or false to disable it.
+ * When True, the radio is expected to stay in receive state during
+ * idle periods. When False, the radio is expected to switch to sleep
+ * state during idle periods.
+ *
+ */
+ SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE = SPINEL_PROP_MAC__BEGIN + 11,
+
SPINEL_PROP_MAC__END = 0x40,
SPINEL_PROP_MAC_EXT__BEGIN = 0x1300,
@@ -4846,6 +4865,24 @@ enum
SPINEL_PROP_RCP_EXT__END = 0x900,
+ SPINEL_PROP_MULTIPAN__BEGIN = 0x900,
+
+ /// Multipan interface selection.
+ /** Format: `C`
+ * Type: Read-Write
+ *
+ * `C`: b[0-1] - Interface id.
+ * b[7] - 1: Complete pending radio operation, 0: immediate(force) switch.
+ *
+ * This feature gets or sets the radio interface to be used in multipan configuration
+ *
+ * Default value: 0
+ *
+ */
+ SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE = SPINEL_PROP_MULTIPAN__BEGIN + 0,
+
+ SPINEL_PROP_MULTIPAN__END = 0x910,
+
SPINEL_PROP_NEST__BEGIN = 0x3BC0,
SPINEL_PROP_NEST_STREAM_MFG = SPINEL_PROP_NEST__BEGIN + 0,
@@ -4940,11 +4977,15 @@ typedef uint32_t spinel_prop_key_t;
#define SPINEL_HEADER_IID_SHIFT 4
#define SPINEL_HEADER_IID_MASK (3 << SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_IID(iid) (static_cast<uint8_t>((iid) << SPINEL_HEADER_IID_SHIFT))
+#define SPINEL_HEADER_IID_MAX 3
-#define SPINEL_HEADER_IID_0 (0 << SPINEL_HEADER_IID_SHIFT)
-#define SPINEL_HEADER_IID_1 (1 << SPINEL_HEADER_IID_SHIFT)
-#define SPINEL_HEADER_IID_2 (2 << SPINEL_HEADER_IID_SHIFT)
-#define SPINEL_HEADER_IID_3 (3 << SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_IID_0 SPINEL_HEADER_IID(0)
+#define SPINEL_HEADER_IID_1 SPINEL_HEADER_IID(1)
+#define SPINEL_HEADER_IID_2 SPINEL_HEADER_IID(2)
+#define SPINEL_HEADER_IID_3 SPINEL_HEADER_IID(3)
+
+#define SPINEL_HEADER_INVALID_IID 0xFF
#define SPINEL_HEADER_GET_IID(x) (((x)&SPINEL_HEADER_IID_MASK) >> SPINEL_HEADER_IID_SHIFT)
#define SPINEL_HEADER_GET_TID(x) (spinel_tid_t)(((x)&SPINEL_HEADER_TID_MASK) >> SPINEL_HEADER_TID_SHIFT)
@@ -4959,6 +5000,10 @@ typedef uint32_t spinel_prop_key_t;
#define SPINEL_BEACON_THREAD_FLAG_NATIVE (1 << 3)
+#define SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_SHIFT 7
+#define SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_MASK (1 << SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_SHIFT)
+#define SPINEL_MULTIPAN_INTERFACE_ID_MASK 0x03
+
// ----------------------------------------------------------------------------
enum
diff --git a/src/lib/spinel/spinel_interface.hpp b/src/lib/spinel/spinel_interface.hpp
index 432b8b7ee..10d0c9637 100644
--- a/src/lib/spinel/spinel_interface.hpp
+++ b/src/lib/spinel/spinel_interface.hpp
@@ -175,9 +175,27 @@ protected:
*/
bool IsSpinelResetCommand(const uint8_t *aFrame, uint16_t aLength)
{
- static constexpr uint8_t kSpinelResetCommand[] = {SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_RESET};
- return (aLength >= sizeof(kSpinelResetCommand)) &&
- (memcmp(aFrame, kSpinelResetCommand, sizeof(kSpinelResetCommand)) == 0);
+ const uint8_t kSpinelResetCommandLength = 2;
+ bool resetCmd = false;
+
+ if (aLength >= kSpinelResetCommandLength)
+ {
+#ifndef OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ // Validate the iid.
+ VerifyOrExit(((aFrame[0] & SPINEL_HEADER_IID_MASK) == SPINEL_HEADER_IID_0));
+#endif
+
+ // Validate the header flag by masking out the iid bits as it is validated above.
+ VerifyOrExit(((aFrame[0] & ~SPINEL_HEADER_IID_MASK) == SPINEL_HEADER_FLAG));
+
+ // Validate the reset command.
+ VerifyOrExit(aFrame[1] == SPINEL_CMD_RESET);
+
+ ExitNow(resetCmd = true);
+ }
+
+ exit:
+ return resetCmd;
}
};
} // namespace Spinel
diff --git a/src/ncp/BUILD.gn b/src/ncp/BUILD.gn
index 2adfdecaf..2bb99814a 100644
--- a/src/ncp/BUILD.gn
+++ b/src/ncp/BUILD.gn
@@ -31,6 +31,7 @@ openthread_ncp_sources = [
"changed_props_set.cpp",
"changed_props_set.hpp",
"example_vendor_hook.cpp",
+ "multipan_platform.cpp",
"ncp_base.cpp",
"ncp_base.hpp",
"ncp_base_dispatcher.cpp",
diff --git a/src/ncp/CMakeLists.txt b/src/ncp/CMakeLists.txt
index 84062470b..25d7e2de1 100644
--- a/src/ncp/CMakeLists.txt
+++ b/src/ncp/CMakeLists.txt
@@ -33,6 +33,7 @@ set(COMMON_INCLUDES
set(COMMON_SOURCES
changed_props_set.cpp
+ multipan_platform.cpp
ncp_base.cpp
ncp_base_dispatcher.cpp
ncp_base_radio.cpp
@@ -68,6 +69,15 @@ endif()
if(OT_RCP)
include(radio.cmake)
+ if(OT_MULTIPAN_RCP)
+ target_compile_options(ot-config-radio
+ INTERFACE
+ "-DOPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_LOG_PREPEND_UPTIME=0" # Not supporting multiple instances
+ "-DOPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE=1"
+ )
+ endif()
endif()
set_property(SOURCE ncp_base_mtd.cpp
diff --git a/src/ncp/changed_props_set.cpp b/src/ncp/changed_props_set.cpp
index ceac025d9..9e847f05c 100644
--- a/src/ncp/changed_props_set.cpp
+++ b/src/ncp/changed_props_set.cpp
@@ -27,13 +27,13 @@
#include "changed_props_set.hpp"
-#include <limits.h>
-
#include "common/code_utils.hpp"
namespace ot {
namespace Ncp {
+static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte.
+
// ----------------------------------------------------------------------------
// MARK: ChangedPropsSet class
// ----------------------------------------------------------------------------
@@ -95,7 +95,7 @@ const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = {
uint8_t ChangedPropsSet::GetNumEntries(void) const
{
- static_assert(OT_ARRAY_LENGTH(mSupportedProps) <= sizeof(mChangedSet) * CHAR_BIT,
+ static_assert(OT_ARRAY_LENGTH(mSupportedProps) <= sizeof(mChangedSet) * kBitsPerByte,
"Changed set size is smaller than number of entries in `mSupportedProps[]` array");
return OT_ARRAY_LENGTH(mSupportedProps);
diff --git a/src/ncp/example_vendor_hook.cpp b/src/ncp/example_vendor_hook.cpp
index 62c0b6aaa..116b8493c 100644
--- a/src/ncp/example_vendor_hook.cpp
+++ b/src/ncp/example_vendor_hook.cpp
@@ -141,6 +141,12 @@ public:
: ot::Ncp::NcpHdlc(aInstance, &NcpVendorUart::SendHdlc)
{
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ NcpVendorUart(ot::Instance **aInstances, uint8_t count)
+ : ot::Ncp::NcpHdlc(aInstances, count, &NcpVendorUart::SendHdlc)
+ {
+ }
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
// Add public/private methods or member variables
};
@@ -159,5 +165,28 @@ extern "C" void otAppNcpInit(otInstance *aInstance)
// assert(false);
}
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+extern "C" void otAppNcpInitMulti(otInstance **aInstances, uint8_t count)
+{
+ NcpVendorUart *ncpVendor = nullptr;
+ ot::Instance *instances[SPINEL_HEADER_IID_MAX];
+
+ OT_ASSERT(count < SPINEL_HEADER_IID_MAX);
+ OT_ASSERT(count > 0);
+ OT_ASSERT(aInstances[0] != nullptr);
+
+ for (int i = 0; i < count; i++)
+ {
+ instances[i] = static_cast<ot::Instance *>(aInstances[i]);
+ }
+
+ ncpVendor = new (&sNcpVendorRaw) NcpVendorUart(instances, count);
+
+ if (ncpVendor == nullptr || ncpVendor != ot::Ncp::NcpBase::GetNcpInstance())
+ {
+ OT_ASSERT(false);
+ }
+}
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
#endif // #if OPENTHREAD_ENABLE_NCP_VENDOR_HOOK
diff --git a/src/ncp/multipan_platform.cpp b/src/ncp/multipan_platform.cpp
new file mode 100644
index 000000000..92374e322
--- /dev/null
+++ b/src/ncp/multipan_platform.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * This file implements the multipan radio platform callbacks into OpenThread and default/weak radio platform APIs.
+ */
+
+#include <openthread/instance.h>
+#include <openthread/platform/multipan.h>
+
+#include "common/as_core_type.hpp"
+#include "common/code_utils.hpp"
+#include "instance/instance.hpp"
+#include "ncp/ncp_base.hpp"
+
+using namespace ot;
+
+//---------------------------------------------------------------------------------------------------------------------
+// otPlatRadio callbacks
+
+otInstance *otPlatMultipanIidToInstance(uint8_t aIid)
+{
+ Ncp::NcpBase *ncpBase = Ncp::NcpBase::GetNcpInstance();
+ OT_ASSERT(ncpBase);
+
+ return ncpBase->IidToInstance(aIid);
+}
+
+uint8_t otPlatMultipanInstanceToIid(otInstance *aInstance)
+{
+ Ncp::NcpBase *ncpBase = Ncp::NcpBase::GetNcpInstance();
+ OT_ASSERT(ncpBase);
+
+ return ncpBase->InstanceToIid(static_cast<ot::Instance *>(aInstance));
+}
+
+#if OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+
+void otPlatMultipanSwitchoverDone(otInstance *aInstance, bool success)
+{
+ Ncp::NcpBase *ncpBase = Ncp::NcpBase::GetNcpInstance();
+ OT_ASSERT(ncpBase);
+
+ ncpBase->NotifySwitchoverDone(aInstance, success);
+
+ return;
+}
+
+#else // OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+
+// default implementation
+OT_TOOL_WEAK void otPlatMultipanSwitchoverDone(otInstance *aInstance, bool success)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(success);
+}
+
+#endif // OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+
+//---------------------------------------------------------------------------------------------------------------------
+// Default/weak implementation of multipan APIs
+
+OT_TOOL_WEAK otError otPlatMultipanGetActiveInstance(otInstance **aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ return kErrorNotImplemented;
+}
+
+OT_TOOL_WEAK otError otPlatMultipanSetActiveInstance(otInstance *aInstance, bool aCompletePending)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aCompletePending);
+
+ return kErrorNotImplemented;
+}
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 780772879..e0b4c1881 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -55,6 +55,43 @@ namespace Ncp {
// MARK: Utility Functions
// ----------------------------------------------------------------------------
+uint8_t NcpBase::InstanceToIid(Instance *aInstance)
+{
+ uint8_t index = 0;
+
+ OT_UNUSED_VARIABLE(aInstance);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ index = SPINEL_HEADER_GET_IID(SPINEL_HEADER_IID_BROADCAST); // use broadcast if no match
+
+ for (int i = 0; i < kSpinelInterfaceCount; i++)
+ {
+ if (aInstance == mInstances[i])
+ {
+ index = i;
+ break;
+ }
+ }
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
+ return index;
+}
+
+Instance *NcpBase::IidToInstance(uint8_t aIid)
+{
+ Instance *instance;
+ OT_ASSERT(aIid < kSpinelInterfaceCount);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ instance = mInstances[aIid];
+#else
+ OT_UNUSED_VARIABLE(aIid);
+ instance = mInstance;
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
+ return instance;
+}
+
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
static bool HasOnly1BitSet(uint32_t aValue) { return aValue != 0 && ((aValue & (aValue - 1)) == 0); }
@@ -202,6 +239,29 @@ static spinel_status_t ResetReasonToSpinelStatus(otPlatResetReason aReason)
NcpBase *NcpBase::sNcpInstance = nullptr;
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+NcpBase::NcpBase(Instance **aInstances, uint8_t aCount)
+ : NcpBase(aInstances[0])
+{
+ OT_ASSERT(aCount > 0);
+ OT_ASSERT(aCount < SPINEL_HEADER_IID_MAX); // One IID reserved for broadcast
+
+ uint8_t skipped = 0;
+
+ for (int i = 0; i < aCount; i++)
+ {
+ if ((i + skipped) == SPINEL_HEADER_GET_IID(SPINEL_HEADER_IID_BROADCAST))
+ {
+ mInstances[i + skipped] = nullptr;
+ skipped++;
+ }
+
+ OT_ASSERT(i + skipped <= SPINEL_HEADER_IID_MAX);
+ mInstances[i + skipped] = aInstances[i];
+ }
+}
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
NcpBase::NcpBase(Instance *aInstance)
: mInstance(aInstance)
, mTxFrameBuffer(mTxBuffer, sizeof(mTxBuffer))
@@ -222,12 +282,10 @@ NcpBase::NcpBase(Instance *aInstance)
, mAllowPeekDelegate(nullptr)
, mAllowPokeDelegate(nullptr)
#endif
- , mNextExpectedTid(0)
, mResponseQueueHead(0)
, mResponseQueueTail(0)
, mAllowLocalNetworkDataChange(false)
, mRequireJoinExistingNetwork(false)
- , mIsRawStreamEnabled(false)
, mPcapEnabled(false)
, mDisableStreamWrite(false)
, mShouldEmitChildTableUpdate(false)
@@ -237,11 +295,7 @@ NcpBase::NcpBase(Instance *aInstance)
#if OPENTHREAD_FTD
, mPreferredRouteId(0)
#endif
-#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
- , mCurTransmitTID(0)
- , mCurScanChannel(kInvalidScanChannel)
- , mSrcMatchEnabled(false)
-#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
+ , mCurCommandIid(0)
#if OPENTHREAD_MTD || OPENTHREAD_FTD
, mInboundSecureIpFrameCounter(0)
, mInboundInsecureIpFrameCounter(0)
@@ -267,6 +321,13 @@ NcpBase::NcpBase(Instance *aInstance)
mTxFrameBuffer.SetFrameRemovedCallback(&NcpBase::HandleFrameRemovedFromNcpBuffer, this);
memset(&mResponseQueue, 0, sizeof(mResponseQueue));
+#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
+ memset(mCurTransmitTID, 0, sizeof(mCurTransmitTID));
+ memset(mSrcMatchEnabled, 0, sizeof(mSrcMatchEnabled));
+ memset(mCurScanChannel, kInvalidScanChannel, sizeof(mCurScanChannel));
+#endif
+ memset(mIsRawStreamEnabled, 0, sizeof(mIsRawStreamEnabled));
+ memset(mNextExpectedTid, 0, sizeof(mNextExpectedTid));
#if OPENTHREAD_MTD || OPENTHREAD_FTD
otMessageQueueInit(&mMessageQueue);
@@ -303,6 +364,8 @@ NcpBase::NcpBase(Instance *aInstance)
NcpBase *NcpBase::GetNcpInstance(void) { return sNcpInstance; }
+spinel_iid_t NcpBase::GetCurCommandIid(void) const { return mCurCommandIid; }
+
void NcpBase::ResetCounters(void)
{
mFramingErrorCounter = 0;
@@ -348,8 +411,20 @@ void NcpBase::HandleReceive(const uint8_t *aBuf, uint16_t aBufLength)
mRxSpinelFrameCounter++;
- // We only support IID zero for now.
- if (SPINEL_HEADER_GET_IID(header) != 0)
+ mCurCommandIid = SPINEL_HEADER_GET_IID(header);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ if (mCurCommandIid > SPINEL_HEADER_IID_MAX)
+#else
+ if (mCurCommandIid != 0)
+#endif
+ {
+ IgnoreError(WriteLastStatusFrame(header, SPINEL_STATUS_INVALID_INTERFACE));
+ ExitNow();
+ }
+
+ mInstance = IidToInstance(mCurCommandIid);
+ if (mInstance == nullptr)
{
IgnoreError(WriteLastStatusFrame(header, SPINEL_STATUS_INVALID_INTERFACE));
ExitNow();
@@ -378,12 +453,12 @@ void NcpBase::HandleReceive(const uint8_t *aBuf, uint16_t aBufLength)
tid = SPINEL_HEADER_GET_TID(header);
- if ((mNextExpectedTid != 0) && (tid != mNextExpectedTid))
+ if ((mNextExpectedTid[mCurCommandIid] != 0) && (tid != mNextExpectedTid[mCurCommandIid]))
{
mRxSpinelOutOfOrderTidCounter++;
}
- mNextExpectedTid = SPINEL_GET_NEXT_TID(tid);
+ mNextExpectedTid[mCurCommandIid] = SPINEL_GET_NEXT_TID(tid);
exit:
mDisableStreamWrite = false;
@@ -469,7 +544,7 @@ void NcpBase::IncrementFrameErrorCounter(void) { mFramingErrorCounter++; }
otError NcpBase::StreamWrite(int aStreamId, const uint8_t *aDataPtr, int aDataLen)
{
otError error = OT_ERROR_NONE;
- uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
+ uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID;
spinel_prop_key_t streamPropKey;
if (aStreamId == 0)
@@ -644,7 +719,7 @@ unsigned int NcpBase::ConvertLogRegion(otLogRegion aLogRegion)
void NcpBase::Log(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aLogString)
{
otError error = OT_ERROR_NONE;
- uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
+ uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID;
VerifyOrExit(!mDisableStreamWrite, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(SPINEL_PROP_STREAM_LOG));
@@ -699,6 +774,7 @@ uint8_t NcpBase::GetWrappedResponseQueueIndex(uint8_t aPosition)
otError NcpBase::EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned int aPropKeyOrStatus)
{
otError error = OT_ERROR_NONE;
+ spinel_iid_t iid = SPINEL_HEADER_GET_IID(aHeader);
spinel_tid_t tid = SPINEL_HEADER_GET_TID(aHeader);
ResponseEntry *entry;
@@ -731,13 +807,13 @@ otError NcpBase::EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned i
// get an out of sequence TID, check if we already have a response
// queued for this TID and if so mark the old entry as deleted.
- if (tid != mNextExpectedTid)
+ if (tid != mNextExpectedTid[iid])
{
for (uint8_t cur = mResponseQueueHead; cur < mResponseQueueTail; cur++)
{
entry = &mResponseQueue[GetWrappedResponseQueueIndex(cur)];
- if (entry->mIsInUse && (entry->mTid == tid))
+ if (entry->mIsInUse && (entry->mIid == iid) && (entry->mTid == tid))
{
// Entry is just marked here and will be removed
// from `SendQueuedResponses()`.
@@ -752,6 +828,7 @@ otError NcpBase::EnqueueResponse(uint8_t aHeader, ResponseType aType, unsigned i
entry = &mResponseQueue[GetWrappedResponseQueueIndex(mResponseQueueTail)];
+ entry->mIid = iid;
entry->mTid = tid;
entry->mIsInUse = true;
entry->mType = aType;
@@ -773,8 +850,8 @@ otError NcpBase::SendQueuedResponses(void)
if (entry.mIsInUse)
{
- uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
-
+ uint8_t header = SPINEL_HEADER_FLAG;
+ header |= SPINEL_HEADER_IID(entry.mIid);
header |= static_cast<uint8_t>(entry.mTid << SPINEL_HEADER_TID_SHIFT);
if (entry.mType == kResponseTypeLastStatus)
@@ -857,11 +934,11 @@ void NcpBase::UpdateChangedProps(void)
status = ResetReasonToSpinelStatus(otPlatGetResetReason(mInstance));
}
- SuccessOrExit(WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, status));
+ SuccessOrExit(WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID, status));
}
else if (mDidInitialUpdates)
{
- SuccessOrExit(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, propKey));
+ SuccessOrExit(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID, propKey));
}
mChangedPropsSet.RemoveEntry(index);
@@ -1102,7 +1179,7 @@ otError NcpBase::WriteLastStatusFrame(uint8_t aHeader, spinel_status_t aLastStat
{
otError error = OT_ERROR_NONE;
- if (SPINEL_HEADER_GET_IID(aHeader) == 0)
+ if (SPINEL_HEADER_GET_IID(aHeader) == SPINEL_HEADER_GET_IID(SPINEL_HEADER_TX_NOTIFICATION_IID))
{
mLastStatus = aLastStatus;
}
@@ -1201,16 +1278,24 @@ otError NcpBase::CommandHandler_RESET(uint8_t aHeader)
{
otInstanceResetRadioStack(mInstance);
- mIsRawStreamEnabled = false;
- mCurTransmitTID = 0;
- mCurScanChannel = kInvalidScanChannel;
- mSrcMatchEnabled = false;
+ mIsRawStreamEnabled[mCurCommandIid] = false;
+ mCurTransmitTID[mCurCommandIid] = 0;
+ mCurScanChannel[mCurCommandIid] = kInvalidScanChannel;
+ mSrcMatchEnabled[mCurCommandIid] = false;
ResetCounters();
- SuccessOrAssert(
- error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_RESET_POWER_ON));
+ SuccessOrAssert(error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID,
+ SPINEL_STATUS_RESET_POWER_ON));
}
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+ else if (reset_type == SPINEL_RESET_BOOTLOADER)
+ {
+ // Signal a platform reset to bootloader mode.
+ // If implemented, this function shouldn't return.
+ error = otInstanceResetToBootloader(mInstance);
+ }
+#endif
else
#endif
{
@@ -1393,7 +1478,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN>(void)
// Make sure we are update the receiving channel if raw link is enabled and we have raw
// stream enabled already
- if (otLinkRawIsEnabled(mInstance) && mIsRawStreamEnabled)
+ if (otLinkRawIsEnabled(mInstance) && mIsRawStreamEnabled[mCurCommandIid])
{
error = otLinkRawReceive(mInstance);
}
@@ -1452,6 +1537,18 @@ exit:
return error;
}
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE>(void)
+{
+ bool enabled;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadBool(enabled));
+ otPlatRadioSetRxOnWhenIdle(mInstance, enabled);
+
+exit:
+ return error;
+}
+
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_15_4_PANID>(void)
{
return mEncoder.WriteUint16(otLinkGetPanId(mInstance));
@@ -1495,7 +1592,7 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_15_4_SADDR>(void)
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_RAW_STREAM_ENABLED>(void)
{
- return mEncoder.WriteBool(mIsRawStreamEnabled);
+ return mEncoder.WriteBool(mIsRawStreamEnabled[mCurCommandIid]);
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RAW_STREAM_ENABLED>(void)
@@ -1521,7 +1618,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RAW_STREAM_ENABLE
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
- mIsRawStreamEnabled = enabled;
+ mIsRawStreamEnabled[mCurCommandIid] = enabled;
exit:
return error;
@@ -1610,7 +1707,8 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_STATE>(void)
if (otLinkRawIsEnabled(mInstance))
{
- scanState = (mCurScanChannel == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE : SPINEL_SCAN_STATE_ENERGY;
+ scanState = (mCurScanChannel[mCurCommandIid] == kInvalidScanChannel) ? SPINEL_SCAN_STATE_IDLE
+ : SPINEL_SCAN_STATE_ENERGY;
}
else
@@ -1668,11 +1766,11 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
// Make sure we aren't already scanning and that we have
// only 1 bit set for the channel mask.
- VerifyOrExit(mCurScanChannel == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
+ VerifyOrExit(mCurScanChannel[mCurCommandIid] == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(HasOnly1BitSet(mScanChannelMask), error = OT_ERROR_INVALID_ARGS);
- scanChannel = IndexOfMSB(mScanChannelMask);
- mCurScanChannel = static_cast<int8_t>(scanChannel);
+ scanChannel = IndexOfMSB(mScanChannelMask);
+ mCurScanChannel[mCurCommandIid] = static_cast<int8_t>(scanChannel);
error = otLinkRawEnergyScan(mInstance, scanChannel, mScanPeriod, LinkRawEnergyScanDone);
}
@@ -1748,8 +1846,8 @@ exit:
if (error != OT_ERROR_NONE)
{
- IgnoreError(
- WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_PROP_UNSOL_UPDATE_FILTER));
+ IgnoreError(WritePropertyValueIsFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID,
+ SPINEL_PROP_UNSOL_UPDATE_FILTER));
}
return error;
@@ -1843,6 +1941,10 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_MIN_HOST_API_VERSION));
#endif
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+ SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_RCP_RESET_TO_BOOTLOADER));
+#endif
+
#if OPENTHREAD_PLATFORM_POSIX
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_POSIX));
#endif
@@ -1972,7 +2074,19 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NCP_VERSION>(void)
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_INTERFACE_COUNT>(void)
{
- return mEncoder.WriteUint8(1); // Only one interface for now
+ uint8_t instances = 1;
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ instances = 0;
+ for (uint8_t i = 0; i <= SPINEL_HEADER_IID_MAX; i++)
+ {
+ if (mInstances[i] != nullptr)
+ {
+ instances++;
+ }
+ }
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
+ return mEncoder.WriteUint8(instances);
}
#if OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index bd1110124..7b8d94f87 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -55,13 +55,27 @@
#endif
#include "changed_props_set.hpp"
-#include "common/instance.hpp"
#include "common/tasklet.hpp"
+#include "instance/instance.hpp"
#include "lib/spinel/spinel.h"
#include "lib/spinel/spinel_buffer.hpp"
#include "lib/spinel/spinel_decoder.hpp"
#include "lib/spinel/spinel_encoder.hpp"
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+#define SPINEL_HEADER_IID_BROADCAST OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID
+#else
+#define SPINEL_HEADER_IID_BROADCAST SPINEL_HEADER_IID_0
+#endif
+
+// In case of host<->ncp<->rcp configuration, notifications shall be
+// received on broadcast iid on ncp, but transmitted on IID 0 to host.
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+#define SPINEL_HEADER_TX_NOTIFICATION_IID SPINEL_HEADER_IID_BROADCAST
+#else
+#define SPINEL_HEADER_TX_NOTIFICATION_IID SPINEL_HEADER_IID_0
+#endif
+
namespace ot {
namespace Ncp {
@@ -72,6 +86,11 @@ public:
{
kSpinelCmdHeaderSize = 2, ///< Size of spinel command header (in bytes).
kSpinelPropIdSize = 3, ///< Size of spinel property identifier (in bytes).
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_RADIO
+ kSpinelInterfaceCount = SPINEL_HEADER_IID_MAX + 1, // Number of supported spinel interfaces
+#else
+ kSpinelInterfaceCount = 1, // Only one interface supported in single instance configuration
+#endif
};
/**
@@ -82,6 +101,18 @@ public:
*/
explicit NcpBase(Instance *aInstance);
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ /**
+ * Creates and initializes an NcpBase instance.
+ *
+ * @param[in] aInstances The OpenThread instances structure pointer array.
+ * @param[in] aCount Number of the instances in the array.
+ *
+ */
+ explicit NcpBase(Instance **aInstances, uint8_t aCount);
+
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
/**
* Returns the pointer to the single NCP instance.
*
@@ -91,6 +122,50 @@ public:
static NcpBase *GetNcpInstance(void);
/**
+ * Returns an IID for the given instance
+ *
+ * Returned IID is an integer value that must be shifted by SPINEL_HEADER_IID_SHIFT before putting into spinel
+ * header. If multipan interface is not enabled or build is not for RCP IID=0 is returned. If nullptr is passed it
+ * matches broadcast IID in current implementation. Broadcast IID is also returned in case no match was found.
+ *
+ * @param[in] aInstance Instance pointer to match with IID
+ *
+ * @returns Spinel Interface Identifier to use for communication for this instance
+ *
+ */
+ uint8_t InstanceToIid(Instance *aInstance);
+
+ /**
+ * Returns an OT instance for the given IID
+ *
+ * Returns an OpenThread instance object associated to the given IID.
+ * If multipan interface is not enabled or build is not for RCP returned value is the same instance object
+ * regardless of the aIid parameter In current implementation nullptr is returned for broadcast IID and values
+ * exceeding the instances count but lower than kSpinelInterfaceCount.
+ *
+ * @param[in] aIid IID used in the Spinel communication
+ *
+ * @returns OpenThread instance object associated with the given IID
+ *
+ */
+ Instance *IidToInstance(uint8_t aIid);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ /**
+ * Called to send notification to host about switchower results.
+ */
+ void NotifySwitchoverDone(otInstance *aInstance, bool aSuccess);
+#endif
+
+ /**
+ * This method returns the IID of the current spinel command.
+ *
+ * @returns IID.
+ *
+ */
+ spinel_iid_t GetCurCommandIid(void) const;
+
+ /**
* Sends data to host via specific stream.
*
*
@@ -151,6 +226,8 @@ public:
bool ShouldDeferHostSend(void);
protected:
+ static constexpr uint8_t kBitsPerByte = 8; ///< Number of bits in a byte.
+
typedef otError (NcpBase::*PropertyHandler)(void);
/**
@@ -170,6 +247,7 @@ protected:
*/
struct ResponseEntry
{
+ uint8_t mIid : 2; ///< Spinel interface id.
uint8_t mTid : 4; ///< Spinel transaction id.
bool mIsInUse : 1; ///< `true` if this entry is in use, `false` otherwise.
ResponseType mType : 2; ///< Response type.
@@ -244,17 +322,26 @@ protected:
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
otError PackRadioFrame(otRadioFrame *aFrame, otError aError);
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ void NotifySwitchoverDone(bool aSuccess);
+#endif
+
static void LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
- void LinkRawReceiveDone(otRadioFrame *aFrame, otError aError);
+ void LinkRawReceiveDone(uint8_t aIid, otRadioFrame *aFrame, otError aError);
static void LinkRawTransmitDone(otInstance *aInstance,
otRadioFrame *aFrame,
otRadioFrame *aAckFrame,
otError aError);
- void LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
+ void LinkRawTransmitDone(uint8_t aIid, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
static void LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi);
- void LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi);
+ void LinkRawEnergyScanDone(uint8_t aIid, int8_t aEnergyScanMaxRssi);
+
+ static inline uint8_t GetNcpBaseIid(otInstance *aInstance)
+ {
+ return sNcpInstance->InstanceToIid(static_cast<Instance *>(aInstance));
+ }
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
@@ -532,11 +619,6 @@ protected:
static NcpBase *sNcpInstance;
static spinel_status_t ThreadErrorToSpinelStatus(otError aError);
static uint8_t LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aDeviceType, bool aNetworkData);
- Instance *mInstance;
- Spinel::Buffer mTxFrameBuffer;
- Spinel::Encoder mEncoder;
- Spinel::Decoder mDecoder;
- bool mHostPowerStateInProgress;
enum
{
@@ -545,6 +627,15 @@ protected:
kInvalidScanChannel = -1, // Invalid scan channel.
};
+ Instance *mInstance;
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_RADIO
+ Instance *mInstances[kSpinelInterfaceCount];
+#endif
+ Spinel::Buffer mTxFrameBuffer;
+ Spinel::Encoder mEncoder;
+ Spinel::Decoder mDecoder;
+ bool mHostPowerStateInProgress;
+
spinel_status_t mLastStatus;
uint32_t mScanChannelMask;
uint16_t mScanPeriod;
@@ -567,7 +658,7 @@ protected:
uint8_t mTxBuffer[kTxBufferSize];
- spinel_tid_t mNextExpectedTid;
+ spinel_tid_t mNextExpectedTid[kSpinelInterfaceCount];
uint8_t mResponseQueueHead;
uint8_t mResponseQueueTail;
@@ -575,7 +666,7 @@ protected:
bool mAllowLocalNetworkDataChange;
bool mRequireJoinExistingNetwork;
- bool mIsRawStreamEnabled;
+ bool mIsRawStreamEnabled[kSpinelInterfaceCount];
bool mPcapEnabled;
bool mDisableStreamWrite;
bool mShouldEmitChildTableUpdate;
@@ -589,11 +680,12 @@ protected:
#endif
uint8_t mPreferredRouteId;
#endif
+ uint8_t mCurCommandIid;
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
- uint8_t mCurTransmitTID;
- int8_t mCurScanChannel;
- bool mSrcMatchEnabled;
+ uint8_t mCurTransmitTID[kSpinelInterfaceCount];
+ int8_t mCurScanChannel[kSpinelInterfaceCount];
+ bool mSrcMatchEnabled[kSpinelInterfaceCount];
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
#if OPENTHREAD_MTD || OPENTHREAD_FTD
diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp
index 6fc426785..e653f8311 100644
--- a/src/ncp/ncp_base_dispatcher.cpp
+++ b/src/ncp/ncp_base_dispatcher.cpp
@@ -217,6 +217,9 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_RCP_CSL_UNCERTAINTY),
#endif
+#if OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE),
+#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_LIST),
@@ -430,6 +433,7 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_PROMISCUOUS_MODE),
#if OPENTHREAD_MTD || OPENTHREAD_FTD
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_DATA_POLL_PERIOD),
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_MODE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_IF_UP),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_STACK_UP),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NET_ROLE),
@@ -488,6 +492,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_ENH_ACK_PROBING),
#endif
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
+#if OPENTHREAD_RADIO && OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE),
+#endif
#if OPENTHREAD_MTD || OPENTHREAD_FTD
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER),
#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp
index 2ba875165..b0d723312 100644
--- a/src/ncp/ncp_base_ftd.cpp
+++ b/src/ncp/ncp_base_ftd.cpp
@@ -50,7 +50,7 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
#include "meshcop/commissioner.hpp"
#endif
diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp
index 70d958982..f5b06dd55 100644
--- a/src/ncp/ncp_base_mtd.cpp
+++ b/src/ncp/ncp_base_mtd.cpp
@@ -70,8 +70,8 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/string.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_MTD || OPENTHREAD_FTD
@@ -2432,7 +2432,7 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MONITOR_CHANN
{
otError error = OT_ERROR_NONE;
uint32_t channelMask = otLinkGetSupportedChannelMask(mInstance);
- uint8_t channelNum = sizeof(channelMask) * CHAR_BIT;
+ uint8_t channelNum = sizeof(channelMask) * kBitsPerByte;
for (uint8_t channel = 0; channel < channelNum; channel++)
{
diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp
index 11ec6aa0d..cad3ef52d 100644
--- a/src/ncp/ncp_base_radio.cpp
+++ b/src/ncp/ncp_base_radio.cpp
@@ -35,12 +35,13 @@
#include <openthread/link.h>
#include <openthread/link_raw.h>
#include <openthread/ncp.h>
+#include <openthread/platform/multipan.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/time.h>
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_frame.hpp"
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
@@ -123,15 +124,32 @@ exit:
return error;
}
-void NcpBase::LinkRawReceiveDone(otInstance *, otRadioFrame *aFrame, otError aError)
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+void NcpBase::NotifySwitchoverDone(otInstance *aInstance, bool aSuccess)
{
- sNcpInstance->LinkRawReceiveDone(aFrame, aError);
+ OT_UNUSED_VARIABLE(aInstance);
+ NotifySwitchoverDone(aSuccess);
}
-void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
+void NcpBase::NotifySwitchoverDone(bool aSuccess)
{
- uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
+ uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_TX_NOTIFICATION_IID;
+ spinel_status_t result = aSuccess ? SPINEL_STATUS_SWITCHOVER_DONE : SPINEL_STATUS_SWITCHOVER_FAILED;
+ IgnoreError(WriteLastStatusFrame(header, result));
+}
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+
+void NcpBase::LinkRawReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
+{
+ sNcpInstance->LinkRawReceiveDone(GetNcpBaseIid(aInstance), aFrame, aError);
+}
+
+void NcpBase::LinkRawReceiveDone(uint8_t aIid, otRadioFrame *aFrame, otError aError)
+{
+ uint8_t header = SPINEL_HEADER_FLAG;
+
+ header |= SPINEL_HEADER_IID(aIid);
// Append frame header
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW));
@@ -142,23 +160,24 @@ exit:
return;
}
-void NcpBase::LinkRawTransmitDone(otInstance *, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
+void NcpBase::LinkRawTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
- sNcpInstance->LinkRawTransmitDone(aFrame, aAckFrame, aError);
+ sNcpInstance->LinkRawTransmitDone(GetNcpBaseIid(aInstance), aFrame, aAckFrame, aError);
}
-void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
+void NcpBase::LinkRawTransmitDone(uint8_t aIid, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
OT_UNUSED_VARIABLE(aFrame);
+ OT_ASSERT(aIid < kSpinelInterfaceCount);
- if (mCurTransmitTID)
+ if (mCurTransmitTID[aIid])
{
- uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | mCurTransmitTID;
+ uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID(aIid) | mCurTransmitTID[aIid];
bool framePending = (aAckFrame != nullptr && static_cast<Mac::RxFrame *>(aAckFrame)->GetFramePending());
bool headerUpdated = static_cast<Mac::TxFrame *>(aFrame)->IsHeaderUpdated();
// Clear cached transmit TID
- mCurTransmitTID = 0;
+ mCurTransmitTID[aIid] = 0;
SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_LAST_STATUS));
SuccessOrExit(mEncoder.WriteUintPacked(ThreadErrorToSpinelStatus(aError)));
@@ -190,23 +209,24 @@ exit:
return;
}
-void NcpBase::LinkRawEnergyScanDone(otInstance *, int8_t aEnergyScanMaxRssi)
+void NcpBase::LinkRawEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi)
{
- sNcpInstance->LinkRawEnergyScanDone(aEnergyScanMaxRssi);
+ sNcpInstance->LinkRawEnergyScanDone(GetNcpBaseIid(aInstance), aEnergyScanMaxRssi);
}
-void NcpBase::LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi)
+void NcpBase::LinkRawEnergyScanDone(uint8_t aIid, int8_t aEnergyScanMaxRssi)
{
- int8_t scanChannel = mCurScanChannel;
+ OT_ASSERT(aIid < kSpinelInterfaceCount);
+ int8_t scanChannel = mCurScanChannel[aIid];
// Clear current scan channel
- mCurScanChannel = kInvalidScanChannel;
+ mCurScanChannel[aIid] = kInvalidScanChannel;
// Make sure we are back listening on the original receive channel,
// since the energy scan could have been on a different channel.
- IgnoreError(otLinkRawReceive(mInstance));
+ IgnoreError(otLinkRawReceive(IidToInstance(aIid)));
- SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
+ SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID(aIid), SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_MAC_ENERGY_SCAN_RESULT));
SuccessOrExit(mEncoder.WriteUint8(static_cast<uint8_t>(scanChannel)));
@@ -215,7 +235,7 @@ void NcpBase::LinkRawEnergyScanDone(int8_t aEnergyScanMaxRssi)
// We are finished with the scan, so send out
// a property update indicating such.
- SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
+ SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID(aIid), SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_MAC_SCAN_STATE));
SuccessOrExit(mEncoder.WriteUint8(SPINEL_SCAN_STATE_IDLE));
@@ -233,7 +253,7 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RADIO_CAPS>(void)
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SRC_MATCH_ENABLED>(void)
{
// TODO: Would be good to add an `otLinkRaw` API to give the status of source match.
- return mEncoder.WriteBool(mSrcMatchEnabled);
+ return mEncoder.WriteBool(mSrcMatchEnabled[mCurCommandIid]);
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RCP_TIMESTAMP>(void)
@@ -250,9 +270,9 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SRC_MATCH_ENABLED
{
otError error = OT_ERROR_NONE;
- SuccessOrExit(error = mDecoder.ReadBool(mSrcMatchEnabled));
+ SuccessOrExit(error = mDecoder.ReadBool(mSrcMatchEnabled[mCurCommandIid]));
- error = otLinkRawSrcMatchEnable(mInstance, mSrcMatchEnabled);
+ error = otLinkRawSrcMatchEnable(mInstance, mSrcMatchEnabled[mCurCommandIid]);
exit:
return error;
@@ -386,6 +406,25 @@ exit:
return error;
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE>(void)
+{
+ uint8_t interface;
+ Instance *instance;
+ bool softSwitch;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = mDecoder.ReadUint8(interface));
+ softSwitch = (interface & SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_MASK) != 0;
+ instance = IidToInstance(interface & SPINEL_MULTIPAN_INTERFACE_ID_MASK);
+ VerifyOrExit(instance != nullptr, error = OT_ERROR_NOT_IMPLEMENTED); // Instance out of range
+ SuccessOrExit(error = otPlatMultipanSetActiveInstance(instance, softSwitch));
+
+exit:
+ return error;
+}
+#endif /* OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE */
+
otError NcpBase::DecodeStreamRawTxRequest(otRadioFrame &aFrame)
{
otError error;
@@ -449,8 +488,11 @@ exit:
otError NcpBase::HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader)
{
otError error = OT_ERROR_NONE;
+ uint8_t iid = SPINEL_HEADER_GET_IID(aHeader);
otRadioFrame *frame;
+ OT_ASSERT(iid < kSpinelInterfaceCount);
+
VerifyOrExit(otLinkRawIsEnabled(mInstance), error = OT_ERROR_INVALID_STATE);
frame = otLinkRawGetTransmitBuffer(mInstance);
@@ -463,7 +505,7 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader)
SuccessOrExit(error = otLinkRawTransmit(mInstance, &NcpBase::LinkRawTransmitDone));
// Cache the transaction ID for async response
- mCurTransmitTID = SPINEL_HEADER_GET_TID(aHeader);
+ mCurTransmitTID[iid] = SPINEL_HEADER_GET_TID(aHeader);
exit:
@@ -537,6 +579,22 @@ exit:
return error;
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE>(void)
+{
+ otInstance *instance;
+ spinel_iid_t iid;
+ otError error = OT_ERROR_NONE;
+
+ SuccessOrExit(error = otPlatMultipanGetActiveInstance(&instance));
+ iid = InstanceToIid(static_cast<Instance *>(instance));
+ SuccessOrExit(error = mEncoder.WriteUint8(static_cast<uint8_t>(iid)));
+
+exit:
+ return error;
+}
+#endif /* OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE */
+
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_ENH_ACK_PROBING>(void)
{
diff --git a/src/ncp/ncp_hdlc.cpp b/src/ncp/ncp_hdlc.cpp
index a18c345cb..9950de8a3 100644
--- a/src/ncp/ncp_hdlc.cpp
+++ b/src/ncp/ncp_hdlc.cpp
@@ -41,8 +41,8 @@
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/new.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_CONFIG_NCP_HDLC_ENABLE
@@ -77,6 +77,31 @@ extern "C" void otNcpHdlcInit(otInstance *aInstance, otNcpHdlcSendCallback aSend
}
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
+extern "C" void otNcpHdlcInitMulti(otInstance **aInstances, uint8_t aCount, otNcpHdlcSendCallback aSendCallback)
+{
+ NcpHdlc *ncpHdlc = nullptr;
+ ot::Instance *instances[SPINEL_HEADER_IID_MAX];
+
+ OT_ASSERT(aCount < SPINEL_HEADER_IID_MAX + 1);
+ OT_ASSERT(aCount > 0);
+ OT_ASSERT(aInstances[0] != nullptr);
+
+ for (int i = 0; i < aCount; i++)
+ {
+ instances[i] = static_cast<ot::Instance *>(aInstances[i]);
+ }
+
+ ncpHdlc = new (&sNcpRaw) NcpHdlc(instances, aCount, aSendCallback);
+
+ if (ncpHdlc == nullptr || ncpHdlc != NcpBase::GetNcpInstance())
+ {
+ OT_ASSERT(false);
+ }
+}
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
#endif // OPENTHREAD_ENABLE_NCP_VENDOR_HOOK == 0
NcpHdlc::NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback)
@@ -95,6 +120,26 @@ NcpHdlc::NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback)
mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this);
}
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
+NcpHdlc::NcpHdlc(Instance **aInstances, uint8_t aCount, otNcpHdlcSendCallback aSendCallback)
+ : NcpBase(aInstances, aCount)
+ , mSendCallback(aSendCallback)
+ , mFrameEncoder(mHdlcBuffer)
+ , mState(kStartingFrame)
+ , mByte(0)
+ , mHdlcSendImmediate(false)
+ , mHdlcSendTask(*aInstances[0], EncodeAndSend)
+#if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
+ , mTxFrameBufferEncrypterReader(mTxFrameBuffer)
+#endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
+{
+ mFrameDecoder.Init(mRxBuffer, &NcpHdlc::HandleFrame, this);
+ mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this);
+}
+
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
void NcpHdlc::HandleFrameAddedToNcpBuffer(void *aContext,
Spinel::Buffer::FrameTag aTag,
Spinel::Buffer::Priority aPriority,
diff --git a/src/ncp/ncp_hdlc.hpp b/src/ncp/ncp_hdlc.hpp
index d99ef96de..751611db2 100644
--- a/src/ncp/ncp_hdlc.hpp
+++ b/src/ncp/ncp_hdlc.hpp
@@ -59,6 +59,19 @@ public:
*/
explicit NcpHdlc(Instance *aInstance, otNcpHdlcSendCallback aSendCallback);
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+ /**
+ * Constructor
+ *
+ * @param[in] aInstancs The OpenThread instance pointers array.
+ * @param[in] aCount Number of instances in the array.
+ * @param[in] aSendCallback Callback for sending data.
+ *
+ */
+ explicit NcpHdlc(Instance **aInstances, uint8_t aCount, otNcpHdlcSendCallback aSendCallback);
+
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && OPENTHREAD_RADIO
+
/**
* Is called when uart tx is finished. It prepares and sends the next data chunk (if any) to uart.
*
diff --git a/src/ncp/ncp_spi.cpp b/src/ncp/ncp_spi.cpp
index 1cd4f9aab..c6d105156 100644
--- a/src/ncp/ncp_spi.cpp
+++ b/src/ncp/ncp_spi.cpp
@@ -40,8 +40,8 @@
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/new.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_CONFIG_NCP_SPI_ENABLE
diff --git a/src/posix/cli.cmake b/src/posix/cli.cmake
index 4b7347b40..a11ef0b85 100644
--- a/src/posix/cli.cmake
+++ b/src/posix/cli.cmake
@@ -50,6 +50,7 @@ target_link_libraries(ot-cli PRIVATE
openthread-posix
openthread-cli-ftd
openthread-hdlc
+ openthread-radio-spinel
openthread-spinel-rcp
${OT_MBEDTLS}
${READLINE_LINK_LIBRARIES}
diff --git a/src/posix/daemon.cmake b/src/posix/daemon.cmake
index dd726df27..dd19a2280 100644
--- a/src/posix/daemon.cmake
+++ b/src/posix/daemon.cmake
@@ -42,6 +42,7 @@ target_link_libraries(ot-daemon PRIVATE
openthread-ftd
openthread-posix
openthread-hdlc
+ openthread-radio-spinel
openthread-spinel-rcp
${OT_MBEDTLS}
ot-posix-config
diff --git a/src/posix/main.c b/src/posix/main.c
index db1dd7380..026c6c6eb 100644
--- a/src/posix/main.c
+++ b/src/posix/main.c
@@ -34,7 +34,6 @@
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt
index b367d8758..6dd328811 100644
--- a/src/posix/platform/CMakeLists.txt
+++ b/src/posix/platform/CMakeLists.txt
@@ -45,6 +45,13 @@ if(OT_DAEMON)
set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
endif()
+if(OT_MULTIPAN_RCP)
+ target_compile_definitions(ot-posix-config
+ INTERFACE "OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE=1"
+ )
+endif()
+
+
option(OT_POSIX_INSTALL_EXTERNAL_ROUTES "Install External Routes as IPv6 routes" ON)
if(OT_POSIX_INSTALL_EXTERNAL_ROUTES)
target_compile_definitions(ot-posix-config
@@ -117,7 +124,6 @@ endif()
add_library(openthread-posix
alarm.cpp
- backbone.cpp
backtrace.cpp
configuration.cpp
config_file.cpp
@@ -154,6 +160,7 @@ target_link_libraries(openthread-posix
openthread-cli-ftd
openthread-ftd
openthread-hdlc
+ openthread-radio-spinel
openthread-spinel-rcp
openthread-url
ot-config-ftd
diff --git a/src/posix/platform/backbone.cpp b/src/posix/platform/backbone.cpp
deleted file mode 100644
index 517dc90f1..000000000
--- a/src/posix/platform/backbone.cpp
+++ /dev/null
@@ -1,101 +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 the platform Backbone interface management on Linux.
- */
-
-#include "openthread-posix-config.h"
-
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
-
-#include "multicast_routing.hpp"
-#include "platform-posix.h"
-#include "common/code_utils.hpp"
-#include "posix/platform/mainloop.hpp"
-
-char gBackboneNetifName[IFNAMSIZ] = "";
-unsigned int gBackboneNetifIndex = 0;
-#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
-static ot::Posix::MulticastRoutingManager sMulticastRoutingManager;
-#endif
-
-void platformBackboneInit(const char *aInterfaceName)
-{
- if (aInterfaceName == nullptr || aInterfaceName[0] == '\0')
- {
- otLogWarnPlat("Backbone Router feature is disabled: infra/backbone interface is missing");
- ExitNow();
- }
-
- VerifyOrDie(strnlen(aInterfaceName, sizeof(gBackboneNetifName)) < sizeof(gBackboneNetifName),
- OT_EXIT_INVALID_ARGUMENTS);
- strcpy(gBackboneNetifName, aInterfaceName);
-
- gBackboneNetifIndex = if_nametoindex(gBackboneNetifName);
- VerifyOrDie(gBackboneNetifIndex > 0, OT_EXIT_FAILURE);
-
- otLogInfoPlat("Backbone interface is configured to %s (%d)", gBackboneNetifName, gBackboneNetifIndex);
-
-exit:
- return;
-}
-
-void platformBackboneSetUp(void)
-{
-#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
- sMulticastRoutingManager.SetUp();
-#endif
-}
-
-void platformBackboneTearDown(void)
-{
-#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
- sMulticastRoutingManager.TearDown();
-#endif
-}
-
-void platformBackboneDeinit(void)
-{
- gBackboneNetifIndex = 0;
-
- memset(gBackboneNetifName, 0, sizeof(gBackboneNetifName));
-}
-
-void platformBackboneStateChange(otInstance *aInstance, otChangedFlags aFlags)
-{
- OT_UNUSED_VARIABLE(aInstance);
- OT_UNUSED_VARIABLE(aFlags);
-
-#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
- sMulticastRoutingManager.HandleStateChange(aInstance, aFlags);
-#endif
-}
-
-#endif
diff --git a/src/posix/platform/configuration.cpp b/src/posix/platform/configuration.cpp
index 6510c4cf9..07f120840 100644
--- a/src/posix/platform/configuration.cpp
+++ b/src/posix/platform/configuration.cpp
@@ -43,6 +43,15 @@
namespace ot {
namespace Posix {
+#if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+const char Configuration::kKeyCalibratedPower[] = "calibrated_power";
+#endif
+const char Configuration::kKeyTargetPower[] = "target_power";
+const char Configuration::kKeyRegionDomainMapping[] = "region_domain_mapping";
+const char Configuration::kKeySupportedChannelMask[] = "supported_channel_mask";
+const char Configuration::kKeyPreferredChannelMask[] = "preferred_channel_mask";
+const char Configuration::kCommaDelimiter[] = ",";
+
otError Configuration::SetRegion(uint16_t aRegionCode)
{
otError error = OT_ERROR_NONE;
diff --git a/src/posix/platform/configuration.hpp b/src/posix/platform/configuration.hpp
index dd6c6a209..71c479ddb 100644
--- a/src/posix/platform/configuration.hpp
+++ b/src/posix/platform/configuration.hpp
@@ -55,8 +55,8 @@ class Configuration
{
public:
Configuration(void)
- : mFactoryConfigFile(kFactoryConfigFile)
- , mProductConfigFile(kProductConfigFile)
+ : mFactoryConfigFile(OPENTHREAD_POSIX_CONFIG_FACTORY_CONFIG_FILE)
+ , mProductConfigFile(OPENTHREAD_POSIX_CONFIG_PRODUCT_CONFIG_FILE)
, mRegionCode(0)
, mSupportedChannelMask(kDefaultChannelMask)
, mPreferredChannelMask(kDefaultChannelMask)
@@ -114,17 +114,17 @@ public:
bool IsValid(void) const;
private:
- const char *kFactoryConfigFile = OPENTHREAD_POSIX_CONFIG_FACTORY_CONFIG_FILE;
- const char *kProductConfigFile = OPENTHREAD_POSIX_CONFIG_PRODUCT_CONFIG_FILE;
- const char *kKeyCalibratedPower = "calibrated_power";
- const char *kKeyTargetPower = "target_power";
- const char *kKeyRegionDomainMapping = "region_domain_mapping";
- const char *kKeySupportedChannelMask = "supported_channel_mask";
- const char *kKeyPreferredChannelMask = "preferred_channel_mask";
- const char *kCommaDelimiter = ",";
- static constexpr uint16_t kMaxValueSize = 512;
- static constexpr uint16_t kRegionCodeWorldWide = 0x5757; // Region Code: "WW"
- static constexpr uint32_t kDefaultChannelMask = 0x7fff800; // Channel 11 ~ 26
+#if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+ static const char kKeyCalibratedPower[];
+#endif
+ static const char kKeyTargetPower[];
+ static const char kKeyRegionDomainMapping[];
+ static const char kKeySupportedChannelMask[];
+ static const char kKeyPreferredChannelMask[];
+ static const char kCommaDelimiter[];
+ static constexpr uint16_t kMaxValueSize = 512;
+ static constexpr uint16_t kRegionCodeWorldWide = 0x5757; // Region Code: "WW"
+ static constexpr uint32_t kDefaultChannelMask = 0x7fff800; // Channel 11 ~ 26
uint16_t StringToRegionCode(const char *aString) const
{
diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h
index 820cf2b1f..29dc3ee80 100644
--- a/src/posix/platform/include/openthread/openthread-system.h
+++ b/src/posix/platform/include/openthread/openthread-system.h
@@ -188,6 +188,14 @@ unsigned int otSysGetThreadNetifIndex(void);
const char *otSysGetInfraNetifName(void);
/**
+ * Returns the infrastructure network interface index.
+ *
+ * @returns The infrastructure network interface index.
+ *
+ */
+uint32_t otSysGetInfraNetifIndex(void);
+
+/**
* Returns the radio spinel metrics.
*
* @returns The radio spinel metrics.
diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp
index e86fdafed..626d12822 100644
--- a/src/posix/platform/infra_if.cpp
+++ b/src/posix/platform/infra_if.cpp
@@ -91,6 +91,7 @@ exit:
return ret;
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
const otIp6Address *aDestAddress,
const uint8_t *aBuffer,
@@ -98,6 +99,7 @@ otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
{
return ot::Posix::InfraNetif::Get().SendIcmp6Nd(aInfraIfIndex, *aDestAddress, aBuffer, aBufferLength);
}
+#endif
otError otPlatInfraIfDiscoverNat64Prefix(uint32_t aInfraIfIndex)
{
@@ -114,6 +116,8 @@ bool platformInfraIfIsRunning(void) { return ot::Posix::InfraNetif::Get().IsRunn
const char *otSysGetInfraNetifName(void) { return ot::Posix::InfraNetif::Get().GetNetifName(); }
+uint32_t otSysGetInfraNetifIndex(void) { return ot::Posix::InfraNetif::Get().GetNetifIndex(); }
+
uint32_t otSysGetInfraNetifFlags(void) { return ot::Posix::InfraNetif::Get().GetFlags(); }
void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCounters)
@@ -206,6 +210,7 @@ int CreateNetLinkSocket(void)
return sock;
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
otError InfraNetif::SendIcmp6Nd(uint32_t aInfraIfIndex,
const otIp6Address &aDestAddress,
const uint8_t *aBuffer,
@@ -279,6 +284,7 @@ otError InfraNetif::SendIcmp6Nd(uint32_t aInfraIfIndex,
exit:
return error;
}
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
bool InfraNetif::IsRunning(void) const
{
@@ -289,6 +295,7 @@ uint32_t InfraNetif::GetFlags(void) const
{
int sock;
struct ifreq ifReq;
+ uint32_t flags = 0;
OT_ASSERT(mInfraIfIndex != 0);
@@ -299,11 +306,20 @@ uint32_t InfraNetif::GetFlags(void) const
static_assert(sizeof(ifReq.ifr_name) >= sizeof(mInfraIfName), "mInfraIfName is not of appropriate size.");
strcpy(ifReq.ifr_name, mInfraIfName);
- VerifyOrDie(ioctl(sock, SIOCGIFFLAGS, &ifReq) != -1, OT_EXIT_ERROR_ERRNO);
+ if (ioctl(sock, SIOCGIFFLAGS, &ifReq) == -1)
+ {
+#if OPENTHREAD_POSIX_CONFIG_EXIT_ON_INFRA_NETIF_LOST_ENABLE
+ otLogCritPlat("The infra link %s may be lost. Exiting.", mInfraIfName);
+ DieNow(OT_EXIT_ERROR_ERRNO);
+#endif
+ ExitNow();
+ }
+ flags = static_cast<uint32_t>(ifReq.ifr_flags);
+exit:
close(sock);
- return static_cast<uint32_t>(ifReq.ifr_flags);
+ return flags;
}
void InfraNetif::CountAddresses(otSysInfraNetIfAddressCounters &aAddressCounters) const
@@ -342,6 +358,20 @@ exit:
return;
}
+#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
+void InfraNetif::HandleBackboneStateChange(otInstance *aInstance, otChangedFlags aFlags)
+{
+ OT_ASSERT(gInstance == aInstance);
+
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aFlags);
+
+#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+ mMulticastRoutingManager.HandleStateChange(aInstance, aFlags);
+#endif
+}
+#endif
+
bool InfraNetif::HasLinkLocalAddress(void) const
{
bool hasLla = false;
@@ -379,18 +409,23 @@ void InfraNetif::Init(void) { mNetLinkSocket = CreateNetLinkSocket(); }
void InfraNetif::SetInfraNetif(const char *aIfName, int aIcmp6Socket)
{
- uint32_t ifIndex = 0;
- otBorderRoutingState state = otBorderRoutingGetState(gInstance);
+ uint32_t ifIndex = 0;
- OT_ASSERT(gInstance != nullptr);
+ OT_UNUSED_VARIABLE(aIcmp6Socket);
+ OT_ASSERT(gInstance != nullptr);
VerifyOrDie(mNetLinkSocket != -1, OT_EXIT_INVALID_STATE);
- VerifyOrDie(state == OT_BORDER_ROUTING_STATE_UNINITIALIZED || state == OT_BORDER_ROUTING_STATE_DISABLED,
- OT_EXIT_INVALID_STATE);
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ SetInfraNetifIcmp6SocketForBorderRouting(aIcmp6Socket);
+#endif
+#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+ VerifyOrDie(!mMulticastRoutingManager.IsEnabled(), OT_EXIT_INVALID_STATE);
+#endif
if (aIfName == nullptr || aIfName[0] == '\0')
{
- otLogWarnPlat("Border Routing feature is disabled: infra/backbone interface is missing");
+ otLogWarnPlat("Border Routing/Backbone Router feature is disabled: infra interface is missing");
ExitNow();
}
@@ -407,12 +442,6 @@ void InfraNetif::SetInfraNetif(const char *aIfName, int aIcmp6Socket)
mInfraIfIndex = ifIndex;
- if (mInfraIfIcmp6Socket != -1)
- {
- close(mInfraIfIcmp6Socket);
- }
- mInfraIfIcmp6Socket = aIcmp6Socket;
-
exit:
return;
}
@@ -422,8 +451,15 @@ void InfraNetif::SetUp(void)
OT_ASSERT(gInstance != nullptr);
VerifyOrExit(mNetLinkSocket != -1);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
SuccessOrDie(otBorderRoutingInit(gInstance, mInfraIfIndex, platformInfraIfIsRunning()));
SuccessOrDie(otBorderRoutingSetEnabled(gInstance, /* aEnabled */ true));
+#endif
+
+#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+ mMulticastRoutingManager.SetUp();
+#endif
+
Mainloop::Manager::Get().Add(*this);
exit:
return;
@@ -431,17 +467,26 @@ exit:
void InfraNetif::TearDown(void)
{
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
IgnoreError(otBorderRoutingSetEnabled(gInstance, false));
+#endif
+
+#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+ mMulticastRoutingManager.TearDown();
+#endif
+
Mainloop::Manager::Get().Remove(*this);
}
void InfraNetif::Deinit(void)
{
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
if (mInfraIfIcmp6Socket != -1)
{
close(mInfraIfIcmp6Socket);
mInfraIfIcmp6Socket = -1;
}
+#endif
if (mNetLinkSocket != -1)
{
@@ -449,16 +494,20 @@ void InfraNetif::Deinit(void)
mNetLinkSocket = -1;
}
- mInfraIfIndex = 0;
+ mInfraIfName[0] = '\0';
+ mInfraIfIndex = 0;
}
void InfraNetif::Update(otSysMainloopContext &aContext)
{
- VerifyOrExit(mInfraIfIcmp6Socket != -1);
VerifyOrExit(mNetLinkSocket != -1);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ VerifyOrExit(mInfraIfIcmp6Socket != -1);
+
FD_SET(mInfraIfIcmp6Socket, &aContext.mReadFdSet);
aContext.mMaxFd = OT_MAX(aContext.mMaxFd, mInfraIfIcmp6Socket);
+#endif
FD_SET(mNetLinkSocket, &aContext.mReadFdSet);
aContext.mMaxFd = OT_MAX(aContext.mMaxFd, mNetLinkSocket);
@@ -496,7 +545,9 @@ void InfraNetif::ReceiveNetLinkMessage(void)
case RTM_DELADDR:
case RTM_NEWLINK:
case RTM_DELLINK:
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
SuccessOrDie(otPlatInfraIfStateChanged(gInstance, mInfraIfIndex, platformInfraIfIsRunning()));
+#endif
break;
case NLMSG_ERROR:
{
@@ -515,6 +566,7 @@ exit:
return;
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
void InfraNetif::ReceiveIcmp6Message(void)
{
otError error = OT_ERROR_NONE;
@@ -586,6 +638,7 @@ exit:
otLogDebgPlat("Failed to handle ICMPv6 message: %s", otThreadErrorToString(error));
}
}
+#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#if OPENTHREAD_POSIX_CONFIG_NAT64_AIL_PREFIX_ENABLE
const char InfraNetif::kWellKnownIpv4OnlyName[] = "ipv4only.arpa";
@@ -661,7 +714,9 @@ void InfraNetif::DiscoverNat64PrefixDone(union sigval sv)
}
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
otPlatInfraIfDiscoverNat64PrefixDone(gInstance, Get().mInfraIfIndex, &prefix);
+#endif
exit:
freeaddrinfo(res);
@@ -671,9 +726,9 @@ exit:
otError InfraNetif::DiscoverNat64Prefix(uint32_t aInfraIfIndex)
{
- otError error = OT_ERROR_NONE;
- struct addrinfo *hints = nullptr;
- struct gaicb *reqs[1];
+ otError error = OT_ERROR_NONE;
+ struct addrinfo *hints = nullptr;
+ struct gaicb *reqs[1] = {nullptr};
struct sigevent sig;
int status;
@@ -716,15 +771,35 @@ exit:
}
#endif // OPENTHREAD_POSIX_CONFIG_NAT64_AIL_PREFIX_ENABLE
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+void InfraNetif::SetInfraNetifIcmp6SocketForBorderRouting(int aIcmp6Socket)
+{
+ otBorderRoutingState state = otBorderRoutingGetState(gInstance);
+
+ VerifyOrDie(state == OT_BORDER_ROUTING_STATE_UNINITIALIZED || state == OT_BORDER_ROUTING_STATE_DISABLED,
+ OT_EXIT_INVALID_STATE);
+
+ if (mInfraIfIcmp6Socket != -1)
+ {
+ close(mInfraIfIcmp6Socket);
+ }
+ mInfraIfIcmp6Socket = aIcmp6Socket;
+}
+#endif
+
void InfraNetif::Process(const otSysMainloopContext &aContext)
{
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
VerifyOrExit(mInfraIfIcmp6Socket != -1);
+#endif
VerifyOrExit(mNetLinkSocket != -1);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
if (FD_ISSET(mInfraIfIcmp6Socket, &aContext.mReadFdSet))
{
ReceiveIcmp6Message();
}
+#endif
if (FD_ISSET(mNetLinkSocket, &aContext.mReadFdSet))
{
diff --git a/src/posix/platform/infra_if.hpp b/src/posix/platform/infra_if.hpp
index b468e10a1..e8aedd2f9 100644
--- a/src/posix/platform/infra_if.hpp
+++ b/src/posix/platform/infra_if.hpp
@@ -37,6 +37,7 @@
#include <openthread/nat64.h>
#include <openthread/openthread-system.h>
+#include "multicast_routing.hpp"
#include "core/common/non_copyable.hpp"
#include "posix/platform/mainloop.hpp"
@@ -82,7 +83,8 @@ public:
* Sets the infrastructure network interface.
*
* @param[in] aIfName A pointer to infrastructure network interface name.
- * @param[in] aIcmp6Socket A SOCK_RAW socket for sending/receiving ICMPv6 messages.
+ * @param[in] aIcmp6Socket A SOCK_RAW socket for sending/receiving ICMPv6 messages. If you don't need border
+ * routing feature, you can pass in -1.
*
*/
void SetInfraNetif(const char *aIfName, int aIcmp6Socket);
@@ -134,6 +136,15 @@ public:
void CountAddresses(otSysInfraNetIfAddressCounters &aAddressCounters) const;
/**
+ * Handles the backbone state change events.
+ *
+ * @param[in] aInstance A pointer to the OpenThread instance.
+ * @param[in] aFlags Flags that denote the state change events.
+ *
+ */
+ void HandleBackboneStateChange(otInstance *aInstance, otChangedFlags aFlags);
+
+ /**
* Sends an ICMPv6 Neighbor Discovery message on given infrastructure interface.
*
* See RFC 4861: https://tools.ietf.org/html/rfc4861.
@@ -177,6 +188,14 @@ public:
const char *GetNetifName(void) const { return (mInfraIfIndex != 0) ? mInfraIfName : nullptr; }
/**
+ * Gets the infrastructure network interface index.
+ *
+ * @returns The infrastructure network interface index.
+ *
+ */
+ uint32_t GetNetifIndex(void) const { return mInfraIfIndex; }
+
+ /**
* Gets the infrastructure network interface singleton.
*
* @returns The singleton object.
@@ -201,14 +220,22 @@ private:
static const uint8_t kValidNat64PrefixLength[];
char mInfraIfName[IFNAMSIZ];
- uint32_t mInfraIfIndex = 0;
- int mInfraIfIcmp6Socket = -1;
- int mNetLinkSocket = -1;
+ uint32_t mInfraIfIndex = 0;
+ int mNetLinkSocket = -1;
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ int mInfraIfIcmp6Socket = -1;
+#endif
+#if OPENTHREAD_POSIX_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
+ MulticastRoutingManager mMulticastRoutingManager;
+#endif
void ReceiveNetLinkMessage(void);
- void ReceiveIcmp6Message(void);
bool HasLinkLocalAddress(void) const;
static void DiscoverNat64PrefixDone(union sigval sv);
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ void SetInfraNetifIcmp6SocketForBorderRouting(int aIcmp6Socket);
+ void ReceiveIcmp6Message(void);
+#endif
};
} // namespace Posix
diff --git a/src/posix/platform/multicast_routing.cpp b/src/posix/platform/multicast_routing.cpp
index abced8c4d..40af863a6 100644
--- a/src/posix/platform/multicast_routing.cpp
+++ b/src/posix/platform/multicast_routing.cpp
@@ -159,7 +159,7 @@ void MulticastRoutingManager::UpdateMldReport(const Ip6::Address &aAddress, bool
struct ipv6_mreq ipv6mr;
otError error = OT_ERROR_NONE;
- ipv6mr.ipv6mr_interface = if_nametoindex(gBackboneNetifName);
+ ipv6mr.ipv6mr_interface = if_nametoindex(otSysGetInfraNetifName());
memcpy(&ipv6mr.ipv6mr_multiaddr, aAddress.GetBytes(), sizeof(ipv6mr.ipv6mr_multiaddr));
error = (setsockopt(mMulticastRouterSock, IPPROTO_IPV6, (isAdd ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP),
(void *)&ipv6mr, sizeof(ipv6mr))
@@ -243,7 +243,7 @@ void MulticastRoutingManager::InitMulticastRouterSock(void)
// Add Backbone network interface to MIF
mif6ctl.mif6c_mifi = kMifIndexBackbone;
- mif6ctl.mif6c_pifi = if_nametoindex(gBackboneNetifName);
+ mif6ctl.mif6c_pifi = otSysGetInfraNetifIndex();
VerifyOrDie(mif6ctl.mif6c_pifi > 0, OT_EXIT_ERROR_ERRNO);
VerifyOrDie(0 == setsockopt(mMulticastRouterSock, IPPROTO_IPV6, MRT6_ADD_MIF, &mif6ctl, sizeof(mif6ctl)),
OT_EXIT_ERROR_ERRNO);
diff --git a/src/posix/platform/multicast_routing.hpp b/src/posix/platform/multicast_routing.hpp
index 08d87ca58..c4d7e32fd 100644
--- a/src/posix/platform/multicast_routing.hpp
+++ b/src/posix/platform/multicast_routing.hpp
@@ -58,6 +58,7 @@ public:
{
}
+ bool IsEnabled(void) const { return mMulticastRouterSock >= 0; }
void SetUp(void);
void TearDown(void);
void Update(otSysMainloopContext &aContext) override;
@@ -110,7 +111,6 @@ private:
void Remove(const Ip6::Address &aAddress);
void UpdateMldReport(const Ip6::Address &aAddress, bool isAdd);
bool HasMulticastListener(const Ip6::Address &aAddress) const;
- bool IsEnabled(void) const { return mMulticastRouterSock >= 0; }
void InitMulticastRouterSock(void);
void FinalizeMulticastRouterSock(void);
void ProcessMulticastRouterMessages(void);
diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp
index 331c0d747..3d546eb3c 100644
--- a/src/posix/platform/netif.cpp
+++ b/src/posix/platform/netif.cpp
@@ -291,40 +291,22 @@ static bool sIsSyncingState = false;
#define OPENTHREAD_POSIX_LOG_TUN_PACKETS 0
-#if !defined(__linux__)
-static bool UnicastAddressIsSubscribed(otInstance *aInstance, const otNetifAddress *netAddr)
-{
- const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance);
-
- while (address != nullptr)
- {
- if (memcmp(address->mAddress.mFields.m8, netAddr->mAddress.mFields.m8, sizeof(address->mAddress.mFields.m8)) ==
- 0)
- {
- return true;
- }
-
- address = address->mNext;
- }
-
- return false;
-}
-#endif
-
#if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
static const uint8_t allOnes[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+#define BITS_PER_BYTE 8
+#define MAX_PREFIX_LENGTH (OT_IP6_ADDRESS_SIZE * BITS_PER_BYTE)
+
static void InitNetaskWithPrefixLength(struct in6_addr *address, uint8_t prefixLen)
{
-#define MAX_PREFIX_LENGTH (OT_IP6_ADDRESS_SIZE * CHAR_BIT)
+ ot::Ip6::Address addr;
+
if (prefixLen > MAX_PREFIX_LENGTH)
{
prefixLen = MAX_PREFIX_LENGTH;
}
- ot::Ip6::Address addr;
-
addr.Clear();
addr.SetPrefix(allOnes, prefixLen);
memcpy(address, addr.mFields.m8, sizeof(addr.mFields.m8));
@@ -918,6 +900,7 @@ exit:
static void processNat64StateChange(void)
{
otIp4Cidr translatorCidr;
+ otError error = OT_ERROR_NONE;
// Skip if NAT64 translator has not been configured with a CIDR.
SuccessOrExit(otNat64GetCidr(gInstance, &translatorCidr));
@@ -928,7 +911,10 @@ static void processNat64StateChange(void)
if (sActiveNat64Cidr.mLength != 0)
{
- DeleteIp4Route(sActiveNat64Cidr);
+ if ((error = DeleteIp4Route(sActiveNat64Cidr)) != OT_ERROR_NONE)
+ {
+ otLogWarnPlat("[netif] failed to delete route for NAT64: %s", otThreadErrorToString(error));
+ }
}
sActiveNat64Cidr = translatorCidr;
@@ -938,12 +924,18 @@ static void processNat64StateChange(void)
if (otNat64GetTranslatorState(gInstance) == OT_NAT64_STATE_ACTIVE)
{
- AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority);
+ if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
+ {
+ otLogWarnPlat("[netif] failed to add route for NAT64: %s", otThreadErrorToString(error));
+ }
otLogInfoPlat("[netif] Adding route for NAT64");
}
else if (sActiveNat64Cidr.mLength > 0) // Translator is not active.
{
- DeleteIp4Route(sActiveNat64Cidr);
+ if ((error = DeleteIp4Route(sActiveNat64Cidr)) != OT_ERROR_NONE)
+ {
+ otLogWarnPlat("[netif] failed to delete route for NAT64: %s", otThreadErrorToString(error));
+ }
otLogInfoPlat("[netif] Deleting route for NAT64");
}
@@ -1319,7 +1311,10 @@ static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetli
if (isUp && sActiveNat64Cidr.mLength > 0)
{
// Recover NAT64 route.
- AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority);
+ if ((error = AddIp4Route(sActiveNat64Cidr, kNat64RoutePriority)) != OT_ERROR_NONE)
+ {
+ otLogWarnPlat("[netif] failed to add route for NAT64: %s", otThreadErrorToString(error));
+ }
}
#endif
@@ -1435,14 +1430,11 @@ static void processNetifAddrEvent(otInstance *aInstance, struct rt_msghdr *rtm)
if (!addr.IsMulticast())
{
otNetifAddress netAddr;
- bool subscribed;
netAddr.mAddress = addr;
netAddr.mPrefixLength = NetmaskToPrefixLength(&netmask);
- subscribed = UnicastAddressIsSubscribed(aInstance, &netAddr);
-
- if (subscribed)
+ if (otIp6HasUnicastAddress(aInstance, &addr))
{
logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY);
error = OT_ERROR_NONE;
@@ -1659,7 +1651,18 @@ static void processNetlinkEvent(otInstance *aInstance)
length = recv(sNetlinkFd, msgBuffer.buffer, sizeof(msgBuffer.buffer), 0);
- VerifyOrExit(length > 0);
+#if defined(__linux__)
+#define HEADER_SIZE sizeof(nlmsghdr)
+#else
+#define HEADER_SIZE sizeof(rt_msghdr)
+#endif
+
+ // Ensures full netlink header is received
+ if (length < static_cast<ssize_t>(HEADER_SIZE))
+ {
+ otLogWarnPlat("[netif] Unexpected netlink recv() result: %ld", static_cast<long>(length));
+ ExitNow();
+ }
#if defined(__linux__)
for (struct nlmsghdr *msg = &msgBuffer.nlMsg; NLMSG_OK(msg, static_cast<size_t>(length));
@@ -1677,6 +1680,12 @@ static void processNetlinkEvent(otInstance *aInstance)
#endif
switch (msg->nlmsg_type)
{
+#if defined(__linux__)
+ case NLMSG_DONE:
+ // NLMSG_DONE indicates the end of the netlink message, exits now
+ ExitNow();
+#endif
+
case RTM_NEWADDR:
case RTM_DELADDR:
processNetifAddrEvent(aInstance, msg);
@@ -2084,10 +2093,14 @@ void platformNetifInit(otPlatformConfig *aPlatformConfig)
void nat64Init(void)
{
otIp4Cidr cidr;
+ otError error = OT_ERROR_NONE;
if (otIp4CidrFromString(OPENTHREAD_POSIX_CONFIG_NAT64_CIDR, &cidr) == OT_ERROR_NONE && cidr.mLength != 0)
{
- otNat64SetIp4Cidr(gInstance, &cidr);
+ if ((error = otNat64SetIp4Cidr(gInstance, &cidr)) != OT_ERROR_NONE)
+ {
+ otLogWarnPlat("[netif] failed to set CIDR for NAT64: %s", otThreadErrorToString(error));
+ }
}
else
{
diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h
index 262d37ca0..cc8afe5cb 100644
--- a/src/posix/platform/openthread-posix-config.h
+++ b/src/posix/platform/openthread-posix-config.h
@@ -394,7 +394,8 @@
* not explicit defined.
*/
#ifndef OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
-#define OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE \
+ (OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE || OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE)
#endif
/**
@@ -441,4 +442,15 @@
#ifdef OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL
#error "OPENTHREAD_POSIX_CONFIG_RCP_TIME_SYNC_INTERVAL was replaced by OPENTHREAD_SPINEL_CONFIG_RCP_TIME_SYNC_INTERVAL"
#endif
+
+/**
+ * @def OPENTHREAD_POSIX_CONFIG_EXIT_ON_INFRA_NETIF_LOST_ENABLE
+ *
+ * Define as 1 to let the process exit when the infra network interface is lost on the POSIX platform.
+ *
+ */
+#ifndef OPENTHREAD_POSIX_CONFIG_EXIT_ON_INFRA_NETIF_LOST_ENABLE
+#define OPENTHREAD_POSIX_CONFIG_EXIT_ON_INFRA_NETIF_LOST_ENABLE 1
+#endif
+
#endif // OPENTHREAD_PLATFORM_CONFIG_H_
diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h
index 8f05602a2..0617bfc05 100644
--- a/src/posix/platform/platform-posix.h
+++ b/src/posix/platform/platform-posix.h
@@ -410,69 +410,12 @@ extern char gNetifName[IFNAMSIZ];
extern unsigned int gNetifIndex;
/**
- * Initializes platform Backbone network.
- *
- * @note This function is called before OpenThread instance is created.
- *
- * @param[in] aInterfaceName A pointer to Thread network interface name.
- *
- */
-void platformBackboneInit(const char *aInterfaceName);
-
-/**
- * Sets up platform Backbone network.
- *
- * @note This function is called after OpenThread instance is created.
- *
- * @param[in] aInstance A pointer to the OpenThread instance.
- *
- */
-void platformBackboneSetUp(void);
-
-/**
- * Tears down platform Backbone network.
- *
- * @note This function is called before OpenThread instance is destructed.
- *
- */
-void platformBackboneTearDown(void);
-
-/**
- * Shuts down the platform Backbone network.
- *
- * @note This function is called after OpenThread instance is destructed.
- *
- */
-void platformBackboneDeinit(void);
-
-/**
- * Performs notifies state changes to platform Backbone network.
- *
- * @param[in] aInstance A pointer to the OpenThread instance.
- * @param[in] aFlags Flags that denote the state change events.
- *
- */
-void platformBackboneStateChange(otInstance *aInstance, otChangedFlags aFlags);
-
-/**
* A pointer to the OpenThread instance.
*
*/
extern otInstance *gInstance;
/**
- * The name of Backbone network interface.
- *
- */
-extern char gBackboneNetifName[IFNAMSIZ];
-
-/**
- * The index of Backbone network interface.
- *
- */
-extern unsigned int gBackboneNetifIndex;
-
-/**
* Tells if the infrastructure interface is running.
*
* @returns TRUE if the infrastructure interface is running, FALSE if not.
diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp
index aafe9b502..491c6db1f 100644
--- a/src/posix/platform/radio.cpp
+++ b/src/posix/platform/radio.cpp
@@ -66,12 +66,26 @@ Radio::Radio(void)
void Radio::Init(const char *aUrl)
{
- bool resetRadio;
- bool skipCompatibilityCheck;
+ bool resetRadio;
+ bool skipCompatibilityCheck;
+ spinel_iid_t iidList[Spinel::kSpinelHeaderMaxNumIid];
+ struct ot::Spinel::RadioSpinelCallbacks callbacks;
mRadioUrl = aUrl;
VerifyOrDie(mRadioUrl.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
+ memset(&callbacks, 0, sizeof(callbacks));
+#if OPENTHREAD_CONFIG_DIAG_ENABLE
+ callbacks.mDiagReceiveDone = otPlatDiagRadioReceiveDone;
+ callbacks.mDiagTransmitDone = otPlatDiagRadioTransmitDone;
+#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
+ callbacks.mEnergyScanDone = otPlatRadioEnergyScanDone;
+ callbacks.mReceiveDone = otPlatRadioReceiveDone;
+ callbacks.mTransmitDone = otPlatRadioTxDone;
+ callbacks.mTxStarted = otPlatRadioTxStarted;
+
+ GetIidListFromRadioUrl(iidList);
+
#if OPENTHREAD_POSIX_VIRTUAL_TIME
VirtualTimeInit();
#endif
@@ -81,7 +95,10 @@ void Radio::Init(const char *aUrl)
resetRadio = !mRadioUrl.HasParam("no-reset");
skipCompatibilityCheck = mRadioUrl.HasParam("skip-rcp-compatibility-check");
- mRadioSpinel.Init(*mSpinelInterface, resetRadio, skipCompatibilityCheck);
+
+ mRadioSpinel.SetCallbacks(callbacks);
+ mRadioSpinel.Init(*mSpinelInterface, resetRadio, skipCompatibilityCheck, iidList, OT_ARRAY_LENGTH(iidList));
+ otLogDebgPlat("instance init:%p - iid = %d", (void *)&mRadioSpinel, iidList[0]);
ProcessRadioUrl(mRadioUrl);
}
@@ -229,6 +246,53 @@ exit:
#endif // OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
}
+void Radio::GetIidListFromRadioUrl(spinel_iid_t (&aIidList)[Spinel::kSpinelHeaderMaxNumIid])
+{
+ const char *iidString;
+ const char *iidListString;
+
+ memset(aIidList, SPINEL_HEADER_INVALID_IID, sizeof(aIidList));
+
+ iidString = (mRadioUrl.GetValue("iid"));
+ iidListString = (mRadioUrl.GetValue("iid-list"));
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ // First entry to the aIidList must be the IID of the host application.
+ VerifyOrDie(iidString != nullptr, OT_EXIT_INVALID_ARGUMENTS);
+ aIidList[0] = static_cast<spinel_iid_t>(atoi(iidString));
+
+ if (iidListString != nullptr)
+ {
+ // Convert string to an array of integers.
+ // Integer i is for traverse the iidListString.
+ // Integer j is for aIidList array offset location.
+ // First entry of aIidList is for host application iid hence j start from 1.
+ for (uint8_t i = 0, j = 1; iidListString[i] != '\0' && j < Spinel::kSpinelHeaderMaxNumIid; i++)
+ {
+ if (iidListString[i] == ',')
+ {
+ j++;
+ continue;
+ }
+
+ if (iidListString[i] < '0' || iidListString[i] > '9')
+ {
+ DieNow(OT_EXIT_INVALID_ARGUMENTS);
+ }
+ else
+ {
+ aIidList[j] = iidListString[i] - '0';
+ VerifyOrDie(aIidList[j] < Spinel::kSpinelHeaderMaxNumIid, OT_EXIT_INVALID_ARGUMENTS);
+ }
+ }
+ }
+#else // !OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ VerifyOrDie(iidString == nullptr, OT_EXIT_INVALID_ARGUMENTS);
+ VerifyOrDie(iidListString == nullptr, OT_EXIT_INVALID_ARGUMENTS);
+ aIidList[0] = 0;
+#endif // OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+}
+
} // namespace Posix
} // namespace ot
@@ -978,6 +1042,15 @@ otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t a
return OT_ERROR_NOT_IMPLEMENTED;
}
+#if OPENTHREAD_CONFIG_PLATFORM_BOOTLOADER_MODE_ENABLE
+otError otPlatResetToBootloader(otInstance *aInstance)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+
+ return GetRadioSpinel().SendReset(SPINEL_RESET_BOOTLOADER);
+}
+#endif
+
const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void) { return GetRadioSpinel().GetRadioSpinelMetrics(); }
const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void)
diff --git a/src/posix/platform/radio.hpp b/src/posix/platform/radio.hpp
index ae0626614..439483f00 100644
--- a/src/posix/platform/radio.hpp
+++ b/src/posix/platform/radio.hpp
@@ -88,6 +88,7 @@ private:
void ProcessMaxPowerTable(const RadioUrl &aRadioUrl);
Spinel::SpinelInterface *CreateSpinelInterface(const char *aInterfaceName);
+ void GetIidListFromRadioUrl(spinel_iid_t (&aIidList)[Spinel::kSpinelHeaderMaxNumIid]);
#if OPENTHREAD_POSIX_CONFIG_SPINEL_HDLC_INTERFACE_ENABLE && OPENTHREAD_POSIX_CONFIG_SPINEL_SPI_INTERFACE_ENABLE
static constexpr size_t kSpinelInterfaceRawSize = sizeof(ot::Posix::SpiInterface) > sizeof(ot::Posix::HdlcInterface)
diff --git a/src/posix/platform/radio_url.cpp b/src/posix/platform/radio_url.cpp
index b57e29f81..bd34d9c65 100644
--- a/src/posix/platform/radio_url.cpp
+++ b/src/posix/platform/radio_url.cpp
@@ -120,7 +120,16 @@ const char *otSysGetRadioUrlHelpString(void)
" Disable coex with 0, and enable it with other values.\n"
" fem-lnagain[=dbm] Set the Rx LNA gain in dBm of the external FEM.\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";
+ " skip-rcp-compatibility-check Skip checking RCP API version and capabilities during initialization.\n"
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ " iid Set the Spinel Interface ID for this process. Valid values are 0-3.\n"
+ " iid-list List of IIDs a host can subscribe to receive spinel frames other than \n"
+ " provided in 'iid' argument. If not specified, host will subscribe to \n"
+ " the interface ID provided in 'iid` argument. Valid values are 0-3. \n"
+ " Upto three IIDs can be provided with each IID separated by ',' \n"
+ " e.g. iid-list=1,2,3 \n"
+#endif
+ ;
}
namespace ot {
diff --git a/src/posix/platform/settings.cpp b/src/posix/platform/settings.cpp
index 73925fe21..3b4c2fd56 100644
--- a/src/posix/platform/settings.cpp
+++ b/src/posix/platform/settings.cpp
@@ -88,7 +88,7 @@ static void getSettingsFileName(otInstance *aInstance, char aFileName[kMaxFileNa
uint64_t nodeId;
otPlatRadioGetIeeeEui64(aInstance, reinterpret_cast<uint8_t *>(&nodeId));
- nodeId = ot::Encoding::BigEndian::HostSwap64(nodeId);
+ nodeId = ot::BigEndian::HostSwap64(nodeId);
snprintf(aFileName, kMaxFileNameSize, OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH "/%s_%" PRIx64 ".%s",
offset == nullptr ? "0" : offset, nodeId, (aSwap ? "swap" : "data"));
}
@@ -436,7 +436,7 @@ otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex,
assert(swapFd != -1);
assert(offset == 0);
- VerifyOrExit(offset == 0 && size >= 0, error = OT_ERROR_PARSE);
+ VerifyOrExit(offset == 0 && size >= 0, error = OT_ERROR_FAILED);
while (offset < size)
{
@@ -445,10 +445,10 @@ otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex,
ssize_t rval;
rval = read(sSettingsFd, &key, sizeof(key));
- VerifyOrExit(rval == sizeof(key), error = OT_ERROR_PARSE);
+ VerifyOrExit(rval == sizeof(key), error = OT_ERROR_FAILED);
rval = read(sSettingsFd, &length, sizeof(length));
- VerifyOrExit(rval == sizeof(length), error = OT_ERROR_PARSE);
+ VerifyOrExit(rval == sizeof(length), error = OT_ERROR_FAILED);
offset += sizeof(key) + sizeof(length) + length;
@@ -456,14 +456,14 @@ otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex,
{
if (aIndex == 0)
{
- VerifyOrExit(offset == lseek(sSettingsFd, length, SEEK_CUR), error = OT_ERROR_PARSE);
+ VerifyOrExit(offset == lseek(sSettingsFd, length, SEEK_CUR), error = OT_ERROR_FAILED);
swapWrite(aInstance, swapFd, static_cast<uint16_t>(size - offset));
error = OT_ERROR_NONE;
break;
}
else if (aIndex == -1)
{
- VerifyOrExit(offset == lseek(sSettingsFd, length, SEEK_CUR), error = OT_ERROR_PARSE);
+ VerifyOrExit(offset == lseek(sSettingsFd, length, SEEK_CUR), error = OT_ERROR_FAILED);
error = OT_ERROR_NONE;
continue;
}
@@ -474,19 +474,15 @@ otError PlatformSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex,
}
rval = write(swapFd, &key, sizeof(key));
- assert(rval == sizeof(key));
- VerifyOrDie(rval == sizeof(key), OT_EXIT_FAILURE);
+ VerifyOrExit(rval == sizeof(key), error = OT_ERROR_FAILED);
rval = write(swapFd, &length, sizeof(length));
- assert(rval == sizeof(length));
- VerifyOrDie(rval == sizeof(length), OT_EXIT_FAILURE);
+ VerifyOrExit(rval == sizeof(length), error = OT_ERROR_FAILED);
swapWrite(aInstance, swapFd, length);
}
exit:
- VerifyOrDie(error != OT_ERROR_PARSE, OT_EXIT_FAILURE);
-
if (aSwapFd != nullptr)
{
*aSwapFd = swapFd;
@@ -499,6 +495,11 @@ exit:
{
swapDiscard(aInstance, swapFd);
}
+ else if (error == OT_ERROR_FAILED)
+ {
+ swapDiscard(aInstance, swapFd);
+ DieNow(error);
+ }
return error;
}
diff --git a/src/posix/platform/spi_interface.cpp b/src/posix/platform/spi_interface.cpp
index 54e889a7b..167f4b9c3 100644
--- a/src/posix/platform/spi_interface.cpp
+++ b/src/posix/platform/spi_interface.cpp
@@ -569,6 +569,8 @@ otError SpiInterface::PushPullSpi(void)
mInterfaceMetrics.mTxFrameCount++;
mInterfaceMetrics.mTxFrameByteCount += mSpiTxPayloadSize;
+ // Clear tx buffer after usage
+ memset(&mSpiTxFrameBuffer[kSpiFrameHeaderSize], 0, mSpiTxPayloadSize);
mSpiTxIsReady = false;
mSpiTxPayloadSize = 0;
mSpiTxRefusedCount = 0;
diff --git a/src/posix/platform/system.cpp b/src/posix/platform/system.cpp
index a154ff829..9b0aa9cbc 100644
--- a/src/posix/platform/system.cpp
+++ b/src/posix/platform/system.cpp
@@ -72,10 +72,7 @@ static void processStateChange(otChangedFlags aFlags, void *aContext)
#endif
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- if (gBackboneNetifIndex != 0)
- {
- platformBackboneStateChange(instance, aFlags);
- }
+ ot::Posix::InfraNetif::Get().HandleBackboneStateChange(instance, aFlags);
#endif
}
#endif
@@ -145,10 +142,6 @@ void platformInit(otPlatformConfig *aPlatformConfig)
#endif
platformRandomInit();
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- platformBackboneInit(aPlatformConfig->mBackboneInterfaceName);
-#endif
-
#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
ot::Posix::InfraNetif::Get().Init();
@@ -178,8 +171,17 @@ void platformSetUp(otPlatformConfig *aPlatformConfig)
VerifyOrExit(!gDryRun);
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- platformBackboneSetUp();
+#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
+ if (aPlatformConfig->mBackboneInterfaceName != nullptr && strlen(aPlatformConfig->mBackboneInterfaceName) > 0)
+ {
+ int icmp6Sock = -1;
+
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+ icmp6Sock = ot::Posix::InfraNetif::CreateIcmp6Socket(aPlatformConfig->mBackboneInterfaceName);
+#endif
+
+ otSysSetInfraNetif(aPlatformConfig->mBackboneInterfaceName, icmp6Sock);
+ }
#endif
#if OPENTHREAD_POSIX_CONFIG_INFRA_IF_ENABLE
@@ -246,10 +248,6 @@ void platformTearDown(void)
ot::Posix::InfraNetif::Get().TearDown();
#endif
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- platformBackboneTearDown();
-#endif
-
exit:
return;
}
@@ -278,10 +276,6 @@ void platformDeinit(void)
ot::Posix::InfraNetif::Get().Deinit();
#endif
-#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- platformBackboneDeinit();
-#endif
-
exit:
return;
}
diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp
index 7f78acccb..6d7c880a3 100644
--- a/src/posix/platform/udp.cpp
+++ b/src/posix/platform/udp.cpp
@@ -324,11 +324,12 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId
{
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#if __linux__
- VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, gBackboneNetifName, strlen(gBackboneNetifName)) == 0,
+ VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, otSysGetInfraNetifName(),
+ strlen(otSysGetInfraNetifName())) == 0,
error = OT_ERROR_FAILED);
#else // __NetBSD__ || __FreeBSD__ || __APPLE__
- VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) ==
- 0,
+ uint32_t backboneNetifIndex = otSysGetInfraNetifIndex();
+ VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &backboneNetifIndex, sizeof(backboneNetifIndex)) == 0,
error = OT_ERROR_FAILED);
#endif // __linux__
#else
@@ -473,7 +474,7 @@ otError otPlatUdpJoinMulticastGroup(otUdpSocket *aUdpSocket,
break;
case OT_NETIF_BACKBONE:
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- mreq.ipv6mr_interface = gBackboneNetifIndex;
+ mreq.ipv6mr_interface = otSysGetInfraNetifIndex();
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
@@ -513,7 +514,7 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *aUdpSocket,
break;
case OT_NETIF_BACKBONE:
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- mreq.ipv6mr_interface = gBackboneNetifIndex;
+ mreq.ipv6mr_interface = otSysGetInfraNetifIndex();
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
diff --git a/tests/fuzz/fuzzer_platform.cpp b/tests/fuzz/fuzzer_platform.cpp
index 012cee49b..e616fc25e 100644
--- a/tests/fuzz/fuzzer_platform.cpp
+++ b/tests/fuzz/fuzzer_platform.cpp
@@ -38,6 +38,7 @@
#include <openthread/platform/entropy.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/misc.h>
+#include <openthread/platform/multipan.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/settings.h>
@@ -230,6 +231,10 @@ OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const
void otPlatWakeHost(void) {}
+otError otPlatMultipanGetActiveInstance(otInstance **) { return OT_ERROR_NOT_IMPLEMENTED; }
+
+otError otPlatMultipanSetActiveInstance(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
+
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -260,6 +265,12 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnabled)
OT_UNUSED_VARIABLE(aEnabled);
}
+void otPlatRadioSetRxOnWhenIdle(otInstance *aInstance, bool aEnabled)
+{
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aEnabled);
+}
+
bool otPlatRadioIsEnabled(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
diff --git a/tests/scripts/expect/cli-commissioner.exp b/tests/scripts/expect/cli-commissioner.exp
index 2c6737e86..e5849d3e4 100755
--- a/tests/scripts/expect/cli-commissioner.exp
+++ b/tests/scripts/expect/cli-commissioner.exp
@@ -52,9 +52,9 @@ expect_line "Done"
send "commissioner id\n"
expect "OpenThread Commissioner"
expect_line "Done"
-send "commissioner id reallyAndUnnecessaryLongOpenthreadComisionerCustomIdShouldNotFit\n"
+send "commissioner id 12345678901234567890123456789012345678901234567890123456789012345\n"
expect "Error 7: InvalidArgs"
-send "commissioner id reallyAndUnnecessaryLongOpenthreadCommissionerCustomIdShouldFit\n"
+send "commissioner id 1234567890123456789012345678901234567890123456789012345678901234\n"
expect "Done"
send "commissioner id customId\n"
expect "Done"
diff --git a/tests/scripts/expect/cli-promiscuous.exp b/tests/scripts/expect/cli-promiscuous.exp
index 228c21cf6..58a51e17b 100755
--- a/tests/scripts/expect/cli-promiscuous.exp
+++ b/tests/scripts/expect/cli-promiscuous.exp
@@ -76,9 +76,8 @@ expect "16 bytes from $addr: icmp_seq=1"
expect_line "Done"
switch_node 3
-expect -re {============================================\[len = +\d+]============================}
-expect -re {\|( ([0-9A-Z]{2}|\.\.)){16}\|( .){16}\|}
-expect -- "-----------------------------------------------------------------------------------"
+expect -re {==============================\[RX len=\d+\]==============================}
+expect -- "------------------------------------------------------------------------"
send "promiscuous disable\n"
expect_line "Done"
diff --git a/tests/scripts/expect/cli-reset.exp b/tests/scripts/expect/cli-reset.exp
index b43069717..9e828ef92 100755
--- a/tests/scripts/expect/cli-reset.exp
+++ b/tests/scripts/expect/cli-reset.exp
@@ -71,4 +71,7 @@ send "panid\n"
expect "0xffff"
expect_line "Done"
+send "reset bootloader\n"
+expect_line "Error 27: NotCapable"
+
dispose_all
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
index 4e0823b0a..eaa1e13a0 100755
--- a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
+++ b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py
@@ -130,17 +130,10 @@ class MultiThreadNetworks(thread_cert.TestCase):
# Each BR should independently register an external route for the on-link prefix
# and OMR prefix in another Thread Network.
- self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 1)
- self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 1)
- self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 1)
- self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 1)
-
- br1_external_routes = br1.get_routes()
- br2_external_routes = br2.get_routes()
-
- br1_external_routes.sort()
- br2_external_routes.sort()
- self.assertNotEqual(br1_external_routes, br2_external_routes)
+ self.assertEqual(br1.get_netdata_non_nat64_prefixes(), ['fc00::/7'])
+ self.assertEqual(router1.get_netdata_non_nat64_prefixes(), ['fc00::/7'])
+ self.assertEqual(br2.get_netdata_non_nat64_prefixes(), ['fc00::/7'])
+ self.assertEqual(router2.get_netdata_non_nat64_prefixes(), ['fc00::/7'])
self.assertTrue(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
self.assertTrue(len(router2.get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1)
diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py
index 6fd893f72..25e254aba 100755
--- a/tests/scripts/thread-cert/node.py
+++ b/tests/scripts/thread-cert/node.py
@@ -1880,8 +1880,8 @@ class NodeImpl:
self.send_command(cmd)
self._expect_done()
- def get_addrs(self):
- self.send_command('ipaddr')
+ def get_addrs(self, verbose=False):
+ self.send_command('ipaddr' + (' -v' if verbose else ''))
return self._expect_results(r'\S+(:\S*)+')
@@ -2336,8 +2336,8 @@ class NodeImpl:
def get_netdata(self):
raw_netdata = self.netdata_show()
- netdata = {'Prefixes': [], 'Routes': [], 'Services': [], 'Contexts': []}
- key_list = ['Prefixes', 'Routes', 'Services', 'Contexts']
+ netdata = {'Prefixes': [], 'Routes': [], 'Services': [], 'Contexts': [], 'Commissioning': []}
+ key_list = ['Prefixes', 'Routes', 'Services', 'Contexts', 'Commissioning']
key = None
for i in range(0, len(raw_netdata)):
diff --git a/tests/scripts/thread-cert/test_srp_auto_host_address.py b/tests/scripts/thread-cert/test_srp_auto_host_address.py
index bb9ac6e1e..f714e6c4a 100755
--- a/tests/scripts/thread-cert/test_srp_auto_host_address.py
+++ b/tests/scripts/thread-cert/test_srp_auto_host_address.py
@@ -156,6 +156,19 @@ class SrpAutoHostAddress(thread_cert.TestCase):
self.check_registered_addresses(client, server)
#-------------------------------------------------------------------
+ # Add a non-preferred SLAAC on-mesh prefix and check that the
+ # set of registered addresses remains unchanged and that the
+ # non-preferred address is not registered by SRP client.
+
+ client.add_prefix('fd00:a:b:c::/64', 'aos')
+ client.register_netdata()
+ self.simulator.go(5)
+
+ slaac_addr = [addr.strip() for addr in client.get_addrs() if addr.strip().startswith('fd00:a:b:c:')]
+ self.assertEqual(len(slaac_addr), 1)
+ self.check_registered_addresses(client, server)
+
+ #-------------------------------------------------------------------
# Remove the on-mesh prefix (which will trigger an address to be
# removed) and check that the SRP client re-registered and updated
# server with the remaining address.
@@ -219,19 +232,21 @@ class SrpAutoHostAddress(thread_cert.TestCase):
# Check the host addresses on server to match client.
host_addresses = [addr.strip() for addr in server_host['addresses']]
- client_addresses = [addr.strip() for addr in client.get_addrs()]
+
+ client_mleid = client.get_mleid()
+ client_addresses = [addr.split(' ')[0] for addr in client.get_addrs(verbose=True) if 'preferred:1' in addr]
+ client_addresses += [client_mleid]
# All registered addresses must be in client list of addresses.
for addr in host_addresses:
self.assertIn(addr, client_addresses)
- # All addresses on client excluding link-local and mesh-local
- # addresses must be seen on server side. But if there was
- # no address, then mesh-local address should be the only
+ # All preferred addresses on client excluding link-local and
+ # mesh-local addresses must be seen on server side. But if there
+ # was no address, then mesh-local address should be the only
# one registered.
- client_mleid = client.get_mleid()
checked_address = False
for addr in client_addresses:
diff --git a/tests/toranj/build.sh b/tests/toranj/build.sh
index cdf6c3614..0c9a6983c 100755
--- a/tests/toranj/build.sh
+++ b/tests/toranj/build.sh
@@ -50,7 +50,8 @@ display_usage()
echo " posix-15.4+trel : Build OpenThread POSIX - multi radio (15.4+TREL)"
echo ""
echo "Options:"
- echo " -c/--enable-coverage Enable code coverage"
+ echo " -c/--enable-coverage Enable code coverage"
+ echo " -k/--enable-plat-key-ref Enable OT_PLATFORM_KEY_REF"
echo ""
}
@@ -64,6 +65,7 @@ cd "$(dirname "$0")" || die "cd failed"
cd ../.. || die "cd failed"
ot_coverage=OFF
+ot_plat_key_ref=OFF
while [ $# -ge 2 ]; do
case $1 in
@@ -74,6 +76,10 @@ while [ $# -ge 2 ]; do
-t | --enable-tests)
shift
;;
+ -k | --enable-plat-key-ref)
+ ot_plat_key_ref=ON
+ shift
+ ;;
"")
shift
;;
@@ -108,7 +114,7 @@ case ${build_config} in
cd "${top_builddir}" || die "cd failed"
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
- -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \
+ -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -122,6 +128,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=OFF -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -136,6 +143,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=OFF -DOT_TREL=ON -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -150,6 +158,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=OFF -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=ON -DOT_OPERATIONAL_DATASET_AUTO_INIT=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -163,6 +172,7 @@ case ${build_config} in
cd "${top_builddir}" || die "cd failed"
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -176,6 +186,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=OFF \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -190,6 +201,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \
-DOT_15_4=OFF -DOT_TREL=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -204,6 +216,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=OFF -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -217,6 +230,7 @@ case ${build_config} in
cd "${top_builddir}" || die "cd failed"
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=OFF -DOT_APP_NCP=OFF -DOT_APP_RCP=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
@@ -229,6 +243,7 @@ case ${build_config} in
cd "${top_builddir}" || die "cd failed"
cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \
"${top_srcdir}" || die
ninja || die
@@ -242,6 +257,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=OFF \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \
"${top_srcdir}" || die
ninja || die
@@ -255,6 +271,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=OFF -DOT_TREL=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \
"${top_srcdir}" || die
ninja || die
@@ -268,6 +285,7 @@ case ${build_config} in
cmake -GNinja -DOT_PLATFORM=posix -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=OFF \
-DOT_15_4=ON -DOT_TREL=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-posix.h \
"${top_srcdir}" || die
ninja || die
@@ -280,6 +298,7 @@ case ${build_config} in
cd "${top_builddir}" || die "cd failed"
cmake -GNinja -DOT_PLATFORM=simulation -DOT_COMPILE_WARNING_AS_ERROR=ON -DOT_COVERAGE=${ot_coverage} \
-DOT_THREAD_VERSION=1.3.1 -DOT_APP_CLI=ON -DOT_APP_NCP=ON -DOT_APP_RCP=ON \
+ -DOT_PLATFORM_KEY_REF=${ot_plat_key_ref} \
-DOT_PROJECT_CONFIG=../tests/toranj/openthread-core-toranj-config-simulation.h \
"${top_srcdir}" || die
ninja || die
diff --git a/tests/toranj/cli/cli.py b/tests/toranj/cli/cli.py
index 39427cd34..e5533ad1a 100644
--- a/tests/toranj/cli/cli.py
+++ b/tests/toranj/cli/cli.py
@@ -387,11 +387,13 @@ class Node(object):
routes_index = outputs.index('Routes:')
services_index = outputs.index('Services:')
contexts_index = outputs.index('Contexts:')
+ commissioning_index = outputs.index('Commissioning:')
result = {}
result['prefixes'] = outputs[1:routes_index]
result['routes'] = outputs[routes_index + 1:services_index]
result['services'] = outputs[services_index + 1:contexts_index]
- result['contexts'] = outputs[contexts_index + 1:]
+ result['contexts'] = outputs[contexts_index + 1:commissioning_index]
+ result['commissioning'] = outputs[commissioning_index + 1:]
return result
diff --git a/tests/toranj/cli/test-008-multicast-traffic.py b/tests/toranj/cli/test-008-multicast-traffic.py
index 7623a9c5a..d83bd1f06 100755
--- a/tests/toranj/cli/test-008-multicast-traffic.py
+++ b/tests/toranj/cli/test-008-multicast-traffic.py
@@ -53,8 +53,17 @@ import time
# - r1 =>> mesh-local all-thread (two hops). Expected response from [r2, r3, fed].
# - r1 =>> mesh-local all-thread (three hops). Expected response from [r2, r3, r4, fed].
# - r1 =>> mesh-local all-thread (four hops). Expected response from [r2, r3, r4, fed, sed].
-# - r1 =>> specific address (on r2 and sed). Expected to receive on [r2, sed].
#
+# - r1 =>> realm-local scope mcast addr (on r2 and sed). Expected to receive on [r2, sed].
+# - r2 =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [sed].
+# - r2 =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
+# - sed =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [r2].
+# - sed =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
+#
+# - r3 =>> site-local mcast addr (on r1, r2, sed). Expected to receive from [r1, r2, sed].
+# - r1 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
+# - r1 =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r2, sed].
+# - sed =>> site-local mcast addr (on r1, r2, sed). Expected to receive from [r1, r2].
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
print('-' * 120)
@@ -223,7 +232,7 @@ for node in [r2, r3, r4, fed, sed]:
verify(any(ml_addr in line for line in outputs))
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# Subscribe to a specific multicast address on r2 and sed
+# Subscribe to a realm-local scope multicast address on r2 and sed
mcast_addr = 'ff03:0:0:0:0:0:0:114'
r2.add_ip_maddr(mcast_addr)
@@ -234,12 +243,93 @@ verify(any(mcast_addr in maddr for maddr in maddrs))
maddrs = sed.get_ip_maddrs()
verify(any(mcast_addr in maddr for maddr in maddrs))
+# r1 =>> realm-local scope mcast addr (on r2 and sed). Expected to receive on [r2, sed].
+
outputs = r1.cli('ping', mcast_addr)
verify(len(outputs) == 3)
for node in [r2, sed]:
ml_addr = node.get_mleid_ip_addr()
verify(any(ml_addr in line for line in outputs))
+# r2 =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [sed].
+
+outputs = r2.cli('ping', mcast_addr)
+verify(len(outputs) == 2)
+for node in [sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# r2 =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
+
+outputs = r2.cli('ping', '-m', mcast_addr)
+verify(len(outputs) == 3)
+for node in [r2, sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# sed =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [r2].
+
+outputs = sed.cli('ping', mcast_addr)
+verify(len(outputs) == 2)
+for node in [r2]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# sed =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
+
+outputs = sed.cli('ping', '-m', mcast_addr)
+verify(len(outputs) == 3)
+for node in [r2, sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Subscribe to a larger than realm-local scope (site-local) multicast address on r1, r2, and sed
+
+mcast_addr = 'ff05:0:0:0:0:0:0:abcd'
+r1.add_ip_maddr(mcast_addr)
+r2.add_ip_maddr(mcast_addr)
+sed.add_ip_maddr(mcast_addr)
+time.sleep(1)
+maddrs = r1.get_ip_maddrs()
+verify(any(mcast_addr in maddr for maddr in maddrs))
+maddrs = r2.get_ip_maddrs()
+verify(any(mcast_addr in maddr for maddr in maddrs))
+maddrs = sed.get_ip_maddrs()
+verify(any(mcast_addr in maddr for maddr in maddrs))
+
+# r3 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
+
+outputs = r3.cli('ping', '-m', mcast_addr)
+verify(len(outputs) == 4)
+for node in [r1, r2, sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# r1 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
+
+outputs = r1.cli('ping', '-m', mcast_addr)
+verify(len(outputs) == 4)
+for node in [r1, r2, sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# r1 =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r2, sed].
+
+outputs = r1.cli('ping', mcast_addr)
+verify(len(outputs) == 3)
+for node in [r2, sed]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
+# sed =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r1, r2].
+
+outputs = sed.cli('ping', mcast_addr)
+verify(len(outputs) >= 3)
+for node in [r1, r2]:
+ ml_addr = node.get_mleid_ip_addr()
+ verify(any(ml_addr in line for line in outputs))
+
# -----------------------------------------------------------------------------------------------------------------------
# Test finished
diff --git a/tests/toranj/cli/test-025-mesh-local-prefix-change.py b/tests/toranj/cli/test-025-mesh-local-prefix-change.py
new file mode 100755
index 000000000..a3f75b96a
--- /dev/null
+++ b/tests/toranj/cli/test-025-mesh-local-prefix-change.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2023, The OpenThread Authors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from cli import verify
+from cli import verify_within
+import cli
+import time
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test description: Validate update of unicast/multicast mesh-local addresses on prefix change
+#
+# Network topology
+#
+# r1 ---- r2
+#
+
+test_name = __file__[:-3] if __file__.endswith('.py') else __file__
+print('-' * 120)
+print('Starting \'{}\''.format(test_name))
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Creating `cli.Node` instances
+
+speedup = 40
+cli.Node.set_time_speedup_factor(speedup)
+
+r1 = cli.Node()
+r2 = cli.Node()
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Form topology
+
+r1.form('ml-change')
+r2.join(r1)
+
+verify(r1.get_state() == 'leader')
+verify(r2.get_state() == 'router')
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test Implementation
+
+r1.srp_server_enable()
+r1.srp_client_enable_auto_start_mode()
+r2.srp_client_enable_auto_start_mode()
+
+time.sleep(0.5)
+
+ml_prefix = r1.get_mesh_local_prefix()
+ml_prefix = ml_prefix[:ml_prefix.index("/64") - 1]
+
+# Validate that r1 has 4 mesh-local address: ML-EID, RLOC, leader ALOC
+# and since it is acting as SRP server the service ALOC.
+
+r1_addrs = r1.get_ip_addrs()
+verify(sum([addr.startswith(ml_prefix) for addr in r1_addrs]) == 4)
+
+# Validate that r1 has link-local and realm-local All Thread Nodes
+# multicast addresses which are prefix-based and use mesh-local
+# prefix.
+
+r1_maddrs = r1.get_ip_maddrs()
+verify(sum([ml_prefix in maddr for maddr in r1_maddrs]) == 2)
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Change the mesh-local prefix on all devices.
+
+r2.cli('dataset clear')
+r2.cli('dataset meshlocalprefix fd00:1122:3344:5566::')
+r2.cli('dataset delaytimer 1100') # `toranj` allows 1000 msec as minimum in its config
+r2.cli('dataset updater start')
+
+time.sleep(0.5)
+
+ml_prefix = r1.get_mesh_local_prefix()
+ml_prefix = ml_prefix[:ml_prefix.index("/64") - 1]
+
+verify(ml_prefix == 'fd00:1122:3344:5566:')
+
+# Validate that all 4 mesh-local address on r1 are updated to use the
+# new mesh-local prefix.
+
+r1_addrs = r1.get_ip_addrs()
+verify(sum([addr.startswith(ml_prefix) for addr in r1_addrs]) == 4)
+
+# Validate the network data entry for SRP server is also updated to
+# used the new address.
+
+verify(r1.srp_client_get_server_address().startswith(ml_prefix))
+
+# Validate the r1 multicast addresses are also updated
+
+r1_maddrs = r1.get_ip_maddrs()
+verify(sum([ml_prefix in maddr for maddr in r1_maddrs]) == 2)
+
+# -----------------------------------------------------------------------------------------------------------------------
+# Test finished
+
+cli.Node.finalize_all_nodes()
+
+print('\'{}\' passed.'.format(test_name))
diff --git a/tests/toranj/cli/test-603-channel-announce-recovery.py b/tests/toranj/cli/test-603-channel-announce-recovery.py
index 6482aa989..8fe8b68c2 100755
--- a/tests/toranj/cli/test-603-channel-announce-recovery.py
+++ b/tests/toranj/cli/test-603-channel-announce-recovery.py
@@ -46,43 +46,47 @@ print('Starting \'{}\''.format(test_name))
speedup = 40
cli.Node.set_time_speedup_factor(speedup)
-router = cli.Node()
+r1 = cli.Node()
+r2 = cli.Node()
c1 = cli.Node()
c2 = cli.Node()
# -----------------------------------------------------------------------------------------------------------------------
# Form topology
-router.form('announce-tst', channel=11)
+r1.form('announce-tst', channel=11)
-c1.join(router, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
-c2.join(router, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
+r2.join(r1, cli.JOIN_TYPE_ROUTER)
+c1.join(r1, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
+c2.join(r1, cli.JOIN_TYPE_SLEEPY_END_DEVICE)
c1.set_pollperiod(500)
c2.set_pollperiod(500)
-verify(router.get_state() == 'leader')
+verify(r1.get_state() == 'leader')
+verify(r2.get_state() == 'router')
verify(c1.get_state() == 'child')
verify(c2.get_state() == 'child')
# -----------------------------------------------------------------------------------------------------------------------
# Test Implementation
-# Stop c2
+# Stop c2 and r2
+r2.thread_stop()
c2.thread_stop()
# Switch the rest of network to channel 26
-router.cli('channel manager change 26')
+r1.cli('channel manager change 26')
def check_channel_changed_to_26_on_r1_c1():
- for node in [router, c1]:
+ for node in [r1, c1]:
verify(int(node.get_channel()) == 26)
verify_within(check_channel_changed_to_26_on_r1_c1, 10)
-# Now re-enable c2 and verify that it does attach to router and is on
+# Now re-enable c2 and verify that it does attach to r1 and is on
# channel 26. c2 would go through the ML Announce recovery.
c2.thread_start()
@@ -100,6 +104,20 @@ verify_within(check_c2_is_attched, 20)
# Check that c2 is now on channel 26.
verify(int(c2.get_channel()) == 26)
+# Now re-enable r2, and verify that it switches to channel 26
+# after processing announce from r1.
+
+r2.thread_start()
+verify(int(r2.get_channel()) == 11)
+
+
+def check_r2_switches_to_channel_26():
+ verify(r2.get_state() != 'detached')
+ verify(int(r2.get_channel()) == 26)
+
+
+verify_within(check_r2_switches_to_channel_26, 60)
+
# -----------------------------------------------------------------------------------------------------------------------
# Test finished
diff --git a/tests/toranj/openthread-core-toranj-config-posix.h b/tests/toranj/openthread-core-toranj-config-posix.h
index 95cf37ac3..60e86777f 100644
--- a/tests/toranj/openthread-core-toranj-config-posix.h
+++ b/tests/toranj/openthread-core-toranj-config-posix.h
@@ -47,4 +47,7 @@
#define OPENTHREAD_POSIX_CONFIG_SPINEL_HDLC_INTERFACE_ENABLE 1
+// Disabled explicitly on posix `toranj` to validate the build with this config
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 0
+
#endif /* OPENTHREAD_CORE_TORANJ_CONFIG_POSIX_H_ */
diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h
index 234465a6f..8a1063c5c 100644
--- a/tests/toranj/openthread-core-toranj-config-simulation.h
+++ b/tests/toranj/openthread-core-toranj-config-simulation.h
@@ -59,6 +59,8 @@
#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1
+#define OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1
+
#define OPENTHREAD_CONFIG_RADIO_STATS_ENABLE 0
#endif /* OPENTHREAD_CORE_TORANJ_CONFIG_SIMULATION_H_ */
diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h
index 52e766be5..7e2d4c7d4 100644
--- a/tests/toranj/openthread-core-toranj-config.h
+++ b/tests/toranj/openthread-core-toranj-config.h
@@ -131,6 +131,8 @@
#define OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1
+#define OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE 1
+
#define OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE 1
#define OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE 1
diff --git a/tests/toranj/start.sh b/tests/toranj/start.sh
index 609faf7f8..3e07304e6 100755
--- a/tests/toranj/start.sh
+++ b/tests/toranj/start.sh
@@ -189,6 +189,7 @@ if [ "$TORANJ_CLI" = 1 ]; then
run cli/test-022-netdata-full.py
run cli/test-023-mesh-diag.py
run cli/test-024-mle-adv-imax-change.py
+ run cli/test-025-mesh-local-prefix-change.py
run cli/test-400-srp-client-server.py
run cli/test-601-channel-manager-channel-change.py
# Skip the "channel-select" test on a TREL only radio link, since it
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 5ffdbd33b..e14e30ad5 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -32,27 +32,75 @@ set(COMMON_INCLUDES
${PROJECT_SOURCE_DIR}/src/core
)
+set(COMMON_INCLUDES_RCP
+ ${COMMON_INCLUDES}
+ ${PROJECT_SOURCE_DIR}/src/core/radio
+)
+
set(COMMON_COMPILE_OPTIONS
-DOPENTHREAD_FTD=1
-DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
)
-add_library(ot-test-platform
+set(COMMON_COMPILE_OPTIONS_RCP
+ -DOPENTHREAD_RADIO=1
+ -DOPENTHREAD_SPINEL_CONFIG_OPENTHREAD_MESSAGE_ENABLE=1
+ -DOPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE=0
+)
+
+set(MULTIPAN_RCP_COMPILE_OPTIONS
+ -DOPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1
+ -DOPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE=1
+ -DOPENTHREAD_CONFIG_LOG_PREPEND_UPTIME=0
+ -DOPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE=0 # used to skip backoff and request tx from platform directly.
+ -DOPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE=1
+)
+
+add_library(ot-test-platform-ftd
+ test_platform.cpp
+ test_util.cpp
+)
+add_library(ot-test-platform-rcp
test_platform.cpp
test_util.cpp
)
-target_include_directories(ot-test-platform
+target_include_directories(ot-test-platform-ftd
PRIVATE
${COMMON_INCLUDES}
)
-target_compile_options(ot-test-platform
+target_include_directories(ot-test-platform-rcp
+ PRIVATE
+ ${COMMON_INCLUDES}
+)
+
+target_compile_options(ot-test-platform-ftd
PRIVATE
${COMMON_COMPILE_OPTIONS}
)
-target_link_libraries(ot-test-platform
+target_compile_options(ot-test-platform-rcp
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS_RCP}
+)
+
+if(OT_MULTIPAN_RCP)
+ target_compile_options(ot-test-platform-rcp
+ PRIVATE
+ "-DOPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE=1"
+ "-DOPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE=1"
+ )
+endif()
+
+target_link_libraries(ot-test-platform-ftd
+ PRIVATE
+ ot-config
+ ${OT_MBEDTLS}
+)
+
+target_link_libraries(ot-test-platform-rcp
PRIVATE
ot-config
${OT_MBEDTLS}
@@ -61,14 +109,21 @@ target_link_libraries(ot-test-platform
set(COMMON_LIBS
openthread-spinel-ncp
openthread-hdlc
- ot-test-platform
+ ot-test-platform-ftd
openthread-ftd
- ot-test-platform
+ ot-test-platform-ftd
${OT_MBEDTLS}
ot-config
openthread-ftd
)
+set(COMMON_LIBS_RCP
+ ot-test-platform-rcp
+ openthread-rcp
+ ${OT_MBEDTLS}
+ ot-config
+)
+
add_executable(ot-test-aes
test_aes.cpp
)
@@ -748,6 +803,40 @@ target_link_libraries(ot-test-multicast-listeners-table
add_test(NAME ot-test-multicast-listeners-table COMMAND ot-test-multicast-listeners-table)
+if(OT_MULTIPAN_RCP)
+ add_executable(ot-test-multipan-rcp-instances
+ test_multipan_rcp_instances.cpp
+ )
+
+ target_include_directories(ot-test-multipan-rcp-instances
+ PRIVATE
+ ${COMMON_INCLUDES_RCP}
+ )
+
+ target_compile_options(ot-test-multipan-rcp-instances
+ PRIVATE
+ ${COMMON_COMPILE_OPTIONS_RCP}
+ ${MULTIPAN_RCP_COMPILE_OPTIONS}
+ )
+
+ target_compile_definitions(ot-test-multipan-rcp-instances
+ PRIVATE
+ "OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE=1"
+ )
+
+ target_compile_options(ot-config-radio
+ INTERFACE
+ "-DOPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE=0" # used to skip backoff and request tx from platform directly.
+ )
+
+ target_link_libraries(ot-test-multipan-rcp-instances
+ PRIVATE
+ ${COMMON_LIBS_RCP}
+ )
+
+ add_test(NAME ot-test-multipan-rcp-instances COMMAND ot-test-multipan-rcp-instances)
+ endif()
+
add_test(NAME ot-test-nat64 COMMAND ot-test-nat64)
add_executable(ot-test-nat64
diff --git a/tests/unit/test_aes.cpp b/tests/unit/test_aes.cpp
index 4ed31edd1..d1ae1ba49 100644
--- a/tests/unit/test_aes.cpp
+++ b/tests/unit/test_aes.cpp
@@ -34,6 +34,8 @@
#include "test_platform.h"
#include "test_util.hpp"
+namespace ot {
+
/**
* Verifies test vectors from IEEE 802.15.4-2006 Annex C Section C.2.1
*/
@@ -55,11 +57,11 @@ void TestMacBeaconFrame(void)
0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52,
0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53};
- otInstance *instance = testInitInstance();
- ot::Crypto::AesCcm aesCcm;
- uint32_t headerLength = sizeof(test) - 8;
- uint32_t payloadLength = 0;
- uint8_t tagLength = 8;
+ otInstance *instance = testInitInstance();
+ Crypto::AesCcm aesCcm;
+ uint32_t headerLength = sizeof(test) - 8;
+ uint32_t payloadLength = 0;
+ uint8_t tagLength = 8;
uint8_t nonce[] = {
0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02,
@@ -122,23 +124,23 @@ void TestMacCommandFrame(void)
uint8_t tag[kTagLength];
- ot::Instance *instance = testInitInstance();
- ot::Message *message;
- ot::Crypto::AesCcm aesCcm;
+ Instance *instance = testInitInstance();
+ Message *message;
+ Crypto::AesCcm aesCcm;
VerifyOrQuit(instance != nullptr);
aesCcm.SetKey(key, sizeof(key));
aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
aesCcm.Header(test, kHeaderLength);
- aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kEncrypt);
+ aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt);
VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
VerifyOrQuit(memcmp(test, encrypted, sizeof(encrypted)) == 0);
aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
aesCcm.Header(test, kHeaderLength);
- aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kDecrypt);
+ aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kDecrypt);
VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
@@ -146,7 +148,7 @@ void TestMacCommandFrame(void)
// Verify encryption/decryption in place within a message.
- message = instance->Get<ot::MessagePool>().Allocate(ot::Message::kTypeIp6);
+ message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(message->AppendBytes(test, kHeaderLength + kPayloadLength));
@@ -154,7 +156,7 @@ void TestMacCommandFrame(void)
aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
aesCcm.Header(test, kHeaderLength);
- aesCcm.Payload(*message, kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kEncrypt);
+ aesCcm.Payload(*message, kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt);
VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
aesCcm.Finalize(tag);
SuccessOrQuit(message->Append(tag));
@@ -163,7 +165,7 @@ void TestMacCommandFrame(void)
aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
aesCcm.Header(test, kHeaderLength);
- aesCcm.Payload(*message, kHeaderLength, kPayloadLength, ot::Crypto::AesCcm::kDecrypt);
+ aesCcm.Payload(*message, kHeaderLength, kPayloadLength, Crypto::AesCcm::kDecrypt);
VerifyOrQuit(message->GetLength() == sizeof(encrypted));
VerifyOrQuit(message->Compare(0, decrypted));
@@ -194,14 +196,14 @@ void TestInPlaceAesCcmProcessing(void)
uint8_t tag[kTagLength];
uint8_t header[kHeaderLength];
- ot::Crypto::AesCcm aesCcm;
- ot::Instance *instance = testInitInstance();
- ot::Message *message;
- ot::Message *messageClone;
+ Crypto::AesCcm aesCcm;
+ Instance *instance = testInitInstance();
+ Message *message;
+ Message *messageClone;
VerifyOrQuit(instance != nullptr);
- message = instance->Get<ot::MessagePool>().Allocate(ot::Message::kTypeIp6);
+ message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
VerifyOrQuit(message != nullptr);
aesCcm.SetKey(kKey, sizeof(kKey));
@@ -226,7 +228,7 @@ void TestInPlaceAesCcmProcessing(void)
// Encrypt in place
aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
aesCcm.Header(header);
- aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, ot::Crypto::AesCcm::kEncrypt);
+ aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kEncrypt);
// Append the tag
aesCcm.Finalize(tag);
@@ -237,7 +239,7 @@ void TestInPlaceAesCcmProcessing(void)
// Decrypt in place
aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
aesCcm.Header(header);
- aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, ot::Crypto::AesCcm::kDecrypt);
+ aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kDecrypt);
// Check the tag against what is the message
aesCcm.Finalize(tag);
@@ -253,11 +255,13 @@ void TestInPlaceAesCcmProcessing(void)
testFreeInstance(instance);
}
+} // namespace ot
+
int main(void)
{
- TestMacBeaconFrame();
- TestMacCommandFrame();
- TestInPlaceAesCcmProcessing();
+ ot::TestMacBeaconFrame();
+ ot::TestMacCommandFrame();
+ ot::TestInPlaceAesCcmProcessing();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_array.cpp b/tests/unit/test_array.cpp
index 0840f999c..b185d4170 100644
--- a/tests/unit/test_array.cpp
+++ b/tests/unit/test_array.cpp
@@ -36,8 +36,8 @@
#include "common/array.hpp"
#include "common/debug.hpp"
#include "common/equatable.hpp"
-#include "common/instance.hpp"
#include "common/type_traits.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
diff --git a/tests/unit/test_checksum.cpp b/tests/unit/test_checksum.cpp
index 82e74fdd7..dafd2dbbb 100644
--- a/tests/unit/test_checksum.cpp
+++ b/tests/unit/test_checksum.cpp
@@ -27,9 +27,10 @@
*/
#include "common/encoding.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
+#include "common/numeric_limits.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "net/checksum.hpp"
#include "net/icmp6.hpp"
#include "net/ip4_types.hpp"
@@ -50,7 +51,7 @@ uint16_t CalculateChecksum(const void *aBuffer, uint16_t aLength)
while (aLength >= sizeof(uint16_t))
{
- sum += Encoding::BigEndian::ReadUint16(bytes);
+ sum += BigEndian::ReadUint16(bytes);
bytes += sizeof(uint16_t);
aLength -= sizeof(uint16_t);
}
@@ -101,8 +102,8 @@ uint16_t CalculateChecksum(const Ip6::Address &aSource,
data.mPseudoHeader.mSource = aSource;
data.mPseudoHeader.mDestination = aDestination;
- data.mPseudoHeader.mProtocol = Encoding::BigEndian::HostSwap32(aIpProto);
- data.mPseudoHeader.mPayloadLength = Encoding::BigEndian::HostSwap32(payloadLength);
+ data.mPseudoHeader.mProtocol = BigEndian::HostSwap32(aIpProto);
+ data.mPseudoHeader.mPayloadLength = BigEndian::HostSwap32(payloadLength);
SuccessOrQuit(aMessage.Read(aMessage.GetOffset(), data.mPayload, payloadLength));
@@ -140,8 +141,8 @@ uint16_t CalculateChecksum(const Ip4::Address &aSource,
data.mPseudoHeader.mSource = aSource;
data.mPseudoHeader.mDestination = aDestination;
- data.mPseudoHeader.mProtocol = Encoding::BigEndian::HostSwap16(aIpProto);
- data.mPseudoHeader.mPayloadLength = Encoding::BigEndian::HostSwap16(payloadLength);
+ data.mPseudoHeader.mProtocol = BigEndian::HostSwap16(aIpProto);
+ data.mPseudoHeader.mPayloadLength = BigEndian::HostSwap16(payloadLength);
SuccessOrQuit(aMessage.Read(aMessage.GetOffset(), data.mPayload, payloadLength));
@@ -160,7 +161,7 @@ void CorruptMessage(Message &aMessage)
SuccessOrQuit(aMessage.Read(byteOffset, byte));
- bitOffset = Random::NonCrypto::GetUint8InRange(0, CHAR_BIT);
+ bitOffset = Random::NonCrypto::GetUint8InRange(0, kBitsPerByte);
byte ^= (1 << bitOffset);
diff --git a/tests/unit/test_child.cpp b/tests/unit/test_child.cpp
index 45fe65a80..eb239f085 100644
--- a/tests/unit/test_child.cpp
+++ b/tests/unit/test_child.cpp
@@ -32,12 +32,12 @@
#include "test_util.h"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "thread/child.hpp"
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
enum
{
diff --git a/tests/unit/test_child_table.cpp b/tests/unit/test_child_table.cpp
index 2fb4583f4..a5497bc92 100644
--- a/tests/unit/test_child_table.cpp
+++ b/tests/unit/test_child_table.cpp
@@ -33,12 +33,12 @@
#include "test_util.h"
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "thread/child_table.hpp"
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
enum
{
diff --git a/tests/unit/test_cmd_line_parser.cpp b/tests/unit/test_cmd_line_parser.cpp
index cc2a93595..fdf6690b0 100644
--- a/tests/unit/test_cmd_line_parser.cpp
+++ b/tests/unit/test_cmd_line_parser.cpp
@@ -32,21 +32,23 @@
#include <openthread/config.h>
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "utils/parse_cmdline.hpp"
#include "test_util.hpp"
-using ot::Utils::CmdLineParser::ParseAsBool;
-using ot::Utils::CmdLineParser::ParseAsHexString;
-using ot::Utils::CmdLineParser::ParseAsHexStringSegment;
-using ot::Utils::CmdLineParser::ParseAsInt16;
-using ot::Utils::CmdLineParser::ParseAsInt32;
-using ot::Utils::CmdLineParser::ParseAsInt8;
-using ot::Utils::CmdLineParser::ParseAsUint16;
-using ot::Utils::CmdLineParser::ParseAsUint32;
-using ot::Utils::CmdLineParser::ParseAsUint64;
-using ot::Utils::CmdLineParser::ParseAsUint8;
+namespace ot {
+
+using Utils::CmdLineParser::ParseAsBool;
+using Utils::CmdLineParser::ParseAsHexString;
+using Utils::CmdLineParser::ParseAsHexStringSegment;
+using Utils::CmdLineParser::ParseAsInt16;
+using Utils::CmdLineParser::ParseAsInt32;
+using Utils::CmdLineParser::ParseAsInt8;
+using Utils::CmdLineParser::ParseAsUint16;
+using Utils::CmdLineParser::ParseAsUint32;
+using Utils::CmdLineParser::ParseAsUint64;
+using Utils::CmdLineParser::ParseAsUint8;
template <typename ValueType> struct TestCase
{
@@ -352,10 +354,12 @@ void TestParsingHexStrings(void)
}
}
+} // namespace ot
+
int main(void)
{
- TestParsingInts();
- TestParsingHexStrings();
+ ot::TestParsingInts();
+ ot::TestParsingHexStrings();
printf("All tests passed\n");
return 0;
diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp
index 2a2597efb..a8408aad4 100644
--- a/tests/unit/test_dns.cpp
+++ b/tests/unit/test_dns.cpp
@@ -34,7 +34,7 @@
#include "test_util.hpp"
#include "common/array.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "net/dns_types.hpp"
namespace ot {
@@ -1302,6 +1302,9 @@ void TestDnsTxtEntry(void)
const char kKey6[] = "boolKey"; // Should be encoded as "boolKey" (without `=`).
const char kKey7[] = "emptyKey"; // Should be encoded as "emptyKey=".
+ const char kKey8[] = "1234567890123456789012345678901234567890123456789012345678901234567890";
+ const uint8_t kValue8[] = "abcd";
+
// Invalid key
const char kShortKey[] = "";
@@ -1312,6 +1315,17 @@ void TestDnsTxtEntry(void)
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 kEncodedTxt8[] = {
+ 75, // length
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 10
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 20
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 40
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 50
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 60
+ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 70
+ '=', 'a', 'b', 'c', 'd',
+ };
const uint8_t kInvalidEncodedTxt1[] = {4, 'a', '=', 'b'}; // Incorrect length
@@ -1327,6 +1341,7 @@ void TestDnsTxtEntry(void)
Dns::TxtEntry(kKey5, kValue5, sizeof(kValue5)),
Dns::TxtEntry(kKey6, nullptr, 0),
Dns::TxtEntry(kKey7, kValue1, 0),
+ Dns::TxtEntry(kKey8, kValue8, sizeof(kValue8)),
};
const EncodedTxtData kEncodedTxtData[] = {
@@ -1381,7 +1396,7 @@ void TestDnsTxtEntry(void)
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)
+ if (expectedKeyLength > Dns::TxtEntry::kMaxIterKeyLength)
{
// When the key is longer than recommended max key length,
// the full encoded string is returned in `mValue` and
diff --git a/tests/unit/test_dns_client.cpp b/tests/unit/test_dns_client.cpp
index e259ba9ae..59efab72d 100644
--- a/tests/unit/test_dns_client.cpp
+++ b/tests/unit/test_dns_client.cpp
@@ -39,9 +39,9 @@
#include "common/arg_macros.hpp"
#include "common/array.hpp"
-#include "common/instance.hpp"
#include "common/string.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE && \
OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE && OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && \
diff --git a/tests/unit/test_dso.cpp b/tests/unit/test_dso.cpp
index 2ee18286a..a612680b3 100644
--- a/tests/unit/test_dso.cpp
+++ b/tests/unit/test_dso.cpp
@@ -34,10 +34,12 @@
#include "common/arg_macros.hpp"
#include "common/array.hpp"
#include "common/as_core_type.hpp"
-#include "common/instance.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#include "net/dns_dso.hpp"
+namespace ot {
+
#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
extern "C" {
@@ -73,7 +75,7 @@ void AdvanceTime(uint32_t aDuration)
Log(" AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
- while (ot::TimeMilli(sAlarmTime) <= ot::TimeMilli(time))
+ while (TimeMilli(sAlarmTime) <= TimeMilli(time))
{
sNow = sAlarmTime;
otPlatAlarmMilliFired(sInstance);
@@ -82,7 +84,6 @@ void AdvanceTime(uint32_t aDuration)
sNow = time;
}
-namespace ot {
namespace Dns {
OT_TOOL_PACKED_BEGIN
@@ -1218,10 +1219,11 @@ void TestDso(void)
}
} // namespace Dns
-} // namespace ot
#endif // OPENTHREAD_CONFIG_DNS_DSO_ENABLE
+} // namespace ot
+
int main(void)
{
#if OPENTHREAD_CONFIG_DNS_DSO_ENABLE
diff --git a/tests/unit/test_hdlc.cpp b/tests/unit/test_hdlc.cpp
index c4c707cb1..4e96310de 100644
--- a/tests/unit/test_hdlc.cpp
+++ b/tests/unit/test_hdlc.cpp
@@ -29,7 +29,7 @@
#include <ctype.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "lib/hdlc/hdlc.hpp"
#include "lib/spinel/multi_frame_buffer.hpp"
diff --git a/tests/unit/test_heap.cpp b/tests/unit/test_heap.cpp
index b6cc88425..003a54c6c 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"
+namespace ot {
+
#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
/**
@@ -175,10 +177,12 @@ void RunTimerTests(void)
#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+} // namespace ot
+
int main(void)
{
#if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
- RunTimerTests();
+ ot::RunTimerTests();
printf("All tests passed\n");
#endif // !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
return 0;
diff --git a/tests/unit/test_hkdf_sha256.cpp b/tests/unit/test_hkdf_sha256.cpp
index 019db5690..2b3c01dc3 100644
--- a/tests/unit/test_hkdf_sha256.cpp
+++ b/tests/unit/test_hkdf_sha256.cpp
@@ -36,6 +36,8 @@
#include "common/debug.hpp"
#include "crypto/hkdf_sha256.hpp"
+namespace ot {
+
struct TestVector
{
const uint8_t *mInKey;
@@ -126,11 +128,11 @@ void TestHkdfSha256(void)
VerifyOrQuit(instance != nullptr);
- for (const TestVector *test = &kTestVectors[0]; test < ot::GetArrayEnd(kTestVectors); test++)
+ for (const TestVector *test = &kTestVectors[0]; test < GetArrayEnd(kTestVectors); test++)
{
- ot::Crypto::HkdfSha256 hkdf;
- uint8_t outKey[kMaxOuttKey];
- ot::Crypto::Key testInputKey;
+ Crypto::HkdfSha256 hkdf;
+ uint8_t outKey[kMaxOuttKey];
+ Crypto::Key testInputKey;
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
DumpBuffer("\nInput Key", test->mInKey, test->mInKeyLength);
@@ -159,9 +161,11 @@ void TestHkdfSha256(void)
testFreeInstance(instance);
}
+} // namespace ot
+
int main(void)
{
- TestHkdfSha256();
+ ot::TestHkdfSha256();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_ip4_header.cpp b/tests/unit/test_ip4_header.cpp
index e9021a820..7d9eec6de 100644
--- a/tests/unit/test_ip4_header.cpp
+++ b/tests/unit/test_ip4_header.cpp
@@ -31,8 +31,6 @@
#include "test_util.hpp"
-using ot::Encoding::BigEndian::ReadUint16;
-
namespace ot {
namespace Ip4 {
@@ -91,7 +89,8 @@ void TestIp4Header(void)
// Verify the offsets to different fields.
- VerifyOrQuit(ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength, "kTotalLength is incorrect");
+ VerifyOrQuit(BigEndian::ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength,
+ "kTotalLength is incorrect");
VerifyOrQuit(headerBytes[Header::kProtocolOffset] == kProtoIcmp, "kProtocol is incorrect");
VerifyOrQuit(headerBytes[Header::kTtlOffset] == kTtl, "kTtl is incorrect");
VerifyOrQuit(memcmp(&headerBytes[Header::kSourceAddressOffset], &source, sizeof(source)) == 0,
@@ -116,7 +115,8 @@ void TestIp4Header(void)
"Source address is incorrect");
VerifyOrQuit(memcmp(&headerBytes[Header::kDestinationAddressOffset], &destination, sizeof(destination)) == 0,
"Destination address is incorrect");
- VerifyOrQuit(ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength, "kTotalLength is incorrect");
+ VerifyOrQuit(BigEndian::ReadUint16(headerBytes + Header::kTotalLengthOffset) == kTotalLength,
+ "kTotalLength is incorrect");
VerifyOrQuit(headerBytes[Header::kProtocolOffset] == kProtoIcmp, "kProtocol is incorrect");
VerifyOrQuit(headerBytes[Header::kTtlOffset] == kTtl, "kTtl is incorrect");
}
diff --git a/tests/unit/test_ip6_header.cpp b/tests/unit/test_ip6_header.cpp
index eab543d86..f4b4c9c91 100644
--- a/tests/unit/test_ip6_header.cpp
+++ b/tests/unit/test_ip6_header.cpp
@@ -31,8 +31,6 @@
#include "test_util.hpp"
-using ot::Encoding::BigEndian::ReadUint16;
-
namespace ot {
namespace Ip6 {
@@ -97,7 +95,7 @@ void TestIp6Header(void)
// Verify the offsets to different fields.
- VerifyOrQuit(ReadUint16(headerBytes + Header::kPayloadLengthFieldOffset) == kPayloadLength,
+ VerifyOrQuit(BigEndian::ReadUint16(headerBytes + Header::kPayloadLengthFieldOffset) == kPayloadLength,
"kPayloadLengthFieldOffset is incorrect");
VerifyOrQuit(headerBytes[Header::kNextHeaderFieldOffset] == kProtoUdp, "kNextHeaderFieldOffset is incorrect");
VerifyOrQuit(headerBytes[Header::kHopLimitFieldOffset] == kHopLimit, "kHopLimitFieldOffset is incorrect");
diff --git a/tests/unit/test_ip_address.cpp b/tests/unit/test_ip_address.cpp
index a3b71cf42..746ac02c0 100644
--- a/tests/unit/test_ip_address.cpp
+++ b/tests/unit/test_ip_address.cpp
@@ -26,8 +26,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <limits.h>
-
#include "common/array.hpp"
#include "common/encoding.hpp"
#include "common/string.hpp"
@@ -36,16 +34,18 @@
#include "test_util.h"
+namespace ot {
+
template <typename AddressType> struct TestVector
{
const char *mString;
const uint8_t mAddr[sizeof(AddressType)];
- ot::Error mError;
+ Error mError;
};
template <typename AddressType> static void checkAddressFromString(TestVector<AddressType> *aTestVector)
{
- ot::Error error;
+ Error error;
AddressType address;
address.Clear();
@@ -53,11 +53,11 @@ template <typename AddressType> static void checkAddressFromString(TestVector<Ad
error = address.FromString(aTestVector->mString);
printf("%-42s -> %-42s\n", aTestVector->mString,
- (error == ot::kErrorNone) ? address.ToString().AsCString() : "(parse error)");
+ (error == kErrorNone) ? address.ToString().AsCString() : "(parse error)");
VerifyOrQuit(error == aTestVector->mError, "Address::FromString returned unexpected error code");
- if (error == ot::kErrorNone)
+ if (error == kErrorNone)
{
VerifyOrQuit(0 == memcmp(address.GetBytes(), aTestVector->mAddr, sizeof(AddressType)),
"Address::FromString parsing failed");
@@ -66,102 +66,102 @@ template <typename AddressType> static void checkAddressFromString(TestVector<Ad
void TestIp6AddressFromString(void)
{
- typedef TestVector<ot::Ip6::Address> Ip6AddressTestVector;
+ typedef TestVector<Ip6::Address> Ip6AddressTestVector;
Ip6AddressTestVector testVectors[] = {
// 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::kErrorNone},
+ kErrorNone},
// Valid full address using capital 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::kErrorNone},
+ 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::kErrorNone},
+ 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::kErrorNone},
+ 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::kErrorNone},
+ kErrorNone},
// Short multicast address.
{"ff03::0b",
{0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b},
- ot::kErrorNone},
+ kErrorNone},
// Unspecified address.
- {"::", {0}, ot::kErrorNone},
+ {"::", {0}, kErrorNone},
// Starts with ::
{"::1:2:3:4",
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04},
- ot::kErrorNone},
+ kErrorNone},
// Ends with ::
{"1001:2002:3003:4004::",
{0x10, 0x01, 0x20, 0x02, 0x30, 0x03, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- ot::kErrorNone},
+ 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::kErrorNone},
+ 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::kErrorNone},
+ kErrorNone},
// Valid embedded IPv4 address.
{"1:2:3:4:5:6:127.1.2.3",
{0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x03},
- ot::kErrorNone},
+ kErrorNone},
// Two :: should cause a parse error.
- {"2001:db8::a::b", {0}, ot::kErrorParse},
+ {"2001:db8::a::b", {0}, kErrorParse},
// The "g" and "h" are not the hex characters.
- {"2001:db8::abcd:efgh", {0}, ot::kErrorParse},
+ {"2001:db8::abcd:efgh", {0}, kErrorParse},
// Too many colons.
- {"1:2:3:4:5:6:7:8:9", {0}, ot::kErrorParse},
+ {"1:2:3:4:5:6:7:8:9", {0}, kErrorParse},
// Too many characters in a single part.
- {"2001:db8::abc:def12:1:2", {0}, ot::kErrorParse},
+ {"2001:db8::abc:def12:1:2", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::123.231.0.257", {0}, ot::kErrorParse},
+ {"64:ff9b::123.231.0.257", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::1.22.33", {0}, ot::kErrorParse},
+ {"64:ff9b::1.22.33", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {"64:ff9b::1.22.33.44.5", {0}, ot::kErrorParse},
+ {"64:ff9b::1.22.33.44.5", {0}, kErrorParse},
// Too long with embedded IPv4 address.
- {"1:2:3:4:5:6:7:127.1.2.3", {0}, ot::kErrorParse},
+ {"1:2:3:4:5:6:7:127.1.2.3", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {".", {0}, ot::kErrorParse},
+ {".", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {":.", {0}, ot::kErrorParse},
+ {":.", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {"::.", {0}, ot::kErrorParse},
+ {"::.", {0}, kErrorParse},
// Invalid embedded IPv4 address.
- {":f:0:0:c:0:f:f:.", {0}, ot::kErrorParse},
+ {":f:0:0:c:0:f:f:.", {0}, kErrorParse},
};
for (Ip6AddressTestVector &testVector : testVectors)
@@ -175,11 +175,11 @@ void TestIp6AddressFromString(void)
{
constexpr uint16_t kMaxString = 80;
- ot::Ip6::Prefix prefix;
- char string[kMaxString];
- uint16_t length;
+ Ip6::Prefix prefix;
+ char string[kMaxString];
+ uint16_t length;
- length = ot::StringLength(testVector.mString, kMaxString);
+ length = StringLength(testVector.mString, kMaxString);
memcpy(string, testVector.mString, length);
VerifyOrQuit(length + sizeof("/128") <= kMaxString);
strcpy(&string[length], "/128");
@@ -188,9 +188,9 @@ void TestIp6AddressFromString(void)
VerifyOrQuit(prefix.FromString(string) == testVector.mError);
- if (testVector.mError == ot::kErrorNone)
+ if (testVector.mError == kErrorNone)
{
- VerifyOrQuit(memcmp(prefix.GetBytes(), testVector.mAddr, sizeof(ot::Ip6::Address)) == 0);
+ VerifyOrQuit(memcmp(prefix.GetBytes(), testVector.mAddr, sizeof(Ip6::Address)) == 0);
VerifyOrQuit(prefix.GetLength() == 128);
}
}
@@ -198,7 +198,7 @@ void TestIp6AddressFromString(void)
void TestIp6PrefixFromString(void)
{
- ot::Ip6::Prefix prefix;
+ Ip6::Prefix prefix;
SuccessOrQuit(prefix.FromString("::/128"));
VerifyOrQuit(prefix.GetLength() == 128);
@@ -212,32 +212,32 @@ void TestIp6PrefixFromString(void)
SuccessOrQuit(prefix.FromString("::/0"));
VerifyOrQuit(prefix.GetLength() == 0);
- VerifyOrQuit(prefix.FromString("::") == ot::kErrorParse);
- VerifyOrQuit(prefix.FromString("::/") == ot::kErrorParse);
- VerifyOrQuit(prefix.FromString("::/129") == ot::kErrorParse);
- VerifyOrQuit(prefix.FromString(":: /12") == ot::kErrorParse);
- VerifyOrQuit(prefix.FromString("::/a1") == ot::kErrorParse);
- VerifyOrQuit(prefix.FromString("::/12 ") == ot::kErrorParse);
+ VerifyOrQuit(prefix.FromString("::") == kErrorParse);
+ VerifyOrQuit(prefix.FromString("::/") == kErrorParse);
+ VerifyOrQuit(prefix.FromString("::/129") == kErrorParse);
+ VerifyOrQuit(prefix.FromString(":: /12") == kErrorParse);
+ VerifyOrQuit(prefix.FromString("::/a1") == kErrorParse);
+ VerifyOrQuit(prefix.FromString("::/12 ") == kErrorParse);
}
void TestIp4AddressFromString(void)
{
- typedef TestVector<ot::Ip4::Address> Ip4AddressTestVector;
+ typedef TestVector<Ip4::Address> Ip4AddressTestVector;
Ip4AddressTestVector testVectors[] = {
- {"0.0.0.0", {0, 0, 0, 0}, ot::kErrorNone},
- {"255.255.255.255", {255, 255, 255, 255}, ot::kErrorNone},
- {"127.0.0.1", {127, 0, 0, 1}, ot::kErrorNone},
- {"1.2.3.4", {1, 2, 3, 4}, ot::kErrorNone},
- {"001.002.003.004", {1, 2, 3, 4}, ot::kErrorNone},
- {"00000127.000.000.000001", {127, 0, 0, 1}, ot::kErrorNone},
- {"123.231.0.256", {0}, ot::kErrorParse}, // Invalid byte value.
- {"100123.231.0.256", {0}, ot::kErrorParse}, // Invalid byte value.
- {"1.22.33", {0}, ot::kErrorParse}, // Too few bytes.
- {"1.22.33.44.5", {0}, ot::kErrorParse}, // Too many bytes.
- {"a.b.c.d", {0}, ot::kErrorParse}, // Wrong digit char.
- {"123.23.45 .12", {0}, ot::kErrorParse}, // Extra space.
- {".", {0}, ot::kErrorParse}, // Invalid.
+ {"0.0.0.0", {0, 0, 0, 0}, kErrorNone},
+ {"255.255.255.255", {255, 255, 255, 255}, kErrorNone},
+ {"127.0.0.1", {127, 0, 0, 1}, kErrorNone},
+ {"1.2.3.4", {1, 2, 3, 4}, kErrorNone},
+ {"001.002.003.004", {1, 2, 3, 4}, kErrorNone},
+ {"00000127.000.000.000001", {127, 0, 0, 1}, kErrorNone},
+ {"123.231.0.256", {0}, kErrorParse}, // Invalid byte value.
+ {"100123.231.0.256", {0}, kErrorParse}, // Invalid byte value.
+ {"1.22.33", {0}, kErrorParse}, // Too few bytes.
+ {"1.22.33.44.5", {0}, kErrorParse}, // Too many bytes.
+ {"a.b.c.d", {0}, kErrorParse}, // Wrong digit char.
+ {"123.23.45 .12", {0}, kErrorParse}, // Extra space.
+ {".", {0}, kErrorParse}, // Invalid.
};
for (Ip4AddressTestVector &testVector : testVectors)
@@ -251,24 +251,24 @@ struct CidrTestVector
const char *mString;
const uint8_t mAddr[sizeof(otIp4Address)];
const uint8_t mLength;
- ot::Error mError;
+ Error mError;
};
static void checkCidrFromString(CidrTestVector *aTestVector)
{
- ot::Error error;
- ot::Ip4::Cidr cidr;
+ Error error;
+ Ip4::Cidr cidr;
cidr.Clear();
error = cidr.FromString(aTestVector->mString);
printf("%-42s -> %-42s\n", aTestVector->mString,
- (error == ot::kErrorNone) ? cidr.ToString().AsCString() : "(parse error)");
+ (error == kErrorNone) ? cidr.ToString().AsCString() : "(parse error)");
VerifyOrQuit(error == aTestVector->mError, "Address::FromString returned unexpected error code");
- if (error == ot::kErrorNone)
+ if (error == kErrorNone)
{
VerifyOrQuit(0 == memcmp(cidr.GetBytes(), aTestVector->mAddr, sizeof(aTestVector->mAddr)),
"Cidr::FromString parsing failed");
@@ -279,37 +279,37 @@ static void checkCidrFromString(CidrTestVector *aTestVector)
void TestIp4CidrFromString(void)
{
CidrTestVector testVectors[] = {
- {"0.0.0.0/0", {0, 0, 0, 0}, 0, ot::kErrorNone},
- {"255.255.255.255/32", {255, 255, 255, 255}, 32, ot::kErrorNone},
- {"127.0.0.1/8", {127, 0, 0, 1}, 8, ot::kErrorNone},
- {"1.2.3.4/24", {1, 2, 3, 4}, 24, ot::kErrorNone},
- {"001.002.003.004/20", {1, 2, 3, 4}, 20, ot::kErrorNone},
- {"00000127.000.000.000001/8", {127, 0, 0, 1}, 8, ot::kErrorNone},
+ {"0.0.0.0/0", {0, 0, 0, 0}, 0, kErrorNone},
+ {"255.255.255.255/32", {255, 255, 255, 255}, 32, kErrorNone},
+ {"127.0.0.1/8", {127, 0, 0, 1}, 8, kErrorNone},
+ {"1.2.3.4/24", {1, 2, 3, 4}, 24, kErrorNone},
+ {"001.002.003.004/20", {1, 2, 3, 4}, 20, kErrorNone},
+ {"00000127.000.000.000001/8", {127, 0, 0, 1}, 8, kErrorNone},
// Valid suffix, invalid address
- {"123.231.0.256/4", {0}, 0, ot::kErrorParse}, // Invalid byte value.
- {"100123.231.0.256/4", {0}, 0, ot::kErrorParse}, // Invalid byte value.
- {"1.22.33/4", {0}, 0, ot::kErrorParse}, // Too few bytes.
- {"1.22.33.44.5/4", {0}, 0, ot::kErrorParse}, // Too many bytes.
- {"a.b.c.d/4", {0}, 0, ot::kErrorParse}, // Wrong digit char.
- {"123.23.45 .12/4", {0}, 0, ot::kErrorParse}, // Extra space.
- {"./4", {0}, 0, ot::kErrorParse}, // Invalid.
+ {"123.231.0.256/4", {0}, 0, kErrorParse}, // Invalid byte value.
+ {"100123.231.0.256/4", {0}, 0, kErrorParse}, // Invalid byte value.
+ {"1.22.33/4", {0}, 0, kErrorParse}, // Too few bytes.
+ {"1.22.33.44.5/4", {0}, 0, kErrorParse}, // Too many bytes.
+ {"a.b.c.d/4", {0}, 0, kErrorParse}, // Wrong digit char.
+ {"123.23.45 .12/4", {0}, 0, kErrorParse}, // Extra space.
+ {"./4", {0}, 0, kErrorParse}, // Invalid.
// valid address, invalid suffix
- {"1.2.3.4/33", {0}, 0, ot::kErrorParse}, // Prefix length too large
- {"1.2.3.4/12345678", {0}, 0, ot::kErrorParse}, // Prefix length too large?
- {"1.2.3.4/12a", {0}, 0, ot::kErrorParse}, // Extra char after prefix length.
- {"1.2.3.4/-1", {0}, 0, ot::kErrorParse}, // Not even a non-negative integer.
- {"1.2.3.4/3.14", {0}, 0, ot::kErrorParse}, // Not even a integer.
- {"1.2.3.4/abcd", {0}, 0, ot::kErrorParse}, // Not even a number.
- {"1.2.3.4/", {0}, 0, ot::kErrorParse}, // Where is the suffix?
- {"1.2.3.4", {0}, 0, ot::kErrorParse}, // Where is the suffix?
+ {"1.2.3.4/33", {0}, 0, kErrorParse}, // Prefix length too large
+ {"1.2.3.4/12345678", {0}, 0, kErrorParse}, // Prefix length too large?
+ {"1.2.3.4/12a", {0}, 0, kErrorParse}, // Extra char after prefix length.
+ {"1.2.3.4/-1", {0}, 0, kErrorParse}, // Not even a non-negative integer.
+ {"1.2.3.4/3.14", {0}, 0, kErrorParse}, // Not even a integer.
+ {"1.2.3.4/abcd", {0}, 0, kErrorParse}, // Not even a number.
+ {"1.2.3.4/", {0}, 0, kErrorParse}, // Where is the suffix?
+ {"1.2.3.4", {0}, 0, kErrorParse}, // Where is the suffix?
// invalid address and invalid suffix
- {"123.231.0.256/41", {0}, 0, ot::kErrorParse}, // Invalid byte value.
- {"100123.231.0.256/abc", {0}, 0, ot::kErrorParse}, // Invalid byte value.
- {"1.22.33", {0}, 0, ot::kErrorParse}, // Too few bytes.
- {"1.22.33.44.5/36", {0}, 0, ot::kErrorParse}, // Too many bytes.
- {"a.b.c.d/99", {0}, 0, ot::kErrorParse}, // Wrong digit char.
- {"123.23.45 .12", {0}, 0, ot::kErrorParse}, // Extra space.
- {".", {0}, 0, ot::kErrorParse}, // Invalid.
+ {"123.231.0.256/41", {0}, 0, kErrorParse}, // Invalid byte value.
+ {"100123.231.0.256/abc", {0}, 0, kErrorParse}, // Invalid byte value.
+ {"1.22.33", {0}, 0, kErrorParse}, // Too few bytes.
+ {"1.22.33.44.5/36", {0}, 0, kErrorParse}, // Too many bytes.
+ {"a.b.c.d/99", {0}, 0, kErrorParse}, // Wrong digit char.
+ {"123.23.45 .12", {0}, 0, kErrorParse}, // Extra space.
+ {".", {0}, 0, kErrorParse}, // Invalid.
};
for (CidrTestVector &testVector : testVectors)
@@ -318,7 +318,7 @@ void TestIp4CidrFromString(void)
}
}
-bool CheckPrefix(const ot::Ip6::Address &aAddress, const uint8_t *aPrefix, uint8_t aPrefixLength)
+bool CheckPrefix(const Ip6::Address &aAddress, const uint8_t *aPrefix, uint8_t aPrefixLength)
{
// Check the first aPrefixLength bits of aAddress to match the given aPrefix.
@@ -326,8 +326,8 @@ bool CheckPrefix(const ot::Ip6::Address &aAddress, const uint8_t *aPrefix, uint8
for (uint8_t bit = 0; bit < aPrefixLength; bit++)
{
- uint8_t index = bit / CHAR_BIT;
- uint8_t mask = (0x80 >> (bit % CHAR_BIT));
+ uint8_t index = bit / kBitsPerByte;
+ uint8_t mask = (0x80 >> (bit % kBitsPerByte));
if ((aAddress.mFields.m8[index] & mask) != (aPrefix[index] & mask))
{
@@ -339,7 +339,7 @@ bool CheckPrefix(const ot::Ip6::Address &aAddress, const uint8_t *aPrefix, uint8
return matches;
}
-bool CheckPrefixInIid(const ot::Ip6::InterfaceIdentifier &aIid, const uint8_t *aPrefix, uint8_t aPrefixLength)
+bool CheckPrefixInIid(const Ip6::InterfaceIdentifier &aIid, const uint8_t *aPrefix, uint8_t aPrefixLength)
{
// Check the IID to contain the prefix bits (applicable when prefix length is longer than 64).
@@ -347,8 +347,8 @@ bool CheckPrefixInIid(const ot::Ip6::InterfaceIdentifier &aIid, const uint8_t *a
for (uint8_t bit = 64; bit < aPrefixLength; bit++)
{
- uint8_t index = bit / CHAR_BIT;
- uint8_t mask = (0x80 >> (bit % CHAR_BIT));
+ uint8_t index = bit / kBitsPerByte;
+ uint8_t mask = (0x80 >> (bit % kBitsPerByte));
if ((aIid.mFields.m8[index - 8] & mask) != (aPrefix[index] & mask))
{
@@ -360,16 +360,16 @@ bool CheckPrefixInIid(const ot::Ip6::InterfaceIdentifier &aIid, const uint8_t *a
return matches;
}
-bool CheckInterfaceId(const ot::Ip6::Address &aAddress1, const ot::Ip6::Address &aAddress2, uint8_t aPrefixLength)
+bool CheckInterfaceId(const Ip6::Address &aAddress1, const Ip6::Address &aAddress2, uint8_t aPrefixLength)
{
// Check whether all the bits after aPrefixLength of the two given IPv6 Address match or not.
bool matches = true;
- for (size_t bit = aPrefixLength; bit < sizeof(ot::Ip6::Address) * CHAR_BIT; bit++)
+ for (size_t bit = aPrefixLength; bit < sizeof(Ip6::Address) * kBitsPerByte; bit++)
{
- uint8_t index = bit / CHAR_BIT;
- uint8_t mask = (0x80 >> (bit % CHAR_BIT));
+ uint8_t index = bit / kBitsPerByte;
+ uint8_t mask = (0x80 >> (bit % kBitsPerByte));
if ((aAddress1.mFields.m8[index] & mask) != (aAddress2.mFields.m8[index] & mask))
{
@@ -390,10 +390,10 @@ void TestIp6AddressSetPrefix(void)
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
};
- ot::Ip6::Address address;
- ot::Ip6::Address allZeroAddress;
- ot::Ip6::Address allOneAddress;
- ot::Ip6::Prefix ip6Prefix;
+ Ip6::Address address;
+ Ip6::Address allZeroAddress;
+ Ip6::Address allOneAddress;
+ Ip6::Prefix ip6Prefix;
allZeroAddress.Clear();
memset(&allOneAddress, 0xff, sizeof(allOneAddress));
@@ -403,7 +403,7 @@ void TestIp6AddressSetPrefix(void)
memcpy(address.mFields.m8, prefix, sizeof(address));
printf("Prefix is %s\n", address.ToString().AsCString());
- for (size_t prefixLength = 0; prefixLength <= sizeof(ot::Ip6::Address) * CHAR_BIT; prefixLength++)
+ for (size_t prefixLength = 0; prefixLength <= sizeof(Ip6::Address) * kBitsPerByte; prefixLength++)
{
ip6Prefix.Clear();
ip6Prefix.Set(prefix, prefixLength);
@@ -436,10 +436,10 @@ void TestIp6AddressSetPrefix(void)
}
}
-ot::Ip6::Prefix PrefixFrom(const char *aAddressString, uint8_t aPrefixLength)
+Ip6::Prefix PrefixFrom(const char *aAddressString, uint8_t aPrefixLength)
{
- ot::Ip6::Prefix prefix;
- ot::Ip6::Address address;
+ Ip6::Prefix prefix;
+ Ip6::Address address;
SuccessOrQuit(address.FromString(aAddressString));
prefix.Set(address.GetBytes(), aPrefixLength);
@@ -455,8 +455,8 @@ void TestIp6Prefix(void)
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
};
- ot::Ip6::Prefix prefix;
- ot::Ip6::Address address1, address2;
+ Ip6::Prefix prefix;
+ Ip6::Address address1, address2;
for (auto prefixBytes : kPrefixes)
{
@@ -464,7 +464,7 @@ void TestIp6Prefix(void)
address2 = address1;
address2.mFields.m8[0] ^= 0x80; // Change first bit.
- for (uint8_t prefixLength = 1; prefixLength <= ot::Ip6::Prefix::kMaxLength; prefixLength++)
+ for (uint8_t prefixLength = 1; prefixLength <= Ip6::Prefix::kMaxLength; prefixLength++)
{
prefix.Set(prefixBytes, prefixLength);
@@ -482,7 +482,7 @@ void TestIp6Prefix(void)
for (uint8_t subPrefixLength = 1; subPrefixLength <= prefixLength; subPrefixLength++)
{
- ot::Ip6::Prefix subPrefix;
+ Ip6::Prefix subPrefix;
subPrefix.Set(prefixBytes, subPrefixLength);
@@ -504,10 +504,10 @@ void TestIp6Prefix(void)
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;
+ 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);
@@ -528,8 +528,8 @@ void TestIp6Prefix(void)
{
struct TestCase
{
- ot::Ip6::Prefix mPrefixA;
- ot::Ip6::Prefix mPrefixB;
+ Ip6::Prefix mPrefixA;
+ Ip6::Prefix mPrefixB;
};
TestCase kTestCases[] = {
@@ -735,16 +735,16 @@ void TestIp6PrefixTidy(void)
for (auto test : kPrefixes)
{
- for (uint16_t i = 0; i < ot::GetArrayLength(test.prefixStringAfterTidy); i++)
+ for (uint16_t i = 0; i < GetArrayLength(test.prefixStringAfterTidy); i++)
{
- ot::Ip6::Prefix prefix, answer;
+ Ip6::Prefix prefix, answer;
SuccessOrQuit(answer.FromString(test.prefixStringAfterTidy[i]));
prefix.Set(test.originalPrefix, i);
prefix.Tidy();
{
- ot::Ip6::Prefix::InfoString prefixString = prefix.ToString();
+ Ip6::Prefix::InfoString prefixString = prefix.ToString();
printf("Prefix: %-36s TidyResult: %-36s\n", test.prefixStringAfterTidy[i],
prefix.ToString().AsCString());
@@ -781,7 +781,7 @@ void TestIp4Ip6Translation(void)
const uint8_t kIp4Address[] = {192, 0, 2, 33};
- ot::Ip4::Address ip4Address;
+ Ip4::Address ip4Address;
printf("\nTestIp4Ip6Translation()\n");
@@ -789,9 +789,9 @@ void TestIp4Ip6Translation(void)
for (const TestCase &testCase : kTestCases)
{
- ot::Ip6::Prefix prefix;
- ot::Ip6::Address address;
- ot::Ip6::Address expectedAddress;
+ Ip6::Prefix prefix;
+ Ip6::Address address;
+ Ip6::Address expectedAddress;
SuccessOrQuit(address.FromString(testCase.mPrefix));
prefix.Set(address.GetBytes(), testCase.mLength);
@@ -809,9 +809,9 @@ void TestIp4Ip6Translation(void)
for (const TestCase &testCase : kTestCases)
{
- const ot::Ip4::Address expectedAddress = ip4Address;
- ot::Ip4::Address address;
- ot::Ip6::Address ip6Address;
+ const Ip4::Address expectedAddress = ip4Address;
+ Ip4::Address address;
+ Ip6::Address ip6Address;
SuccessOrQuit(ip6Address.FromString(testCase.mIp6Address));
@@ -826,7 +826,6 @@ void TestIp4Ip6Translation(void)
void TestIp4Cidr(void)
{
- using ot::Encoding::BigEndian::HostSwap32;
struct TestCase
{
const char *mNetwork;
@@ -857,9 +856,9 @@ void TestIp4Cidr(void)
for (const TestCase &testCase : kTestCases)
{
- ot::Ip4::Address network;
- ot::Ip4::Cidr cidr;
- ot::Ip4::Address generated;
+ Ip4::Address network;
+ Ip4::Cidr cidr;
+ Ip4::Address generated;
SuccessOrQuit(network.FromString(testCase.mNetwork));
cidr.mAddress = network;
@@ -875,17 +874,20 @@ void TestIp4Cidr(void)
}
}
+} // namespace ot
+
int main(void)
{
- TestIp6AddressSetPrefix();
- TestIp4AddressFromString();
- TestIp6AddressFromString();
- TestIp6PrefixFromString();
- TestIp6Prefix();
- TestIp6PrefixTidy();
- TestIp4Ip6Translation();
- TestIp4Cidr();
- TestIp4CidrFromString();
+ ot::TestIp6AddressSetPrefix();
+ ot::TestIp4AddressFromString();
+ ot::TestIp6AddressFromString();
+ ot::TestIp6PrefixFromString();
+ ot::TestIp6Prefix();
+ ot::TestIp6PrefixTidy();
+ ot::TestIp4Ip6Translation();
+ ot::TestIp4Cidr();
+ ot::TestIp4CidrFromString();
+
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_link_metrics_manager.cpp b/tests/unit/test_link_metrics_manager.cpp
index 4125680be..6c928b234 100644
--- a/tests/unit/test_link_metrics_manager.cpp
+++ b/tests/unit/test_link_metrics_manager.cpp
@@ -33,13 +33,13 @@
#include "test_util.h"
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "mac/mac_types.hpp"
#include "thread/child_table.hpp"
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
#if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
@@ -77,17 +77,17 @@ const TestChild UnitTester::mTestChildList[] = {
{
Child::kStateValid,
{{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x16}},
- ot::kThreadVersion1p2,
+ kThreadVersion1p2,
},
{
Child::kStateValid,
{{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x17}},
- ot::kThreadVersion1p2,
+ kThreadVersion1p2,
},
{
Child::kStateParentRequest,
{{0x10, 0x20, 0x03, 0x15, 0x10, 0x00, 0x60, 0x18}},
- ot::kThreadVersion1p2,
+ kThreadVersion1p2,
},
};
diff --git a/tests/unit/test_link_quality.cpp b/tests/unit/test_link_quality.cpp
index 8070abe52..a674ccb8c 100644
--- a/tests/unit/test_link_quality.cpp
+++ b/tests/unit/test_link_quality.cpp
@@ -36,7 +36,7 @@
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
enum
{
diff --git a/tests/unit/test_linked_list.cpp b/tests/unit/test_linked_list.cpp
index 0032ee2c1..8c581d76f 100644
--- a/tests/unit/test_linked_list.cpp
+++ b/tests/unit/test_linked_list.cpp
@@ -34,9 +34,9 @@
#include <openthread/config.h>
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/linked_list.hpp"
#include "common/owning_list.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
diff --git a/tests/unit/test_lowpan.cpp b/tests/unit/test_lowpan.cpp
index 67fe5f6b9..a630086ac 100644
--- a/tests/unit/test_lowpan.cpp
+++ b/tests/unit/test_lowpan.cpp
@@ -31,11 +31,9 @@
#include "test_platform.h"
#include "test_util.hpp"
-using namespace ot;
-
namespace ot {
-ot::Instance *sInstance;
+Instance *sInstance;
Ip6::Ip6 *sIp6;
Lowpan::Lowpan *sLowpan;
@@ -2091,9 +2089,9 @@ void TestLowpanFragmentHeader(void)
int main(void)
{
- TestLowpanIphc();
- TestLowpanMeshHeader();
- TestLowpanFragmentHeader();
+ ot::TestLowpanIphc();
+ ot::TestLowpanMeshHeader();
+ ot::TestLowpanFragmentHeader();
printf("All tests passed\n");
return 0;
diff --git a/tests/unit/test_lowpan.hpp b/tests/unit/test_lowpan.hpp
index a9542b9e7..8a6e3976d 100644
--- a/tests/unit/test_lowpan.hpp
+++ b/tests/unit/test_lowpan.hpp
@@ -32,7 +32,7 @@
#include <stdint.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "mac/mac.hpp"
#include "net/ip6_headers.hpp"
#include "thread/lowpan.hpp"
diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp
index db6ebb1b9..722b41aa4 100644
--- a/tests/unit/test_mac_frame.cpp
+++ b/tests/unit/test_mac_frame.cpp
@@ -82,7 +82,7 @@ void TestMacAddress(void)
const uint8_t kExtAddr[OT_EXT_ADDRESS_SIZE] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
const Mac::ShortAddress kShortAddr = 0x1234;
- ot::Instance *instance;
+ Instance *instance;
Mac::Address addr;
Mac::ExtAddress extAddr;
uint8_t buffer[OT_EXT_ADDRESS_SIZE];
diff --git a/tests/unit/test_macros.cpp b/tests/unit/test_macros.cpp
index a8ebdc289..2ec73f90f 100644
--- a/tests/unit/test_macros.cpp
+++ b/tests/unit/test_macros.cpp
@@ -30,6 +30,8 @@
#include "common/arg_macros.hpp"
+namespace ot {
+
static constexpr uint8_t NumberOfArgs(void) { return 0; }
static constexpr uint8_t NumberOfArgs(uint8_t) { return 1; }
@@ -132,13 +134,15 @@ exit:
VerifyOrQuit(!reachedEnd && didAction, "VerifyOrExit() failed");
}
+} // namespace ot
+
int main(void)
{
- TestMacros();
- TestVerifyOrExitSuccessNoAction();
- TestVerifyOrExitFailureNoAction();
- TestVerifyOrExitSuccessWithAction();
- TestVerifyOrExitFailureWithAction();
+ ot::TestMacros();
+ ot::TestVerifyOrExitSuccessNoAction();
+ ot::TestVerifyOrExitFailureNoAction();
+ ot::TestVerifyOrExitSuccessWithAction();
+ ot::TestVerifyOrExitFailureWithAction();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_message.cpp b/tests/unit/test_message.cpp
index 095536442..ac1320095 100644
--- a/tests/unit/test_message.cpp
+++ b/tests/unit/test_message.cpp
@@ -28,9 +28,9 @@
#include "common/appender.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "test_platform.h"
#include "test_util.hpp"
diff --git a/tests/unit/test_message_queue.cpp b/tests/unit/test_message_queue.cpp
index 9eb3c7721..a1c2b5821 100644
--- a/tests/unit/test_message_queue.cpp
+++ b/tests/unit/test_message_queue.cpp
@@ -33,23 +33,25 @@
#include <openthread/config.h>
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
+namespace ot {
+
#define kNumTestMessages 5
-static ot::Instance *sInstance;
-static ot::MessagePool *sMessagePool;
+static Instance *sInstance;
+static MessagePool *sMessagePool;
// This function verifies the content of the message queue to match the passed in messages
-void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLength, ...)
+void VerifyMessageQueueContent(MessageQueue &aMessageQueue, int aExpectedLength, ...)
{
- const ot::MessageQueue &constQueue = aMessageQueue;
- va_list args;
- ot::Message *message;
- ot::Message *msgArg;
+ const MessageQueue &constQueue = aMessageQueue;
+ va_list args;
+ Message *message;
+ Message *msgArg;
va_start(args, aExpectedLength);
@@ -64,7 +66,7 @@ void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLen
{
VerifyOrQuit(aExpectedLength != 0, "contains more entries than expected");
- msgArg = va_arg(args, ot::Message *);
+ msgArg = va_arg(args, Message *);
VerifyOrQuit(msgArg == message, "content does not match what is expected.");
aExpectedLength--;
@@ -79,7 +81,7 @@ void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLen
message = aMessageQueue.GetHead();
- for (ot::Message &msg : aMessageQueue)
+ for (Message &msg : aMessageQueue)
{
VerifyOrQuit(message == &msg, "`for` loop iteration does not match expected");
message = message->GetNext();
@@ -91,7 +93,7 @@ void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLen
message = aMessageQueue.GetHead();
- for (const ot::Message &constMsg : constQueue)
+ for (const Message &constMsg : constQueue)
{
VerifyOrQuit(message == &constMsg, "`for` loop iteration does not match expected");
message = message->GetNext();
@@ -102,18 +104,18 @@ void VerifyMessageQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLen
void TestMessageQueue(void)
{
- ot::MessageQueue messageQueue;
- ot::Message *messages[kNumTestMessages];
- ot::MessageQueue::Info info;
+ MessageQueue messageQueue;
+ Message *messages[kNumTestMessages];
+ MessageQueue::Info info;
sInstance = testInitInstance();
VerifyOrQuit(sInstance != nullptr);
- sMessagePool = &sInstance->Get<ot::MessagePool>();
+ sMessagePool = &sInstance->Get<MessagePool>();
- for (ot::Message *&msg : messages)
+ for (Message *&msg : messages)
{
- msg = sMessagePool->Allocate(ot::Message::kTypeIp6);
+ msg = sMessagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msg != nullptr, "Message::Allocate() failed");
}
@@ -126,7 +128,7 @@ void TestMessageQueue(void)
VerifyMessageQueueContent(messageQueue, 0);
// Enqueue 1 message at head and remove it
- messageQueue.Enqueue(*messages[0], ot::MessageQueue::kQueuePositionHead);
+ messageQueue.Enqueue(*messages[0], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
messageQueue.Dequeue(*messages[0]);
VerifyMessageQueueContent(messageQueue, 0);
@@ -171,7 +173,7 @@ void TestMessageQueue(void)
VerifyMessageQueueContent(messageQueue, 3, messages[1], messages[0], messages[3]);
// Add to head
- messageQueue.Enqueue(*messages[2], ot::MessageQueue::kQueuePositionHead);
+ messageQueue.Enqueue(*messages[2], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 4, messages[2], messages[1], messages[0], messages[3]);
// Remove from head
@@ -183,11 +185,11 @@ void TestMessageQueue(void)
VerifyMessageQueueContent(messageQueue, 2, messages[0], messages[3]);
// Add to head
- messageQueue.Enqueue(*messages[1], ot::MessageQueue::kQueuePositionHead);
+ messageQueue.Enqueue(*messages[1], MessageQueue::kQueuePositionHead);
VerifyMessageQueueContent(messageQueue, 3, messages[1], messages[0], messages[3]);
// Add to tail
- messageQueue.Enqueue(*messages[2], ot::MessageQueue::kQueuePositionTail);
+ messageQueue.Enqueue(*messages[2], MessageQueue::kQueuePositionTail);
VerifyMessageQueueContent(messageQueue, 4, messages[1], messages[0], messages[3], messages[2]);
// Remove all messages.
@@ -214,7 +216,7 @@ void TestMessageQueue(void)
VerifyMessageQueueContent(messageQueue, 5, messages[0], messages[1], messages[2], messages[3], messages[4]);
// While iterating over the queue remove the entry at `removeIndex`
- for (ot::Message &message : messageQueue)
+ for (Message &message : messageQueue)
{
if (index == removeIndex)
{
@@ -227,7 +229,7 @@ void TestMessageQueue(void)
index = 0;
// Iterate over the queue and remove all
- for (ot::Message &message : messageQueue)
+ for (Message &message : messageQueue)
{
if (index == removeIndex)
{
@@ -341,10 +343,12 @@ void TestMessageQueueOtApis(void)
testFreeInstance(sInstance);
}
+} // namespace ot
+
int main(void)
{
- TestMessageQueue();
- TestMessageQueueOtApis();
+ ot::TestMessageQueue();
+ ot::TestMessageQueueOtApis();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_multicast_listeners_table.cpp b/tests/unit/test_multicast_listeners_table.cpp
index 20c810e7f..ba50711ca 100644
--- a/tests/unit/test_multicast_listeners_table.cpp
+++ b/tests/unit/test_multicast_listeners_table.cpp
@@ -38,11 +38,11 @@
#include "test_util.h"
#include "backbone_router/multicast_listeners_table.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
using namespace ot::BackboneRouter;
@@ -100,7 +100,7 @@ void TestMulticastListenersTable(void)
Ip6::Address address;
address = static_cast<const Ip6::Address &>(MA401);
- address.mFields.m16[7] = HostSwap16(i);
+ address.mFields.m16[7] = BigEndian::HostSwap16(i);
SuccessOrQuit(table.Add(address, TimerMilli::GetNow() + i));
VerifyOrQuit(table.Count() == i + 1, "Table count is wrong");
diff --git a/tests/unit/test_multipan_rcp_instances.cpp b/tests/unit/test_multipan_rcp_instances.cpp
new file mode 100644
index 000000000..790e457cf
--- /dev/null
+++ b/tests/unit/test_multipan_rcp_instances.cpp
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2023, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <openthread/config.h>
+
+#include "common/array.hpp"
+#include "common/code_utils.hpp"
+#include "instance/instance.hpp"
+
+#include "ncp/ncp_base.hpp"
+#include "openthread/link_raw.h"
+
+#include "test_platform.h"
+#include "test_util.hpp"
+
+using namespace ot;
+using namespace ot::Ncp;
+
+enum
+{
+ kTestBufferSize = 800
+};
+
+enum
+{
+ kTestMacScanChannelMask = 0x01
+};
+
+OT_TOOL_PACKED_BEGIN
+struct RadioMessage
+{
+ uint8_t mChannel;
+ uint8_t mPsdu[OT_RADIO_FRAME_MAX_SIZE];
+} OT_TOOL_PACKED_END;
+
+static struct RadioMessage sDefaultMessages[OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM];
+static otRadioFrame sTxFrame[OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM];
+static ot::Instance *sInstances[OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM];
+static ot::Instance *sLastInstance;
+
+otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
+{
+ otRadioFrame *frame = nullptr;
+
+ for (size_t i = 0; i < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM; i++)
+ {
+ if (sInstances[i] == aInstance || sInstances[i] == nullptr)
+ {
+ sTxFrame[i].mPsdu = sDefaultMessages->mPsdu;
+ frame = &sTxFrame[i];
+
+ break;
+ }
+ }
+
+ return frame;
+}
+
+otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *)
+{
+ sLastInstance = static_cast<ot::Instance *>(aInstance);
+ return OT_ERROR_NONE;
+}
+
+otError otPlatMultipanGetActiveInstance(otInstance **aInstance)
+{
+ otError error = OT_ERROR_NOT_IMPLEMENTED;
+ OT_UNUSED_VARIABLE(aInstance);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ *aInstance = sLastInstance;
+ error = OT_ERROR_NONE;
+#endif
+
+ return error;
+}
+
+otError otPlatMultipanSetActiveInstance(otInstance *aInstance, bool aCompletePending)
+{
+ otError error = OT_ERROR_NOT_IMPLEMENTED;
+ OT_UNUSED_VARIABLE(aInstance);
+ OT_UNUSED_VARIABLE(aCompletePending);
+
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
+ VerifyOrExit(sLastInstance != static_cast<ot::Instance *>(aInstance), error = OT_ERROR_ALREADY);
+ sLastInstance = static_cast<ot::Instance *>(aInstance);
+ error = OT_ERROR_NONE;
+exit:
+#endif
+
+ return error;
+}
+
+class TestNcp : public NcpBase
+{
+public:
+ explicit TestNcp(ot::Instance *aInstance)
+ : mLastHeader(0)
+ , mLastStatus(0)
+ , mLastProp(0)
+ , NcpBase(aInstance)
+ {
+ memset(mMsgBuffer, 0, kTestBufferSize);
+ mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this);
+ mTxFrameBuffer.SetFrameRemovedCallback(nullptr, this);
+ };
+
+ explicit TestNcp(ot::Instance **aInstances, uint8_t aCount)
+ : mLastHeader(0)
+ , mLastStatus(0)
+ , mLastProp(0)
+ , NcpBase(aInstances, aCount)
+ {
+ memset(mMsgBuffer, 0, kTestBufferSize);
+ mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this);
+ mTxFrameBuffer.SetFrameRemovedCallback(nullptr, this);
+ };
+
+ static void HandleFrameAddedToNcpBuffer(void *aContext,
+ Spinel::Buffer::FrameTag aTag,
+ Spinel::Buffer::Priority aPriority,
+ Spinel::Buffer *aBuffer)
+ {
+ OT_UNUSED_VARIABLE(aTag);
+ OT_UNUSED_VARIABLE(aPriority);
+
+ static_cast<TestNcp *>(aContext)->HandleFrameAddedToNcpBuffer(aBuffer);
+ }
+
+ void HandleFrameAddedToNcpBuffer(Spinel::Buffer *aBuffer)
+ {
+ static const size_t display_size = 64;
+
+ memset(mMsgBuffer, 0, kTestBufferSize);
+ SuccessOrQuit(aBuffer->OutFrameBegin());
+ aBuffer->OutFrameRead(kTestBufferSize, mMsgBuffer);
+ SuccessOrQuit(aBuffer->OutFrameRemove());
+
+ // DumpBuffer("Received Buffer", mMsgBuffer, display_size);
+
+ updateSpinelStatus();
+ }
+
+ void Receive(uint8_t *aBuffer, size_t bufferSize) { HandleReceive(aBuffer, static_cast<uint16_t>(bufferSize)); }
+
+ void processTransmit()
+ {
+ uint8_t iid = SPINEL_HEADER_GET_IID(mLastHeader);
+
+ LinkRawTransmitDone(iid, &sTxFrame[iid], nullptr, OT_ERROR_NONE);
+ };
+
+ void updateSpinelStatus()
+ {
+ Spinel::Decoder decoder;
+
+ uint8_t header;
+ unsigned int command;
+ unsigned int propKey;
+ unsigned int status;
+
+ decoder.Init(mMsgBuffer, kTestBufferSize);
+
+ SuccessOrQuit(decoder.ReadUint8(mLastHeader));
+ SuccessOrQuit(decoder.ReadUintPacked(command));
+ SuccessOrQuit(decoder.ReadUintPacked(propKey));
+ SuccessOrQuit(decoder.ReadUintPacked(status));
+
+ mLastStatus = static_cast<uint32_t>(status);
+ mLastProp = static_cast<uint32_t>(propKey);
+ }
+
+ uint32_t getSpinelStatus() const { return mLastStatus; }
+ uint32_t getSpinelProp() const { return mLastProp; }
+
+ uint8_t getLastIid() const
+ {
+ /* Return as SPINEL_HEADER_IID_N format without shift */
+ return SPINEL_HEADER_IID_MASK & mLastHeader;
+ }
+
+ uint8_t getLastTid() { return SPINEL_HEADER_GET_TID(mLastHeader); }
+
+ bool gotResponse(uint8_t aIid, uint8_t aTid) { return ((aIid == getLastIid()) && (aTid == getLastTid())); }
+
+private:
+ uint8_t mLastHeader;
+ uint32_t mLastStatus;
+ uint32_t mLastProp;
+ uint8_t mMsgBuffer[kTestBufferSize];
+};
+
+class TestHost
+{
+public:
+ TestHost(TestNcp *aNcp, uint8_t aIid)
+ : mNcp(aNcp)
+ , mIid(aIid)
+ , mTid(0)
+ , mLastTxTid(0)
+ , mBuffer(mBuf, kTestBufferSize)
+ , mEncoder(mBuffer)
+ , mOffset(0)
+ {
+ memset(mBuf, 0, kTestBufferSize);
+ };
+
+ void createLinkEnableFrame(bool isEnabled)
+ {
+ startFrame(SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_PHY_ENABLED);
+ SuccessOrQuit(mEncoder.WriteBool(isEnabled));
+ endFrame("Enable Frame");
+ }
+
+ void createTransmitFrame()
+ {
+ startFrame(SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_STREAM_RAW);
+
+ SuccessOrQuit(mEncoder.WriteDataWithLen(sTxFrame[mIid].mPsdu, sTxFrame[mIid].mLength));
+ SuccessOrQuit(mEncoder.WriteUint8(sTxFrame[mIid].mChannel));
+ SuccessOrQuit(mEncoder.WriteUint8(sTxFrame[mIid].mInfo.mTxInfo.mMaxCsmaBackoffs));
+ SuccessOrQuit(mEncoder.WriteUint8(sTxFrame[mIid].mInfo.mTxInfo.mMaxFrameRetries));
+ SuccessOrQuit(mEncoder.WriteBool(sTxFrame[mIid].mInfo.mTxInfo.mCsmaCaEnabled));
+ SuccessOrQuit(mEncoder.WriteBool(sTxFrame[mIid].mInfo.mTxInfo.mIsHeaderUpdated));
+ SuccessOrQuit(mEncoder.WriteBool(sTxFrame[mIid].mInfo.mTxInfo.mIsARetx));
+ SuccessOrQuit(mEncoder.WriteBool(sTxFrame[mIid].mInfo.mTxInfo.mIsSecurityProcessed));
+ SuccessOrQuit(mEncoder.WriteUint32(sTxFrame[mIid].mInfo.mTxInfo.mTxDelay));
+ SuccessOrQuit(mEncoder.WriteUint32(sTxFrame[mIid].mInfo.mTxInfo.mTxDelayBaseTime));
+
+ endFrame("Transmit Frame");
+ }
+
+ void createSwitchoverRequest(uint8_t aIid, bool aForce)
+ {
+ startFrame(SPINEL_CMD_PROP_VALUE_SET, SPINEL_PROP_MULTIPAN_ACTIVE_INTERFACE);
+ SuccessOrQuit(mEncoder.WriteUint8(aIid | (aForce ? 0 : (1 << SPINEL_MULTIPAN_INTERFACE_SOFT_SWITCH_SHIFT))));
+ endFrame("Interface Switch Request Frame");
+ }
+
+ void createReadStatusFrame()
+ {
+ startFrame(SPINEL_CMD_PROP_VALUE_GET, SPINEL_PROP_LAST_STATUS);
+ endFrame("Read Status Frame");
+ }
+
+ void enableRawLink()
+ {
+ static const bool isLinkEnabled = true;
+ createLinkEnableFrame(isLinkEnabled);
+ sendToRcp();
+ }
+
+ void disableRawLink()
+ {
+ static const bool isLinkEnabled = false;
+ createLinkEnableFrame(isLinkEnabled);
+ sendToRcp();
+ }
+
+ spinel_status_t startTransmit()
+ {
+ mLastTxTid = mTid;
+ createTransmitFrame();
+ sendToRcp();
+ prepareResponse(mLastTxTid);
+ return static_cast<spinel_status_t>(mNcp->getSpinelStatus());
+ };
+
+ spinel_status_t requestSwitchover(uint8_t aIid, bool aForce)
+ {
+ mLastTxTid = mTid;
+ createSwitchoverRequest(aIid, aForce);
+ sendToRcp();
+ prepareResponse(mLastTxTid);
+ return static_cast<spinel_status_t>(mNcp->getSpinelStatus());
+ };
+
+ void getCommandStatus()
+ {
+ createReadStatusFrame();
+ sendToRcp();
+ }
+
+ void finishTransmit()
+ {
+ /* Reset instance submac state to sleep by resetting link
+ This is needed for a second transmit command to succeed
+ as the HandleTimer method will not be called to reset the submac */
+ disableRawLink();
+ enableRawLink();
+
+ /* Proceed with transmit done callback from ncp */
+ mNcp->processTransmit();
+ };
+
+ uint8_t getLastTransmitTid(void) { return mLastTxTid; }
+
+private:
+ void startFrame(unsigned int aCommand, spinel_prop_key_t aKey)
+ {
+ uint8_t spinelHeader = SPINEL_HEADER_FLAG | mIid | mTid;
+
+ SuccessOrQuit(mEncoder.BeginFrame(Spinel::Buffer::kPriorityLow));
+ SuccessOrQuit(mEncoder.WriteUint8(spinelHeader));
+ SuccessOrQuit(mEncoder.WriteUintPacked(aCommand));
+ SuccessOrQuit(mEncoder.WriteUintPacked(aKey));
+ }
+
+ void endFrame(const char *aTextMessage)
+ {
+ static const uint16_t display_length = 64;
+ SuccessOrQuit(mEncoder.EndFrame());
+ // DumpBuffer(aTextMessage, mBuf, display_length);
+ }
+
+ void sendToRcp()
+ {
+ static const uint8_t data_offset = 2;
+ size_t frame_len = mBuffer.OutFrameGetLength();
+
+ mOffset += data_offset;
+
+ mNcp->Receive(mBuf + mOffset, frame_len);
+
+ mTid = SPINEL_GET_NEXT_TID(mTid);
+ SuccessOrQuit(mBuffer.OutFrameRemove());
+
+ mOffset += frame_len;
+ mOffset %= kTestBufferSize;
+ }
+
+ void prepareResponse(uint8_t aTid)
+ {
+ /* Some spinel commands immediately send queued responses when command is complete
+ while others require a separate command to the ncp in order to receive the response.
+ If a response is needed and not immediately received. Issue a command to update the status. */
+
+ if (!mNcp->gotResponse(mIid, aTid))
+ {
+ getCommandStatus();
+ }
+ }
+
+ TestNcp *mNcp;
+ uint8_t mIid;
+ uint8_t mTid;
+ uint8_t mLastTxTid;
+ uint8_t mBuf[kTestBufferSize];
+ Spinel::Buffer mBuffer;
+ Spinel::Encoder mEncoder;
+ size_t mOffset;
+};
+
+void InitInstances(void)
+{
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ for (size_t i = 0; i < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM; i++)
+ {
+ sInstances[i] = testInitAdditionalInstance(i);
+ VerifyOrQuit(sInstances[i] != nullptr);
+ }
+#endif
+}
+
+void FreeInstances(void)
+{
+ for (size_t i = 0; i < OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM; i++)
+ {
+ if (sInstances[i] != nullptr)
+ {
+ testFreeInstance(sInstances[i]);
+ sInstances[i] = nullptr;
+ }
+ }
+}
+
+void TestNcpBaseTransmitWithLinkRawDisabled(void)
+{
+ printf("\tTransmit With Link Raw Disabled");
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+ TestHost host3(&ncp, SPINEL_HEADER_IID_2);
+
+ host1.disableRawLink();
+ host2.disableRawLink();
+ host3.disableRawLink();
+
+ /* Test that the response status is Invalid State when transmit is skipped due to disabled link */
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_INVALID_STATE);
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_INVALID_STATE);
+ VerifyOrQuit(host3.startTransmit() == SPINEL_STATUS_INVALID_STATE);
+
+ FreeInstances();
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseTransmitWithLinkRawEnabled(void)
+{
+ printf("\tTransmit With Link Raw Enabled");
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host(&ncp, SPINEL_HEADER_IID_0);
+
+ host.enableRawLink();
+
+ /* Test that the response status is OK when transmit is started successfully */
+ VerifyOrQuit(host.startTransmit() == SPINEL_STATUS_OK);
+
+ host.finishTransmit();
+
+ FreeInstances();
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseTransmitWithIncorrectLinkRawEnabled(void)
+{
+ printf("\tTransmit With Incorrect Link Raw Enabled");
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ host1.disableRawLink();
+ host2.enableRawLink();
+
+ /* Test that Invalid State is reported when different endpoint was enabled */
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_INVALID_STATE);
+
+ /* Test that status is OK when transmitting on the proper interface */
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+
+ host1.finishTransmit();
+
+ FreeInstances();
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseTransmitOnBoth(void)
+{
+ printf("\tTransmit on both interfaces");
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+
+ host1.finishTransmit();
+ host2.finishTransmit();
+
+ FreeInstances();
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseDifferentInstanceCall(void)
+{
+ printf("\tTransmit on both interfaces - verify instances used");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(sLastInstance != nullptr);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(sLastInstance != nullptr);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+
+ host1.finishTransmit();
+ host2.finishTransmit();
+
+ /* Test reverse order of calls to make sure it is not just a fixed order */
+ sLastInstance = nullptr;
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(sLastInstance != nullptr);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(sLastInstance != nullptr);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ host1.finishTransmit();
+ host2.finishTransmit();
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseTransmitDoneInterface(void)
+{
+ printf("\tTransmit on both interfaces - verify transmit done IID");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+
+ otPlatRadioTxDone(sInstances[0], &sTxFrame[0], nullptr, OT_ERROR_NONE);
+ VerifyOrQuit(ncp.gotResponse(SPINEL_HEADER_IID_0, host1.getLastTransmitTid()));
+
+ otPlatRadioTxDone(sInstances[1], &sTxFrame[1], nullptr, OT_ERROR_NONE);
+ VerifyOrQuit(ncp.gotResponse(SPINEL_HEADER_IID_1, host2.getLastTransmitTid()));
+
+ /* Test reverse order of tx processing */
+ VerifyOrQuit(host1.startTransmit() == SPINEL_STATUS_OK);
+ VerifyOrQuit(host2.startTransmit() == SPINEL_STATUS_OK);
+
+ otPlatRadioTxDone(sInstances[1], &sTxFrame[1], nullptr, OT_ERROR_NONE);
+ VerifyOrQuit(ncp.gotResponse(SPINEL_HEADER_IID_1, host2.getLastTransmitTid()));
+
+ otPlatRadioTxDone(sInstances[0], &sTxFrame[0], nullptr, OT_ERROR_NONE);
+ VerifyOrQuit(ncp.gotResponse(SPINEL_HEADER_IID_0, host1.getLastTransmitTid()));
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseReceive(void)
+{
+ printf("\tReceive on a single interface");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+
+ host1.enableRawLink();
+
+ otPlatRadioReceiveDone(sInstances[0], &sTxFrame[0], OT_ERROR_NONE);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_STREAM_RAW);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == SPINEL_HEADER_IID_0);
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseReceiveOnTwoInterfaces(void)
+{
+ printf("\tReceive on both interfaces");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ otPlatRadioReceiveDone(sInstances[1], &sTxFrame[1], OT_ERROR_NONE);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_STREAM_RAW);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == SPINEL_HEADER_IID_1);
+
+ otPlatRadioReceiveDone(sInstances[0], &sTxFrame[0], OT_ERROR_NONE);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_STREAM_RAW);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == SPINEL_HEADER_IID_0);
+
+ /* reverse order */
+ otPlatRadioReceiveDone(sInstances[0], &sTxFrame[0], OT_ERROR_NONE);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_STREAM_RAW);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == SPINEL_HEADER_IID_0);
+
+ otPlatRadioReceiveDone(sInstances[1], &sTxFrame[1], OT_ERROR_NONE);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_STREAM_RAW);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == SPINEL_HEADER_IID_1);
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseSwitchoverRequest(void)
+{
+ printf("\tSwitchover requests from different interfaces");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+ TestHost host3(&ncp, SPINEL_HEADER_IID_2);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+ host3.enableRawLink();
+
+ VerifyOrQuit(host1.requestSwitchover(0, true) == 0);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+ VerifyOrQuit(host1.requestSwitchover(1, true) == 1);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+ VerifyOrQuit(host1.requestSwitchover(2, true) == 2);
+ VerifyOrQuit(sLastInstance == sInstances[2]);
+ VerifyOrQuit(host2.requestSwitchover(0, true) == 0);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+ VerifyOrQuit(host2.requestSwitchover(1, true) == 1);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+ VerifyOrQuit(host2.requestSwitchover(2, true) == 2);
+ VerifyOrQuit(sLastInstance == sInstances[2]);
+ VerifyOrQuit(host3.requestSwitchover(0, true) == 0);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+ VerifyOrQuit(host3.requestSwitchover(1, true) == 1);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+ VerifyOrQuit(host3.requestSwitchover(2, true) == 2);
+ VerifyOrQuit(sLastInstance == sInstances[2]);
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseSwitchoverRequestFail(void)
+{
+ printf("\tSwitchover requests Fail - same interface");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ VerifyOrQuit(host1.requestSwitchover(0, true) == 0);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ VerifyOrQuit(host1.requestSwitchover(0, true) == SPINEL_STATUS_ALREADY);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ VerifyOrQuit(host2.requestSwitchover(0, true) == SPINEL_STATUS_ALREADY);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ printf(" - PASS\n");
+}
+
+void TestNcpBaseSwitchoverResponse(void)
+{
+ printf("\tSwitchover responses");
+
+ InitInstances();
+
+ TestNcp ncp(sInstances, OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_NUM);
+ TestHost host1(&ncp, SPINEL_HEADER_IID_0);
+ TestHost host2(&ncp, SPINEL_HEADER_IID_1);
+
+ sLastInstance = nullptr;
+
+ host1.enableRawLink();
+ host2.enableRawLink();
+
+ VerifyOrQuit(host1.requestSwitchover(0, true) == 0);
+ VerifyOrQuit(sLastInstance == sInstances[0]);
+
+ otPlatMultipanSwitchoverDone(sLastInstance, true);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_LAST_STATUS);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID);
+ VerifyOrQuit(ncp.getSpinelStatus() == SPINEL_STATUS_SWITCHOVER_DONE);
+
+ VerifyOrQuit(host1.requestSwitchover(1, true) == 1);
+ VerifyOrQuit(sLastInstance == sInstances[1]);
+
+ otPlatMultipanSwitchoverDone(sLastInstance, false);
+
+ VerifyOrQuit(ncp.getSpinelProp() == SPINEL_PROP_LAST_STATUS);
+ VerifyOrQuit(ncp.getLastTid() == 0);
+ VerifyOrQuit(ncp.getLastIid() == OPENTHREAD_SPINEL_CONFIG_BROADCAST_IID);
+ VerifyOrQuit(ncp.getSpinelStatus() == SPINEL_STATUS_SWITCHOVER_FAILED);
+
+ printf(" - PASS\n");
+}
+
+///
+int main(void)
+{
+#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE && (OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE)
+ printf("Executing Transmit Tests\n");
+ TestNcpBaseTransmitWithLinkRawDisabled();
+ TestNcpBaseTransmitWithLinkRawEnabled();
+ TestNcpBaseTransmitWithIncorrectLinkRawEnabled();
+ TestNcpBaseTransmitOnBoth();
+ TestNcpBaseDifferentInstanceCall();
+ TestNcpBaseTransmitDoneInterface();
+ printf("Transmit Tests - PASS\n");
+
+ printf("Executing Receive Tests\n");
+ TestNcpBaseReceive();
+ TestNcpBaseReceiveOnTwoInterfaces();
+ printf("Receive Tests - PASS\n");
+
+ printf("Executing Interface Switching Tests\n");
+ TestNcpBaseSwitchoverRequest();
+ TestNcpBaseSwitchoverRequestFail();
+ TestNcpBaseSwitchoverResponse();
+ printf("Executing Interface Switching Tests - PASS\n");
+
+ printf("\nAll tests passed\n");
+
+#else
+ printf("MULTIPAN_RCP feature and RADIO/LINK_RAW option are not enabled\n");
+#endif
+ return 0;
+}
diff --git a/tests/unit/test_nat64.cpp b/tests/unit/test_nat64.cpp
index d699d83f8..55bd0e003 100644
--- a/tests/unit/test_nat64.cpp
+++ b/tests/unit/test_nat64.cpp
@@ -35,8 +35,8 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
diff --git a/tests/unit/test_ndproxy_table.cpp b/tests/unit/test_ndproxy_table.cpp
index 80f5d13dd..e350a1563 100644
--- a/tests/unit/test_ndproxy_table.cpp
+++ b/tests/unit/test_ndproxy_table.cpp
@@ -38,11 +38,11 @@
#include "test_util.h"
#include "backbone_router/ndproxy_table.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
namespace ot {
-static ot::Instance *sInstance;
+static Instance *sInstance;
using namespace ot::BackboneRouter;
diff --git a/tests/unit/test_netif.cpp b/tests/unit/test_netif.cpp
index 1a5c0e120..c8c9a5dbb 100644
--- a/tests/unit/test_netif.cpp
+++ b/tests/unit/test_netif.cpp
@@ -34,7 +34,7 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "net/netif.hpp"
#include "test_util.h"
diff --git a/tests/unit/test_network_data.cpp b/tests/unit/test_network_data.cpp
index 6fcdfd3ec..286870908 100644
--- a/tests/unit/test_network_data.cpp
+++ b/tests/unit/test_network_data.cpp
@@ -30,7 +30,7 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/network_data_local.hpp"
#include "thread/network_data_service.hpp"
@@ -106,7 +106,7 @@ void TestNetworkDataIterator(void)
{
static constexpr uint8_t kMaxRlocsArray = 10;
- ot::Instance *instance;
+ Instance *instance;
Iterator iter = kIteratorInit;
ExternalRouteConfig rconfig;
OnMeshPrefixConfig pconfig;
@@ -496,7 +496,7 @@ void TestNetworkDataIterator(void)
class TestNetworkData : public Local
{
public:
- explicit TestNetworkData(ot::Instance &aInstance)
+ explicit TestNetworkData(Instance &aInstance)
: Local(aInstance)
{
}
@@ -583,7 +583,7 @@ public:
void TestNetworkDataFindNextService(void)
{
- ot::Instance *instance;
+ Instance *instance;
printf("\n\n-------------------------------------------------");
printf("\nTestNetworkDataFindNextService()\n");
@@ -616,7 +616,7 @@ void TestNetworkDataDsnSrpServices(void)
}
};
- ot::Instance *instance;
+ Instance *instance;
printf("\n\n-------------------------------------------------");
printf("\nTestNetworkDataDsnSrpServices()\n");
@@ -764,7 +764,7 @@ void TestNetworkDataDsnSrpAnycastSeqNumSelection(void)
uint8_t mPreferredSeqNum;
};
- ot::Instance *instance;
+ Instance *instance;
printf("\n\n-------------------------------------------------");
printf("\nTestNetworkDataDsnSrpAnycastSeqNumSelection()\n");
diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp
index 548764314..8c339d443 100644
--- a/tests/unit/test_platform.cpp
+++ b/tests/unit/test_platform.cpp
@@ -49,6 +49,9 @@ ot::Instance *testInitInstance(void)
otInstance *instance = nullptr;
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ instance = otInstanceInitMultiple(0);
+#else
size_t instanceBufferLength = 0;
uint8_t *instanceBuffer = nullptr;
@@ -62,6 +65,7 @@ ot::Instance *testInitInstance(void)
// Initialize OpenThread with the buffer
instance = otInstanceInit(instanceBuffer, &instanceBufferLength);
+#endif
#else
instance = otInstanceInitSingle();
#endif
@@ -69,11 +73,22 @@ ot::Instance *testInitInstance(void)
return static_cast<ot::Instance *>(instance);
}
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ot::Instance *testInitAdditionalInstance(uint8_t id)
+{
+ otInstance *instance = nullptr;
+
+ instance = otInstanceInitMultiple(id);
+
+ return static_cast<ot::Instance *>(instance);
+}
+#endif
+
void testFreeInstance(otInstance *aInstance)
{
otInstanceFinalize(aInstance);
-#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && !OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
free(aInstance);
#endif
}
@@ -116,6 +131,10 @@ OT_TOOL_WEAK uint32_t otPlatAlarmMicroGetNow(void)
return (uint32_t)((tv.tv_sec * 1000000) + tv.tv_usec + 123456);
}
+OT_TOOL_WEAK otError otPlatMultipanGetActiveInstance(otInstance **) { return OT_ERROR_NOT_IMPLEMENTED; }
+
+OT_TOOL_WEAK otError otPlatMultipanSetActiveInstance(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
+
OT_TOOL_WEAK void otPlatRadioGetIeeeEui64(otInstance *, uint8_t *) {}
OT_TOOL_WEAK void otPlatRadioSetPanId(otInstance *, uint16_t) {}
@@ -126,6 +145,8 @@ OT_TOOL_WEAK void otPlatRadioSetShortAddress(otInstance *, uint16_t) {}
OT_TOOL_WEAK void otPlatRadioSetPromiscuous(otInstance *, bool) {}
+OT_TOOL_WEAK void otPlatRadioSetRxOnWhenIdle(otInstance *, bool) {}
+
OT_TOOL_WEAK bool otPlatRadioIsEnabled(otInstance *) { return true; }
OT_TOOL_WEAK otError otPlatRadioEnable(otInstance *) { return OT_ERROR_NONE; }
@@ -223,8 +244,12 @@ OT_TOOL_WEAK void otPlatUartReceived(const uint8_t *, uint16_t) {}
OT_TOOL_WEAK void otPlatReset(otInstance *) {}
+OT_TOOL_WEAK otError otPlatResetToBootloader(otInstance *) { return OT_ERROR_NOT_CAPABLE; }
+
OT_TOOL_WEAK otPlatResetReason otPlatGetResetReason(otInstance *) { return OT_PLAT_RESET_REASON_POWER_ON; }
+OT_TOOL_WEAK void otPlatWakeHost(void) {}
+
OT_TOOL_WEAK void otPlatLog(otLogLevel, otLogRegion, const char *, ...) {}
OT_TOOL_WEAK void otPlatSettingsInit(otInstance *, const uint16_t *, uint16_t) {}
@@ -474,8 +499,6 @@ bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
return false;
}
-#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
-
otError otPlatCryptoEcdsaGenerateAndImportKey(otCryptoKeyRef aKeyRef)
{
OT_UNUSED_VARIABLE(aKeyRef);
@@ -513,6 +536,8 @@ otError otPlatCryptoEcdsaVerifyUsingKeyRef(otCryptoKeyRef aKe
return OT_ERROR_NONE;
}
+#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
+
otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
{
OT_UNUSED_VARIABLE(aInstance);
@@ -623,4 +648,38 @@ void otPlatDnsCancelUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery
}
#endif
+OT_TOOL_WEAK otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *, int8_t *) { return OT_ERROR_NONE; }
+
+OT_TOOL_WEAK otError otPlatRadioGetCoexMetrics(otInstance *, otRadioCoexMetrics *) { return OT_ERROR_NONE; }
+
+OT_TOOL_WEAK otError otPlatRadioGetTransmitPower(otInstance *, int8_t *) { return OT_ERROR_NONE; }
+
+OT_TOOL_WEAK bool otPlatRadioIsCoexEnabled(otInstance *) { return true; }
+
+OT_TOOL_WEAK otError otPlatRadioSetCoexEnabled(otInstance *, bool) { return OT_ERROR_NOT_IMPLEMENTED; }
+
+#if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+OT_TOOL_WEAK otError otPlatRadioSetChannelTargetPower(otInstance *aInstance, uint8_t aChannel, int16_t aTargetPower)
+{
+ return OT_ERROR_NONE;
+}
+
+OT_TOOL_WEAK otError otPlatRadioAddCalibratedPower(otInstance *aInstance,
+ uint8_t aChannel,
+ int16_t aActualPower,
+ const uint8_t *aRawPowerSetting,
+ uint16_t aRawPowerSettingLength)
+{
+ return OT_ERROR_NONE;
+}
+
+OT_TOOL_WEAK otError otPlatRadioClearCalibratedPowers(otInstance *aInstance) { return OT_ERROR_NONE; }
+#endif // OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+
+#if OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
+OT_TOOL_WEAK otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance) { return OT_PLAT_MCU_POWER_STATE_ON; }
+
+OT_TOOL_WEAK otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) { return OT_ERROR_NONE; }
+#endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
+
} // extern "C"
diff --git a/tests/unit/test_platform.h b/tests/unit/test_platform.h
index ec5f88709..97a9d79d9 100644
--- a/tests/unit/test_platform.h
+++ b/tests/unit/test_platform.h
@@ -38,14 +38,18 @@
#include <openthread/platform/entropy.h>
#include <openthread/platform/logging.h>
#include <openthread/platform/misc.h>
+#include <openthread/platform/multipan.h>
#include <openthread/platform/radio.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
ot::Instance *testInitInstance(void);
-void testFreeInstance(otInstance *aInstance);
+#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
+ot::Instance *testInitAdditionalInstance(uint8_t id);
+#endif
+void testFreeInstance(otInstance *aInstance);
#endif // TEST_PLATFORM_H
diff --git a/tests/unit/test_pool.cpp b/tests/unit/test_pool.cpp
index 51656cdc6..28f586066 100644
--- a/tests/unit/test_pool.cpp
+++ b/tests/unit/test_pool.cpp
@@ -30,17 +30,19 @@
#include <openthread/config.h>
-#include "common/instance.hpp"
#include "common/pool.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
+namespace ot {
+
struct EntryBase
{
EntryBase *mNext;
};
-struct Entry : public EntryBase, ot::LinkedListEntry<Entry>
+struct Entry : public EntryBase, LinkedListEntry<Entry>
{
public:
Entry(void)
@@ -48,7 +50,7 @@ public:
{
}
- void Init(ot::Instance &) { mInitWithInstance = true; }
+ void Init(Instance &) { mInitWithInstance = true; }
bool IsInitializedWithInstance(void) const { return mInitWithInstance; }
@@ -61,7 +63,7 @@ enum : uint16_t
kPoolSize = 11,
};
-typedef ot::Pool<Entry, kPoolSize> EntryPool;
+typedef Pool<Entry, kPoolSize> EntryPool;
static Entry sNonPoolEntry;
@@ -118,9 +120,9 @@ void TestPool(EntryPool &aPool, bool aInitWithInstance)
void TestPool(void)
{
- ot::Instance *instance = testInitInstance();
- EntryPool pool1;
- EntryPool pool2(*instance);
+ Instance *instance = testInitInstance();
+ EntryPool pool1;
+ EntryPool pool2(*instance);
TestPool(pool1, /* aInitWithInstance */ false);
TestPool(pool2, /* aInitWithInstance */ true);
@@ -128,9 +130,11 @@ void TestPool(void)
testFreeInstance(instance);
}
+} // namespace ot
+
int main(void)
{
- TestPool();
+ ot::TestPool();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_power_calibration.cpp b/tests/unit/test_power_calibration.cpp
index 91c1d6920..9c8067ba6 100644
--- a/tests/unit/test_power_calibration.cpp
+++ b/tests/unit/test_power_calibration.cpp
@@ -144,8 +144,8 @@ int main(void)
#if OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
ot::TestPowerCalibration();
printf("All tests passed\n");
-#else // OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+#else
printf("Power calibration is not enabled\n");
-#endif // OPENTHREAD_CONFIG_POWER_CALIBRATION_ENABLE && OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE
+#endif
return 0;
}
diff --git a/tests/unit/test_priority_queue.cpp b/tests/unit/test_priority_queue.cpp
index 6348f55c5..4642ee1e1 100644
--- a/tests/unit/test_priority_queue.cpp
+++ b/tests/unit/test_priority_queue.cpp
@@ -29,25 +29,27 @@
#include <stdarg.h>
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
+#include "instance/instance.hpp"
#include "test_platform.h"
#include "test_util.h"
+namespace ot {
+
#define kNumNewPriorityTestMessages 2
#define kNumSetPriorityTestMessages 2
#define kNumTestMessages (kNumNewPriorityTestMessages + kNumSetPriorityTestMessages)
// This function verifies the content of the priority queue to match the passed in messages
-void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpectedLength, ...)
+void VerifyPriorityQueueContent(PriorityQueue &aPriorityQueue, int aExpectedLength, ...)
{
- const ot::PriorityQueue &constQueue = aPriorityQueue;
- va_list args;
- ot::Message *message;
- ot::Message *msgArg;
- int8_t curPriority = ot::Message::kNumPriorities;
- ot::PriorityQueue::Info info;
+ const PriorityQueue &constQueue = aPriorityQueue;
+ va_list args;
+ Message *message;
+ Message *msgArg;
+ int8_t curPriority = Message::kNumPriorities;
+ PriorityQueue::Info info;
// Check the `GetInfo`
memset(&info, 0, sizeof(info));
@@ -61,10 +63,10 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
message = aPriorityQueue.GetHead();
VerifyOrQuit(message == nullptr, "PriorityQueue is not empty when expected len is zero.");
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(ot::Message::kPriorityLow) == nullptr);
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(ot::Message::kPriorityNormal) == nullptr);
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(ot::Message::kPriorityHigh) == nullptr);
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(ot::Message::kPriorityNet) == nullptr);
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(Message::kPriorityLow) == nullptr);
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(Message::kPriorityNormal) == nullptr);
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(Message::kPriorityHigh) == nullptr);
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(Message::kPriorityNet) == nullptr);
}
else
{
@@ -73,7 +75,7 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
{
VerifyOrQuit(aExpectedLength != 0, "PriorityQueue contains more entries than expected.");
- msgArg = va_arg(args, ot::Message *);
+ msgArg = va_arg(args, Message *);
if (msgArg->GetPriority() != curPriority)
{
@@ -81,14 +83,13 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
{
// Check the `GetHeadForPriority` is nullptr if there are no expected message for this priority
// level.
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<ot::Message::Priority>(curPriority)) ==
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<Message::Priority>(curPriority)) ==
nullptr,
"is non-nullptr when no expected msg for this priority.");
}
// Check the `GetHeadForPriority`.
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<ot::Message::Priority>(curPriority)) ==
- msgArg);
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<Message::Priority>(curPriority)) == msgArg);
}
// Check the queued message to match the one from argument list
@@ -102,7 +103,7 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
// Check the `GetHeadForPriority` is nullptr if there are no expected message for any remaining priority level.
for (curPriority--; curPriority >= 0; curPriority--)
{
- VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<ot::Message::Priority>(curPriority)) == nullptr,
+ VerifyOrQuit(aPriorityQueue.GetHeadForPriority(static_cast<Message::Priority>(curPriority)) == nullptr,
"is non-nullptr when no expected msg for this priority.");
}
}
@@ -113,7 +114,7 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
message = aPriorityQueue.GetHead();
- for (ot::Message &msg : aPriorityQueue)
+ for (Message &msg : aPriorityQueue)
{
VerifyOrQuit(message == &msg, "`for` loop iteration does not match expected");
message = message->GetNext();
@@ -125,7 +126,7 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
message = aPriorityQueue.GetHead();
- for (const ot::Message &constMsg : constQueue)
+ for (const Message &constMsg : constQueue)
{
VerifyOrQuit(message == &constMsg, "`for` loop iteration does not match expected");
message = message->GetNext();
@@ -135,11 +136,11 @@ void VerifyPriorityQueueContent(ot::PriorityQueue &aPriorityQueue, int aExpected
}
// This function verifies the content of the message queue to match the passed in messages
-void VerifyMsgQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLength, ...)
+void VerifyMsgQueueContent(MessageQueue &aMessageQueue, int aExpectedLength, ...)
{
- va_list args;
- ot::Message *message;
- ot::Message *msgArg;
+ va_list args;
+ Message *message;
+ Message *msgArg;
va_start(args, aExpectedLength);
@@ -154,7 +155,7 @@ void VerifyMsgQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLength,
{
VerifyOrQuit(aExpectedLength != 0, "contains more entries than expected");
- msgArg = va_arg(args, ot::Message *);
+ msgArg = va_arg(args, Message *);
VerifyOrQuit(msgArg == message, "content does not match what is expected.");
aExpectedLength--;
@@ -168,58 +169,57 @@ void VerifyMsgQueueContent(ot::MessageQueue &aMessageQueue, int aExpectedLength,
void TestPriorityQueue(void)
{
- ot::Instance *instance;
- ot::MessagePool *messagePool;
- ot::PriorityQueue queue;
- ot::MessageQueue messageQueue;
- ot::Message *msgNet[kNumTestMessages];
- ot::Message *msgHigh[kNumTestMessages];
- ot::Message *msgNor[kNumTestMessages];
- ot::Message *msgLow[kNumTestMessages];
+ Instance *instance;
+ MessagePool *messagePool;
+ PriorityQueue queue;
+ MessageQueue messageQueue;
+ Message *msgNet[kNumTestMessages];
+ Message *msgHigh[kNumTestMessages];
+ Message *msgNor[kNumTestMessages];
+ Message *msgLow[kNumTestMessages];
instance = testInitInstance();
VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
- messagePool = &instance->Get<ot::MessagePool>();
+ messagePool = &instance->Get<MessagePool>();
// Use the function "Allocate()" to allocate messages with different priorities
for (int i = 0; i < kNumNewPriorityTestMessages; i++)
{
- msgNet[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityNet));
+ msgNet[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityNet));
VerifyOrQuit(msgNet[i] != nullptr);
- msgHigh[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityHigh));
+ msgHigh[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityHigh));
VerifyOrQuit(msgHigh[i] != nullptr);
- msgNor[i] =
- messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityNormal));
+ msgNor[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityNormal));
VerifyOrQuit(msgNor[i] != nullptr);
- msgLow[i] = messagePool->Allocate(ot::Message::kTypeIp6, 0, ot::Message::Settings(ot::Message::kPriorityLow));
+ msgLow[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityLow));
VerifyOrQuit(msgLow[i] != nullptr);
}
// Use the function "SetPriority()" to allocate messages with different priorities
for (int i = kNumNewPriorityTestMessages; i < kNumTestMessages; i++)
{
- msgNet[i] = messagePool->Allocate(ot::Message::kTypeIp6);
+ msgNet[i] = messagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msgNet[i] != nullptr);
- SuccessOrQuit(msgNet[i]->SetPriority(ot::Message::kPriorityNet));
- msgHigh[i] = messagePool->Allocate(ot::Message::kTypeIp6);
+ SuccessOrQuit(msgNet[i]->SetPriority(Message::kPriorityNet));
+ msgHigh[i] = messagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msgHigh[i] != nullptr);
- SuccessOrQuit(msgHigh[i]->SetPriority(ot::Message::kPriorityHigh));
- msgNor[i] = messagePool->Allocate(ot::Message::kTypeIp6);
+ SuccessOrQuit(msgHigh[i]->SetPriority(Message::kPriorityHigh));
+ msgNor[i] = messagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msgNor[i] != nullptr);
- SuccessOrQuit(msgNor[i]->SetPriority(ot::Message::kPriorityNormal));
- msgLow[i] = messagePool->Allocate(ot::Message::kTypeIp6);
+ SuccessOrQuit(msgNor[i]->SetPriority(Message::kPriorityNormal));
+ msgLow[i] = messagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msgLow[i] != nullptr);
- SuccessOrQuit(msgLow[i]->SetPriority(ot::Message::kPriorityLow));
+ SuccessOrQuit(msgLow[i]->SetPriority(Message::kPriorityLow));
}
// Check the `GetPriority()`
for (int i = 0; i < kNumTestMessages; i++)
{
- VerifyOrQuit(msgLow[i]->GetPriority() == ot::Message::kPriorityLow);
- VerifyOrQuit(msgNor[i]->GetPriority() == ot::Message::kPriorityNormal);
- VerifyOrQuit(msgHigh[i]->GetPriority() == ot::Message::kPriorityHigh);
- VerifyOrQuit(msgNet[i]->GetPriority() == ot::Message::kPriorityNet);
+ VerifyOrQuit(msgLow[i]->GetPriority() == Message::kPriorityLow);
+ VerifyOrQuit(msgNor[i]->GetPriority() == Message::kPriorityNormal);
+ VerifyOrQuit(msgHigh[i]->GetPriority() == Message::kPriorityHigh);
+ VerifyOrQuit(msgNet[i]->GetPriority() == Message::kPriorityNet);
}
// Verify case of an empty queue.
@@ -272,18 +272,18 @@ void TestPriorityQueue(void)
queue.Enqueue(*msgLow[0]);
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
- SuccessOrQuit(msgNor[0]->SetPriority(ot::Message::kPriorityNet));
+ SuccessOrQuit(msgNor[0]->SetPriority(Message::kPriorityNet));
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityLow));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow));
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityNormal));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityNormal));
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityHigh));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityHigh));
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgHigh[0], msgLow[0]);
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityNet));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityNet));
VerifyPriorityQueueContent(queue, 3, msgNor[0], msgLow[0], msgHigh[0]);
- SuccessOrQuit(msgNor[0]->SetPriority(ot::Message::kPriorityNormal));
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityLow));
+ SuccessOrQuit(msgNor[0]->SetPriority(Message::kPriorityNormal));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow));
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
messageQueue.Enqueue(*msgNor[1]);
@@ -292,10 +292,10 @@ void TestPriorityQueue(void)
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
// Change priority of message and check for not in messageQueue.
- SuccessOrQuit(msgNor[1]->SetPriority(ot::Message::kPriorityNet));
+ SuccessOrQuit(msgNor[1]->SetPriority(Message::kPriorityNet));
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
- SuccessOrQuit(msgLow[0]->SetPriority(ot::Message::kPriorityHigh));
+ SuccessOrQuit(msgLow[0]->SetPriority(Message::kPriorityHigh));
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgLow[0], msgNor[0]);
VerifyMsgQueueContent(messageQueue, 3, msgNor[1], msgHigh[1], msgNet[1]);
@@ -321,9 +321,9 @@ void TestPriorityQueue(void)
messageQueue.Dequeue(*msgNor[1]);
VerifyMsgQueueContent(messageQueue, 0);
- for (ot::Message *message : msgNor)
+ for (Message *message : msgNor)
{
- SuccessOrQuit(message->SetPriority(ot::Message::kPriorityNormal));
+ SuccessOrQuit(message->SetPriority(Message::kPriorityNormal));
}
// Range-based `for` and dequeue during iteration
@@ -339,7 +339,7 @@ void TestPriorityQueue(void)
VerifyPriorityQueueContent(queue, 4, msgNor[0], msgNor[1], msgNor[2], msgNor[3]);
// While iterating over the queue remove the entry at `removeIndex`
- for (ot::Message &message : queue)
+ for (Message &message : queue)
{
if (index == removeIndex)
{
@@ -352,7 +352,7 @@ void TestPriorityQueue(void)
index = 0;
// Iterate over the queue and remove all
- for (ot::Message &message : queue)
+ for (Message &message : queue)
{
if (index == removeIndex)
{
@@ -369,9 +369,11 @@ void TestPriorityQueue(void)
testFreeInstance(instance);
}
+} // namespace ot
+
int main(void)
{
- TestPriorityQueue();
+ ot::TestPriorityQueue();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp
index 0ae4e973e..25156378c 100644
--- a/tests/unit/test_pskc.cpp
+++ b/tests/unit/test_pskc.cpp
@@ -33,6 +33,8 @@
#include "test_platform.h"
#include "test_util.h"
+namespace ot {
+
#if OPENTHREAD_FTD
void TestMinimumPassphrase(void)
@@ -97,21 +99,19 @@ void TestExampleInSpec(void)
testFreeInstance(instance);
}
-int main(void)
-{
- TestMinimumPassphrase();
- TestMaximumPassphrase();
- TestExampleInSpec();
- printf("All tests passed\n");
- return 0;
-}
+} // namespace ot
-#else // #if OPENTHREAD_FTD
+#endif // OPENTHREAD_FTD
int main(void)
{
+#if OPENTHREAD_FTD
+ ot::TestMinimumPassphrase();
+ ot::TestMaximumPassphrase();
+ ot::TestExampleInSpec();
+ printf("All tests passed\n");
+#else
printf("PSKc generation is not supported on non-ftd build\n");
+#endif
return 0;
}
-
-#endif // #if OPENTHREAD_FTD
diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp
index c5cbb5cda..ef2a53bf1 100644
--- a/tests/unit/test_routing_manager.cpp
+++ b/tests/unit/test_routing_manager.cpp
@@ -38,14 +38,14 @@
#include "border_router/routing_manager.hpp"
#include "common/arg_macros.hpp"
#include "common/array.hpp"
-#include "common/instance.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#include "net/icmp6.hpp"
#include "net/nd6.hpp"
-#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+namespace ot {
-using namespace ot;
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
// Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
#define Log(...) \
@@ -111,7 +111,7 @@ static constexpr otOperationalDataset kDataset = {
},
};
-static ot::Instance *sInstance;
+static Instance *sInstance;
static uint32_t sNow = 0;
static uint32_t sAlarmTime;
@@ -155,6 +155,18 @@ bool sRespondToNs; // Indicates whether or not to respond to NS.
ExpectedPio sExpectedPio; // Expected PIO in the emitted RA by BR (MUST be seen in RA to set `sRaValidated`).
uint32_t sOnLinkLifetime; // Valid lifetime for local on-link prefix from the last processed RA.
+enum ExpectedRaHeaderFlags
+{
+ kRaHeaderFlagsSkipChecking, // Skip checking the RA header flags.
+ kRaHeaderFlagsNone, // Expect no flag (neither M or O).
+ kRaHeaderFlagsOnlyM, // Expect M flag only.
+ kRaHeaderFlagsOnlyO, // Expect O flag only.
+ kRaHeaderFlagsBothMAndO, // Expect both M and O flags.
+};
+
+// The expected RA header flags when validating emitted RA message.
+ExpectedRaHeaderFlags sExpectedRaHeaderFlags;
+
// Array containing deprecating prefixes from PIOs in the last processed RA.
Array<DeprecatingPrefix, kMaxDeprecatingPrefixes> sDeprecatingPrefixes;
@@ -371,9 +383,36 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
bool sawExpectedPio = false;
Array<Ip6::Prefix, kMaxPrefixes> pioPrefixes;
Array<Ip6::Prefix, kMaxPrefixes> rioPrefixes;
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
+ bool sawStubRouterFlag = false;
+#endif
VerifyOrQuit(raMsg.IsValid());
+ VerifyOrQuit(raMsg.GetHeader().GetRouterLifetime() == 0);
+
+ switch (sExpectedRaHeaderFlags)
+ {
+ case kRaHeaderFlagsSkipChecking:
+ break;
+ case kRaHeaderFlagsNone:
+ VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
+ VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
+ break;
+ case kRaHeaderFlagsOnlyM:
+ VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
+ VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
+ break;
+ case kRaHeaderFlagsOnlyO:
+ VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
+ VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
+ break;
+ case kRaHeaderFlagsBothMAndO:
+ VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
+ VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
+ break;
+ }
+
sDeprecatingPrefixes.Clear();
for (const Ip6::Nd::Option &option : raMsg)
@@ -456,6 +495,7 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
VerifyOrQuit(flagsOption.IsValid());
VerifyOrQuit(flagsOption.IsStubRouterFlagSet());
+ sawStubRouterFlag = true;
break;
}
#endif
@@ -465,6 +505,10 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket)
}
}
+#if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
+ VerifyOrQuit(sawStubRouterFlag);
+#endif
+
if (!sRaValidated)
{
switch (sExpectedPio)
@@ -524,6 +568,8 @@ void LogRouterAdvert(const Icmp6Packet &aPacket)
VerifyOrQuit(raMsg.IsValid());
+ Log(" RA header - M:%u, O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
+ raMsg.GetHeader().IsOtherConfigFlagSet());
Log(" RA header - lifetime %u, prf:%s", raMsg.GetHeader().GetRouterLifetime(),
PreferenceToString(raMsg.GetHeader().GetDefaultRouterPreference()));
@@ -788,13 +834,28 @@ struct DefaultRoute
RoutePreference mPreference;
};
+struct RaFlags : public Clearable<RaFlags>
+{
+ RaFlags(void)
+ : mManagedAddressConfigFlag(false)
+ , mOtherConfigFlag(false)
+ , mStubRouterFlag(false)
+ {
+ }
+
+ bool mManagedAddressConfigFlag;
+ bool mOtherConfigFlag;
+ bool mStubRouterFlag;
+};
+
template <size_t N>
uint16_t BuildRouterAdvert(uint8_t (&aBuffer)[N],
const Pio *aPios,
uint16_t aNumPios,
const Rio *aRios,
uint16_t aNumRios,
- const DefaultRoute &aDefaultRoute)
+ const DefaultRoute &aDefaultRoute,
+ const RaFlags &aRaFlags)
{
Ip6::Nd::RouterAdvertMessage::Header header;
uint16_t length;
@@ -802,9 +863,24 @@ uint16_t BuildRouterAdvert(uint8_t (&aBuffer)[N],
header.SetRouterLifetime(aDefaultRoute.mLifetime);
header.SetDefaultRouterPreference(aDefaultRoute.mPreference);
+ if (aRaFlags.mManagedAddressConfigFlag)
+ {
+ header.SetManagedAddressConfigFlag();
+ }
+
+ if (aRaFlags.mOtherConfigFlag)
+ {
+ header.SetOtherConfigFlag();
+ }
+
{
Ip6::Nd::RouterAdvertMessage raMsg(header, aBuffer);
+ if (aRaFlags.mStubRouterFlag)
+ {
+ SuccessOrQuit(raMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
+ }
+
for (; aNumPios > 0; aPios++, aNumPios--)
{
SuccessOrQuit(
@@ -827,10 +903,11 @@ void SendRouterAdvert(const Ip6::Address &aRouterAddress,
uint16_t aNumPios,
const Rio *aRios,
uint16_t aNumRios,
- const DefaultRoute &aDefaultRoute)
+ const DefaultRoute &aDefaultRoute,
+ const RaFlags &aRaFlags)
{
uint8_t buffer[kMaxRaSize];
- uint16_t length = BuildRouterAdvert(buffer, aPios, aNumPios, aRios, aNumRios, aDefaultRoute);
+ uint16_t length = BuildRouterAdvert(buffer, aPios, aNumPios, aRios, aNumRios, aDefaultRoute, aRaFlags);
SendRouterAdvert(aRouterAddress, buffer, length);
Log("Sending RA from router %s", aRouterAddress.ToString().AsCString());
@@ -841,37 +918,48 @@ template <uint16_t kNumPios, uint16_t kNumRios>
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
const Pio (&aPios)[kNumPios],
const Rio (&aRios)[kNumRios],
- const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium))
+ const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
+ const RaFlags &aRaFlags = RaFlags())
{
- SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute);
+ SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute, aRaFlags);
}
template <uint16_t kNumPios>
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
const Pio (&aPios)[kNumPios],
- const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium))
+ const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
+ const RaFlags &aRaFlags = RaFlags())
{
- SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute);
+ SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute, aRaFlags);
}
template <uint16_t kNumRios>
void SendRouterAdvert(const Ip6::Address &aRouterAddress,
const Rio (&aRios)[kNumRios],
- const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium))
+ const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
+ const RaFlags &aRaFlags = RaFlags())
{
- SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute);
+ SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute, aRaFlags);
}
-void SendRouterAdvert(const Ip6::Address &aRouterAddress, const DefaultRoute &aDefaultRoute)
+void SendRouterAdvert(const Ip6::Address &aRouterAddress,
+ const DefaultRoute &aDefaultRoute,
+ const RaFlags &aRaFlags = RaFlags())
{
- SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute);
+ SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute, aRaFlags);
+}
+
+void SendRouterAdvert(const Ip6::Address &aRouterAddress, const RaFlags &aRaFlags)
+{
+ SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
+ aRaFlags);
}
template <uint16_t kNumPios> void SendRouterAdvertToBorderRoutingProcessIcmp6Ra(const Pio (&aPios)[kNumPios])
{
uint8_t buffer[kMaxRaSize];
- uint16_t length =
- BuildRouterAdvert(buffer, aPios, kNumPios, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium));
+ uint16_t length = BuildRouterAdvert(buffer, aPios, kNumPios, nullptr, 0,
+ DefaultRoute(0, NetworkData::kRoutePreferenceMedium), RaFlags());
otPlatBorderRoutingProcessIcmp6Ra(sInstance, buffer, length);
Log("Passing RA to otPlatBorderRoutingProcessIcmp6Ra");
@@ -945,7 +1033,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
{
Log(" on-link prefix:%s, valid:%u, preferred:%u, router:%s, age:%u",
AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime, entry.mPreferredLifetime,
- AsCoreType(&entry.mRouterAddress).ToString().AsCString(), entry.mMsecSinceLastUpdate / 1000);
+ AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(), entry.mMsecSinceLastUpdate / 1000);
onLinkPrefixCount++;
@@ -954,7 +1042,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
const OnLinkPrefix &onLinkPrefix = aOnLinkPrefixes[index];
if ((onLinkPrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
- (AsCoreType(&entry.mRouterAddress) == onLinkPrefix.mRouterAddress))
+ (AsCoreType(&entry.mRouter.mAddress) == onLinkPrefix.mRouterAddress))
{
VerifyOrQuit(entry.mValidLifetime == onLinkPrefix.mValidLifetime);
VerifyOrQuit(entry.mPreferredLifetime == onLinkPrefix.mPreferredLifetime);
@@ -967,7 +1055,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
{
Log(" route prefix:%s, valid:%u, prf:%s, router:%s, age:%u",
AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime,
- PreferenceToString(entry.mRoutePreference), AsCoreType(&entry.mRouterAddress).ToString().AsCString(),
+ PreferenceToString(entry.mRoutePreference), AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(),
entry.mMsecSinceLastUpdate / 1000);
routePrefixCount++;
@@ -977,7 +1065,7 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
const RoutePrefix &routePrefix = aRoutePrefixes[index];
if ((routePrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
- (AsCoreType(&entry.mRouterAddress) == routePrefix.mRouterAddress))
+ (AsCoreType(&entry.mRouter.mAddress) == routePrefix.mRouterAddress))
{
VerifyOrQuit(entry.mValidLifetime == routePrefix.mValidLifetime);
VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == routePrefix.mPreference);
@@ -996,6 +1084,66 @@ void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
void VerifyPrefixTableIsEmpty(void) { VerifyPrefixTable(nullptr, 0, nullptr, 0); }
+struct InfraRouter
+{
+ InfraRouter(const Ip6::Address &aAddress,
+ bool aManagedAddressConfigFlag,
+ bool aOtherConfigFlag,
+ bool aStubRouterFlag)
+ : mAddress(aAddress)
+ {
+ mFlags.Clear();
+ mFlags.mManagedAddressConfigFlag = aManagedAddressConfigFlag;
+ mFlags.mOtherConfigFlag = aOtherConfigFlag;
+ mFlags.mStubRouterFlag = aStubRouterFlag;
+ }
+
+ Ip6::Address mAddress;
+ RaFlags mFlags;
+};
+
+template <uint16_t kNumRouters> void VerifyDiscoveredRouters(const InfraRouter (&aRouters)[kNumRouters])
+{
+ VerifyDiscoveredRouters(aRouters, kNumRouters);
+}
+
+void VerifyDiscoveredRouters(const InfraRouter *aRouters, uint16_t aNumRouters)
+{
+ BorderRouter::RoutingManager::PrefixTableIterator iter;
+ BorderRouter::RoutingManager::RouterEntry entry;
+ uint16_t count = 0;
+
+ Log("VerifyDiscoveredRouters()");
+
+ sInstance->Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(iter);
+
+ while (sInstance->Get<BorderRouter::RoutingManager>().GetNextRouterEntry(iter, entry) == kErrorNone)
+ {
+ bool didFind = false;
+
+ Log(" address:%s, M:%u, O:%u, StubRouter:%u", AsCoreType(&entry.mAddress).ToString().AsCString(),
+ entry.mManagedAddressConfigFlag, entry.mOtherConfigFlag, entry.mStubRouterFlag);
+
+ for (uint16_t index = 0; index < aNumRouters; index++)
+ {
+ if (AsCoreType(&entry.mAddress) == aRouters[index].mAddress)
+ {
+ VerifyOrQuit(entry.mManagedAddressConfigFlag == aRouters[index].mFlags.mManagedAddressConfigFlag);
+ VerifyOrQuit(entry.mOtherConfigFlag == aRouters[index].mFlags.mOtherConfigFlag);
+ VerifyOrQuit(entry.mStubRouterFlag == aRouters[index].mFlags.mStubRouterFlag);
+ didFind = true;
+ }
+ }
+
+ VerifyOrQuit(didFind);
+ count++;
+ }
+
+ VerifyOrQuit(count == aNumRouters);
+}
+
+void VerifyDiscoveredRoutersIsEmpty(void) { VerifyDiscoveredRouters(nullptr, 0); }
+
void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
{
uint32_t delay = 10000;
@@ -1032,19 +1180,20 @@ void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
SuccessOrQuit(otThreadSetEnabled(sInstance, true));
SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, aEnablBorderRouting));
+ // Reset all test flags
+ sRsEmitted = false;
+ sRaValidated = false;
+ sExpectedPio = kNoPio;
+ sExpectedRios.Clear();
+ sRespondToNs = true;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
+
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ensure device starts as leader.
AdvanceTime(delay);
VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
-
- // Reset all test flags
- sRsEmitted = false;
- sRaValidated = false;
- sExpectedPio = kNoPio;
- sExpectedRios.Clear();
- sRespondToNs = true;
}
void FinalizeTest(void)
@@ -1309,7 +1458,7 @@ void TestOmrSelection(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestOmrSelection");
FinalizeTest();
@@ -1474,7 +1623,7 @@ void TestDefaultRoute(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestDefaultRoute");
@@ -1640,7 +1789,7 @@ void TestAdvNonUlaRoute(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestAdvNonUlaRoute");
@@ -1779,7 +1928,7 @@ void TestLocalOnLinkPrefixDeprecation(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestLocalOnLinkPrefixDeprecation");
@@ -1931,7 +2080,7 @@ void TestDomainPrefixAsOmr(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestDomainPrefixAsOmr");
FinalizeTest();
@@ -2440,7 +2589,7 @@ void TestExtPanIdChange(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestExtPanIdChange");
FinalizeTest();
@@ -2593,12 +2742,184 @@ void TestRouterNsProbe(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestRouterNsProbe");
FinalizeTest();
}
+void TestLearningAndCopyingOfFlags(void)
+{
+ Ip6::Prefix localOnLink;
+ Ip6::Prefix localOmr;
+ Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64);
+ Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
+ Ip6::Address routerAddressB = AddressFromString("fd00::bbbb");
+ Ip6::Address routerAddressC = AddressFromString("fd00::cccc");
+ uint16_t heapAllocations;
+ RaFlags raFlags;
+
+ Log("--------------------------------------------------------------------------------------------");
+ Log("TestLearningAndCopyingOfFlags");
+
+ InitTest();
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Start Routing Manager. Check emitted RS and RA messages.
+
+ sRsEmitted = false;
+ sRaValidated = false;
+ sExpectedPio = kPioAdvertisingLocalOnLink;
+ sExpectedRios.Clear();
+
+ heapAllocations = sHeapAllocatedPtrs.GetLength();
+ SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
+
+ SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
+ SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
+
+ Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
+ Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
+
+ sExpectedRios.Add(localOmr);
+
+ AdvanceTime(30000);
+
+ VerifyOrQuit(sRsEmitted);
+ VerifyOrQuit(sRaValidated);
+ VerifyOrQuit(sExpectedRios.SawAll());
+ Log("Received RA was validated");
+
+ VerifyDiscoveredRoutersIsEmpty();
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Send an RA from router A with M flag set, and make sure the
+ // emitted RA from BR also includes M flag.
+
+ raFlags.Clear();
+ raFlags.mManagedAddressConfigFlag = true;
+
+ SendRouterAdvert(routerAddressA, raFlags);
+
+ AdvanceTime(1);
+ VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ false)});
+
+ sRaValidated = false;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyM;
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Send an RA from router A without the M flag. Now the emitted
+ // RA should no longer contain the M flag.
+
+ raFlags.Clear();
+
+ SendRouterAdvert(routerAddressA, raFlags);
+
+ sRaValidated = false;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
+
+ AdvanceTime(1);
+ VerifyDiscoveredRoutersIsEmpty();
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Send an RA from router A with both M and StubRouter flags.
+ // Since it is from a stub router, the M flag should be ignored.
+ // Ensure emitted RA does not set the M flag.
+
+ raFlags.Clear();
+ raFlags.mManagedAddressConfigFlag = true;
+ raFlags.mStubRouterFlag = true;
+
+ SendRouterAdvert(routerAddressA, raFlags);
+
+ AdvanceTime(1);
+ VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true)});
+
+ sRaValidated = false;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Send an RA from router B with O flag and check that emitted
+ // RA include the same flag.
+
+ raFlags.Clear();
+ raFlags.mOtherConfigFlag = true;
+
+ SendRouterAdvert(routerAddressB, raFlags);
+
+ AdvanceTime(1);
+ VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
+ InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false)});
+
+ sRaValidated = false;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyO;
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Send an RA from router C with M flag and check that emitted
+ // RA now includes both M and O flags.
+
+ raFlags.Clear();
+ raFlags.mManagedAddressConfigFlag = true;
+
+ SendRouterAdvert(routerAddressC, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
+ DefaultRoute(0, NetworkData::kRoutePreferenceMedium), raFlags);
+
+ AdvanceTime(1);
+ VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
+ InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false),
+ InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
+
+ sRaValidated = false;
+ sExpectedPio = kPioDeprecatingLocalOnLink;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsBothMAndO;
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // Stop responding to NS, this should cause all routers
+ // to age and considered offline
+
+ sRespondToNs = false;
+
+ sExpectedRaHeaderFlags = kRaHeaderFlagsSkipChecking;
+
+ AdvanceTime(300 * 1000);
+
+ // Router C should be in the table since it will have a deprecating
+ // on-link prefix.
+ VerifyDiscoveredRouters({InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
+
+ sRaValidated = false;
+ sExpectedPio = kPioAdvertisingLocalOnLink;
+ sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
+
+ AdvanceTime(610 * 1000);
+ VerifyOrQuit(sRaValidated);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
+ VerifyDiscoveredRoutersIsEmpty();
+
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
+
+ Log("End of TestLearningAndCopyingOfFlags");
+ FinalizeTest();
+}
+
void TestConflictingPrefix(void)
{
static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
@@ -2812,7 +3133,7 @@ void TestConflictingPrefix(void)
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
- VerifyOrQuit(heapAllocations = sHeapAllocatedPtrs.GetLength());
+ VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
Log("End of TestConflictingPrefix");
@@ -3543,40 +3864,45 @@ void TestBorderRoutingProcessPlatfromGeneratedNd(void)
}
SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, false));
- VerifyOrQuit(sHeapAllocatedPtrs.GetLength() == heapAllocations);
+ VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
Log("End of TestBorderRoutingProcessPlatfromGeneratedNd");
+
+ FinalizeTest();
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
+} // namespace ot
+
int main(void)
{
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
- TestSamePrefixesFromMultipleRouters();
- TestOmrSelection();
- TestDefaultRoute();
- TestAdvNonUlaRoute();
- TestLocalOnLinkPrefixDeprecation();
+ ot::TestSamePrefixesFromMultipleRouters();
+ ot::TestOmrSelection();
+ ot::TestDefaultRoute();
+ ot::TestAdvNonUlaRoute();
+ ot::TestLocalOnLinkPrefixDeprecation();
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
- TestDomainPrefixAsOmr();
+ ot::TestDomainPrefixAsOmr();
#endif
- TestExtPanIdChange();
- TestConflictingPrefix();
- TestRouterNsProbe();
+ ot::TestExtPanIdChange();
+ ot::TestConflictingPrefix();
+ ot::TestRouterNsProbe();
+ ot::TestLearningAndCopyingOfFlags();
#if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
- TestSavedOnLinkPrefixes();
+ ot::TestSavedOnLinkPrefixes();
#endif
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
- TestAutoEnableOfSrpServer();
+ ot::TestAutoEnableOfSrpServer();
#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
- TestNat64PrefixSelection();
+ ot::TestNat64PrefixSelection();
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
- TestBorderRoutingProcessPlatfromGeneratedNd();
-#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
+ ot::TestBorderRoutingProcessPlatfromGeneratedNd();
+#endif
printf("All tests passed\n");
#else
diff --git a/tests/unit/test_spinel_buffer.cpp b/tests/unit/test_spinel_buffer.cpp
index 8d4f32257..288b2fba1 100644
--- a/tests/unit/test_spinel_buffer.cpp
+++ b/tests/unit/test_spinel_buffer.cpp
@@ -29,9 +29,9 @@
#include <ctype.h>
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
#include "common/message.hpp"
#include "common/random.hpp"
+#include "instance/instance.hpp"
#include "lib/spinel/spinel_buffer.hpp"
#include "test_platform.h"
@@ -57,8 +57,8 @@ static const uint8_t sMottoText[] = "Think good thoughts, say good words, d
static const uint8_t sMysteryText[] = "4871(\\):|(3$}{4|/4/2%14(\\)";
static const uint8_t sHexText[] = "0123456789abcdef";
-static ot::Instance *sInstance;
-static MessagePool *sMessagePool;
+static Instance *sInstance;
+static MessagePool *sMessagePool;
struct CallbackContext
{
diff --git a/tests/unit/test_spinel_decoder.cpp b/tests/unit/test_spinel_decoder.cpp
index 1a2249ab7..e8ee85822 100644
--- a/tests/unit/test_spinel_decoder.cpp
+++ b/tests/unit/test_spinel_decoder.cpp
@@ -27,7 +27,7 @@
*/
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "lib/spinel/spinel_decoder.hpp"
#include "test_util.hpp"
diff --git a/tests/unit/test_spinel_encoder.cpp b/tests/unit/test_spinel_encoder.cpp
index 4b76d4c6b..09c8de93e 100644
--- a/tests/unit/test_spinel_encoder.cpp
+++ b/tests/unit/test_spinel_encoder.cpp
@@ -27,7 +27,7 @@
*/
#include "common/code_utils.hpp"
-#include "common/instance.hpp"
+#include "instance/instance.hpp"
#include "lib/spinel/spinel_encoder.hpp"
#include "test_util.hpp"
diff --git a/tests/unit/test_srp_server.cpp b/tests/unit/test_srp_server.cpp
index 230375902..ddf1e6e75 100644
--- a/tests/unit/test_srp_server.cpp
+++ b/tests/unit/test_srp_server.cpp
@@ -38,9 +38,9 @@
#include "common/arg_macros.hpp"
#include "common/array.hpp"
-#include "common/instance.hpp"
#include "common/string.hpp"
#include "common/time.hpp"
+#include "instance/instance.hpp"
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && \
!OPENTHREAD_CONFIG_TIME_SYNC_ENABLE && !OPENTHREAD_PLATFORM_POSIX
@@ -49,9 +49,9 @@
#define ENABLE_SRP_TEST 0
#endif
-#if ENABLE_SRP_TEST
+namespace ot {
-using namespace ot;
+#if ENABLE_SRP_TEST
// Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
#define Log(...) \
@@ -60,7 +60,7 @@ using namespace ot;
static constexpr uint16_t kMaxRaSize = 800;
-static ot::Instance *sInstance;
+static Instance *sInstance;
static uint32_t sNow = 0;
static uint32_t sAlarmTime;
@@ -1028,16 +1028,18 @@ void TestUpdateLeaseShortVariant(void)
#endif // ENABLE_SRP_TEST
+} // namespace ot
+
int main(void)
{
#if ENABLE_SRP_TEST
- TestSrpServerBase();
- TestSrpServerReject();
- TestSrpServerIgnore();
- TestSrpServerClientRemove(/* aShouldRemoveKeyLease */ true);
- TestSrpServerClientRemove(/* aShouldRemoveKeyLease */ false);
+ ot::TestSrpServerBase();
+ ot::TestSrpServerReject();
+ ot::TestSrpServerIgnore();
+ ot::TestSrpServerClientRemove(/* aShouldRemoveKeyLease */ true);
+ ot::TestSrpServerClientRemove(/* aShouldRemoveKeyLease */ false);
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
- TestUpdateLeaseShortVariant();
+ ot::TestUpdateLeaseShortVariant();
#endif
printf("All tests passed\n");
#else
diff --git a/tests/unit/test_string.cpp b/tests/unit/test_string.cpp
index 80ff3b099..7158ca28c 100644
--- a/tests/unit/test_string.cpp
+++ b/tests/unit/test_string.cpp
@@ -366,6 +366,36 @@ void TestStringParseUint8(void)
printf("\n\n -- PASS\n");
}
+void TestStringCopy(void)
+{
+ char buffer[10];
+ char smallBuffer[1];
+
+ printf("\nTest 11: StringCopy() function\n");
+
+ SuccessOrQuit(StringCopy(buffer, "foo", kStringCheckUtf8Encoding));
+ VerifyOrQuit(StringMatch(buffer, "foo"));
+
+ SuccessOrQuit(StringCopy(buffer, nullptr, kStringCheckUtf8Encoding));
+ VerifyOrQuit(StringMatch(buffer, ""));
+
+ SuccessOrQuit(StringCopy(buffer, "", kStringCheckUtf8Encoding));
+ VerifyOrQuit(StringMatch(buffer, ""));
+
+ SuccessOrQuit(StringCopy(buffer, "123456789", kStringCheckUtf8Encoding));
+ VerifyOrQuit(StringMatch(buffer, "123456789"));
+
+ VerifyOrQuit(StringCopy(buffer, "1234567890") == kErrorInvalidArgs);
+ VerifyOrQuit(StringCopy(buffer, "1234567890abcdef") == kErrorInvalidArgs);
+
+ SuccessOrQuit(StringCopy(smallBuffer, "", kStringCheckUtf8Encoding));
+ VerifyOrQuit(StringMatch(smallBuffer, ""));
+
+ VerifyOrQuit(StringCopy(smallBuffer, "a") == kErrorInvalidArgs);
+
+ printf(" -- PASS\n");
+}
+
// gcc-4 does not support constexpr function
#if __GNUC__ > 4
static_assert(ot::AreStringsInOrder("a", "b"), "AreStringsInOrder() failed");
@@ -389,6 +419,7 @@ int main(void)
ot::TestStringMatch();
ot::TestStringToLowercase();
ot::TestStringParseUint8();
+ ot::TestStringCopy();
printf("\nAll tests passed.\n");
return 0;
}
diff --git a/tests/unit/test_timer.cpp b/tests/unit/test_timer.cpp
index b3509f833..8666ba755 100644
--- a/tests/unit/test_timer.cpp
+++ b/tests/unit/test_timer.cpp
@@ -31,9 +31,11 @@
#include "common/array.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/num_utils.hpp"
#include "common/timer.hpp"
+#include "instance/instance.hpp"
+
+namespace ot {
enum
{
@@ -91,19 +93,19 @@ uint32_t otPlatAlarmMicroGetNow(void) { return sNow; }
void InitCounters(void) { memset(sCallCount, 0, sizeof(sCallCount)); }
/**
- * `TestTimer` sub-classes `ot::TimerMilli` and provides a handler and a counter to keep track of number of times timer
+ * `TestTimer` sub-classes `TimerMilli` and provides a handler and a counter to keep track of number of times timer
* gets fired.
*/
template <typename TimerType> class TestTimer : public TimerType
{
public:
- explicit TestTimer(ot::Instance &aInstance)
+ explicit TestTimer(Instance &aInstance)
: TimerType(aInstance, TestTimer::HandleTimerFired)
, mFiredCounter(0)
{
}
- static void HandleTimerFired(ot::Timer &aTimer) { static_cast<TestTimer &>(aTimer).HandleTimerFired(); }
+ static void HandleTimerFired(Timer &aTimer) { static_cast<TestTimer &>(aTimer).HandleTimerFired(); }
void HandleTimerFired(void)
{
@@ -115,7 +117,7 @@ public:
void ResetFiredCounter(void) { mFiredCounter = 0; }
- static void RemoveAll(ot::Instance &aInstance) { TimerType::RemoveAll(aInstance); }
+ static void RemoveAll(Instance &aInstance) { TimerType::RemoveAll(aInstance); }
private:
uint32_t mFiredCounter; //< Number of times timer has been fired so far
@@ -123,10 +125,10 @@ private:
template <typename TimerType> void AlarmFired(otInstance *aInstance);
-template <> void AlarmFired<ot::TimerMilli>(otInstance *aInstance) { otPlatAlarmMilliFired(aInstance); }
+template <> void AlarmFired<TimerMilli>(otInstance *aInstance) { otPlatAlarmMilliFired(aInstance); }
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
-template <> void AlarmFired<ot::TimerMicro>(otInstance *aInstance) { otPlatAlarmMicroFired(aInstance); }
+template <> void AlarmFired<TimerMicro>(otInstance *aInstance) { otPlatAlarmMicroFired(aInstance); }
#endif
/**
@@ -136,7 +138,7 @@ template <typename TimerType> int TestOneTimer(void)
{
const uint32_t kTimeT0 = 1000;
const uint32_t kTimerInterval = 10;
- ot::Instance *instance = testInitInstance();
+ Instance *instance = testInitInstance();
TestTimer<TimerType> timer(*instance);
// Test one Timer basic operation.
@@ -262,7 +264,7 @@ template <typename TimerType> int TestTwoTimers(void)
{
const uint32_t kTimeT0 = 1000;
const uint32_t kTimerInterval = 10;
- ot::Instance *instance = testInitInstance();
+ Instance *instance = testInitInstance();
TestTimer<TimerType> timer1(*instance);
TestTimer<TimerType> timer2(*instance);
@@ -338,7 +340,7 @@ template <typename TimerType> int TestTwoTimers(void)
sNow += kTimerInterval;
- timer2.StartAt(ot::TimeMilli(kTimeT0), kTimerInterval - 2); // Timer 2 is even before timer 1
+ timer2.StartAt(TimeMilli(kTimeT0), kTimerInterval - 2); // Timer 2 is even before timer 1
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 0, "Handler CallCount Failed.");
VerifyOrQuit(timer1.IsRunning() == true, "Timer running Failed.");
@@ -385,7 +387,7 @@ template <typename TimerType> int TestTwoTimers(void)
sNow += kTimerInterval + 5;
- timer2.Start(ot::Timer::kMaxDelay);
+ timer2.Start(Timer::kMaxDelay);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 1, "Start CallCount Failed.");
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStop] == 0, "Stop CallCount Failed.");
@@ -401,12 +403,12 @@ template <typename TimerType> int TestTwoTimers(void)
VerifyOrQuit(sCallCount[kCallCountIndexTimerHandler] == 1, "Handler CallCount Failed.");
VerifyOrQuit(timer1.GetFiredCounter() == 1, "Fire Counter failed.");
VerifyOrQuit(sPlatT0 == sNow, "Start params Failed.");
- VerifyOrQuit(sPlatDt == ot::Timer::kMaxDelay, "Start params Failed.");
+ VerifyOrQuit(sPlatDt == Timer::kMaxDelay, "Start params Failed.");
VerifyOrQuit(timer1.IsRunning() == false, "Timer running Failed.");
VerifyOrQuit(timer2.IsRunning() == true, "Timer running Failed.");
VerifyOrQuit(sTimerOn == true, "Platform Timer State Failed.");
- sNow += ot::Timer::kMaxDelay;
+ sNow += Timer::kMaxDelay;
AlarmFired<TimerType>(instance);
VerifyOrQuit(sCallCount[kCallCountIndexAlarmStart] == 2, "Start CallCount Failed.");
@@ -436,7 +438,7 @@ template <typename TimerType> static void TenTimers(uint32_t aTimeShift)
const uint32_t kNumTriggers = 7;
const uint32_t kTimeT0[kNumTimers] = {1000, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008};
const uint32_t kTimerInterval[kNumTimers] = {
- 20, 100, (ot::Timer::kMaxDelay - kTimeT0[2]), 100000, 1000000, 10, ot::Timer::kMaxDelay, 200, 200, 200};
+ 20, 100, (Timer::kMaxDelay - kTimeT0[2]), 100000, 1000000, 10, Timer::kMaxDelay, 200, 200, 200};
// Expected timer fire order
// timer # Trigger time
// 5 1014
@@ -450,7 +452,7 @@ template <typename TimerType> static void TenTimers(uint32_t aTimeShift)
// 2 kMaxDuration
// 6 kMaxDuration + 1005
const uint32_t kTriggerTimes[kNumTriggers] = {
- 1014, 1020, 1100, 1207, 101004, ot::Timer::kMaxDelay, ot::Timer::kMaxDelay + kTimeT0[6]};
+ 1014, 1020, 1100, 1207, 101004, Timer::kMaxDelay, Timer::kMaxDelay + kTimeT0[6]};
// Expected timers fired by each kTriggerTimes[] value
// Trigger # Timers Fired
// 0 5
@@ -478,7 +480,7 @@ template <typename TimerType> static void TenTimers(uint32_t aTimeShift)
const uint32_t kTimerStartCountAfterTrigger[kNumTriggers] = {3, 4, 5, 7, 9, 11, 11};
- ot::Instance *instance = testInitInstance();
+ Instance *instance = testInitInstance();
TestTimer<TimerType> timer0(*instance);
TestTimer<TimerType> timer1(*instance);
@@ -567,12 +569,12 @@ template <typename TimerType> int TestTenTimers(void)
{
// Time shift to change the start/fire time of ten timers.
const uint32_t kTimeShift[] = {
- 0, 100000U, 0U - 1U, 0U - 1100U, ot::Timer::kMaxDelay, ot::Timer::kMaxDelay + 1020U,
+ 0, 100000U, 0U - 1U, 0U - 1100U, Timer::kMaxDelay, Timer::kMaxDelay + 1020U,
};
size_t i;
- for (i = 0; i < ot::GetArrayLength(kTimeShift); i++)
+ for (i = 0; i < GetArrayLength(kTimeShift); i++)
{
TenTimers<TimerType>(kTimeShift[i]);
}
@@ -587,10 +589,10 @@ int TestTimerTime(void)
{
const uint32_t kMaxTime = 0xffffffff;
const uint32_t kStartTimes[] = {0, 100, kMaxTime / 2, kMaxTime - 100, kMaxTime};
- const uint32_t kDurations[] = {1, 100, ot::Timer::kMaxDelay - 1, ot::Timer::kMaxDelay};
+ const uint32_t kDurations[] = {1, 100, Timer::kMaxDelay - 1, Timer::kMaxDelay};
- ot::Time t1;
- ot::Time t2;
+ Time t1;
+ Time t2;
for (uint32_t startTime : kStartTimes)
{
@@ -680,13 +682,15 @@ template <typename TimerType> void RunTimerTests(void)
TestTenTimers<TimerType>();
}
+} // namespace ot
+
int main(void)
{
- RunTimerTests<ot::TimerMilli>();
+ ot::RunTimerTests<ot::TimerMilli>();
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
- RunTimerTests<ot::TimerMicro>();
+ ot::RunTimerTests<ot::TimerMicro>();
#endif
- TestTimerTime();
+ ot::TestTimerTime();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_tlv.cpp b/tests/unit/test_tlv.cpp
index 1af0121be..703abe3e5 100644
--- a/tests/unit/test_tlv.cpp
+++ b/tests/unit/test_tlv.cpp
@@ -30,9 +30,9 @@
#include <openthread/config.h>
-#include "common/instance.hpp"
#include "common/message.hpp"
#include "common/tlvs.hpp"
+#include "instance/instance.hpp"
#include "test_util.h"
diff --git a/tests/unit/test_toolchain.cpp b/tests/unit/test_toolchain.cpp
index ead3b1e42..03c741038 100644
--- a/tests/unit/test_toolchain.cpp
+++ b/tests/unit/test_toolchain.cpp
@@ -35,6 +35,8 @@
#include "test_util.h"
#include "thread/neighbor.hpp"
+namespace ot {
+
extern "C" {
uint32_t otNetifAddress_Size_c();
uint32_t otNetifAddress_offset_mNext_c();
@@ -95,11 +97,11 @@ void test_packed_union(void)
void test_packed_enum(void)
{
- ot::Neighbor neighbor;
- neighbor.SetState(ot::Neighbor::kStateValid);
+ Neighbor neighbor;
+ neighbor.SetState(Neighbor::kStateValid);
// Make sure that when we read the 3 bit field it is read as unsigned, so it return '4'
- VerifyOrQuit(neighbor.GetState() == ot::Neighbor::kStateValid, "OT_TOOL_PACKED failed 4");
+ VerifyOrQuit(neighbor.GetState() == Neighbor::kStateValid, "OT_TOOL_PACKED failed 4");
}
void test_addr_sizes(void)
@@ -171,9 +173,11 @@ void TestToolchain(void)
test_packed_alignment();
}
+} // namespace ot
+
int main(void)
{
- TestToolchain();
+ ot::TestToolchain();
printf("All tests passed\n");
return 0;
}
diff --git a/tests/unit/test_trickle_timer.cpp b/tests/unit/test_trickle_timer.cpp
index f5851f261..45a0bc79c 100644
--- a/tests/unit/test_trickle_timer.cpp
+++ b/tests/unit/test_trickle_timer.cpp
@@ -30,11 +30,13 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
-#include "common/instance.hpp"
#include "common/num_utils.hpp"
#include "common/trickle_timer.hpp"
+#include "instance/instance.hpp"
-static ot::Instance *sInstance;
+namespace ot {
+
+static Instance *sInstance;
static uint32_t sNow = 0;
static uint32_t sAlarmTime;
@@ -54,8 +56,6 @@ uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
} // extern "C"
-namespace ot {
-
void AdvanceTime(uint32_t aDuration)
{
uint32_t time = sNow + aDuration;
diff --git a/tests/unit/test_url.cpp b/tests/unit/test_url.cpp
index e10796e9e..a7ff34d50 100644
--- a/tests/unit/test_url.cpp
+++ b/tests/unit/test_url.cpp
@@ -36,8 +36,8 @@ namespace Url {
void TestSimple(void)
{
- char url[] = "spinel:///dev/ttyUSB0?baudrate=115200";
- ot::Url::Url args;
+ char url[] = "spinel:///dev/ttyUSB0?baudrate=115200";
+ Url args;
VerifyOrQuit(!args.Init(url));
@@ -53,8 +53,8 @@ void TestSimple(void)
void TestSimpleNoQueryString(void)
{
- char url[] = "spinel:///dev/ttyUSB0";
- ot::Url::Url args;
+ char url[] = "spinel:///dev/ttyUSB0";
+ Url args;
VerifyOrQuit(!args.Init(url));
VerifyOrQuit(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
@@ -67,9 +67,9 @@ void TestSimpleNoQueryString(void)
void TestEmptyValue(void)
{
- char url[] = "spinel:///dev/ttyUSB0?rtscts&baudrate=115200&verbose&verbose&verbose";
- ot::Url::Url args;
- const char *arg = nullptr;
+ char url[] = "spinel:///dev/ttyUSB0?rtscts&baudrate=115200&verbose&verbose&verbose";
+ Url args;
+ const char *arg = nullptr;
VerifyOrQuit(!args.Init(url));
VerifyOrQuit(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
@@ -85,8 +85,8 @@ void TestEmptyValue(void)
void TestMultipleProtocols(void)
{
- char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
- ot::Url::Url args;
+ char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
+ Url args;
VerifyOrQuit(!args.Init(url));
VerifyOrQuit(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
@@ -97,9 +97,9 @@ void TestMultipleProtocols(void)
void TestMultipleProtocolsAndDuplicateParameters(void)
{
- char url[] = "spinel+exec:///path/to/ot-rcp?arg=1&arg=arg2&arg=3";
- ot::Url::Url args;
- const char *arg = nullptr;
+ char url[] = "spinel+exec:///path/to/ot-rcp?arg=1&arg=arg2&arg=3";
+ Url args;
+ const char *arg = nullptr;
VerifyOrQuit(!args.Init(url));
VerifyOrQuit(!strcmp(args.GetPath(), "/path/to/ot-rcp"));
@@ -126,10 +126,10 @@ void TestIntValue(void)
char int16url[] = "spinel:///dev/ttyUSB0?val1=1&val2=0x02&val3=-0X03&val4=-400&val5=+500&val6=32768&val7=-32769";
char int32url[] =
"spinel:///dev/ttyUSB0?val1=1&val2=0x02&val3=-0X03&val4=-40000&val5=+50000&val6=2147483648&val7=-2147483649";
- ot::Url::Url args;
- int8_t int8val;
- int16_t int16val;
- int32_t int32val;
+ Url args;
+ int8_t int8val;
+ int16_t int16val;
+ int32_t int32val;
VerifyOrQuit(!args.Init(int8url));
VerifyOrQuit(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
@@ -199,10 +199,10 @@ void TestUintValue(void)
char uint16url[] = "spinel:///dev/ttyUSB0?val1=1&val2=0x02&val3=0X03&val4=-400&val5=+500&val6=65536&val7=-1";
char uint32url[] =
"spinel:///dev/ttyUSB0?val1=1&val2=0x02&val3=0X03&val4=-40000&val5=+70000&val6=4294967296&val7=-1";
- ot::Url::Url args;
- uint8_t uint8val;
- uint16_t uint16val;
- uint32_t uint32val;
+ Url args;
+ uint8_t uint8val;
+ uint16_t uint16val;
+ uint32_t uint32val;
VerifyOrQuit(!args.Init(uint8url));
VerifyOrQuit(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py
index ed31a172d..476d09997 100644
--- a/tools/harness-thci/OpenThread.py
+++ b/tools/harness-thci/OpenThread.py
@@ -1701,7 +1701,7 @@ class OpenThreadTHCI(object):
@watched
def getNetworkData(self):
lines = self.__executeCommand('netdata show')
- prefixes, routes, services, contexts = [], [], [], []
+ prefixes, routes, services, contexts, commissioning = [], [], [], []
classify = None
for line in lines:
@@ -1713,6 +1713,8 @@ class OpenThreadTHCI(object):
classify = services
elif line == 'Contexts:':
classify = contexts
+ elif line == 'Commissioning':
+ classify = commissioning
elif line == 'Done':
classify = None
else:
@@ -1723,6 +1725,7 @@ class OpenThreadTHCI(object):
'Routes': routes,
'Services': services,
'Contexts': contexts,
+ 'Commissioning': commissioning,
}
@API