Code Flow and System Interaction
From CLI/API to SoC Layer: End-to-End Data Flow
Flow:
- CLI/API: User issues
uci set
orLuCI
command. - UCI: Updates
/etc/config/
files. - UBUS: Notifies
netifd
or other services. - Kernel: Applies changes (e.g., interface configuration) via drivers.
- SoC: Hardware (e.g., Ethernet, Wi-Fi) executes changes.
Network Interface Bring-Up Flow (ifup, hotplug, netifd)
Flow:
- Hotplug: Detects interface events (e.g., cable plugged in).
- netifd: Reads UCI config and applies settings via
ifup
. - Kernel: Configures network stack (e.g., IP addresses, routes).
- UBUS: Notifies subscribers of interface status.
Firewall and Packet Filtering (nftables integration)
Integration:
- OpenWRT uses
nftables
(since 22.03) for firewall rules. - Configured via UCI (
/etc/config/firewall
). fw4
(firewall4) manages rules, replacingfw3
/iptables
.- Supports NAT, filtering, and QoS.
Boot Sequence and Init Scripts (Procd rc.d)
Sequence:
- U-Boot: Loads kernel and device tree.
- Kernel: Mounts filesystems, initializes drivers.
- procd: Runs
/etc/init.d/
scripts in order (e.g.,boot
,network
). - Services: Starts
netifd
,dnsmasq
, etc., based on UCI settings.
Code Walkthrough: A Sample UBUS Application
Example: A C program registering a UBUS object to expose system status.
Sample UBUS Application Code
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/blobmsg_json.h>
#include <uci.h>
#include <stdio.h>
#include <unistd.h>
// UBUS method to get system status
static int system_status(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg) {
struct blob_buf b = {0};
blob_buf_init(&b, 0);
// Add system info to response
blobmsg_add_string(&b, "hostname", "openwrt-router");
blobmsg_add_u32(&b, "uptime", (uint32_t)time(NULL));
// Send response
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
return 0;
}
// UBUS method to read UCI config
static int get_config(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg) {
struct uci_context *uci_ctx = uci_alloc_context();
struct uci_package *pkg = NULL;
struct blob_buf b = {0};
blob_buf_init(&b, 0);
// Load UCI network config
uci_load(uci_ctx, "network", &pkg);
if (pkg) {
struct uci_section *s = uci_lookup_section(uci_ctx, pkg, "lan");
if (s) {
const char *ipaddr = uci_lookup_option_string(uci_ctx, s, "ipaddr");
if (ipaddr)
blobmsg_add_string(&b, "lan_ip", ipaddr);
}
uci_unload(uci_ctx, pkg);
}
uci_free_context(uci_ctx);
ubus_send_reply(ctx, req, b.head);
blob_buf_free(&b);
return 0;
}
// UBUS method table
static const struct ubus_method methods[] = {
UBUS_METHOD_NOARG("status", system_status),
UBUS_METHOD_NOARG("config", get_config),
};
// UBUS object type
static struct ubus_object_type obj_type =
UBUS_OBJECT_TYPE("system_info", methods);
// UBUS object
static struct ubus_object obj = {
.name = "system",
.type = &obj_type,
.methods = methods,
.n_methods = ARRAY_SIZE(methods),
};
int main(void) {
struct ubus_context *ctx;
// Initialize uloop
uloop_init();
// Connect to ubusd
ctx = ubus_connect(NULL);
if (!ctx) {
fprintf(stderr, "Failed to connect to ubusd\n");
return -1;
}
// Add ubus to uloop
ubus_add_uloop(ctx);
// Register UBUS object
if (ubus_add_object(ctx, &obj)) {
fprintf(stderr, "Failed to add object\n");
ubus_free(ctx);
return -1;
}
// Run event loop
uloop_run();
// Cleanup
ubus_free(ctx);
uloop_done();
return 0;
}
Code Walkthrough
Includes and Setup:
- Includes
libubus.h
for UBUS communication,libubox/uloop.h
for event loop,libubox/blobmsg_json.h
for JSON-like message formatting, anduci.h
for configuration18 configuration access. - The program uses
uloop
for event handling andblob_buf
for message construction.
- Includes
UBUS Methods:
system_status
: Responds with system information (hostname and uptime) usingblob_buf
to format the response.get_config
: Reads the LAN IP address from the UCInetwork
configuration file and returns it in the response.- Both methods use
ubus_send_reply
to send data back to the caller.
UBUS Object Definition:
- Defines a method table (
methods
) with two methods:status
andconfig
, both without arguments. - Creates an object type (
obj_type
) and object (obj
) named “system” to register withubusd
.
- Defines a method table (
Main Function:
- Initializes
uloop
for event handling. - Connects to
ubusd
usingubus_connect(NULL)
(default UNIX socket). - Integrates UBUS with
uloop
viaubus_add_uloop
. - Registers the
system
object withubus_add_object
. - Runs the event loop with
uloop_run
to handle incoming UBUS calls. - Cleans up with
ubus_free
anduloop_done
.
- Initializes
UCI Integration:
- In
get_config
, a UCI context is created (uci_alloc_context
), thenetwork
config is loaded, and thelan
section’sipaddr
is retrieved and added to the response.
- In
How to Test
- Compile with
gcc -o system_info system_info.c -lubus -lubox -luci
. - Run on an OpenWRT system:
./system_info
. - Use the
ubus
CLI to test:Expected output:ubus call system status ubus call system config
// For status { "hostname": "openwrt-router", "uptime": 123456789 } // For config { "lan_ip": "192.168.1.1" }
Notes
- The program registers a UBUS object named
system
with two methods:status
(returns hostname and uptime) andconfig
(returns LAN IP from UCI). - It uses
libubus
for communication withubusd
andlibuci
for configuration access. - The
uloop
event loop ensures the program handles incoming UBUS calls asynchronously. - Ensure
libubus
,libubox
, andlibuci
are installed on the OpenWrt system.
This is a basic example demonstrating UBUS object registration and UCI integration. For production, error handling and support for method arguments are to be added.
Service Startup, Watchdog, and Daemonization
Startup:
procd
manages service startup via/etc/init.d/
scripts.- Scripts define
start
,stop
, andrestart
functions.
Watchdog:
procd
monitors services and restarts them if they crash.- Hardware watchdog supported on compatible SoCs.
Daemonization:
- Services run as daemons, managed by
procd
.