IEEE 1905.1 is a standard developed by the Institute of Electrical and Electronics Engineers (IEEE) for providing a uniform method for devices to communicate and interoperate within a home network environment. It defines a protocol that enables devices from different manufacturers to seamlessly communicate and share resources, regardless of their underlying technologies.
One of the key components of IEEE 1905 is the Application Layer SAP, which is responsible for managing communication between the higher-level entities (HLEs) and the lower layers of the network stack, and more specifically the IEEE 1905 adaptation layer. In order to identify multiple SAPs between AL and HLE layers, we identify the SAP as the AL_MAC_ADDRESS of the remote entity.
A short, high-level plan:
- Topology map.
- FSM definition and implementation.
- Adaptation Layer Service Access Point for Easymesh High Level Entities.
- LLDP implementation.
- IEEE1905 CMDU parsing and serialization (version 2023)
- Docker integration for stand-alone.
- RDK integration.
- OWRT integration.
- TR.181 data-model integration using RBUS
- Link Metric management and topology inegration.
- Interoperability.
- IEEE1905 CMDU parsing and serialization (version 2024)
- Controller Redundancy.
- Artifact Exchange Service from Controller to Agents.
- Service binary upgrade.
- IEEE1905 Layer security capability Message integrity code.
- IEEE1905 Layer security capability encryption.
This project documents its key architectural decisions using Architecture Decision Records (ADRs). These decisions define the protocol design, topology handling, and integration model with EasyMesh on Linux-based platforms.
- ADR-0001: Use Rust for IEEE 1905 Protocol Core
- ADR-0002: Use Tokio and Asynchronous Programming
- ADR-0003: Observer Pattern for CMDU Reception and Processing
- ADR-0004: Proxy Pattern for CMDU Transmission
- ADR-0005: Facade Pattern for AL-SAP Integration
- ADR-0006: Use
nomfor TLV/CMDU Parsing and Serialization
- ADR-0007: Virtual Interface and Linux Bridge for CMDU Transmission
- ADR-0008: IEEE 1905 Does Not Own Per-Media Forwarding State
- ADR-0009: IEEE 1905 Topology Is Informational, Not Authoritative
- ADR-0019: Use Link-Local IPv6 on Control Interface to Reuse IP-Based Services
- ADR-0020: Isolate IEEE1905 Virtual Ethernet in a Dedicated Network Namespace
- ADR-0010: How IEEE 1905 Topology Is Consumed by EasyMesh
- ADR-0011: Eventual Consistency Model for Topology
- ADR-0012: Topology Map as a Singleton
- ADR-0013: Controlled Mutation and Locking Strategy
- ADR-0014: Topology Aging and Garbage Collection
- ADR-0015: Snapshot vs Live-View Semantics
- ADR-0016: Observability and Debugging of Convergence
- ADR-0017: Failure Isolation Between IEEE 1905 and EasyMesh
- ADR-0018: Backpressure and Rate-Limiting of Topology Events
| Functional Requirement | Description |
|---|---|
| Activation process | SAP will provide the API's necessary to activate the transport service from the EasyMesh Agent and Controller through the AL_SAP |
| Registration request | SAP will provide the API necessary to activate and deactivate the transport service through the SAP and to identify the role ot the applicatoin that requests access to IEEE1905 layer |
| Registration response | SAP will provide the API necessary to provide the response to a registration request to the IEEE1905 service including the result of the registration request and any information necessary to make use of the transport service |
| Payload transport | EasyMesh agent, EasyMesh Controller and any other High Level Entity will use binary payload through SAP as transport using SDUs defined as part ot the AL_SAP definition and AL_SAP API (primitives) for data transmission and reception |
| Content Agnostic | AL_SAP will be agnostic in regards of the content of the SDU's, they will treated as as binary payload through the AL_SAP and at the IEEE1905 layer they will be treated as CMDU's (framing functionality) or as a vector of TLV's (parsing functionality) |
| CMDU responsability | IEEE1905 SAP will provide payload transport service of EasyMesh CMDU's in addition to the CMDU's used internally by the IEEE1905 to maintain the topology map |
| CMDU validation | IEEE1905 will be responsible for the completeness of CMDU's sent and received |
| SDU/CMDU fragmentation | IEEE1905 SAP will provide fragmentation and reassembly service for SDU's and CMDU's |
| CMDU encryption | IEEE1905 will provide encryption service and message integrity validation for CMDU's |
In current implementations of EasyMesh, the IEEE1905 stack is deeply integrated into both the EasyMesh agents and controller. This tight coupling between the two standards means that the functionalities of IEEE1905, which handles the transport of network information, and EasyMesh, which manages mesh network control, are often intertwined within the same system components.
However, in our implementation, we found it necessary to clearly separate the EasyMesh functionalities from the IEEE1905 stack. This separation allows for more modular design and flexibility, enabling independent development, testing, and maintenance of each protocol. By decoupling EasyMesh from IEEE1905, we ensure that each layer can evolve independently while maintaining interoperability, which is particularly important in complex mesh networking environments. This also allows for clearer distinction between mesh network management (EasyMesh) and control transport services and topology management (IEEE1905), improving the overall system architecture. The IEEE1905 SAP will be used as C++ library compiled as part of application binaries that will be required to use IEEE1905 transport service, and the implementation will follow OOP principles of reusability and modularity.
IEEE1905 Adaptation Layer MAC Service Access Point will provide IEEE1905 transport service to applications in the RDK-B stack through a set of service primitives. These primitives have been creted with two goals in mind, registration of consumers that will make use of the IEEE1905 stack, using service-registration-request and service-registration-response APIs and exchange of service data units via service-data-request and service-data-indication, through the AL MAC service access point, refered as SAP in the rest of the document.
The IEEE1905_AL_SAP will provide the following API abstraction to use the service:
- Registration APIs: it will be used to register the application (EMagent or EMcontroller for instance) to access the SAP, initializing parameters that the application could require from the IEEE1905 service.
- AlServiceRegistrationRequest(): This primitive is used to establish the connection to the IEEE1905 service. The application will register to use one of the services currently supported by the IEEE1905 service:
- EasyMeshClient: it will use standard IEEE1905 framing, assuming the application is the Controller/Registree.
- EasyMeshController: it will use standard IEEE1905 framing, assuming the application is the Controller/Registrar.
- AlServiceRegistrationResponse(): This primitive is used by the IEEE1905 service to inform about the result of the registration and to provide the local AlMacAddress in case the application cannot select one.
- AlServiceTopologyNotification(): This primitive is used by the IEEE1905 service to keep the cache of the al_mac addresses availabe in the topology map so if the HLE tries to send an SDU to a node which al_mac is not in the cache, IEEE1905 service will generate a primitive error, in a shape of a C++ exception according to C++ standard library.
- AlServiceRegistrationRequest(): This primitive is used to establish the connection to the IEEE1905 service. The application will register to use one of the services currently supported by the IEEE1905 service:
sequenceDiagram
activate Agent
participant Agent as "EasyMeshComponent"
participant IEEE1905_AL_AGENT as "IEEE1905_AL_SAP"
Agent ->> IEEE1905_AL_AGENT: AlServiceAccessPointRegistrationRequest(EasyMeshServiceType, Enable/disable)
IEEE1905_AL_AGENT -->> Agent: AlServiceAccessPointRegistrationResponse(RegistrationResult,AlMacAddressLocal)
opt
Note right of Agent: In case of error
IEEE1905_AL_AGENT -->> Agent: PrimitiveError::ErrorType
end
deactivate Agent
-
Control plane transport service APIs.
- AlServiceDataRequest(): This API is used to request the transmission of a SDU (service data unit) to the IEEE1905 service through the SAP, and the SDU will contain, the IEEE1905 CMDU and the AlMacAddress of the source and destination. In case of SDU processing errors during SAP transfer for transmission, IEEE1905 service will generate a primitive error, in a shape of a C++ exception according to C++ standard library.
- AlServiceDataIndication(): This API is used by applications to listen and receive a SDUs (service data unit) from the IEEE1905 service through the SAP, as before for the request,the SDU will contain the IEEE1905 CMDU created by the remote application, plus AlMacAddress source and destination. In case of SDU processing errors during SAP transfer for reception, IEEE1905 service will generate a primitive error, in a shape of a C++ exception according to C++ standard library.
sequenceDiagram
activate Agent
participant Agent as "EasyMeshComponent (AL_MAC_X)"
participant IEEE1905_AL_AGENT as "IEEE1905.1_SAP_OUTBOUND"
participant IEEE1905_AL_CONTROLLER as "IEEE1905.1_SAP_INBOUND"
participant Controller as "EasyMeshComponent (AL_MAC_Y)"
Agent ->> IEEE1905_AL_AGENT: ServiceAccessPoint.Request[SDU (AL_MAC_SOURCE,AL_MAC_DESTINATION, CMDU)]
opt
Note right of Agent: In case of Error
IEEE1905_AL_AGENT -->> Agent: PrimitiveError::ErrorType
end
IEEE1905_AL_AGENT ->> IEEE1905_AL_CONTROLLER: Transmit(CMDU)
IEEE1905_AL_CONTROLLER ->> Controller: ServiceAccessPoint.Indication[SDU (AL_MAC_SOURCE,AL_MAC_DESTINATION, CMDU)]
opt
Note left of Controller: In case of Error
IEEE1905_AL_CONTROLLER -->> Controller: PrimitiveError::ErrorType
end
deactivate Agent
| Input Event | Precondition | New Local | New Remote | Output event |
|---|---|---|---|---|
| DiscoveryReceived (node_new) | — | Idle | Idle | SendTopologyQuery(al_mac) |
| DiscoveryReceived (Idle) | Local == Idle | (unchanged) | (unchanged) | SendTopologyQuery(al_mac) |
| DiscoveryReceived (conv) | Local == ConvergedLocal | (unchanged) | (unchanged) | None |
| NotificationReceived (conv) | Local == ConvergedLocal | Idle | (unchanged) | SendTopologyQuery(al_mac) |
| NotificationReceived | !Local == ConvergedLocal | (unchanged) | (unchanged) | None |
| QueryReceived (node_new) | — | Idle | ConvergingRemote(now) | SendTopologyResponse(al_mac) |
| QueryReceived (node_present) | !Remote == ConvergedLocal | (unchanged) | ConvergingRemote(now)* | SendTopologyResponse(al_mac) |
| QuerySent | !Local == ConvergedLocal | ConvergingLocal(now) | (unchanged) | None |
| ResponseReceived | Local == ConvergingLocal | ConvergedLocal | (unchanged) | Maybe SendTopologyNotification(multic) |
| ResponseSent | Remote= ConvergingRemote | (unchanged) | ConvergedRemote | None |
* Only if remote wasn’t already ConvergedRemote.
| Input Event | Precondition | New State | Output Event |
|---|---|---|---|
| IEEE1905-UP | Local == INIT | LEARNING | None |
| IEEE1905-DOWN | Local == LEARNING | INIT | None |
| AP_AUTOCONFIG_SEARCH | Local == LEARNING && AL_MAC_PRESENT | FORWARDING | StartForwarding |
| TOPOLOGY_DISCOVERY | Local == LEARNING && AL_MAC_PRESENT | FORWARDING | StartForwarding |
| AL_MAC_REMOVED | Local == FORWARDING | LEARNING | StopForwarding |
| AL_MAC_PRESENT | Local == FORWARDING | (unchanged) | None |
| Input Event | Precondition | New State | Output Event |
|---|---|---|---|
| HLE_REGISTRATION_SUCCESS | State == INIT | Registered | None |
| HLE_REGISTRATION_ERROR | State == INIT | INIT | None |
| SAP_ENABLE | State == Registered | Forwarding | None |
| SAP_DISABLE | State == Forwarding | Registered | None |
| EM_CMDU_INCOMING | State == Forwarding && AL_MAC | (unchanged) | Forward |
| EM_CMDU_INCOMING | State == Forwarding && !AL_MAC | (unchanged) | Discard |
| EM_CMDU_FORWARDING | State == Forwarding && AL_MAC | (unchanged) | Forward |
| EM_CMDU_FORWARDING | State == Forwarding && !AL_MAC | (unchanged) | Discard |
Network topology refers to the arrangement of various elements (IEEE1905 nodes) in a home network and it defines how nodes are connected and how data flows between them. IEEE1905 has been specified to work in multiple topologies but it is specially used in daisy chain topologies as the one in EasyMesh, where typically each device is connected to two other devices, forming a linear sequence, much like the links in a chain.
Based on the capability of devices to process IEEE1905 CMDU packets we can distinguish two different kind of nodes:
- IEEE1905 devices: This kind of devices understand CMDU packets and keep a copy of the topology map that they can exchange with other IEEE1905 devices
- Endpoint nodes: The first and last devices in the chain have only one connection each, to their immediate neighbor and they don't require to have bridging capabilities.
- Intermediate nodes: Devices with more than one link connected to a IEEE1905 device with bridging capabilities, to relay CMDU packets through interfaces.
- NON-IEEE1905 devices: This kind of devices don't understand and process IEEE1905 packets In addition to the previous roles in IEEE1905 will build the topology map, adding information related to NON IEEE1905 devices, these devices will not participate in the exchange of CMDU packets, but based on their bridging capabilities they will be able to rely CMDU packets through their bridges.
The topology construction process in IEEE1905 consists of the following steps:
-
LLDP discovery: Before CMDU packet exchange, IEEE1905 will trigger LLDP protocol to discover neighbors with bridging capabilities, and include it as part of the topology graph. LLDPDUs use a link-local multicast address being consumed by the platform bridge, such as a Linux bridge or OVS bridge, so in the RDK-B use case they will not reach the IEEE1905 service.
-
Topology Discovery Advertisement: Each IEEE1905 device periodically broadcasts 1905 Topology Discovery Messages on all its available network interfaces (Wi-Fi, Ethernet, MoCA, PLC). These messages include the AL_MAC address as well as the device's Media Access Control (MAC) address and details about the specific interface over which the message is sent.
-
Neighbor Discovery: Devices that receive the topology discovery messages recognize the sender as a neighboring IEEE1905 device. The receiving device stores this information, including the AL_MAC address of the sender and the MAC address of the interface on which the message was sent, in its local topology map.
-
Topology Query and Report: To get a more detailed view of the network, a device will send a Topology Query Message to any of its neighboring devices. The queried device responds with a Topology Response Message, which contains more comprehensive information about the network topology, including all the devices it knows and their interconnections.
-
Topology Map Update: As devices exchange topology information, each IEEE1905 device updates its local topology map. This map contains information about all known devices in the network, the technologies they are using, the interfaces through which they are connected, and the quality of the paths used to reach them. As result of updates in the topology map, IEEE1905 devices will broadcast Topology Notification to all their neighbors, and their neighbors will retrieve the information using Topology Query/Report messages from teh originator of the modification.
-
Periodic Refresh: The topology discovery process is continuous, with devices periodically re-broadcasting their presence and updating their topology databases as they receive new information. This ensures that the topology information remains current, even as devices join, leave, or move within the network.
-
Split Brain scenario protection. The topology graph shall contain no more than one registrar per network based on a tie-breaking policy defined temporary using AL_MAC address last 4 bytes.
-
1905 Layer Security Capability. [Future improvement; not currently implemented.] According to EasyMesh specification chapters 13.1, 17.2.67, 17.2.68, 17.2.69, we will provide encryption and message integrity service for the TLV's.
The protection against split brain scenraio will work as follow:
- When the AL_SAP receives a registration request from the HLE to assume the controller role, the IEEE1905 entity shall verify whether a registrar is already present in the network.
- If no registrar is detected, the HLE shall assume the registrar role. In this case, AL_SAP shall:
2.1 Accept incoming ServiceRequest SDUs containing AP_Autoconfig_Search messages.
2.2 Transmit outgoing SDUs containing AP_Autoconfig_Response messages.
2.3 A topology Notification will be generated and as part of the Toplogy convergence flow. - If a registrar is detected, the AL_SAP shall perform the tie-breaking procedure:
3.1 If the local entity wins, AL_SAP shall accept incoming ServiceRequest SDUs containing AP_Autoconfig_Search messages and transmit outgoing CMDUs containing AP_Autoconfig_Response messages.
3.2 If the remote entity wins, AL_SAP shall filter all AP_Autoconfig SDUs.
3.3 In case the topology map changes we will proceed as in point 2.3 to propagate the new role. - If the current registrar becomes unavailable, as determined through topology convergence flow, a new registrar shall be selected as part of the network convergence process, following steps 1 through 3.
- If a new registrar is detected through topology-discovery-triggered convergence, registrar selection shall again be performed as part of the network convergence process, following steps 1 through 3.
- When the AL_SAP receives a registration request from the HLE to assume the agent role, the IEEE1905 will propagate it as part of the topology convergence flow.
Remark: SDU filtering is currently inactive; the implementation only tracks which entity is acting as the registrar and which entities are acting as enrollees.
The forwarding table will be used to select the MAC address for source and destination used in the ethernet frames, based on the AL MAC source address and destination, to transport CMDU packets.
Below an example for 2 devices directly connected to our local device.
graph TD;
Local_AL_MAC_ADDRESS_XX:XX:XX:XX <--> Local_virtual_interface_XX:XX:XX:XX;
Local_virtual_interface_XX:XX:XX:XX <--> bridge_interface_AA:AA:AA:AA_VLAN100;
Local_virtual_interface_XX:XX:XX:XX <--> bridge_interface_AA:AA:BB:BB_VLAN101;
bridge_interface_AA:AA:AA:AA_VLAN100 <--> 802.1Q_local_tag_100;
802.1Q_local_tag_100 <--> local_physical_interface_AA:AA:AA:AA;
local_physical_interface_AA:AA:AA:AA --- |COST_DOWN| link_1;
link_1 --- |COST_UP| remote_physical_interface_AA:BB:BB:BB;
remote_physical_interface_AA:BB:BB:BB <--> 802.1Q_remote_tag_100;
802.1Q_remote_tag_100 <--> BRIDGE_Chassis_ID_XX:XX:YY:YY;
BRIDGE_Chassis_ID_XX:XX:YY:YY <--> remote_logical_interface_AA:BB:BB:BB_VLAN100;
remote_logical_interface_AA:BB:BB:BB_VLAN100 <--> Neighbour_AL_MAC_ADDRESS_YY:YY:XX:XX
bridge_interface_AA:AA:BB:BB_VLAN101 <--> 802.1Q_local_tag_101;
802.1Q_local_tag_101 <--> local_physical_interface_AA:AA:BB:BB;
local_physical_interface_AA:AA:BB:BB --- |COST_DOWN| link_2;
link_2 --- |COST_UP| remote_physical_interface_AA:BB:BB:CC;
remote_physical_interface_AA:BB:BB:CC <--> 802.1Q_remote_tag_101;
802.1Q_remote_tag_101 <--> BRIDGE_Chassis_ID_XX:XX:XX:XX;
BRIDGE_Chassis_ID_XX:XX:XX:XX <--> remote_logical_interface_MAC_ADDRESS_AA:BB:BB:CC_VLAN101;
remote_logical_interface_MAC_ADDRESS_AA:BB:BB:CC_VLAN101 <--> Neighbour_AL_MAC_ADDRESS_XX:XX:YY:YY;
The topology map provides all the information collected through Topology CMDUs exchange
|─TOPOLOGY_MAP:
└──AL_MAC_ADDRESS: AA:AA:AA:A0
|
└── INTERFACE_MAC_ADDRESS: (BB:AA:AA:A0)
|── MEDIA_TYPE: (0x0001)
|── BRIDGE_FLAG: TRUE
|── BRIDGE_TUPLE: 0
└── VLAN: 'UNTAG'
|
|── IEEE1905NeighborDeviceList
| |── IEEE1905NeighborDevice
| | |── AL_MAC_ADDRESS: (AA:AA:AA:A1)
| | |── INTERFACE_MAC_ADDRESS: (BB:AA:AA:A1)
| | |── STATE: TOPOLOGY_STATE
| | |── LAST_SEEN: 10
| | |── MESSAGE_ID_LAST_PACKET: 12
| | |── LLDP-INFO
| | |── PATH_METRICS
| | | |── RADIO
| | | └── PATH_PERFORMANCE
| | └── LocalInterfaceList
| | |── INTERFACE_MAC_ADDRESS: BB:AA:AA:A01
| | | |── MEDIA_TYPE: (0x0001)
| | | |── BRIDGE_FLAG: TRUE
| | | |── BRIDGE_TUPLE: 0
| | | └── NonIEEE1905NeighborList
| | | |── (AA:BB:CC:A0)]
| | | |── (AA:BB:CC:A1)]
| | | └── (AA:BB:CC:A2)]
| | └──INTERFACE_MAC_ADDRESS: BB:AA:AE:A01
| | |── MEDIA_TYPE: (0x0001)
| | |── BRIDGE_FLAG: TRUE
| | |── BRIDGE_TUPLE: 0
| | └── NonIEEE1905NeighborList
| | |── (AA:BF:CC:A0)]
| | |── (AA:BF:CC:A1)]
| | └── (AA:BF:CC:A2)]
| |
| └── IEEE1905NeighborDevice
|
└── NonIEEE1905NeighborList
|── (AA:BB:CC:A0)]
|── (AA:BB:CC:A1)]
└── (AA:BB:CC:A2)]
-
Ensure that you have
systemdinstalled on your system. -
Ensure you include in your system rustc and cargo version 1.91.1 (MSRV).
-
Ensure git is installed in your system.
-
Ensure jq is installed in your system.
-
Ensure you can run the script with sudo privileges.
-
Ensure the script is executable.
Logs produced by the application will be stored into /var/log/rdkb-ieee1905/ and the configuration will be included as part of systemd unit configuration.
Log rotation will be possible as part of the installation script by changing /etc/logrotate.d/rdkb-ieee1905:
/var/log/rdkb-ieee1905/*.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 rdkbuser rdkbgroup
postrotate
systemctl restart rdkb-ieee1905.service > /dev/null
endscript
}All the logic for the installation and activation has been included into the build_and_install script:
git clone https://github.com/rdkcentral/rdkb-ieee1905.git
cd rdkb-ieee1905/utils
./build_and_install
You can use this simple systemd unit to launch the ieee1905 service in the
background. Set -i/--interface to the forwarding interface used by the platform;
IEEE1905 derives the related bridge from this interface during local interface discovery:
cat /lib/systemd/system/ieee1905.service
[Unit]
Description=IEEE1905 topology service
After=network.target
[Service]
Type=notify
ExecStart=/usr/bin/ieee1905 -i eth0
[Install]
WantedBy=multi-user.targetThe service uses sd-notify when it is launched by systemd. After the AL-SAP
socket is ready to serve registrations and data indications, IEEE1905 sends a
READY=1 notification. When the process receives SIGTERM or SIGINT, it
sends STOPPING=1 before exiting. If the AL-SAP socket closes internally, the
service attempts to restart that socket path without reporting the whole process
as stopping.
EasyMesh services can then be launched as dependent systemd units. The EasyMesh
unit should start after ieee1905.service, request it as a dependency, and be
stopped/restarted with it when the IEEE1905 service lifecycle is managed:
[Unit]
Description=EasyMesh Monitor
Wants=ieee1905.service
After=ieee1905.service
PartOf=ieee1905.service
[Service]
Type=simple
ExecStart=/usr/local/bin/easymesh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetOnce installed into the systemd service path (/lib/systemd/system), you can
enable the service and manage it like so:
systemctl daemon-reload
systemctl enable ieee1905.service
systemctl start ieee1905
systemctl stop ieee1905Output from the ieee1905 process can be viewed via journalctl:
journalctl -u ieee1905.service
2025 Mar 28 01:09:50 armefi64-rdk-broadband systemd[1]: Started IEEE1905 topology service.
2025 Mar 28 01:09:51 armefi64-rdk-broadband ieee1905[1242]: Tracing initialized!By default, the service runs with the topology CLI disabled, info log level, listening on eth0 interface, and Unix sockets named /tmp/al_control_socket and /tmp/al_data_socket.
By default, topology CLI is disabled and requires topology_ui feature flag.
When topology CLI is enabled. Log files are saved to a file and will not appear on standard output.
/usr/bin/ieee1905 -tBy default, logs will be printed to stdout. Use following command to disable stdout logging:
/usr/bin/ieee1905 --no-stdout-appenderBy default, artifact exchange is disabled. Enable it with
--artifact-exchange <server|client>.
Run the controller-side HTTP artifact exchange service with:
/usr/bin/ieee1905 --artifact-exchange serverRun an agent-side artifact exchange client with:
/usr/bin/ieee1905 --artifact-exchange clientUse server on the controller node that exposes artifacts for agents and
receives uploaded agent artifacts. Use client on agent nodes that pull
controller-to-agent artifacts such as binaries and push agent-to-controller
artifacts such as logs.
For systemd deployments, add the same argument to ExecStart, for example:
ExecStart=/usr/bin/ieee1905 --artifact-exchange serverBy default, file logger is disabled. To enable file logging use following arguments:
/usr/bin/ieee1905 --file-appender ./logsThis will write logs to the folder ./logs.
File logs will rotate on a daily basis and also have files count and file size limits.
Those limits can be changes with the following arguments:
/usr/bin/ieee1905 \
--file-appender ./logs \
--file-appender-files-count 3 \
--file-appender-max-file-size 10Possible log levels are:
tracing- should be used only for deep debugging, enables all logs and dumps all packetsdebug- provides a general debugging informationinfo- entry points and important eventswarn- unexpected states that don't affect the logicerror- errors can unexpected statesoff- disables all logging
To enable error logs for all app modules except crates:
/usr/bin/ieee1905 -f ieee1905=errorTo enable trace logs for every module and crates:
/usr/bin/ieee1905 -f traceLogging can be limited to certain modules for example to set trace level for topology manager and suppress all other logs:
/usr/bin/ieee1905 -f ieee1905::topolgy_manager=traceIf needed certain module can be filtered out completely:
/usr/bin/ieee1905 -f ieee1905=trace,ieee1905::ethernet_subject_reception=offWith above all ieee1905 modules will log with trace level and ethernet_subject_reception will not be visible in logs.
If needed to fully disable the logging:
/usr/bin/ieee1905 -f offOR
RUST_LOG=off /usr/bin/ieee1905ieee1905::rbus
ieee1905::al_sap
ieee1905::cmdu_codec
ieee1905::cmdu_handler
ieee1905::cmdu_message_id_generator
ieee1905::cmdu_observer
ieee1905::cmdu_proxy
ieee1905::cmdu_reassembler
ieee1905::device_edge_manager
ieee1905::ethernet_subject_reception
ieee1905::ethernet_subcjet_transmission
ieee1905::interface_manager
ieee1905::lldpdu_codec
ieee1905::lldpdu_observer
ieee1905::lldpdu_proxy
ieee1905::registration_codec
ieee1905::sdu_codec
ieee1905::tlv_cmdu_codec
ieee1905::tlv_lldpdu_codec
ieee1905::topology_manager
In order to analyze service with tokio-console use:
/usr/bin/ieee1905 -cIn order to disable LLDP receiver workers use:
/usr/bin/ieee1905 --no-lldp-receiversBy default, topology is built by observing the EasyMesh Topology Query and Topology Response exchange instead.
When active mode is enabled, the service drives topology convergence itself: a received Topology Discovery triggers a Topology Query, and a topology change is announced with a Topology Notification.
/usr/bin/ieee1905 --active-modeChange unix sockets to ctrl.sock and data.sock
/usr/bin/ieee1905 --sap-control-path /tmp/ctrl.sock --sap-data-path /tmp/data.sockChange interface to eth1. IEEE1905 uses this interface to derive the related bridge and filter the local interface list accordingly.
/usr/bin/ieee1905 -i eth1/usr/bin/ieee1905 -i eth1 --file-appenderIEEE1905 service can be build with few compile time features:
rbus- enable RBUS providerenable_tokio_console- enable tokio-console
By default, RBUS provider is not included in the binary. In order to enable it one has to build with following command:
cargo build --package ieee1905 --release --features=rbusRBUS-enabled builds require a GNU toolchain. It will be selected by default when building on the target machine. In case it was not selected by default or the binary is cross-compiled, it should be provided manually:
cargo build --package ieee1905 --release --features=rbus --target aarch64-unknown-linux-gnuBy default, tokio-console is not included in the binary. In order to enable it one has to build with following command:
cargo build --package ieee1905 --release --features=enable_tokio_consoleAll features can be enabled at once without listing all them:
cargo build --package ieee1905 --release --all-featuresWill enable all supported features.
For the best experience, use the meta-lts-mixins layer to upgrade the version of Rust from that included in OpenEmbedded.
git clone --branch=kirkstone/rust https://git.yoctoproject.org/meta-lts-mixins
bitbake-layers add-layer meta-lts-mixinsYou can use cargo-bitbake to generate
a BitBake recipe for this package.
As BitBake/Yocto builds do not have network access during the build cycle,
it is a requirement that the entire dependency graph for the package is added
to SRC_URI (including optional packages that are not used at runtime).
cargo-bitbake can generate the SRC_URI additions for you.
On Yocto 5 (scarthgap and later), you will also need to supply
checksums for each package in the dependency graph.
You can use Yocto's cargo-update-recipe-crates
to assist in updating the dependency graph.
Note: Cargo.lock must be up to date (run cargo update) with Cargo.toml,
and with the recipe SRC_URI list, or Bitbake will not proceed with
building the package.
# Ensure Rust and Cargo are available
inherit cargo
DESCRIPTION = "IEEE 1905 Rust Program"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=b538373fe584898492d2ad3a91014d58"
# Source repository
SRC_URI = "git://git@github.com/rdkcentral/rdkb-ieee1905.git;branch=main;protocol=ssh"
SRCREV = "589eccc05be0201592d169597c254375ef8d516c"
# Source directory
S = "${WORKDIR}/git"
# IMPORTANT!
# RUST_PANIC_STRATEGY="abort" must be in the
# machine or bitbake local.conf for this
# package to build successfully
# Builds under bitbake do not have network
# access, so all dependent rust crates
# must be added as SRC_URI
# You can use cargo-bitbake to create this list
SRC_URI += " \
crate://crates.io/addr2line/0.24.2 \
crate://crates.io/adler2/2.0.0 \
...
\"
There are two considerations when cross-compiling for a Yocto environment.
-
Architecture
We are using the 64-bit Arm (arm64/aarch64) SystemReadyArm compliance program environment for verification.
Most people use x86/Intel architecture devices for development. If you have a native Arm64 development environment, you will have a smoother experience, but the considerations below still apply.
-
System library versions
Yocto releases generally use older C Library (GLIBC) versions than used in current desktop distributions.
While rust has excellent cross compilation support, the Rust compiler will target the same GLIBC version as on the host.
The instructions below assume you are using rustup to manage your Rust environments.
By targetting the MUSL C library, we can avoid mismatches between GLIBC versions.
However, you still need an Arm64 C compiler for linking purposes.
On Ubuntu, you can use the pre-packaged Arm64 compiler:
apt install gcc-aarch64-linux-gnuThen, add a MUSL target with rustup:
rustup target add aarch64-unknown-linux-gnuYou will need to tell cargo to use the arm64 compiler when targetting arm64.
This can be done by adding a target option in $HOME/.cargo/config.toml:
cat "$HOME/.cargo/config.toml"
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-gnu-gcc"Then, you can do a build for the aarch64-unknown-linux-musl target:
cargo build --target=aarch64-unknown-linux-muslThe resulting build will be in target/aarch64-unknown-linux-musl:
$ file target/aarch64-unknown-linux-musl/debug/ieee1905
target/aarch64-unknown-linux-musl/debug/ieee1905: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linkedYou can also compile a release build by adding --release:
$ cargo build --release --target=aarch64-unknown-linux-musl
$ file target/aarch64-unknown-linux-musl/release/ieee1905
target/aarch64-unknown-linux-musl/release/ieee1905: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linkedPlease note that binaries cross-compiled against the MUSL target are generally larger than the "native" GLIBC binaries, do not use them for size comparisons.
To build for targets with different architecture and C libraries to the host (development) system, you can use cargo-zigbuild.
Please check the cargo-zigbuild homepage for installation instructions, as you will also need
the Zig programming language compiler.
Example 1: build a 32-bit ARM binary linked with MUSL (armv7-unknown-linux-musleabihf):
- Install Zig and make sure it is available on your
PATH:
$ zig version- Install
cargo-zigbuild:
$ cargo install --locked cargo-zigbuild- Add the Rust target:
$ rustup target add armv7-unknown-linux-musleabihf- Build the
ieee1905package:
$ cargo zigbuild -p ieee1905 --release --target armv7-unknown-linux-musleabihf- Verify the resulting binary:
$ file target/armv7-unknown-linux-musleabihf/release/ieee1905Example 2: build a 64-bit ARM binary linked with GLIBC (aarch64-unknown-linux-gnu).
On the TARGET, check what glibc version is installed:
root@armefi64-rdk-extender:~# /lib/libc.so.6
GNU C Library (GNU libc) stable release version 2.35.Then, run cargo zigbuild while appending the GLIBC version (in this example, 2.35) to the end of the target tuple:
$ cargo zigbuild --release --target=aarch64-unknown-linux-gnu.2.35
$ file target/aarch64-unknown-linux-gnu/debug/ieee1905
target/aarch64-unknown-linux-gnu/debug/ieee1905: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 2.0.0, with debug_info, not strippedYou can copy the cross-compiled ieee1905 binary to the target system and use it to replace the
version built into the image.
There are available two methods for building and testing the project in docker:
-
The first method for simulation using single dockerconfig file.
This is the primary method for building the docker container for simulation process. It requires rebuild of docker container after every rebuild of Rust sources (cargo build)
docker build -t ieee1905 . docker run -it --name ieee1905_node1 ieee1905Once your docker image is present you can use just docker start and stop
docker start -ai ieee1905_node1 docker stop ieee1905_node1 -
Secondary method via docker compose.
docker compose build --no-cache docker compose up
At this point two docker containers: - ieee1905_node1 - ieee1905_node2
should be connected to the bridge ieee1905_bridge.
To be able to run the tests on two running docker containers: ieee1905_node1 and ieee1905_node2 - first it is needed to attach to both containers:
docker exec -it ieee1905_node1 /bin/shand analogically connect to ieee1905_node2:
docker exec -it ieee1905_node2 /bin/shthen inside these containers run the ieee1905 binary (the option "-t" is to open CLI):
./ieee1905 -tpossibly with parameters and arguments.
From the repository root:
Run all tests in the workspace:
cargo testRun tests for a specific package:
cargo test -p ieee1905
cargo test -p ieee1905-testsRun a specific test target by name filter:
cargo test -p ieee1905 cmdu_reassemblerRun all benches for ieee1905:
cargo bench -p ieee1905Run a specific bench target:
cargo bench -p ieee1905 --bench cmdu_handler_bench
cargo bench -p ieee1905 --bench cmdu_proxy_bench
cargo bench -p ieee1905 --bench cmdu_reassembler_bench
cargo bench -p ieee1905 --bench codec_parse_benchRun a specific benchmark case inside a bench target:
cargo bench -p ieee1905 --bench cmdu_handler_bench -- node_present
cargo bench -p ieee1905 --bench codec_parse_bench -- codec_parse_cmduThis repository includes a GitHub Actions workflow (.github/workflows/rust-rss-usage-check.yml) that runs on pull requests targeting develop and posts/updates a sticky PR comment with memory usage statistics (this requires a non-fork PR; on forks the comment step cannot write and will fail unless skipped).
The report is generated on the Ubuntu runner after ieee1905 has been running for 5 seconds and includes /proc/<pid>/status fields such as VmSize, VmRSS, VmHWM, RssAnon, and RssFile.
Artifacts can be transferred automatically between the controller and the agent as an auxiliary service.
This mechanism relies on topology convergence to synchronize the controller's IPv6 address so that agents can discover where to pull artifacts from and where to push artifacts to. The goal is to reuse topology knowledge already maintained by IEEE1905 instead of introducing a separate discovery mechanism.
The artifact exchange server provides an auxiliary HTTP service for transferring operational artifacts between the controller and agents over the IEEE1905 control interface. The controller runs the server side of the service and exposes artifacts prepared under the transmit artifact tree. Agents run the client side, periodically pulling controller-to-agent artifacts such as upgrade binaries and pushing agent-to-controller artifacts such as logs.
The service is discovered through topology convergence and Higher Layer Information metadata, allowing agents to learn the controller artifact exchange URL without a separate discovery protocol. In practice, clients consume the server URL from the Control URL TLV carried in the Higher Layer Response, and that URL includes the controller IPv6 address directly to avoid unnecessary resolution steps. Controller and agent roles are currently exchanged through a vendor proprietary TLV; this can be replaced in the future with a standard TLV such as Supported Role.
On the controller side, the artifact exchange HTTP service is implemented using axum. On the client side, reqwest is used so an AL entity can push artifacts to a remote controller or pull artifacts from it when required.
- The server binds to the IEEE1905 virtual/control interface using the link-local IPv6 address derived from the local AL MAC address.
- Artifact transfers use HTTP endpoints for listing available artifacts, downloading controller-to-agent artifacts, and uploading agent-to-controller artifacts.
- Supported artifact direction is explicit:
binariesare sent from controller to agents, whilelogsare sent from agents to the controller. - Artifact names are filtered by AL MAC prefix so each node only processes artifacts addressed to it.
- Successful and failed transfers are moved into quota-aware archive or failure storage to prevent unbounded filesystem growth.
The Higher Layer Query CMDU is used by an IEEE1905 entity to request Higher Layer Information metadata from a peer. The query itself does not carry additional metadata TLVs; it only identifies the message as a Higher Layer Query and terminates with the End of Message TLV.
The Higher Layer Response CMDU carries the metadata consumed by the requesting peer. In the artifact exchange flow, the response includes the AL MAC address, IEEE1905 profile version, device identification information, and the Control URL used by agents to reach the controller-side artifact exchange service.
The IEEE1905 control-plane virtual Ethernet interface can be assigned a private link-local IPv6 address derived from the AL MAC address using EUI-64 interface-ID rules. This address is in the fe80::/64 scope and is not routable outside the local home link/network.
- Use the AL MAC assigned to the virtual Ethernet interface as the base identifier.
- Build the EUI-64 interface ID from the 48-bit MAC: flip the U/L bit in the first octet, then insert
ff:fein the middle. - Combine the resulting 64-bit interface ID with the link-local IPv6 prefix
fe80::/64. - Assign the address to the virtual Ethernet interface used by the IEEE1905 control plane.
- Validate duplicate-address detection (DAD), route reachability, and namespace placement if isolation is enabled.
Example:
- AL MAC:
02:42:c0:a8:64:02 - EUI-64 ID:
0042:c0ff:fea8:6402 - Link-local
/64prefix:fe80::/64 - Resulting IPv6:
fe80::42:c0ff:fea8:6402/64
To reduce blast radius and improve security boundaries, the IEEE1905 virtual Ethernet interface can be isolated in a dedicated Linux network namespace.
- Create a dedicated namespace for IEEE1905 control-plane traffic.
- Move the virtual Ethernet endpoint used by IEEE1905 into that namespace.
- Expose only the minimum required links and routes between host and IEEE1905 namespaces.
- Apply namespace-scoped firewall rules and permissions to restrict unintended traffic paths.
- Monitor namespace and interface state and fail fast if the virtual interface is missing or detached.
Expected benefits:
- Better separation between IEEE1905 control traffic and unrelated host networking.
- Lower risk of accidental packet leakage across services.
- Cleaner policy enforcement for interface access, logging, and debugging.
Operational notes:
- Startup scripts or systemd units should create or validate the namespace before launching IEEE1905.
- Recovery logic should recreate or reattach the virtual interface if namespace state is lost.
- Diagnostics should include namespace-aware checks such as
ip netns, interface and link state, and routes.
Binary upgrades should preserve IEEE1905 service continuity and prevent topology instability during restart windows. Upgrade coordination metadata between IEEE1905 entities will be handled through the IEEE1905 Higher Layer Information Protocol using Higher Layer Query Message and Higher Layer Response Message exchanges.
In this model, only the controller requires connectivity to the backend binary repository or service. The controller distributes, via IEEE1905, the upgrade metadata required by extenders, for example image URI, version, integrity or checksum, and policy, so extenders can fetch and apply the correct binaries.
- During upgrade or restart, IEEE1905 should gracefully stop transmission workers and release resources in deterministic order.
- On startup after upgrade, the service should rebuild local interface state, restart discovery and notification timers, and repopulate topology state through normal convergence.
- If role-bearing entities such as agent, controller, or registrar restart, role selection and split-brain protection flow must be re-evaluated using the same tie-break logic.
- Upgrade procedures should be backward compatible for topology and CMDU behavior across adjacent binary versions whenever feasible.
- During rolling upgrades, Higher Layer Query and Response should be used to detect peer upgrade state and capability and gate feature activation until compatibility is confirmed.
Logfile exchange should provide a structured way to move operational logs from agents to the controller for diagnostics, observability, and remote troubleshooting without requiring a separate discovery mechanism. Discovery metadata between IEEE1905 entities will be handled through the IEEE1905 Higher Layer Information Protocol using Higher Layer Query Message and Higher Layer Response Message exchanges.
In this model, the controller exposes the artifact exchange HTTP service and receives uploaded log artifacts from agents.
- Logfile exchange should use the
logsartifact direction from agent to controller, while preserving artifact naming based on AL MAC, timestamp, and original filename. - Uploaded logs should be stored in the artifact exchange receive tree and moved into archive or failure storage according to transfer and processing outcome.
- Log exports should include enough stable context to correlate files with topology state, role, interface, and remote peer identity.
- Transfers should tolerate intermittent reachability and retry safely without causing duplicate processing or unbounded storage growth.
- Higher Layer Query and Response should be used to verify peer logfile-exchange capability before relying on cross-node log collection workflows.
We will provide two different kinds of artifacts to be exchanged between controller and agents:
logs: platform telemetry artifacts generated by AL entities and extenders for diagnostics, observability, and troubleshooting.binaries: executable artifacts used to distribute agent upgrades.
When launching the ieee1905 binary, artifact synchronization must be enabled with the following argument:
--artifact-exchange <ARTIFACT_EXCHANGE>
Enables artifact exchange server [possible values: server, client]
Use server when the node must expose the artifact exchange HTTP service, and use client when the node must push or pull artifacts from the controller.
Each stored artifact filename shall include:
- The
AL_MACaddress of the destination entity (the node the artifact is addressed to). - The creation timestamp of the artifact.
- The original artifact name.
Example:
11-22-33-44-55-66__2026-04-29T12-30-00Z__telemetry.log
The artifact exchange service will use the following directory structure:
/tmp/artifacts/ (artifact exchange service root directory)
├── tx/ (artifacts prepared to be transmitted to a remote AL entity)
│ ├── logs/ (log artifacts to send)
│ │ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__telemetry.log
│ └── binaries/ (binary artifacts to send)
│ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__easy_mesh_agent
├── rx/ (artifacts received from a remote AL entity)
│ ├── logs/ (received log artifacts)
│ │ └── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__telemetry.log
│ └── binaries/ (received binary artifacts)
│ └── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__easy_mesh_agent
├── failed/ (artifacts whose transmission or reception failed)
│ ├── tx/ (artifacts that could not be transmitted successfully)
│ │ ├── logs/ (log artifacts that failed during transmission)
│ │ │ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__telemetry.log
│ │ └── binaries/ (binary artifacts that failed during transmission)
│ │ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__easy_mesh_agent
│ └── rx/ (artifacts that could not be received, validated, or stored successfully)
│ ├── logs/ (received log artifacts that failed processing)
│ │ └── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__telemetry.log
│ └── binaries/ (received binary artifacts that failed processing)
│ └── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__easy_mesh_agent
└── archive/ (artifacts kept as history after successful transmission or reception)
├── tx/ (artifacts successfully transmitted and retained for traceability)
│ ├── logs/ (sent log artifacts archived for history)
│ │ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__telemetry.log
│ └── binaries/ (sent binary artifacts archived for history)
│ └── 11-22-33-44-55-66__2026-04-29T12-30-00Z__easy_mesh_agent
└── rx/ (artifacts successfully received and retained for traceability)
├── logs/ (received log artifacts archived for history)
│ └── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__telemetry.log
└── binaries/ (received binary artifacts archived for history)
└── aa-bb-cc-dd-ee-ff__2026-04-29T12-31-00Z__easy_mesh_agent
- Topology convergence propagates and refreshes the controller IPv6 address.
- The controller exposes HTTP endpoints for artifact upload and download.
- Agents use
reqwestto push local artifacts and to pull remote artifacts. - Successful transfers are moved into
archive/, while failed transfers are moved intofailed/.
We can use PKCS#11 to generate, import, and store cryptographic keys in a standard way, following the PKCS#11 API's object model and attribute system.
PKCS#11 defines key objects that can be stored either:
- Persistently (on a token such as an HSM or secure software module)
- Temporarily (in a session, discarded after logout or app exit)
- Initialize the PKCS#11 library
- Get a slot with a token
- Open a session
- Log in
- Prepare the key attributes
- Create the key using
C_CreateObjectorC_GenerateKey - Assign a label or ID to retrieve the key later
We will use SoftHSM2 to provide a reference implementation of PKCS#11 for generating and storing keys. In the future, we may integrate with a TPM 2.0 module for hardware-backed protection, reusing the current implementation based on PKCS#11.
Flow of generation and storage for DPP process
Connects to SoftHSM.
Generates AES-256 keys (256-bit symmetric key) 1905GTK, 1905PMK
Stores it in the token, setting a unique identifier for each key:
CKA_LABEL= 1905GTK, CKA_ID=0x01, CKA_CLASS = CKO_SECRET_KEY.
CKA_LABEL= 1905PTK, CKA_ID=0x02, CKA_CLASS = CKO_SECRET_KEY.Flow to retrieve keys from IEEE1905 for encryption/decryption and message integrity verfication.
Connects to SoftHSM.
Consumes the known CKA_ID or CKA_LABEL to find the key.
KA_LABEL= 1905GTK, CKA_ID=0x01, CKA_CLASS = CKO_SECRET_KEY.
CKA_LABEL= 1905PTK, CKA_ID=0x02, CKA_CLASS = CKO_SECRET_KEY.
Uses 1905GTK for MIC computation
Uses 1905PTK for TLV encryption.- PKCS#11 Rust Binding using cryptoki, acting as wrapper of C APIs.
# Cargo.toml
cryptoki = "0.12"- PKCS#11 Rust Binding:
let pkcs11_module = std::env::var_os("PKCS11_LIB");
let pkcs11 = Pkcs11::new(pkcs11_module
.as_deref()
.unwrap_or(OsStr::new("/usr/lib/softhsm/libsofthsm2.so")))?;- Initialization.
pkcs11.initialize(CInitializeArgs::OsThreads)?;- Discover token and start session.
let slot = pkcs11.get_slots_with_token()?[0];
let mut session = pkcs11.open_session(
slot,
SessionFlags::RW_SESSION | SessionFlags::SERIAL_SESSION,
None
)?;- For softHSM we need to use a PIN to authenticate the access to keys.
let pin = std::env::var("PKCS11_USER_PIN")?;
session.login(UserType::User, Some(&AuthPin::new(pin.into())))?;- Generate and/or find keys.
// Generate AES-256 key
let key_template = vec![
Attribute::Token(true),
Attribute::Sensitive(true),
Attribute::Extractable(false),
Attribute::ValueLen(32),
Attribute::Encrypt(true),
Attribute::Decrypt(true),
Attribute::KeyType(KeyType::AES),
Attribute::Class(ObjectClass::SECRET_KEY),
Attribute::Label("my-aes-key".to_string()),
];
let key_handle = session.generate_key(&Mechanism::AesKeyGen, &key_template)?;- Use the keys for encryption decryption and hashing.
let padded = b"VendorTLV"; // 16 bytes
let ciphertext = session.encrypt(key_handle, &Mechanism::AesEcb, padded)?;- Clean up session
session.logout()?;
pkcs11.finalize()?;
We follow Semantic Versioning (SemVer), using the format MAJOR.MINOR.PATCH:
Contains:
- Bug fixes
- Security patches
- Performance improvements
- Internal changes with no effect on the public API
- No new features
Example:
0.2.0 → 0.2.1
Contains:
- New features
- Enhancements to existing functionality
- Backwards-compatible API additions
- Deprecations (features marked for removal but still working)
- May include multiple patch fixes bundled together
Example:
0.2.3 → 0.3.0
Contains:
- Breaking changes to APIs or behavior
- Removal of deprecated functionality
- Large refactors or architectural changes
- Any change that requires users to modify their code or configs
Example:
0.3.5 → 1.0.0
Summary:
- Patch → fixes only
- Minor → new features, backwards compatible
- Major → breaking changes
This project includes third-party software under permissive open source licenses such as Apache-2.0, MIT, BSD, ISC, Unicode, and others.
We will leave out of scope any service that will not be of any use in our implementation for EasyMesh in RDK-B or in case of a clash with our architecture.











