【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。

 

posted @ 2019-07-16 20:02  稀客  阅读(2990)  评论(0编辑  收藏  举报