【openwrt】设备mt7628关于wan侧eth0.1 mac地址固定的问题
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 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随机生成的新值变动。
如果设备所在局域网内的环境时根据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 $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的代码如下:
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是直接调用
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。