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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM