• Openwrt netifd ubus解析


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

    Openwrt为网络接口管理和配置创建了一个单独的project,netifd。不同于其他发行版上针对同样问题领域采用的方案,netifd的目标是更适合在嵌入式的home-gateway上使用,因此也具有一些特点。

    Package组成

    netifd包含下面这些组件:

    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实现。下面是其语法:

     
    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:

     
    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脚本里面被定义,如下:

     
    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如下:

     
    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得到

    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。

  • 相关阅读:
    Rotate Always Encrypted keys using SQL Server Management Studio
    ABP Web Application Development Tutorial Part 1: Creating the Server Side
    Fiddler 2 Wipes My Internet Explorer Proxy Settings
    API设计浅析
    泛型的实现浅谈
    搜狗workflow异步调度框架
    MQTT 和 CoAP
    深入理解左值、右值
    C++ 头文件接口设计浅谈
    Windows无Internet但能正常上网的问题
  • 原文地址:https://www.cnblogs.com/issuelinux/p/4244681.html
Copyright © 2020-2023  润新知