openwrt-17.01在mt7628上初始化启动时,eth0的mac地址总是随机生成,
mtk_soc_eth 10100000.ethernet: generated random MAC address e6:d7:5d:88:8c:8f
mtk_soc_eth 10100000.ethernet eth0: mediatek frame engine at 0xb0100000, irq 5
每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下面
root@LEDE:/# cat sys/class/net/eth0/address
e6:d7:5d:88:8c:8f
openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址,再生成eth0.1,eth0.2......,生成后的mac地址会保存再/etc/config/network下
root@LEDE:/etc/config# cat 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 'fd59:fc20:6dd9::/48'config interface 'wan'option ifname 'eth0.1'option proto 'dhcp'config device 'wan_dev'option name 'eth0.1'option macaddr '00:1e:73:6e:5a:95'config interface 'wan6'option ifname 'eth0.1'option proto 'dhcpv6'config interface 'lan'option type 'bridge'option ifname 'eth0.2'option proto 'static'option ipaddr '192.168.1.1'option netmask '255.255.255.0'option ip6assign '60'config device 'lan_dev'option name 'eth0.2'option macaddr '00:1e:73:6e:5a:94'config switchoption name 'switch0'option reset '1'option enable_vlan '1'config switch_vlanoption device 'switch0'option vlan '1'option ports '0 6t'config switch_vlanoption device 'switch0'option vlan '2'option ports '2 3 6t'
这也就导致:一旦设备恢复出厂设置,eth0.1,eth0.2等的mac就会丢失,随eth0随机生成的新值变动。
如果设备所在局域网内的环境时根据mac分配IP地址的话,这样就会很麻烦,所以有这样一个需求:
设备每次启动,不管是重启还是恢复出厂,设备的wan 或者 lan侧的mac地址都会根据烧写好在factory区域的值读取出来应用。
所以我们的解决方案就是在每次启动时,将factory区写好的值读取出来,然后在生成/etc/config/network时,将之写进去。
openwrt的/etc/config下的文件,都是动态生成的,uci-defaults.sh会生成默认的/etc/config下的文件,脚本的函数定义在/package/base-files/files/lib/functions中,这里我们主要看一下生成network文件的内容:
ucidef_set_interface_lan() {json_select_object network_ucidef_set_interface lan "$@"json_select ..
}ucidef_set_interface_wan() {json_select_object network_ucidef_set_interface wan "$@"json_select ..
}ucidef_set_interfaces_lan_wan() {local lan_if="$1"local wan_if="$2"json_select_object network_ucidef_set_interface lan "$lan_if"_ucidef_set_interface wan "$wan_if"json_select ..
}ucidef_set_interface_raw() {json_select_object network_ucidef_set_interface "$@"json_select ..
}_ucidef_add_switch_port() {# inherited: $num $device $need_tag $want_untag $role $index $prev_role# inherited: $n_cpu $n_ports $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5n_ports=$((n_ports + 1))json_select_array portsjson_add_objectjson_add_int num "$num"[ -n "$device" ] && json_add_string device "$device"[ -n "$need_tag" ] && json_add_boolean need_tag "$need_tag"[ -n "$want_untag" ] && json_add_boolean want_untag "$want_untag"[ -n "$role" ] && json_add_string role "$role"[ -n "$index" ] && json_add_int index "$index"json_close_objectjson_select ..# record pointer to cpu entry for lookup in _ucidef_finish_switch_roles()[ -n "$device" ] && {export "cpu$n_cpu=$n_ports"n_cpu=$((n_cpu + 1))}# create/append object to role list[ -n "$role" ] && {json_select_array rolesif [ "$role" != "$prev_role" ]; thenjson_add_objectjson_add_string role "$role"json_add_string ports "$num"json_close_objectprev_role="$role"n_vlan=$((n_vlan + 1))elsejson_select_object "$n_vlan"json_get_var port portsjson_add_string ports "$port $num"json_select ..fijson_select ..}
}_ucidef_finish_switch_roles() {# inherited: $name $n_cpu $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5local index role roles num device need_tag want_untag port portsjson_select switchjson_select "$name"json_get_keys roles rolesjson_select ..json_select ..for index in $roles; doeval "port=\$cpu$(((index - 1) % n_cpu))"json_select switchjson_select "$name"json_select portsjson_select "$port"json_get_vars num device need_tag want_untagjson_select ..json_select ..if [ $n_vlan -gt $n_cpu -o ${need_tag:-0} -eq 1 ]; thennum="${num}t"device="${device}.${index}"fijson_select rolesjson_select "$index"json_get_vars role portsjson_add_string ports "$ports $num"json_add_string device "$device"json_select ..json_select ..json_select ..json_select ..json_select_object networklocal devicesjson_select_object "$role"# attach previous interfaces (for multi-switch devices)json_get_var devices ifnameif ! list_contains devices "$device"; thendevices="${devices:+$devices }$device"fijson_select .._ucidef_set_interface "$role" "$devices"json_select ..done
}ucidef_add_switch() {local name="$1"; shiftlocal port num role device index need_tag prev_rolelocal cpu0 cpu1 cpu2 cpu3 cpu4 cpu5local n_cpu=0 n_vlan=0 n_ports=0json_select_object switchjson_select_object "$name"json_add_boolean enable 1json_add_boolean reset 1for port in "$@"; docase "$port" in[0-9]*@*)num="${port%%@*}"device="${port##*@}"need_tag=0want_untag=0[ "${num%t}" != "$num" ] && {num="${num%t}"need_tag=1}[ "${num%u}" != "$num" ] && {num="${num%u}"want_untag=1};;[0-9]*:*:[0-9]*)num="${port%%:*}"index="${port##*:}"role="${port#[0-9]*:}"; role="${role%:*}";;[0-9]*:*)num="${port%%:*}"role="${port##*:}";;esacif [ -n "$num" ] && [ -n "$device$role" ]; then_ucidef_add_switch_portfiunset num device role index need_tag want_untagdonejson_select ..json_select .._ucidef_finish_switch_roles
}ucidef_add_switch_attr() {local name="$1"local key="$2"local val="$3"json_select_object switchjson_select_object "$name"case "$val" intrue|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;;[0-9]) json_add_int "$key" "$val" ;;*) json_add_string "$key" "$val" ;;esacjson_select ..json_select ..
}ucidef_add_switch_port_attr() {local name="$1"local port="$2"local key="$3"local val="$4"local ports i numjson_select_object switchjson_select_object "$name"json_get_keys ports portsjson_select_array portsfor i in $ports; dojson_select "$i"json_get_var num numif [ -n "$num" ] && [ $num -eq $port ]; thenjson_select_object attrcase "$val" intrue|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;;[0-9]) json_add_int "$key" "$val" ;;*) json_add_string "$key" "$val" ;;esacjson_select ..fijson_select ..donejson_select ..json_select ..json_select ..
}ucidef_set_interface_macaddr() {local network="$1"local macaddr="$2"json_select_object networkjson_select "$network"[ $? -eq 0 ] || {json_select ..return}json_add_string macaddr "$macaddr"json_select ..json_select ..
}ucidef_add_atm_bridge() {local vpi="$1"local vci="$2"local encaps="$3"local payload="$4"json_select_object dsljson_select_object atmbridgejson_add_int vpi "$vpi"json_add_int vci "$vci"json_add_string encaps "$encaps"json_add_string payload "$payload"json_select ..json_select ..
}
生成wan,lan侧mac的代码如下:
ucidef_set_interface_macaddr() {local network="$1"local macaddr="$2"json_select_object networkjson_select "$network"[ $? -eq 0 ] || {json_select ..return}json_add_string macaddr "$macaddr"json_select ..json_select ..
}
ucidef_set_interface_macaddr()函数其实是由\target\linux\ramips\base-files\etc\board.d\02_network调用,内容如下(其他型号的board已去掉)
#!/bin/sh. /lib/functions.sh
. /lib/ramips.sh
. /lib/functions/uci-defaults.sh
. /lib/functions/system.shramips_setup_rt3x5x_vlans()
{if [ ! -x /sbin/swconfig ]; then# legacy defaultucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"returnfilocal wanports=""local lanports=""for port in 5 4 3 2 1 0; doif [ `swconfig dev rt305x port $port get disable` = "1" ]; thencontinuefiif [ `swconfig dev rt305x port $port get lan` = "0" ]; thenwanports="$port:wan $wanports"elselanports="$port:lan $lanports"fidoneucidef_add_switch "rt305x" $lanports $wanports "6t@eth0"
}ramips_setup_interfaces()
{local board="$1"case $board inmt7628)ucidef_add_switch "switch0" \"0:wan" "2:lan" "3:lan" "6@eth0";;*)RT3X5X=`cat /proc/cpuinfo | egrep "(RT3.5|RT5350)"`if [ -n "${RT3X5X}" ]; thenramips_setup_rt3x5x_vlanselseucidef_set_interfaces_lan_wan "eth0.1" "eth0.2"fi;;esac
}ramips_setup_macs()
{local board="$1"local lan_mac=""local wan_mac=""case $board inmt7628)lan_mac=$(hexdump -v -s 0x28 -n 6 -e '2/1 "%02x:"' /dev/mtd2)wan_mac=$(hexdump -v -s 0x2e -n 6 -e '2/1 "%02x:"' /dev/mtd2)[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" ${lan_mac%:}[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" ${wan_mac%:};;*)lan_mac=$(cat /sys/class/net/eth0/address)wan_mac=$(macaddr_add "$lan_mac" 1)[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac;;esac}board_config_update
board=$(ramips_board_name)
ramips_setup_interfaces $board
ramips_setup_macs $board
board_config_flushexit 0
这里面就很清楚了,原先openwrt的SDK是直接调用
lan_mac=$(mtd_get_mac_binary factory 40)
wan_mac=$(mtd_get_mac_binary factory 46)
40和46对应的十六进制数就是lan和wan的偏移量0x28和0x2E,但是这样的修改没有用,lan_mac,wam_mac还是根据eth0生成,所以我们直接读取factory里面的值:
lan_mac=$(hexdump -v -s 0x28 -n 6 -e '2/1 "%02x:"' /dev/mtd2)
wan_mac=$(hexdump -v -s 0x2e -n 6 -e '2/1 "%02x:"' /dev/mtd2)
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" ${lan_mac%:}
[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" ${wan_mac%:}
Done。