Openwrt netifd ubus解析

原文地址:http://xinliang.me/blog/?p=149linux

Openwrt爲網絡接口管理和配置建立了一個單獨的project,netifd。不一樣於其餘發行版上針對一樣問題領域採用的方案,netifd的目標是更適合在嵌入式的home-gateway上使用,所以也具備一些特色。

Package組成

netifd包含下面這些組件:shell

  1. Shell腳本:/sbin/ifup, /sbin/ifdown(link to ifup), /sbin/ifstatus, /sbin/devstatus
  2. init.d腳本:/etc/init.d/network
  3. hotplug2腳本:/etc/hotplug.d/iface/00-netstate, /etc/hotplug.d/iface/10-sysctl
  4. udhcpc腳本:/usr/share/udhcpc/default.script
  5. netifd守護進程binary: /sbin/netifd

下面對這些組件,逐一進行分析,以期理解netifd的基本工做機制.網絡

Shell腳本

/sbin/ifup

如前所述,ifdown其實是指向ifup的符號連接,所以這兩個腳本由同一個文件ifup實現。下面是其語法:dom

 
1
2
3
4
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:socket

 
1
2
3
4
5
6
if_call() {
local interface="$1"
for mode in $modes; do
ubus call $interface $mode
done
}

能夠看到這個function有一個參數,是interface,而後還使用了一個全局參數, modes, 在ifup腳本里面被定義,以下:oop

 
1
2
3
4
5
6
7
8
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由下面幾個組件組成:設計

  1. ubusd,這個是ubus系統的後臺進程,負責註冊unix domain socket,分派ubus消息和事件等;
  2. ubus,這是一個CLI utility,能夠經過它訪問ubus系統. ubus的幫助信息以下:
     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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 output
    Commands:
    - 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系統的服務
  3. 最後是使用ubus的各個應用程序。這些應用程序能夠在ubus系統中註冊RPC接口,提供相應的服務。而其餘程序可使用這些接口,來訪問這些服務。

netifd的ubus RPC接口

netifd在ubus系統中註冊了的object以下:unix

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
root@OpenWrt:/# 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獲得rest

 

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 }, };
1
2
3
4
5
6
7
8
9
10
11
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。

相關文章
相關標籤/搜索