openwrt-17.01在mt7628上初始化啓動時,eth0的mac地址老是隨機生成,linux
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目錄下面json
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下app
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 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 '2 3 6t'
這也就致使:一旦設備恢復出廠設置,eth0.1,eth0.2等的mac就會丟失,隨eth0隨機生成的新值變更。dom
若是設備所在局域網內的環境時根據mac分配IP地址的話,這樣就會很麻煩,因此有這樣一個需求:ide
設備每次啓動,無論是重啓仍是恢復出廠,設備的wan 或者 lan側的mac地址都會根據燒寫好在factory區域的值讀取出來應用。函數
因此咱們的解決方案就是在每次啓動時,將factory區寫好的值讀取出來,而後在生成/etc/config/network時,將之寫進去。oop
openwrt的/etc/config下的文件,都是動態生成的,uci-defaults.sh會生成默認的/etc/config下的文件,腳本的函數定義在/package/base-files/files/lib/functions中,這裏咱們主要看一下生成network文件的內容:ui
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 $cpu5 n_ports=$((n_ports + 1)) json_select_array ports json_add_object json_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_object json_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 roles if [ "$role" != "$prev_role" ]; then json_add_object json_add_string role "$role" json_add_string ports "$num" json_close_object prev_role="$role" n_vlan=$((n_vlan + 1)) else json_select_object "$n_vlan" json_get_var port ports json_add_string ports "$port $num" json_select .. fi json_select .. } } _ucidef_finish_switch_roles() { # inherited: $name $n_cpu $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5 local index role roles num device need_tag want_untag port ports json_select switch json_select "$name" json_get_keys roles roles json_select .. json_select .. for index in $roles; do eval "port=\$cpu$(((index - 1) % n_cpu))" json_select switch json_select "$name" json_select ports json_select "$port" json_get_vars num device need_tag want_untag json_select .. json_select .. if [ $n_vlan -gt $n_cpu -o ${need_tag:-0} -eq 1 ]; then num="${num}t" device="${device}.${index}" fi json_select roles json_select "$index" json_get_vars role ports json_add_string ports "$ports $num" json_add_string device "$device" json_select .. json_select .. json_select .. json_select .. json_select_object network local devices json_select_object "$role" # attach previous interfaces (for multi-switch devices) json_get_var devices ifname if ! list_contains devices "$device"; then devices="${devices:+$devices }$device" fi json_select .. _ucidef_set_interface "$role" "$devices" json_select .. done } ucidef_add_switch() { local name="$1"; shift local port num role device index need_tag prev_role local cpu0 cpu1 cpu2 cpu3 cpu4 cpu5 local n_cpu=0 n_vlan=0 n_ports=0 json_select_object switch json_select_object "$name" json_add_boolean enable 1 json_add_boolean reset 1 for port in "$@"; do case "$port" in [0-9]*@*) num="${port%%@*}" device="${port##*@}" need_tag=0 want_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##*:}" ;; esac if [ -n "$num" ] && [ -n "$device$role" ]; then _ucidef_add_switch_port fi unset num device role index need_tag want_untag done json_select .. json_select .. _ucidef_finish_switch_roles } ucidef_add_switch_attr() { local name="$1" local key="$2" local val="$3" json_select_object switch json_select_object "$name" case "$val" in true|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;; [0-9]) json_add_int "$key" "$val" ;; *) json_add_string "$key" "$val" ;; esac json_select .. json_select .. } ucidef_add_switch_port_attr() { local name="$1" local port="$2" local key="$3" local val="$4" local ports i num json_select_object switch json_select_object "$name" json_get_keys ports ports json_select_array ports for i in $ports; do json_select "$i" json_get_var num num if [ -n "$num" ] && [ $num -eq $port ]; then json_select_object attr case "$val" in true|false) [ "$val" != "true" ]; json_add_boolean "$key" $? ;; [0-9]) json_add_int "$key" "$val" ;; *) json_add_string "$key" "$val" ;; esac json_select .. fi json_select .. done json_select .. json_select .. json_select .. } ucidef_set_interface_macaddr() { local network="$1" local macaddr="$2" json_select_object network json_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 dsl json_select_object atmbridge json_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的代碼以下:spa
ucidef_set_interface_macaddr() { local network="$1" local macaddr="$2" json_select_object network json_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.sh ramips_setup_rt3x5x_vlans() { if [ ! -x /sbin/swconfig ]; then # legacy default ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" return fi local wanports="" local lanports="" for port in 5 4 3 2 1 0; do if [ `swconfig dev rt305x port $port get disable` = "1" ]; then continue fi if [ `swconfig dev rt305x port $port get lan` = "0" ]; then wanports="$port:wan $wanports" else lanports="$port:lan $lanports" fi done ucidef_add_switch "rt305x" $lanports $wanports "6t@eth0" } ramips_setup_interfaces() { local board="$1" case $board in mt7628) ucidef_add_switch "switch0" \ "0:wan" "2:lan" "3:lan" "6@eth0" ;; *) RT3X5X=`cat /proc/cpuinfo | egrep "(RT3.5|RT5350)"` if [ -n "${RT3X5X}" ]; then ramips_setup_rt3x5x_vlans else ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" fi ;; esac } ramips_setup_macs() { local board="$1" local lan_mac="" local wan_mac="" case $board in mt7628) 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_flush exit 0
這裏面就很清楚了,原先openwrt的SDK是直接調用code
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。