zoukankan      html  css  js  c++  java
  • 【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()函数其实是由	argetlinux
    amipsase-filesetcoard.d2_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。

  • 相关阅读:
    Linux文件权限管理
    Linux用户权限管理
    压缩,解压缩 和tar详细介绍
    grep基本详细使用
    Vim文本编辑器详细用法
    Linux命令查找文件目录
    Linux文件增删改
    Linux目录管理
    Linux修改主机名
    Linux创建高级用户并删除
  • 原文地址:https://www.cnblogs.com/yeanz/p/11177959.html
Copyright © 2011-2022 走看看