OpenWrt network 啓動過程

OpenWrt network 啓動過程

/etc/config/network

networt 配置文件爲 /etc/config/network

關於/etc/config/network 的生成可以看我的上一篇博文:OpenWrt /etc/config/network 的生成過程

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd20:4754:ca54::/48'

config interface 'lan'
        option ifname 'eth0.1'
        option force_link '1'
        option macaddr 'ff:ff:ff:ff:ff:ff'
        option type 'bridge'
        option proto 'dhcp'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config interface 'wan'
        option force_link '1'
        option macaddr 'ff:ff:ff:ff:ff:ff'
        option proto 'dhcp'
        option ifname 'apcli0'

config interface 'wan6'
        option ifname 'eth0.2'
        option proto 'dhcpv6'

config switch
        option name 'switch0'
        option reset '1'
        option enable_vlan '1'

config switch_vlan
        option device 'switch0'
        option vlan '1'
        option ports '0 6t'

config switch_vlan
        option device 'switch0'
        option vlan '2'
        option ports '1 6t'

/etc/init.d/network

openWrt 網絡啓動腳本爲/etc/init.d/network, 以MT7688 爲例內容如下:

#!/bin/sh /etc/rc.common

START=20
STOP=90

USE_PROCD=1  # 表示由 procd 進程管理
             # 更多說明:https://openwrt.org/start?id=docs/guide-developer/procd-init-scripts

init_switch() {
        setup_switch() { return 0; }

        include /lib/network  
        setup_switch    # 調用的是 /lib/network 裏定義的 setup_switch
}

start_service() {
        init_switch                                     
        #初始化 switch
        procd_open_instance
        # 創建一個實例
        # ubus call service list 可以查看實例
        procd_set_param command /sbin/netifd
        # 執行的命令是 /sbin/netifd
        procd_set_param respawn
        # 定義respawn參數,告知procd當程序退出後嘗試進行重啓
        procd_set_param watch network.interface
        # 監控的ubs 名字
        [ -e /proc/sys/kernel/core_pattern ] && {
                procd_set_param limits core="unlimited"
                echo '/tmp/%e.%p.%s.%t.core' > /proc/sys/kernel/core_pattern
        }
        procd_close_instance
        # 關閉一個實例
}

reload_service() {
        init_switch
        ubus call network reload
        /sbin/wifi reload_legacy
}

...

start_service 中主要做了兩件事情:

  • init_switch
  • /sbin/netifd

init_switch

init_switch -> setup_switch ,找到 setup_switch 的定義在 /lib/network/switch.sh

/lib/network 下有兩個文件

config.sh
switch.sh
#!/bin/sh
# Copyright (C) 2009 OpenWrt.org

setup_switch_dev() {
	local name
	config_get name "$1" name
	name="${name:-$1}"
	[ -d "/sys/class/net/$name" ] && ifconfig "$name" up
	swconfig dev "$name" load network
}

setup_switch() {
	config_load network      # 讀取 /etc/config/network ,config_load 在/lib/functions.sh 中定義
	config_foreach setup_switch_dev switch
}

config_foreach setup_switch_dev switch 最終執行 swconfig dev switch0 load network

swconfig

swconfig 是 openWrt 下用於配置 switch 的 工具,工具是基於 genl (Generic Netlink)接口與內核通信實現的。usage 如下。

~# swconfig --help
swconfig list
swconfig dev <dev> [port <port>|vlan <vlan>] (help|set <key> <value>|get <key>|load <config>|show)

swconfig dev switch0 load network 會讀取 /etc/config/network ,根據裏面的配置信息對swicth 進行配置。所涉及的配置有:

  • vlan 的使能
  • port 的劃分,如上,有port0 和port1 兩個端口,port0 歸valn1 ,port1 歸vlan2

netifd

netifd是openWrt中用於進行網絡配置的守護進程。netifd 讀取 /etc/config/network 和/etc/config/wireless並在ubus 上創建如下對象:

# ubus list network*
network
network.device
network.interface
network.interface.lan
network.interface.loopback
network.interface.wan
network.interface.wan6
network.wireless

同時可看到 /sys/class/net 下面創建了虛擬網卡,也可以 ifconfig 查看到

ls -l /sys/class/net/*
lrwxrwxrwx    1 root     root             0 May 11 15:52 /sys/class/net/apcli0 -> ../../devices/virtual/net/apcli0
lrwxrwxrwx    1 root     root             0 May 12 09:29 /sys/class/net/apcli1 -> ../../devices/virtual/net/apcli1
lrwxrwxrwx    1 root     root             0 May 11 15:52 /sys/class/net/br-lan -> ../../devices/virtual/net/br-lan
lrwxrwxrwx    1 root     root             0 Jan  1  1970 /sys/class/net/eth0 -> ../../devices/10100000.ethernet/net/eth0
lrwxrwxrwx    1 root     root             0 May 12 09:29 /sys/class/net/eth0.1 -> ../../devices/virtual/net/eth0.1
lrwxrwxrwx    1 root     root             0 May 12 09:29 /sys/class/net/eth0.2 -> ../../devices/virtual/net/eth0.2
lrwxrwxrwx    1 root     root             0 Jan  1  1970 /sys/class/net/lo -> ../../devices/virtual/net/lo
lrwxrwxrwx    1 root     root             0 May 11 15:52 /sys/class/net/ra0 -> ../../devices/virtual/net/ra0

netifd 如何通知內核創建虛擬網卡的?

netifd

main 
 config_init_all
  config_init_interfaces
   config_parse_interface
    interface_add
     __interface_add
      vlist_add(&interfaces, &iface->node, iface->name);
       tree->update  // = interfaces.update
         interface_update
          interface_claim_device
           device_get
            get_vlan_device_chain
             get_vlan_device
              vldev->dev.set_state = vlan_set_device_state   // 設置set_state 方法            
           interface_set_device_config(iface, dev)
            device_apply_config
             dev->set_state()                                // 調用set_state 方法
               vlan_set_device_state
                system_vlan_add
                 system_vlan
                  ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);      // 通過socket 給內核發消息 ifr.cmd = ADD_VLAN_CMD

kernel

// linux-3.18.21\net\8021q\vlan.c
vlan_ioctl_handler
  case ADD_VLAN_CMD:		
		err = register_vlan_device(dev, args.u.VID);
		break;

小結

  • 網絡配置文件 /etc/config/network
  • 網絡初始化腳本/etc/init.d/network
  • swconfig 用於配置 switch
  • netifd 進行更復雜的網絡管理,創建虛擬網卡,dhcp 等
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章