OpenWrt network 启动过程

宋宇
2023-12-01

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 等
 类似资料: