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'
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 -> 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 是 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 进行配置。所涉及的配置有:
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
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;