openwrt无线uci文件生成流程
系统开机启动,执行/etc/init.d/boot(源码:package/base-files/etc/init.d/boot)
boot() { /sbin/wifi detect > /tmp/wireless.tmp [ -s /tmp/wireless.tmp ] && { # 在路由器/etc/config目录中生成uci配置文件wireless cat /tmp/wireless.tmp >> /etc/config/wireless } rm -f /tmp/wireless.tmp } |
/sbin/wifi(源码:package/base-files/sbin/wifi)
wifi_detect() { # 对于pros版本,echo "geshifei DRIVERS=$DRIVERS" > /dev/console # 输出geshifei DRIVERS=wave513 wave523 for driver in ${2:-$DRIVERS}; do ( # 对于pros版本,echo "geshifei driver=$driver" > /dev/console # geshifei driver=wave513 # geshifei driver=wave523 if eval "type detect_$driver" 2>/dev/null >/dev/null; then eval "detect_$driver" || echo "$driver: Detect failed" >&2 else echo "$driver: Hardware detection not supported" >&2 fi ); done } DEVICES= DRIVERS= include /lib/wifi scan_wifi case "$1" in down) wifi_updown "disable" "$2";; detect) wifi_detect "$2";; status) ubus_wifi_cmd "status" "$2";; reload) wifi_reload "$2";; reload_legacy) wifi_reload_legacy "$2";; --help|help) usage;; *) ubus call network reload; wifi_updown "enable" "$2";; esac |
/sbin/wifi detect语句执行/sbin/wifi脚本,并传入参数detect,先执行scan_wifi语句,然后才执行/sbin/wifi中的case语句。scan_wifi负责将/etc/config/wireless文件中的配置信息导出到shell环境变量中。
scan_wifi() { local cfgfile="$1" DEVICES= config_cb() { local type="$1" local section="$2" # section start case "$type" in wifi-device) append DEVICES "$section" config_set "$section" vifs "" config_set "$section" ht_capab "" ;; esac # section end config_get TYPE "$CONFIG_SECTION" TYPE case "$TYPE" in wifi-iface) config_get device "$CONFIG_SECTION" device config_get vifs "$device" vifs append vifs "$CONFIG_SECTION" config_set "$device" vifs "$vifs" ;; esac } # 执行到此,$cfgfile为空,所以下面语句等效于config_load "${ wireless}" config_load "${cfgfile:-wireless}" } |
config_cb()这个回调函数会在调用config_load时,对每一个section调用,这个函数有两个参数,分别是section_type 与section_name。
上面脚本执行config_load"${cfgfile:-wireless}",即执行config_load“wireless”,见下:
/lib/functions.sh (源码:package/base-files/files/lib/functions.sh)
config_load() { [ -n "$IPKG_INSTROOT" ] && return 0 uci_load "$@" } |
上面脚本执行了uci_load“wireless”见下
/lib/config/uci.sh(源码:package/system/uci/files/lib/config/uci.sh)
CONFIG_APPEND= uci_load() { local PACKAGE="$1" local DATA local RET local VAR _C=0 if [ -z "$CONFIG_APPEND" ]; then for VAR in $CONFIG_LIST_STATE; do export ${NO_EXPORT:+-n} CONFIG_${VAR}= export ${NO_EXPORT:+-n} CONFIG_${VAR}_LENGTH= done export ${NO_EXPORT:+-n} CONFIG_LIST_STATE= export ${NO_EXPORT:+-n} CONFIG_SECTIONS= export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=0 export ${NO_EXPORT:+-n} CONFIG_SECTION= fi DATA="$(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${LOAD_STATE:+-P /var/state} -S -n export "$PACKAGE" 2>/dev/null)" RET="$?" [ "$RET" != 0 -o -z "$DATA" ] || eval "$DATA" unset DATA ${CONFIG_SECTION:+config_cb} return "$RET" } |
主要执行:
DATA="$(/sbin/uci${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} ${LOAD_STATE:+-P /var/state} -S -nexport "$PACKAGE" 2>/dev/null)"
["$RET" != 0 -o -z "$DATA" ] || eval "$DATA"
说明:
1) $UCI_CONFIG_DIR变量为空,-c <path> 设置配置文件的搜索路径,default:/etc.config,这里/sbin/uci在/etc/config目录中搜索配置文件。
2) $PACKAGE变量为wireless。
3) $LOAD_STATE变量为1。
4) -n 名称未命名部分导出(默认)
5) -s 强制严格模式(停止解析器错误,默认)
6) -S 停止严格模式
上面的DATA命令等价于下面:
root@K3C:~# /sbin/uci -P /var/state -S -n export wireless package wireless config wifi-device 'wave513' option type 'mac80211' option vendor 'intel' option path 'pci0000:02/0000:02:00.0/0000:03:00.0' option band '2.4G' option channel '0' option autoch '2' option autoch_skip '12;13' option country 'CN' option wifimode '9' option bw '2' option beamforming '1' option mu_mimo '1' config wifi-iface 'cfg033579' option device 'wave513' option ifname 'wlan2' option network 'lan' option mode 'ap' option ssid '@PHICOMM_6C' option encryption 'none' option hidden '0' option disabled '0' option phic_disabled '0' option txbf '0' config wifi-iface 'cfg053579' option device 'wave513' option ifname 'wlan3' option network 'wan' option mode 'sta' option macaddr '74:7D:24:11:db:70' option disabled '1' config wifi-iface 'cfg073579' option device 'wave513' option ifname 'wlan2.0' option network 'lan' option mode 'ap' option ssid '@PHICOMM_Guest' option encryption 'none' option disabled '1' config wifi-device 'wave523' option type 'mac80211' option vendor 'intel' option band '5G' option path 'pci0000:00/0000:00:00.0/0000:01:00.0' option channel '0' option autoch '2' option autoch_skip '52;56;60;64' option country 'CN' option wifimode '14' option bw '3' option beamforming '1' option mu_mimo '1' config wifi-iface 'cfg0a3579' option device 'wave523' option ifname 'wlan0' option network 'lan' option mode 'ap' option ssid '@PHICOMM_6C_5G' option encryption 'none' option hidden '0' option disabled '0' option txbf '0' config wifi-iface 'cfg0c3579' option device 'wave523' option ifname 'wlan1' option network 'wan' option mode 'sta' option macaddr '74:7D:24:11:db:6e' option disabled '1' config smart_connect 'smartconnect' option enable '0' |
接着uci_load “wireless”分析,eval "$DATA"表示$DATA中每一行都是一个命令,第一行config wifi-device 'wave513'表示config是可执行的函数或命令,config后面的变量表示参数。config命令的定义见下:
/lib/functions.sh (源码:package/base-files/files/lib/functions.sh)
config () { local cfgtype="$1" local name="$2"
export ${NO_EXPORT:+-n} CONFIG_NUM_SECTIONS=$(($CONFIG_NUM_SECTIONS + 1)) name="${name:-cfg$CONFIG_NUM_SECTIONS}" append CONFIG_SECTIONS "$name" [ -n "$NO_CALLBACK" ] || config_cb "$cfgtype" "$name" export ${NO_EXPORT:+-n} CONFIG_SECTION="$name" export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_TYPE=$cfgtype" } |
对于configwifi-device 'wave513',脚本中语句分析如下:
1) CONFIG_SECTION="$name"即CONFIG_SECTION='wave513'
2) CONFIG_${CONFIG_SECTION}_TYPE=$cfgtype即CONFIG_ wave513_TYPE=wifi-device
对于option type 'mac80211',即CONFIG_ wave513_type=mac80211,见下:
/lib/functions.sh (源码:package/base-files/files/lib/functions.sh)
option () { local varname="$1"; shift local value="$*" export ${NO_EXPORT:+-n} "CONFIG_${CONFIG_SECTION}_${varname}=$value" [ -n "$NO_CALLBACK" ] || option_cb "$varname" "$*" } |
上面的流程(即sacn_wifi)把/etc/config/wireless文件所有的配置信息导出到了shell环境变量中,如果wireless文件没有生成,不会导出任何东西,见下:
root@K3C:~# rm /etc/config/wireless root@K3C:~# root@K3C:~# /sbin/uci -P /var/state -S -n export wireless /sbin/uci: Entry not found root@K3C:~# |
附注/lib/functions.sh中相关的3个函数说明:
config_load将配置文件信息导出到shell变量中
config_get获取shell变量的值
config_set设置shell变量的值
接下来,流程继续执行/sbin/wifidetect中的case流程,进入wifi_detect函数:
/sbin/wifi(源码:package/base-files/sbin/wifi)
wifi_detect() { # 对于pros版本,echo "geshifei DRIVERS=$DRIVERS" > /dev/console # 输出geshifei DRIVERS=wave513 wave523 for driver in ${2:-$DRIVERS}; do ( # 对于pros版本,echo "geshifei driver=$driver" > /dev/console # geshifei driver=wave513 # geshifei driver=wave523 if eval "type detect_$driver" 2>/dev/null >/dev/null; then eval "detect_$driver" || echo "$driver: Detect failed" >&2 else echo "$driver: Hardware detection not supported" >&2 fi ); done } DEVICES= DRIVERS= include /lib/wifi scan_wifi case "$1" in down) wifi_updown "disable" "$2";; detect) wifi_detect "$2";; status) ubus_wifi_cmd "status" "$2";; reload) wifi_reload "$2";; reload_legacy) wifi_reload_legacy "$2";; --help|help) usage;; *) ubus call network reload; wifi_updown "enable" "$2";; esac |
上面脚本中eval"detect_$driver"即detect_ wave513.sh($driver是数组中的一个元素,可能有多个)
/lib/wifi/wave513.sh(源码:packages/netifd/files/lib/wifi/wave513.sh)
#!/bin/sh . /lib/functions/system.sh append DRIVERS "wave513" detect_wave513() { wlan3_phy_offset=4 #ssid2g=@PHICOMM_`ifconfig eth0_1 | grep HWaddr | cut -c 54- | sed 's/[ \t]*$//g'` ssid2g=@PHICOMM_`phic_fac -g mac | cut -c 20-` lan_mac=`phic_fac -g mac|cut -d'=' -f 2` wlan3_macaddr=$(macaddr_add "$lan_mac" $wlan3_phy_offset) ssidguest=@PHICOMM_Guest [ -e /etc/config/wireless ] && return cat <<EOF config wifi-device wave513 option type mac80211 option vendor intel option path pci0000:02/0000:02:00.0/0000:03:00.0 option band 2.4G option channel 0 option autoch 2 option autoch_skip "12;13" option country CN option wifimode 9 option bw 2 option beamforming 1 option mu_mimo 1 config wifi-iface option device wave513 option ifname wlan2 option network lan option mode ap option ssid $ssid2g option encryption none option hidden 0 option disabled 0 option txbf 0 …… EOF } |