一、简介
OpenWrt路由操作系统的框架基础软件有很多,大部分是通用的软件模块,如 dhcp 、dnsmasq、iproute、cmwp、、ipsec等等;OpenWrt还集成部分具有专属特征软件模块,也是OpenWRT系统核心框架软件组件,从此篇开始分析 《OpenWrt系统框架基础软件模块》系列文章。
OpenWrt 核心软件:procd、uci、libubox、ubus、ubox、luci、netifd 软件组件内容,此部分软件模块是构成OpenWrt框架基础软件。
因为OpenWRT是小型软路由操作系统、网络协议栈知识内容十分丰富、望而生畏;我们先把庞大网络协议栈知识放一下,从易于入手的OpenWRT这个开源软路由开始入手,无论是网络协议栈还是OpenWRT的学习,总是要找到起点或入口;OpenWRT入口处就是 libubox ,因为其他软件是依托libubox库 api 接口构建起来的应用,请参考《详解 OpenWRT系统框架基础软件模块之libubox》。
OpenWRT 系统中,netif软件模块可谓是 OpenWRT路由操作系统核心软件组件、负责网络设备、网络接口、网络协议栈、防火墙等与网络相关功能的管理和维护。
二、netifd 软件框架
我们在回顾OpenWRT系统总线ubus,它类似于Linux桌面操作系统的d-Bus,目标是提供系统级的进程间通信(IPC/RPC)功能。ubus在设计理念上与d-Bus基本保持一致,提供了系统级总线功能,与d-Bus相比减少了系统内存占用空间,这样可以适应于嵌入式Linux操作系统的低内存和低端CPU性能的特殊环境。ubus是OpenWrt的RPC/IPC工具,是OpenWrt的微系统总线架构。
OpenWRT 系统中各软件组件之间的关系,如下图:
netifd 通过系统总线 ubus 注册有线网络设备、无线设备、网络接口,源码如下:
设备状态检测方法回调。
// device
static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
[DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
};
static struct ubus_method dev_object_methods[] = {
UBUS_METHOD("status", netifd_dev_status, dev_policy), //UBUS_METHOD 采用宏方式初始化全局 各类结构体
UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
};
static struct ubus_object_type dev_object_type =
UBUS_OBJECT_TYPE("device", dev_object_methods);
static struct ubus_object dev_object = {
.name = "network.device",
.type = &dev_object_type,
.methods = dev_object_methods,
.n_methods = ARRAY_SIZE(dev_object_methods),
};
无线设备状态检测。
// device
static const struct blobmsg_policy dev_policy[__DEV_MAX] = {
[DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },
};
static struct ubus_method dev_object_methods[] = {
UBUS_METHOD("status", netifd_dev_status, dev_policy), //UBUS_METHOD 采用宏方式初始化全局 各类结构体
UBUS_METHOD("set_alias", netifd_handle_alias, alias_attrs),
UBUS_METHOD("set_state", netifd_handle_set_state, dev_state_policy),
};
static struct ubus_object_type dev_object_type =
UBUS_OBJECT_TYPE("device", dev_object_methods);
static struct ubus_object dev_object = {
.name = "network.device",
.type = &dev_object_type,
.methods = dev_object_methods,
.n_methods = ARRAY_SIZE(dev_object_methods),
};
由此看到,OpenWRT路由操作系统,把有线和无线网络设备是分开管理。
// network
static struct ubus_method main_object_methods[] = {
{ .name = "restart", .handler = netifd_handle_restart },
{ .name = "reload", .handler = netifd_handle_reload },
UBUS_METHOD("add_host_route", netifd_add_host_route, route_policy),
{ .name = "get_proto_handlers", .handler = netifd_get_proto_handlers },
UBUS_METHOD("add_dynamic", netifd_add_dynamic, dynamic_policy),
};
static struct ubus_object_type main_object_type =
UBUS_OBJECT_TYPE("netifd", main_object_methods);
static struct ubus_object main_object = {
.name = "network",
.type = &main_object_type,
.methods = main_object_methods,
.n_methods = ARRAY_SIZE(main_object_methods),
};
当网络设备驱动产生状态变化时,内核通过netlink-Kobject的 kevent 事件通知到用户空间,ubusd 守护线程接收到此事件后,就执行
netifd在 ubus 总线注册的回调函数,会触发 netifd_get_proto_handlers 、netifd_add_host_route 回调函数执行;
netifd_get_proto_handlers () 函数根据 /etc/config/network 配置项,重新设置设备协议相关参数;
netifd_add_host_route () 函数会通过 netlink-routing 通讯,触发内核的路由子系统,为依附于该设备的 interface 接口,配置路由信息;至于路由子系统工作原理(四表五链)和运作机制,请关注笔者的《Linux 网络协议栈》子栏目,笔者将梳理内核的网络协议栈的路由子系统系列文章。
netifd 子系统的内容丰富,由于个人时间的问题,暂时先到此处;后面会进一步说明。