標籤:
原文地址:http://xinliang.me/blog/?p=149
Openwrt為網路介面管理和配置建立了一個單獨的project,netifd。不同於其他發行版上針對同樣問題領域採用的方案,netifd的目標是更適合在嵌入式的home-gateway上使用,因此也具有一些特點。Package組成
netifd包含下面這些組件:
- Shell指令碼:/sbin/ifup, /sbin/ifdown(link to ifup), /sbin/ifstatus, /sbin/devstatus
- init.d指令碼:/etc/init.d/network
- hotplug2指令碼:/etc/hotplug.d/iface/00-netstate, /etc/hotplug.d/iface/10-sysctl
- udhcpc指令碼:/usr/share/udhcpc/default.script
- netifd守護進程binary: /sbin/netifd
下面對這些組件,逐一進行分析,以期理解netifd的基本工作機制.
Shell指令碼/sbin/ifup
如前所述,ifdown實際上是指向ifup的符號連結,因此這兩個指令碼由同一個檔案ifup實現。下面是其文法:
1234 |
syntax: /sbin/{ifup|ifdown} [-a] [-w] [interface]-a選項指明對所有介面均執行相同的操作,此時interface被忽略.此參數預設為false-w選項指定是否執行wifi up操作。如果此參數被指定,則wifi up操作不會被執行。如果未指定,則在ifup的時候,wifi up會被執行interface指定down/up操作的目標介面 |
ifup的指令碼裡面,關於wifi的操作是通過/sbin/wifi指令碼執行的,所以在這裡暫時不討論。關於normal的if down/up操作,這個指令碼是通過ubus命令來實現的。下面是一個if_call() function:
123456 |
if_call() {local interface="$1"for mode in $modes; doubus call $interface $modedone} |
可以看到這個function有一個參數,是interface,然後還使用了一個全域參數, modes, 在ifup指令碼裡面被定義,如下:
12345678 |
case "$0" in*ifdown) modes=down;;*ifup)modes="down up"setup_wifi=1;;*) echo "Invalid command: $0";;esac |
所以當執行ifdown lan時,對應的ubus命令為”ubus call network.interface.lan down”;執行ifup lan時,ubus命令為兩條,先執行”ubus call network.interface.lan down”,然後是”ubus call network.interface.lan up”.
ubus & ubusd
Openwrt提供了一個ubus系統,它類似於案頭linux系統的dbus,目標也是提供系統級的IPC和RPC。ubus在設計理念上與dbus基本保持一致,區別在於簡化的API和簡練的模型,以適應於embedded router的特殊環境。
基本上來說, openwrt的ubus由下面幾個組件組成:
- ubusd,這個是ubus系統的後台進程,負責註冊unix domain socket,指派ubus訊息和事件等;
- ubus,這是一個CLI utility,可以通過它訪問ubus系統. ubus的協助資訊如下:
1234567891011 |
Usage: ubus [options] <command></command> [arguments...]Options:-s : Set the unix domain socket to connect to-t : Set the timeout (in seconds) for a command to complete-S: Use simplified output (for scripts)-v: More verbose outputCommands:- list [] List objects- call [] Call an object method- listen [...] Listen for events- send [] Send an event |
ubus提供的command有4種: list, call, listen & send, 通過這四種command,可以訪問註冊到ubus系統的服務
- 最後是使用ubus的各個應用程式。這些應用程式可以在ubus系統中註冊RPC介面,提供相應的服務。而其他程式可以使用這些介面,來訪問這些服務。
netifd的ubus RPC介面
netifd在ubus系統中註冊了的object如下:
12345678910111213141516171819202122232425262728293031323334353637383940 |
[email protected]:/# ubus list -v‘network‘ @25a06dad"restart": { }"reload": { }"add_host_route": { "target": "String", "v6": "Boolean" }"get_proto_handlers": { }‘network.device‘ @9d97d655"status": { "name": "String" }"set_alias": { "alias": "(unknown)", "device": "String" }"set_state": { "name": "String", "defer": "Boolean" }‘network.interface.lan‘ @f9e7258b"up": { }"down": { }"status": { }"prepare": { }"add_device": { "name": "String" }"remove_device": { "name": "String" }"notify_proto": { }"remove": { }"set_data": { }‘network.interface.loopback‘ @6d026db0"up": { }"down": { }"status": { }"prepare": { }"add_device": { "name": "String" }"remove_device": { "name": "String" }"notify_proto": { }"remove": { }"set_data": { }‘network.interface.wan‘ @ade92c65"up": { }"down": { }"status": { }"prepare": { }"add_device": { "name": "String" }"remove_device": { "name": "String" }"notify_proto": { }"remove": { }"set_data": { } |
每個object所提供的RPC介面名稱,以及介面參數類型都可以通過ubus得到
netifd interface RPC
netifd為每個interface object註冊了一組相同的methods,如下:
static struct ubus_method iface_object_methods[] = { { .name = "up", .handler = netifd_handle_up }, { .name = "down", .handler = netifd_handle_down }, { .name = "status", .handler = netifd_handle_status }, { .name = "prepare", .handler = netifd_handle_iface_prepare }, UBUS_METHOD("add_device", netifd_iface_handle_device, dev_policy ), UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_policy ), { .name = "notify_proto", .handler = netifd_iface_notify_proto }, { .name = "remove", .handler = netifd_iface_remove }, { .name = "set_data", .handler = netifd_handle_set_data }, };
1234567891011 |
static struct ubus_method iface_object_methods[] = {{ .name = "up", .handler = netifd_handle_up },{ .name = "down", .handler = netifd_handle_down },{ .name = "status", .handler = netifd_handle_status },{ .name = "prepare", .handler = netifd_handle_iface_prepare },UBUS_METHOD("add_device", netifd_iface_handle_device, dev_policy ),UBUS_METHOD("remove_device", netifd_iface_handle_device, dev_policy ),{ .name = "notify_proto", .handler = netifd_iface_notify_proto },{ .name = "remove", .handler = netifd_iface_remove },{ .name = "set_data", .handler = netifd_handle_set_data },}; |
然後可以發現,netifd裡面還有一個protocol handler的概念,也就是對不同的interface protocol,可以提供不同的handler,來響應各種可能的事件。最常見的static類型的protocol,內建在netifd中。而dhcp,pppoe等類型的協議,則以shell script的形式提供。
netifd protocol handler外掛程式
netifd的protocol handler外掛程式位於/lib/netifd/proto/目錄下,名稱統一為*.sh。
Openwrt netifd ubus解析