Backhaul manager is a mechanism, that is responsible for onboarding between the controller and agent. Onboarding includes the successful connection , and other processes that in result allow to extend the controller's data model with the agent's data model, and properly communicate between each other. This process is one of the most crucial in the proper work of prplMesh.
The backhaul can be wired or wireless, and also it features a fallback mechanism: whenever we have troubles with using the wired connection, the backhaul seamlessly falls from wired to wireless connection.
The general scheme of backhaul looks like this:
In between starting the board and successful onboarding the son_slave_thread, backhaul_manager, controller_connectivity_task and ap_autoconfiguration_task are participating in this process.
The configuration of the backhaul is not that wide:
root@prplOS:/# uci show prplmesh | grep backhaul
prplmesh.config.wired_backhaul='1'
prplmesh.config.backhaul_band='auto'
prplmesh.config.backhaul_wire_iface='wan'
Note: the "prplmesh.config.wired_backhaul" is a deprecated setting since prplmesh v4.1.0!
We can manually force to use the wireless backhaul, even if there is a plugged in cable by setting prplmesh.config.backhaul_wire_iface to "none".
In order to make a successful onboarding the following requirements should be fulfilled:
-
The controller should be operational.
-
The access point interface on the controller should be in the br-lan bridge. (wireless only)
-
The access point has to have MultiAPType "Backhaul" or "Fronthaul + Backhaul". (wireless only)
-
The endpoint must have MultiAPMode=1. (wireless only)
-
The agent has to see the controller's AP and vice-versa. (Obviously + wireless only)
Note: it doesn't matter if one board has 2 radios and the second one has 3 radios.
Note: it doesn't matter if one board runs RDKB and the other one runs prplOS.
The onboarding with the wired backhaul looks like this:
[backhaul_manager FSM]
FSM: INIT --> WAIT_ENABLE
FSM: WAIT_ENABLE --> ENABLED
FSM: ENABLED --> CONNECTED
FSM: CONNECTED --> OPERATIONAL
The onboarding with the wireless backhaul looks like this:
[backhaul_manager FSM]
FSM: INIT --> WAIT_ENABLE
FSM: WAIT_ENABLE --> ENABLED
FSM: ENABLED --> INIT_HAL
FSM: INIT_HAL --> WPA_ATTACH
FSM: WPA_ATTACH --> WAIT_WPS
FSM: WAIT_WPS --> CONNECTED
FSM: CONNECTED --> OPERATIONAL
And the full flow for the wireless backhaul does look like this:
son_slave_thread.cpp --> goto STATE_WAIT_FOR_PLATFORM_MANAGER_REGISTER_RESPONSE
son_slave_thread.cpp --> goto STATE_CONNECT_TO_BACKHAUL_MANAGER
son_slave_thread.cpp --> goto STATE_WAIT_FOR_BACKHAUL_MANAGER_REGISTER_RESPONSE
son_slave_thread.cpp --> goto STATE_JOIN_INIT
son_slave_thread.cpp --> goto STATE_WAIT_FOR_FRONTHAUL_THREADS_JOINED
son_slave_thread.cpp --> goto STATE_BACKHAUL_ENABLE
son_slave_thread.cpp --> goto STATE_SEND_BACKHAUL_MANAGER_ENABLE
son_slave_thread.cpp --> goto STATE_WAIT_FOR_BACKHAUL_MANAGER_CONNECTED_NOTIFICATION
backhaul_manager.cpp --> FSM: WAIT_ENABLE --> ENABLED
backhaul_manager.cpp --> FSM: ENABLED --> INIT_HAL
backhaul_manager.cpp --> FSM: INIT_HAL --> WPA_ATTACH
backhaul_manager.cpp --> FSM: WPA_ATTACH --> WAIT_WPS
backhaul_manager.cpp --> FSM: WAIT_WPS --> CONNECTED
backhaul_manager.cpp --> FSM: CONNECTED --> OPERATIONAL
son_slave_thread.cpp --> goto STATE_BACKHAUL_MANAGER_CONNECTED
wlan1 FSM: UNCONFIGURED --> CONTROLLER_DISCOVERY
wlan0 FSM: UNCONFIGURED --> CONTROLLER_DISCOVERY
wlan2 FSM: UNCONFIGURED --> CONTROLLER_DISCOVERY
wlan2 FSM: CONTROLLER_DISCOVERY --> WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE
wlan0 FSM: CONTROLLER_DISCOVERY --> WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE
wlan1 FSM: CONTROLLER_DISCOVERY --> WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE
wlan2 FSM: WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE --> SEND_AP_AUTOCONFIGURATION_WSC_M1
wlan0 FSM: WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE --> SEND_AP_AUTOCONFIGURATION_WSC_M1
wlan1 FSM: WAIT_FOR_CONTROLLER_DISCOVERY_COMPLETE --> SEND_AP_AUTOCONFIGURATION_WSC_M1
wlan2 FSM: SEND_AP_AUTOCONFIGURATION_WSC_M1 --> WAIT_AP_AUTOCONFIGURATION_WSC_M2
wlan0 FSM: SEND_AP_AUTOCONFIGURATION_WSC_M1 --> WAIT_AP_AUTOCONFIGURATION_WSC_M2
wlan1 FSM: SEND_AP_AUTOCONFIGURATION_WSC_M1 --> WAIT_AP_AUTOCONFIGURATION_WSC_M2
wlan1 FSM: WAIT_AP_AUTOCONFIGURATION_WSC_M2 --> WAIT_AP_CONFIGURATION_COMPLETE
wlan0 FSM: WAIT_AP_AUTOCONFIGURATION_WSC_M2 --> WAIT_AP_CONFIGURATION_COMPLETE
wlan2 FSM: WAIT_AP_AUTOCONFIGURATION_WSC_M2 --> WAIT_AP_CONFIGURATION_COMPLETE
wlan1 FSM: WAIT_AP_CONFIGURATION_COMPLETE --> CONFIGURED
wlan0 FSM: WAIT_AP_CONFIGURATION_COMPLETE --> CONFIGURED
wlan2 FSM: WAIT_AP_CONFIGURATION_COMPLETE --> CONFIGURED
son_slave_thread.cpp --> goto STATE_WAIT_FOR_AUTO_CONFIGURATION_COMPLETE
controller_connectivity_task.cpp --> FSM: WAIT_FOR_CONTROLLER_DISCOVERY --> CONTROLLER_MONITORING
son_slave_thread.cpp --> goto STATE_OPERATIONAL
A little bit of what is what in this big sequence of states and executed code:
son_slave_thread: It is a large FSM by itself, which controls the execution order of all of the processes for the agent side in one way or another.
backhaul_manager: the main FSM for the backhaul, which decides whether to use wired or wireless, connect to the platform manager, creates HAL instances, creates the handlers for the external and internal events for the hal instance, attaches to the AP, and sends the AGENT_DEVICE_INITIALIZED to the topology task.
ap_autoconfiguration_task: this task is responsible for the exchanging messages between agent and controller, which allows agent to find the controller, and share all its needed data with it, such as basic radio capabilities. Also, it stores the BSS credentials for the interfaces. The ap_autoconfiguration flow looks like this:
controller_connectivity_task: a task which is monitoring the state of the controller, and tries to reconnect to it in case the controller become unresponsive. If it is not possible, it can also send the ACTION_BACKHAUL_RECONNECT_COMMAND to try to make a fresh connection in hope that it can fix the problem.
As described earlier in this article, fallback mechanism is a mechanism that lets us to switch from wired to wireless in case of any problems. Whenever the wired backhaul is having problems, the controller_connectivity task starts to send heartbeats to the controller, and if the controller doesn't respond, we are getting pushed at first to the CONECTION_TIMEOUT state, and then into the RECONNECTION state in the controller_connectivity task, which sends the ACTION_BACKHAUL_RECONNECT_COMMAND to the backhaul manager, and in case of wireless backhaul, the backhaul manager goes to INIT_HAL state, and in case of wired backhaul it goes into the RESTART state.
Note: the fallback mechanism always uses wireless to fallback.
The most important thing about the fallback mechanism is that it stores backhaul links to try to reconnect using them:
controller_connectivity_task.cpp --> WAIT_RESPONSE_FROM_CONTROLLER --> CONNECTION_TIMEOUT
controller_connectivity_task.cpp --> Existing BH interfaces:
-type: 2
-iface_name: wlan2
-iface_mac: 02:b5:d4:65:c6:07
controller_connectivity_task.cpp --> Credentials:
-ssid: prplOS
-bssid: 02:b5:d4:65:c6:07
-bss_type: 32
-auth_type: WSC_AUTH_SAE
-encr_type: eWscEncr::WSC_ENCR_NONE
-network_key: password
controller_connectivity_task.cpp --> Credentials:
-ssid:
-bssid: 02:b5:d4:65:c6:08
-bss_type: 16
-auth_type: 41936
-encr_type: 38641
-network_key:
controller_connectivity_task.cpp --> Existing BH interfaces:
-type: 2
-iface_name: wlan0
-iface_mac: 02:b5:d4:65:c6:06
controller_connectivity_task.cpp --> Credentials:
-ssid: prplmesh
-bssid: 02:b5:d4:65:c6:06
-bss_type: 104
-auth_type: WSC_AUTH_WPA2PSK
-encr_type: eWscEncr::WSC_ENCR_NONE
:network_key: prplmesh_pass
controller_connectivity_task.cpp[138] --> Credentials:
-ssid:
-bssid: 02:b5:d4:66:c6:07
-bss_type: 16
-auth_type: 41936
-encr_type: 38641
-network_key:
controller_connectivity_task.cpp --> Existing BH interfaces:
-type: 2
-iface_name: wlan1
-iface_mac: 02:b5:d4:65:c6:05
controller_connectivity_task.cpp --> Credentials:
-ssid: prplOS
-bssid: 02:b5:d4:65:c6:05
-bss_type: 104
-auth_type: WSC_AUTH_WPA2PSK
-encr_type: eWscEncr::WSC_ENCR_NONE
-network_key: password
controller_connectivity_task.cpp --> Credentials:
-ssid:
-bssid: 02:b5:d4:67:c6:06
-bss_type: 16
-auth_type: 41936
-encr_type: 38641
-network_key:
controller_connectivity_task.cpp --> Selected backhaul interface: wlan0
controller_connectivity_task.cpp --> Selected backhaul SSID: prplmesh
controller_connectivity_task.cpp --> Selected backhaul password: prplmesh_pass
controller_connectivity_task.cpp --> Selected backhaul security type: 5
controller_connectivity_task.cpp --> CONTROLLER_CONNECTIVITY FSM: CONNECTION_TIMEOUT --> RECONNECTION
Wired Backhaul Interface and Bridge Membership
Summary
PrplMesh requires a properly configured wired backhaul interface for optimal operation. The prplMesh agent does not modify bridge membership of network interfaces: it does not add or remove interfaces from the LAN bridge (e.g., br-lan). This responsibility remains with the platform or system integrator.
Requirements
- The wired backhaul interface configured for prplMesh (e.g.,
eth0,wan, etc.) must already be a member of the desired LAN bridge (usuallybr-lan) before the agent starts. - If you wish to use a specific Ethernet interface for backhaul, you must ensure it is enslaved to the LAN bridge via your system/network configuration (e.g., OpenWrt’s
/etc/config/network, RDK-B’s bridge setup, or standard Linux tools).
Rationale
- prplMesh does not alter bridge memberships at runtime.
- This avoids unintentional network loops, unpredictable network changes, and potential platform-specific issues.
- Managing bridge membership is highly platform-dependent and often requires elevated privileges and careful planning, which is best handled at the integration layer.
What Happens If the Interface Is Not in the Bridge?
- prplMesh will attempt to bring up the backhaul using the configured interface.
- If the interface is not present in the LAN bridge, the agent will log an error such as:
and will fall back to wireless backhaul if available.
wire iface <iface_name> is not on the bridge - No automated attempt to reconfigure the bridge is made.