OpenThread is an open-source implementation of the Thread networking protocol. This page provides an architectural overview of the codebase, including the layered protocol stack, core subsystems (ot::Mle::Mle, ot::MeshForwarder, ot::Mac::Mac), device type variants (FTD/MTD/RCP), and application entry points (C API, CLI, NCP/Spinel).
Related pages:
OpenThread is an open-source Thread networking protocol stack written in C++. The codebase is located at https://github.com/openthread/openthread and provides a complete implementation of Thread specifications from 1.1 through 1.4.
Repository Structure:
src/core/ - Core protocol implementation (C++)include/openthread/ - Public C API headerssrc/cli/ - Command-line interface (ot::Cli::Interpreter)examples/platforms/ - Hardware platform abstraction layertests/ - Unit tests, certification tests, simulation frameworkCore Capabilities:
OPENTHREAD_CONFIG_THREAD_VERSION)OPENTHREAD_MTD=1), FTD (OPENTHREAD_FTD=1), RCP (OPENTHREAD_RADIO=1)ot::Ip6::Ip6, ot::Lowpan::Lowpan (6LoWPAN), ot::MeshForwarderot::Crypto::AesCcm, ot::KeyManager, ot::MeshCoP::SecureTransportot::BorderRouter::RoutingManager, ot::BorderRouter::InfraIfThe central abstraction is ot::Instance (defined in src/core/instance/instance.hpp380-520), which provides service locator access to all subsystems via Get<T>() methods.
Sources: include/openthread/instance.h1-180 src/core/instance/instance.hpp1-200 src/core/BUILD.gn1-300 src/core/CMakeLists.txt1-100
OpenThread implements the Thread protocol as a layered architecture, with each layer building upon the functionality of lower layers:
Thread Protocol Stack with Code Entities
Sources: src/core/thread/mle.cpp1-300 src/core/thread/mesh_forwarder.cpp1-200 src/core/net/ip6.cpp1-200 src/core/mac/mac.cpp1-200 src/core/thread/lowpan.cpp1-200 src/core/BUILD.gn29-280
OpenThread supports multiple device configurations, each using a different subset of the protocol stack:
| Device Type | Description | Key Components | Build Flag |
|---|---|---|---|
| MTD (Minimal Thread Device) | Sleepy end device, cannot route traffic | ot::Mle::Mle (child mode only), ot::Parent | OPENTHREAD_MTD=1 |
| FTD (Full Thread Device) | Can operate as Child, Router, or Leader | ot::Mle::Mle, ot::RouterTable, ot::ChildTable, ot::MeshForwarder | OPENTHREAD_FTD=1 |
| RCP (Radio Co-Processor) | Offloads MAC/Radio to separate processor | ot::Mac::Mac, ot::Mac::SubMac, Spinel protocol | OPENTHREAD_RADIO=1 |
| Border Router | FTD with infrastructure integration | All FTD components + ot::BorderRouter::RoutingManager, ot::BorderRouter::InfraIf | OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1 |
Thread Device Roles (runtime state managed by ot::Mle::Mle::mRole):
kRoleDisabled) - Thread stack is disabledkRoleDetached) - Not participating in a networkkRoleChild) - Attached to a parent router, cannot routekRoleRouter) - Routes traffic, maintains child tablekRoleLeader) - Manages network data, router ID allocationSources: src/core/thread/mle.hpp244-291 include/openthread/thread.h76-85 src/core/thread/mle.cpp50-160
OpenThread uses a service locator pattern where all components access each other through a central ot::Instance object:
Instance and Service Locator Pattern
All components inherit from ot::InstanceLocator and use Get<T>() to access other components. This pattern:
Key Instance Methods:
otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize) - Initialize instance include/openthread/instance.h87otInstance *otInstanceInitSingle(void) - Initialize single static instance include/openthread/instance.h99void otInstanceFinalize(otInstance *aInstance) - Shutdown and cleanup include/openthread/instance.h180template <typename Type> inline Type &Get(void) - Service locator access src/core/common/locator.hpp108-113Key Classes:
ot::Instance - Central service locator src/core/instance/instance.hpp380-520ot::InstanceLocator - Base class for all components src/core/common/locator.hpp60-120Sources: src/core/instance/instance.hpp1-200 src/core/instance/instance.cpp1-150 include/openthread/instance.h1-180 src/core/common/locator.hpp60-120
ot::Mle::Mle is the core Thread protocol engine managing device roles, network attachment, and neighbor relationships.
Key State Variables:
DeviceRole mRole - Current role: kRoleDisabled, kRoleDetached, kRoleChild, kRoleRouter, kRoleLeader src/core/thread/mle.hpp251Parent mParent - Parent router information src/core/thread/mle.hpp419uint16_t mRloc16 - Device's Routing Locator src/core/thread/mle.hpp497LeaderData mLeaderData - Network leader information src/core/thread/mle.hpp602Key Methods:
Error Start(StartMode aMode) - Start MLE protocol src/core/thread/mle.cpp194-222void Stop(StopMode aMode) - Stop MLE protocol src/core/thread/mle.cpp224-248void SetRole(DeviceRole aRole) - Change device role src/core/thread/mle.cpp297-358void SetStateChild(uint16_t aRloc16) - Transition to child state src/core/thread/mle.cpp608-650Error SendChildUpdateRequestToParent() - Send Child Update Request src/core/thread/mle.cpp1154-1230Key Components:
mAttacher - Handles network attachment process src/core/thread/mle.hpp70mDetacher - Handles graceful detach src/core/thread/mle.hpp71mDelayedSender - Queues delayed MLE messages src/core/thread/mle.hpp67mNeighborTable - Manages neighbor entries src/core/thread/mle.hpp66Sources: src/core/thread/mle.cpp50-650 src/core/thread/mle.hpp121-700 src/core/thread/mle_types.hpp70-110
ot::RouterTable and ot::ChildTable manage network topology for Full Thread Devices.
RouterTable src/core/thread/router_table.cpp:
Array<Router, kMaxRouters> mRouters - Array of up to 64 router entries src/core/thread/router_table.hpp270RouterIdMap mRouterIdMap - Maps Router ID (0-62) to array index src/core/thread/router_table.hpp271Router *Allocate(void) - Allocate a new Router ID src/core/thread/router_table.cpp127-163void RemoveRouter(Router &aRouter) - Remove router from table src/core/thread/router_table.cpp101-124uint8_t mRouterIdSequence - Increments on topology changes src/core/thread/router_table.hpp274ChildTable src/core/thread/child_table.cpp:
Child mChildren[kMaxChildren] - Fixed array of child entries src/core/thread/child_table.hpp165Child *GetNewChild(void) - Find available slot for new child src/core/thread/child_table.cpp87-107uint16_t GetNumChildren(ChildState aState) - Count children by state src/core/thread/child_table.cpp49-62OPENTHREAD_CONFIG_MLE_MAX_CHILDREN src/core/thread/mle_types.hpp83Sources: src/core/thread/router_table.cpp39-177 src/core/thread/router_table.hpp80-280 src/core/thread/child_table.cpp43-140 src/core/thread/child_table.hpp60-180
ot::MeshForwarder handles packet routing, queuing, and transmission.
Key Message Queues:
MessageQueue mSendQueue - Outbound direct transmission queue src/core/thread/mesh_forwarder.hpp392MessageQueue mReassemblyList - Fragment reassembly tracking src/core/thread/mesh_forwarder.hpp394PriorityQueue mSendQueue (FTD) - Priority-based send queue src/core/thread/mesh_forwarder_ftd.cpp60IndirectSender mIndirectSender (FTD) - Queue for sleepy children src/core/thread/mesh_forwarder.hpp401Key Methods:
Error SendMessage(Message &aMessage) - Queue message for transmission src/core/thread/mesh_forwarder.cpp300-350void HandleReceivedFrame(Mac::RxFrame &aFrame) - Process received frame src/core/thread/mesh_forwarder.cpp600-700Error PrepareDataFrame(Mac::TxFrame &aFrame) - Build MAC frame src/core/thread/mesh_forwarder.cpp1100-1200Error SendEmptyFrame(Mac::TxFrame &aFrame, bool aAckRequest) - Send ACK or keepalive src/core/thread/mesh_forwarder.cpp950-1000Sources: src/core/thread/mesh_forwarder.cpp1-500 src/core/thread/mesh_forwarder.hpp100-400 src/core/thread/mesh_forwarder_ftd.cpp1-100
ot::Notifier provides event-driven state change notifications.
Event Types (defined in src/core/common/notifier.hpp60-100):
kEventThreadRoleChanged - Device role transitionkEventThreadNetdataChanged - Network Data updatedkEventIp6AddressAdded / kEventIp6AddressRemoved - Address changeskEventThreadChildAdded / kEventThreadChildRemoved - Child table changesKey Methods:
void Signal(Event aEvent) - Signal single event src/core/common/notifier.cpp56-66void SignalIfFirst(Event aEvent) - Signal only if first occurrence src/core/common/notifier.cpp68-78Error RegisterCallback(Callback &aCallback) - Register listener src/core/common/notifier.cpp42-54otError otSetStateChangedCallback(otInstance *, otStateChangedCallback, void *) - External C API include/openthread/instance.h272Notification Flow:
Get<Notifier>().Signal(kEventX)mFlagsToSignal bitfield src/core/common/notifier.hpp180mTask.Post() src/core/common/notifier.cpp60Notifier::HandleStateChanged() invokes all registered callbacks src/core/common/notifier.cpp83-115Sources: src/core/common/notifier.cpp42-150 src/core/common/notifier.hpp50-200 include/openthread/instance.h214-282
ot::ThreadNetif manages Thread network interface lifecycle and address management.
Key Methods:
void Up(void) - Bring up the Thread interface src/core/thread/thread_netif.cpp46-75
ot::Mac::Mac via SetEnabled(true)ot::MeshForwarder via Start()ot::Mle::Mle via Enable()ot::Tmf::Agent, ot::Dns::ServiceDiscovery::Server, ot::Dns::Clientvoid Down(void) - Take down the Thread interface src/core/thread/thread_netif.cpp78-106
Disable()State Variable:
bool mIsUp - Tracks whether interface is up src/core/thread/thread_netif.hpp65Sources: src/core/thread/thread_netif.cpp40-106 src/core/thread/thread_netif.hpp40-70
OpenThread provides three primary interfaces for applications:
Application Entry Points and Data Flow
The Public C API provides programmatic access to OpenThread functionality.
Thread Control Functions include/openthread/thread.h:
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled) - Enable/disable Thread stack include/openthread/thread.h216-226uint32_t otThreadGetChildTimeout(otInstance *aInstance) - Get child timeout include/openthread/thread.h237otError otThreadSetLinkMode(otInstance *aInstance, otLinkModeConfig aConfig) - Set device mode include/openthread/thread.h253otDeviceRole otThreadGetDeviceRole(otInstance *aInstance) - Get current role include/openthread/thread.h233Implementation Pattern: All C API functions follow the pattern:
// Public C API (include/openthread/thread.h)
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled);
// Implementation (src/core/api/thread_api.cpp:42-47)
otError otThreadSetEnabled(otInstance *aInstance, bool aEnabled) {
return AsCoreType(aInstance).Get<Mle::Mle>().SetEnabled(aEnabled);
}
API Categories:
thread_api.cpp - Thread network operations src/core/api/thread_api.cpp42-200instance_api.cpp - Instance management src/core/api/instance_api.cppip6_api.cpp - IPv6 operations src/core/api/ip6_api.cppcommissioner_api.cpp - Commissioner operations src/core/api/commissioner_api.cppSources: include/openthread/thread.h1-250 src/core/api/thread_api.cpp1-200 include/openthread/instance.h1-180
The CLI (ot::Cli::Interpreter) provides interactive command-line control.
Command Processing Flow:
void ProcessLine(char *aLine) - Entry point for command string src/cli/cli.cpp295-371Utils::CmdLineParser::ParseCmd(aLine, args, kMaxArgs) - Parse into arguments src/cli/cli.cpp311ProcessCommand(Arg aArgs[]) - Dispatch to command handler src/cli/cli.cpp210-365template <CommandId kCommandId> Error Process(Arg aArgs[]) - Execute specific command src/cli/cli.cpp194-261Example Command Implementations:
Process<Cmd("channel")>(Arg aArgs[]) - Get/set radio channel src/cli/cli.cppProcess<Cmd("thread")>(Arg aArgs[]) - Thread start/stop src/cli/cli.cppProcess<Cmd("state")>(Arg aArgs[]) - Get device role state src/cli/cli.cppModular Sub-Commands:
ot::Cli::Dataset - dataset command src/cli/cli_dataset.cppot::Cli::NetworkData - netdata command src/cli/cli_network_data.cppot::Cli::Br - br (Border Router) command src/cli/cli_br.cppot::Cli::Commissioner - commissioner command src/cli/cli_commissioner.cppUser Command Extension:
otError SetUserCommands(const otCliCommand *, uint8_t, void *) - Register custom commands src/cli/cli.cpp395-413Sources: src/cli/cli.cpp76-413 src/cli/cli.hpp107-200 src/cli/README.md1-150
The NCP interface implements the Spinel protocol for host-RCP communication.
Spinel Protocol Basics:
[Header(2 bytes)][Command(1-3 bytes)][Property ID(1-3 bytes)][Payload]SPINEL_CMD_PROP_VALUE_GET, SPINEL_CMD_PROP_VALUE_SET, SPINEL_CMD_PROP_VALUE_INSERT, SPINEL_CMD_PROP_VALUE_REMOVESPINEL_PROP_NET_IF_UP, SPINEL_PROP_NET_STATE, SPINEL_PROP_MAC_15_4_PANIDNCP Base Class (ot::Ncp::NcpBase) src/ncp/ncp_base.cpp:
Error HandleCommand(uint8_t aHeader) - Dispatch Spinel commands src/ncp/ncp_base.cpp400-500Error HandlePropertyGet(uint8_t aHeader, spinel_prop_key_t aKey) - Handle GET request src/ncp/ncp_base.cpp600-700Error HandlePropertySet(uint8_t aHeader, spinel_prop_key_t aKey, const uint8_t *, uint16_t) - Handle SET request src/ncp/ncp_base.cpp800-900Property Handler Example:
// Spinel property: SPINEL_PROP_NET_IF_UP
// Maps to: otIp6SetEnabled(GetInstance(), enabled)
Transport Layer:
ot::Spinel::SpinelEncoder - Encode Spinel frames src/lib/spinel/spinel_encoder.cppot::Spinel::SpinelDecoder - Decode Spinel frames src/lib/spinel/spinel_decoder.cppotPlatUartSend(), otPlatUartReceived() for UART transportSee Network Co-Processor (NCP) Architecture for detailed information.
Sources: src/ncp/ncp_base.cpp1-500 src/ncp/ncp_base.hpp1-200 src/lib/spinel/spinel.h1-200
Sources: src/cli/cli.cpp1-200 include/openthread/instance.h1-180 src/core/api/thread_api.cpp1-100
OpenThread supports CMake, GN, and Automake build systems with extensive compile-time configuration.
CMake (primary) - CMakeLists.txt:
ot_option(OT_BORDER_ROUTER "enable Border Router" OFF) CMakeLists.txt50-150cmake -DOT_BORDER_ROUTER=ONlibopenthread-ftd.a, libopenthread-mtd.a, ot-cli-ftd, etc.GN (Generate Ninja) - BUILD.gn etc/gn/openthread.gni:
openthread_config_border_router_enable = false etc/gn/openthread.gni20-100gn args out --args='openthread_config_border_router_enable=true'Automake - Makefile.am:
--enable-border-router, --enable-ftd, --enable-mtdConfiguration is applied through a hierarchy:
OPENTHREAD_FTD=1, OPENTHREAD_MTD=1, OPENTHREAD_RADIO=1OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE=1OPENTHREAD_PROJECT_CORE_CONFIG_FILE="project-config.h" src/core/BUILD.gn297-299Configuration Macro Examples src/core/BUILD.gn33-242:
OPENTHREAD_CONFIG_THREAD_VERSION - Set Thread version (1.1, 1.2, 1.3, 1.4)OPENTHREAD_CONFIG_MLE_MAX_CHILDREN - Maximum children per router (default varies)OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE - Enable Border Router featuresOPENTHREAD_CONFIG_LOG_OUTPUT - Log output destination (none, debug_uart, app)| Target | Description | Build Flag |
|---|---|---|
libopenthread-ftd | FTD core library | OPENTHREAD_FTD=1 |
libopenthread-mtd | MTD core library | OPENTHREAD_MTD=1 |
libopenthread-radio | RCP radio library | OPENTHREAD_RADIO=1 |
ot-cli-ftd | CLI with FTD stack | OPENTHREAD_FTD=1 + CLI |
ot-cli-mtd | CLI with MTD stack | OPENTHREAD_MTD=1 + CLI |
ot-rcp | Radio Co-Processor | OPENTHREAD_RADIO=1 + Spinel |
ot-ncp-ftd | NCP with FTD stack | OPENTHREAD_FTD=1 + Spinel |
Sources: src/core/BUILD.gn1-300 src/core/CMakeLists.txt1-280 etc/gn/openthread.gni1-150
A typical Thread device lifecycle managed by ot::Mle::Mle:
Thread Device State Machine
Key Role Transition Functions:
void SetRole(DeviceRole aRole) - Core role change handler src/core/thread/mle.cpp297-358void SetStateDetached(void) - Transition to detached state src/core/thread/mle.cpp579-606void SetStateChild(uint16_t aRloc16) - Transition to child state src/core/thread/mle.cpp608-650void SetStateRouter(uint16_t aRloc16) - Transition to router state (FTD) src/core/thread/mle_router.cppvoid SetStateLeader(uint16_t aRloc16) - Transition to leader state (FTD) src/core/thread/mle_router.cppRole Transition Triggers:
Error Start(StartMode aMode) - Start MLE, begin attachment src/core/thread/mle.cpp194-222Error BecomeChild(void) - Initiate attach as child src/core/thread/mle.cpp551-562Error BecomeDetached(void) - Force detach from network src/core/thread/mle.cpp519-549Error BecomeRouter(ThreadStatusTlv::Status aStatus) - Upgrade to router (FTD) src/core/thread/mle_router.cppError BecomeLeader(void) - Upgrade to leader (FTD) src/core/thread/mle_router.cppSources: src/core/thread/mle.cpp194-650 src/core/thread/mle.hpp244-299 include/openthread/thread.h76-85
OpenThread includes comprehensive testing infrastructure across multiple frameworks.
Location: tests/unit/ directory
Test Structure:
./tests/unit/ot-test-core or ninja testExample Tests:
test_child.cpp - Tests ot::Child class tests/unit/test_child.cpp1-300test_child_table.cpp - Tests ot::ChildTable class tests/unit/test_child_table.cpp1-400test_lowpan.cpp - Tests 6LoWPAN compression tests/unit/test_lowpan.cppLocation: tests/scripts/thread-cert/ directory
Framework: Python-based test scripts using pexpect for CLI automation
Key Classes:
Node - Represents a Thread device under test tests/scripts/thread-cert/node.py59-500OtbrDocker - Docker-based Border Router node tests/scripts/thread-cert/node.py59-267./script/test orchestratorExample Test: tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py
Virtual Time Support:
OPENTHREAD_CONFIG_VIRTUAL_TIME=1 src/core/config/misc.hOTNS Integration:
.github/workflows/otns.ymlGitHub Actions Workflows (.github/workflows/):
build.yml - Multi-compiler, multi-platform buildssimulation-1.2.yml, simulation-1.4.yml - Thread compliance testsposix.yml - POSIX platform testsotbr.yml - Border Router integration testscodeql.yml - Static analysis and security scanningsize-tracking.yml - Binary size regression detectionTest Orchestration:
./script/test script/testlcovSources: tests/scripts/thread-cert/node.py1-500 tests/unit/test_child.cpp1-100 tests/unit/test_child_table.cpp1-100 tests/scripts/thread-cert/border_router/test_publish_meshcop_service.py1-150
| Component | Key Files | Description |
|---|---|---|
| Instance | src/core/instance/instance.hpp src/core/instance/instance.cpp | Service locator and lifecycle |
| MLE | src/core/thread/mle.cpp src/core/thread/mle.hpp | Core protocol implementation |
| Router Table | src/core/thread/router_table.cpp src/core/thread/router_table.hpp | FTD routing (importance: 55.92) |
| Child Table | src/core/thread/child_table.cpp src/core/thread/child_table.hpp | FTD child management |
| Notifier | src/core/common/notifier.cpp src/core/common/notifier.hpp | Event system |
| Thread Netif | src/core/thread/thread_netif.cpp src/core/thread/thread_netif.hpp | Network interface |
| CLI | src/cli/cli.cpp src/cli/cli.hpp | Command-line interface (importance: 393.79) |
| C API | src/core/api/thread_api.cpp include/openthread/thread.h | Public API |
| Build | src/core/BUILD.gn src/core/CMakeLists.txt | Build configuration |
OpenThread is a modular, standards-compliant Thread protocol stack organized around:
ot::Instance) for component accessThe most actively developed subsystems are MLE protocol (importance: 619.97), CLI interface (importance: 393.79), and router management (importance: 55.92), reflecting the core functionality and user interaction points.
For detailed information on specific subsystems, continue to the linked sections above.
Sources: src/core/thread/mle.cpp1-160 src/core/instance/instance.hpp1-100 src/cli/cli.cpp1-200 src/core/BUILD.gn1-160
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.