MoreRSS

site iconWuSiYu修改

主题涉猎:高性能计算、AI工具链、智能硬件&DIY、Linux、家庭服务器等
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

WuSiYu的 RSS 预览

OpenWrt One 路由器(MT7981,主线op)超频bl2编译教程

2024-12-13 01:31:47

近日OpenWrt官方出了台MT7981的路由器,就是价格非常感人,不过看在它带RTC、POE、GPIO、nor/nand双启动、type-c转串口、还有M2 nvme槽(以及情怀)的份上还是买了一台玩玩。这机器最大的短板就是弱鸡的双核1.3G的MT7981,跑NAT + WiFi到千兆就几乎吃满了CPU(无offload情况),所以想着超个频。

前置知识:MT7981是一个ARMv8-A SoC,一般使用ARM Trusted Firmware(ATF)方式启动,启动顺序为:BL1(BOOT ROM)-> BL2 -> BL31 -> U-boot -> Linux Kernel,BL位于SoC内的ROM,本机从BL2开始位于外置SPI NAND Flash中(通过切换开关进入恢复模式时会使用SPI NOR Flash)。BL2包含了诸多SoC设备初始化代码,其中包含ARMPLL的初始化代码,其为CPU提供高速时钟(PLL初始化前CPU直接使用外部晶振的40MHz时钟)

参考了恩山论坛里的帖子:MT798X CPU超频1.65G/一键修改无线最大功率方法,不过里面的nand固件只有开NMBM(一种NAND Flash坏快管理机制)的,这台机器的主线OpenWrt不使用NMBM,所以用不了。于是自己研究了下,发在这里以供参考,其他没NMBM的nand理论上也能用(但请先确定自己的环境能成功救砖bl2再刷)。

我手里这台能从1.3GHz超到1.7GHz,跑源里的coremark能从4400分提高到5750分。之后再到1.76G时无线高负载时会崩溃重启,到1.8GHz时开机到一半就会死机,大概是这SoC的极限了,求稳可以只超到1.6GHz(此时coremark为5400分)。

方法简而言之就是修改bl2的pll初始化代码,源码位置:arm-trusted-firmware/plat/mediatek/mt7981/drivers/pll/pll.c (mtk-openwrt/arm-trusted-firmware),需要修改其中PLL的频率值和分频值

以下是详细步骤:

  1. 首先下载最新的OpenWrt 24.10源码,或者直接下载OpenWrt One原厂固件的源码包,里面自带config:https://mirror2.openwrt.org/sources/OpenWrt-One-sources-3098b4bf07.tar.xz
  2. 先编译一遍代码,确保能成功编译出openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin这个文件,这个就是NAND Flash上的bl2(不要跟nor-preloader搞混,那个是给nor flash的,这机器的nor flash基本只在救砖的时候用),顺便也能把bl2的源码下载下来,供下一步使用
  3. 编译完后,这里偷个懒,直接编辑openwrt源码目录下的./build_dir/target-aarch64_cortex-a53_musl/arm-trusted-firmware-mediatek-mt7981-spim-nand-ubi-ddr4/arm-trusted-firmware-mediatek-2024.01.17~bacca82a/plat/mediatek/mt7981/drivers/pll/pll.c文件(注意这样直接编辑的话make clean后这个文件的改动就丢了,标准做法是写个patch,这里只是图省事),其他机型请根据实际情况修改路径中的spim-nand-ubi-ddr4,找到正确的软件包

    需要修改mtk_pll_init()函数其中的/* Set PLL frequency */这段,具体修改后的代码和解释如下:
 /* Set PLL frequency */
// 241208: overclock hack
NOTICE("THIS IS AN OVERCLOKING BL2!\n");
NOTICE("set arm freq to 1.60 GHz:\n");


// 设置频率值,SDMPLL fractional mode,这里只需修改高8位
// 原始为2分频,0x82 = 130,实际对应1.3GHz:
// mmio_write_32(ARMPLL_CON1, 0x82000000); /* 1.3G */)
// 由于这个值再大一些的话会设置失败,所以我们要使用1分频(不分频):
// 例如:0x50 = 80,此时对应1.6G; 0x55 = 85,对应1.7G,一次类推

mmio_write_32(ARMPLL_CON1, 0x50000000); /* 1.6G */
// mmio_write_32(ARMPLL_CON1, 0x55000000); /* 1.7G */
NOTICE("ARMPLL_CON1 = 0x%x\n", mmio_read_32(ARMPLL_CON1));

// 设置分频比,原始为2分频,还有个注释掉的4分频(用这个就是650MHz):
// //mmio_setbits_32(ARMPLL_CON0, 0x124); /* divider for 650M */
// mmio_setbits_32(ARMPLL_CON0, 0x114); /* divider for 1.3G */

// 修改为不分频,这个寄存器的4~6位(从0开始数)为分频值,由于默认是001(2分频),这里要将其清零(1分频),然后再设置其余bits
mmio_clrbits_32(ARMPLL_CON0, 0x70); /* divider for >1.3G */
mmio_setbits_32(ARMPLL_CON0, 0x104);
NOTICE("ARMPLL_CON0 = 0x%x\n", mmio_read_32(ARMPLL_CON0));

  1. 再次编译(直接make,不要clean),然后刷入bin/targets/mediatek/filogic/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin到nand中的bl2分区:
    • 对于OpenWrt One,可以用nor flash里带的插U盘刷固件方法(请参考该型号OP wiki页面
    • 对于其他设备,请在刷之前一定要保证有救砖手段,例如亲自试试自己电脑用mtk_uartboot能正常工作后再刷
    • 还可以在上传到现有系统的/tmp里直接刷:
opkg install mtd kmod-mtd-rw
insmod mtd-rw.ko i_want_a_brick
mtd write /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
mtd verify /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
reboot

下面是我编译的bl2:
对于OpenWrt One,可以直接刷入;
对于其他spim-nand-ubi-ddr4且非NMBM机型,也可以尝试直接刷入;
对于NMBM机型,请使用之前论坛里大佬发的超频bl2,也可以自己参考此方法编译,不要直接刷这个版本;

免责声明:由于刷bl2和超频有不小风险,请在刷之前一定要保证有救砖手段;同时超频会导致功耗增加,会增加供电电路的负荷,会有硬件损坏或者折寿的风险。

参考资料:https://mirror2.openwrt.org/docs/MT7981B_Wi-Fi6_Platform_Registers_Open_Part1_V1.0.pdf ,Page 310~311:

OpenWrt One 路由器(MT7981,主线op)超频bl2编译教程最先出现在WuSiYu Blog

白群晖之 在“不受支持”的机型上启用btrfs和快照功能

2024-07-04 21:24:10

400多块买了个便宜的单盘位DS118白群晖当容灾备份机器用,到手发现这个机型居然不支持创建btrfs的存储空间,这就十分难绷了,毕竟数据校验、快照等功能都用不了。

然后发现,尽管最近一代的新品在售的机器都支持btrfs了,但直到2020年群晖NAS的很多低端型号都不支持btrfs,其中20、19、18系列就包括:DS420j,DS220j,DS120j,DS419slim,DS119j,DS418j,DS218play,DS218j,DS118

尽管这些机型的配置确实不高,但btrfs其实也不是会费太多资源的东西,DS118这种机型完全能够支持,毕竟同为RTD1296 CPU的DS218或者同为1G内存的机器DS216+都是支持btrfs的,这么搞大概只是为了差别对待。

实际上,群晖在这些型号上用的系统都是差不多的,底层其实都带有btrfs功能,只是在Web UI上被隐藏了,这些功能的差异被定义在了/etc.defaults/synoinfo.conf中,因此只需要打开SSH功能,连接后执行sudo vim /etc.defaults/synoinfo.conf,加入以下内容即可:

support_btrfs="yes"
support_btrfs_dedupe="yes"
support_iscsi_btrfs_lun="yes"
support_share_snapshot="yes"
support_share_quota="yes"
support_share_user_quota="yes"
support_dr_snap="yes"
support_dr_replica="yes"
max_btrfs_snapshots="65536"
max_snapshot_per_lun="256"
max_snapshots_per_share="1024"
max_dr_replica="64"
max_sdr_replica="64"

若不会使用vim,也可以使用winscp等软件。此时btrfs存储池便可以被创建和使用,但若想使用群晖的快照套件还需要继续操作。

快照功能

DSM 7的快照功能需要使用套件SnapshotReplication和其依赖ReplicationService,然而这两个套件默认无法在不支持btrfs的机型上安装,但我们可以通过暂时修改机型的方式来强行安装,然后修改软件包信息。

1. 首先找到一个相似架构且支持btrfs的机器,比如对于我的DS118,我找到了DS218,然后在 群晖官网 -> DS218下载中心 -> DSM 套件 中找到SnapshotReplication和ReplicationService的安装包,上传到home目录中。

2. 编辑/etc.defaults/synoinfo.conf,修改synobios和unique字段中的机型,例如synobios=”ds118″和unique=”synology_rtd1296_ds118″中的“ds118”改为“ds218”,然后保存。注意:修改机型后,一定要在稍后改回来,期间不要重启,否则系统会无法启动。

3. 安装软件包,在终端中执行(.spk文件的文件名按实际修改):

sudo synopkg install ReplicationService-ds218-1.3.0-0409.spk
sudo synopkg start ReplicationService
sudo synopkg install SnapshotReplication-ds218-7.4.5-1698.spk
sudo synopkg start SnapshotReplication

4. 重要:恢复synoinfo.conf中的机型修改

5. 此时套件虽然已经安装,但机型不匹配,会提示套件损坏,需要我们修改已安装软件包的信息,依次修改下面两个文件:

/var/packages/ReplicationService/INFO
/var/packages/SnapshotReplication/INFO

找到类似model="synology_rtd1296_ds218"的行,修改为机器的真实型号,然后重启,即可正常使用SnapshotReplication进行快照。

疑难解答

如果你这样做后依然无法创建快照,请尝试以下命令(homes为共享文件夹名称,可修改),观察快照能否被创建,或是否有报错:

sudo sh -x synosnapschedtask.sh local share homes

番外

玩过黑群晖的都知道,除了SA6400机型用的Linux内核版本是5.10.55(2021年发布)外,其他机型都还在使用上古4.4.302内核(2016年发布),然而在4.4老内核下,btrfs的压缩功能并不支持zstd算法,因此99%的白群晖NAS的文件系统压缩功能都是快速但效果较差的lzo,包括那些同样上万的机型(不100%确定,群晖毕竟对btrfs进行了不少魔改,也有可能backport了zstd的功能,其他机型的朋友可以看下synoinfo.conf是否包含btrfs_default_compression="zstd"的配置)。

对于黑群晖而言,也有多了一个用SA6400机型的理由。

白群晖之 在“不受支持”的机型上启用btrfs和快照功能最先出现在WuSiYu Blog

解决群晖Photos iOS客户端备份大视频时报错“备份已暂停-空间不足”

2024-06-24 15:29:51

2024/07/24 UPDATE: 最新版的群晖Photos APP似乎已经修复/缓解了此问题

这是由于iOS设备(比如iPhone)的空间不足,使App无法转存较大文件导致的。在iCloud中照片/视频大小较大时,尽管在设置中可能会看到还有大量的剩余空间,但实际上是一种“已占用但可被释放”的状态。卸载一些大App或删除一些照片/视频能够解决,但如果不想这样做的话,可以使用下方的方法强制iOS去释放一些空间(iPhone 13 Pro测试可用):

手机打开 相机,切换到视频,开启“ProRes HDR”录制,此时会提示一个很短的“最长时间”和“正在释放资源”。等待一段时间后,当“最长时间”上升到5分钟左右时,群晖Photos即可正常工作。

解决群晖Photos iOS客户端备份大视频时报错“备份已暂停-空间不足”最先出现在WuSiYu Blog

Intel Core Ultra 笔记本处理器集成NPU初探(Intel AI Boost)

2024-04-08 05:49:33

(更新Roofline图)在笔记本市场中,Intel Ultra系列和AMD 8000系列不约而同的加入了集成NPU作为卖点(甚至对于AMD而言,是其7000系到8000的几乎唯一变化),各路数码新闻中鼓吹最多的便是所谓“AIPC”概念,但却往往对其NPU的具体用法语焉不详,或者将一些实际使用核显进行的推理归功于NPU。

由于本人近日购入了Intel Core Ultra CPU的笔记本,外加科研需要,对其集成NPU进行了一些调研。

省流:通常跑AI推理的实用性不如核显,目前仅支持静态shape的模型,因此无法做LLM推理,通常只做AI抠图这类简单任务。目前最大的用途是Win11自带的“工作室”效果功能,包含摄像头背景虚化、眼神接触、自动缩放取景三个功能,虽然这些CPU/GPU也能跑,但或许用NPU功耗更低。

设备:华硕 ROG 幻16 air (GU605),CPU:Intel Core Ultra 9 185H

打开Intel官网中Ultra 9 185H的资料,其对NPU的描述如下:

注意最后一行,由于OpenVINO是Intel官方的推理框架,后续我们将用它来测试,OpenVINO显然是支持Ultra的NPU的,相关文档如下:https://docs.openvino.ai/2024/openvino-workflow/running-inference/inference-devices-and-modes/npu-device.html,可以看到Ultra中NPU的实际型号为NPU 3720

测试环境实用Win11,其自带NPU的驱动(Linux下则需要自行编译),OpenVINO使用pip方式安装,具体请参考官方文档,注意其并非所有安装方式都有NPU支持。

硬件属性

使用如下代码检测NPU,并打印其硬件属性:

import openvino as ov
import openvino.properties as ovp
print(f"{ov.__version__ = }")

core = ov.Core()
print(f"{core.available_devices = }")

DEVICE = "NPU"
if DEVICE in core.available_devices:
    print(f"- {DEVICE} found")
    supported_properties = core.get_property(DEVICE, ovp.supported_properties)

    for p, w in supported_properties.items():
        try:
            print(f"{p:>40} ({w}) = {core.get_property(DEVICE, p)}")
        except Exception as e:
            print(f"{p:>40} ({w}):", e)
else:
    print(f"- {DEVICE} not found")

在我的设备上输出如下:

ov.__version__ = '2024.0.0-14509-34caeefd078-releases/2024/0'
core.available_devices = ['CPU', 'GPU.0', 'GPU.1', 'GPU.2', 'GPU.3', 'NPU']
- NPU found
                       AVAILABLE_DEVICES (RO) = ['3720']
                               CACHE_DIR (RO) =
                      CACHING_PROPERTIES (RO) = {'DEVICE_ARCHITECTURE': 'RW', 'NPU_COMPILATION_MODE_PARAMS': 'RW', 'NPU_DMA_ENGINES': 'RW', 'NPU_DPU_GROUPS': 'RW', 'NPU_COMPILATION_MODE': 'RW', 'NPU_DRIVER_VERSION': 'RW', 'NPU_COMPILER_TYPE': 'RW', 'NPU_USE_ELF_COMPILER_BACKEND': 'RW'}
                     DEVICE_ARCHITECTURE (RO) = 3720
                               DEVICE_ID (RW) =
                             DEVICE_UUID (RO) = <已打码>
                      ENABLE_CPU_PINNING (RW) = False
                EXCLUSIVE_ASYNC_REQUESTS (RW) = False
                        FULL_DEVICE_NAME (RO) = Intel(R) AI Boost
           INTERNAL_SUPPORTED_PROPERTIES (RO) = {'CACHING_PROPERTIES': 'RW'}
                               LOG_LEVEL (RW) = Level.NO
                          MODEL_PRIORITY (RW) = Priority.MEDIUM
                        NPU_BACKEND_NAME (RO) = LEVEL0
                    NPU_COMPILATION_MODE (RW) =
             NPU_COMPILATION_MODE_PARAMS (RW) =
                       NPU_COMPILER_TYPE (RW) = DRIVER
               NPU_DEVICE_ALLOC_MEM_SIZE (RO) = 0
               NPU_DEVICE_TOTAL_MEM_SIZE (RO) = 33554432
                         NPU_DMA_ENGINES (RW) = -1
                          NPU_DPU_GROUPS (RW) = -1
                      NPU_DRIVER_VERSION (RO) = 1688
                           NPU_MAX_TILES (RW) = -1
                            NPU_PLATFORM (RW) = AUTO_DETECT
                     NPU_PRINT_PROFILING (RW) = NONE
               NPU_PROFILING_OUTPUT_FILE (RW) =
                      NPU_PROFILING_TYPE (RW): Unable to convert function return value to a Python type! The signature was       
        (self: openvino._pyopenvino.Core, device_name: str, property: str) -> object
                            NPU_STEPPING (RW) = -1
            NPU_USE_ELF_COMPILER_BACKEND (RW) = AUTO
                             NUM_STREAMS (RO) = 1
        OPTIMAL_NUMBER_OF_INFER_REQUESTS (RO) = 1
               OPTIMIZATION_CAPABILITIES (RO) = ['FP16', 'INT8', 'EXPORT_IMPORT']
                        PERFORMANCE_HINT (RW) = PerformanceMode.LATENCY
           PERFORMANCE_HINT_NUM_REQUESTS (RW) = 1
                              PERF_COUNT (RW) = False
          RANGE_FOR_ASYNC_INFER_REQUESTS (RO) = (1, 10, 1)
                       RANGE_FOR_STREAMS (RO) = (1, 4)
                    SUPPORTED_PROPERTIES (RO) = {'AVAILABLE_DEVICES': 'RO', 'CACHE_DIR': 'RO', 'CACHING_PROPERTIES': 'RO', 'DEVICE_ARCHITECTURE': 'RO', 'DEVICE_ID': 'RW', 'DEVICE_UUID': 'RO', 'ENABLE_CPU_PINNING': 'RW', 'EXCLUSIVE_ASYNC_REQUESTS': 'RW', 'FULL_DEVICE_NAME': 'RO', 'INTERNAL_SUPPORTED_PROPERTIES': 'RO', 'LOG_LEVEL': 'RW', 'MODEL_PRIORITY': 'RW', 'NPU_BACKEND_NAME': 'RO', 'NPU_COMPILATION_MODE': 'RW', 'NPU_COMPILATION_MODE_PARAMS': 'RW', 'NPU_COMPILER_TYPE': 'RW', 'NPU_DEVICE_ALLOC_MEM_SIZE': 'RO', 'NPU_DEVICE_TOTAL_MEM_SIZE': 'RO', 'NPU_DMA_ENGINES': 'RW', 'NPU_DPU_GROUPS': 'RW', 'NPU_DRIVER_VERSION': 'RO', 'NPU_MAX_TILES': 'RW', 'NPU_PLATFORM': 'RW', 'NPU_PRINT_PROFILING': 'RW', 'NPU_PROFILING_OUTPUT_FILE': 'RW', 'NPU_PROFILING_TYPE': 'RW', 'NPU_STEPPING': 'RW', 'NPU_USE_ELF_COMPILER_BACKEND': 'RW', 'NUM_STREAMS': 'RO', 'OPTIMAL_NUMBER_OF_INFER_REQUESTS': 'RO', 'OPTIMIZATION_CAPABILITIES': 'RO', 'PERFORMANCE_HINT': 'RW', 'PERFORMANCE_HINT_NUM_REQUESTS': 'RW', 'PERF_COUNT': 'RW', 'RANGE_FOR_ASYNC_INFER_REQUESTS': 'RO', 'RANGE_FOR_STREAMS': 'RO', 'SUPPORTED_PROPERTIES': 'RO'}

ResNet-50 单batch推理测试

使用fp16精度,batchsize = 1,重复2000次推理,单次耗时如下:

avg latency = 3.462ms

根据估计的ResNet-50的计算量,其达到的roofline性能大致如下(不准确,仅预估):

RESNET50_M_FLOP = 8206.520    # approximate
RESNET50_M_MEM_RW = 105.763   # approximate

avg latency = 0.0034620463848114014
reached GFLOP/s: 2370.4246
reached GB/s: 30.5493

达到的fp16性能约为2.35 TFLOP/s,由于是bs=1的推理,离上限值应该还是有不小距离的

功耗的话,用HWInfo64可看到“System Agent Power”在推理时从4w左右增加到10w左右,即6w,不确定这其中是否都是NPU的功耗,否则这个能效表现其实一般。不过在打开全部的“Windows工作室效果”时,System Agent功耗仅上升了1~2w,此时任务管理器中NPU利用率约为46%

多模型Roofline测试

这是多个模型在其上的测试,达到的FLOP/s和内存带宽基于理论估计,模型列表如下,不存在则表示(在当时)尚无法成功运行。

可以看出,其优化程度较差,远远无法跑到理论性能fp16: 5.7 TFLOP/s, int8: 11.5TOP/s(计算方法:2048 fp16 MACs or 4096 int8 MACs per cycle @ 1.4GHz)。也有文章指出,其可能无法利用全部的内存带宽,具有远远更低的内存墙,但依然无法解释为何ResNet-34的性能也很低。

Intel Core Ultra 笔记本处理器集成NPU初探(Intel AI Boost)最先出现在WuSiYu Blog

备忘:OpenWrt在旁路由下Ping通但TCP不通的解决办法

2023-08-06 04:49:07

这里的背景是OpenWRT作为旁路由(aka. 旁路网关,单臂路由,透明网关等),没有一个太准确的叫法,具体的指另一台“主路由”连接公网并作NAT,OpenWrt不启用NAT,用户设备的上行流量先经过OpenWrt旁路由转发到“主路由”,下行时流量直接通过由主路由发送到用户设备,不经过OpenWrt旁路由。主要优点在于下行带宽不会受OpenWrt性能的影响,且OpenWrt设备故障或维护时,可手动(或配置自动)切换到主路由。(OpenWRT旁路由可以是单臂路由,也可以有另一根独立的线路连接到主路由,避免带宽限制,如我之前的文章)

但由于上行和下行的通路不同,仅有部分流量会经过OpenWrt,会导致TCP的conntrack出现问题。

具体表现是:已经正确设置了路由,且能用户设备能ping通外网,但对外进行TCP不通,若在用户设备上抓包分析会看到:

  • (从用户设备,客户端)发送SYN
  • 收到(来自公网设备,服务器)SYN + ACK
  • 发送ACK
  • 发送通信内容(payload)
  • (未收到回应ACK)
  • 重复收到SYN + ACK(多次)
  • (重传)发送通信内容(payload)
  • (还是没有回应ACK)

不难看出,这是由于客户端发送的ACK在中途被丢弃了,使得虽然客户端认为TCP连接已经建立,但在服务端看来没有,因此客户端发送的payload不会被确认,而服务器则会重传SYN + ACK,继续等待客户端的ACK。

这种现象和OpenWrt的conntrack有关,由于服务器回应的SYN + ACK没有经过OpenWrt,使得OpenWrt没有正确追踪TCP连接。在一些特定情况下,OpenWrt认为客户端后续的数据包是“无效数据包”,并丢弃,包括客户端发送的ACK。

在OpenWrt中解决的方法也很简单,首先在“防火墙”页面中关闭“丢弃无效数据包”

其次,若OpenWrt通过独立线路(在防火墙的WAN Zone)连接主路由,则在一些特定情况下(比如因为一些组网需求,对一些内网网段开启了masquerade),还要打开WAN Zone – 编辑 – 连接追踪设置 – 允许“无效”流量,如下图:

具体conntrack的工作方式和该问题的出现条件,有待进一步验证

备忘:OpenWrt在旁路由下Ping通但TCP不通的解决办法最先出现在WuSiYu Blog

为DietPi系统设置网卡优先级

2023-07-09 22:29:09

当你的设备同时带有WiFi和有线网时,你就会希望让系统优先使用有线网,一些系统(比如使用NetworkManager的)会自动完成这件事,但DietPi并没有。

各种Linux的网络配置方案会各不相同,比如桌面Linux和新一些的服务器Linux会使用较为现代的NetworkManager,Ubuntu搞过一个netplan,树莓派官方系统Raspbian直接用dhcpcd来管理网络,而DietPi使用Debian传统的/etc/network/interface(ifupdown),这篇文章的方法也适用于其他使用/etc/network/interface配置方案的系统。

首先编辑/etc/network/interface,为接口设置metric值,格式类似metric 100,数字越小表示表示优先级越高,DietPi中修改完类似如下(注意该文件在dietpi-config中调整网络接口设置后会被覆盖):

root@DietPi:~# cat /etc/network/interfaces
# Location: /etc/network/interfaces
# Please modify network settings via: dietpi-config
# Or create your own drop-ins in: /etc/network/interfaces.d/

# Drop-in configs
source interfaces.d/*

# Ethernet
allow-hotplug eth0
iface eth0 inet dhcp
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
#dns-nameservers 192.168.10.2
metric 100

# WiFi
allow-hotplug wlan0
iface wlan0 inet dhcp
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
#dns-nameservers 192.168.10.2
pre-up iw dev wlan0 set power_save off
post-down iw dev wlan0 set power_save on
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
metric 600

此外,经过测试,这里的metric值不会对本地网络路由中的metric生效(下面的后两行),导致在访问内网机器时,(甚至是ssh 内网ip时的回程),仍然可能使用错误的网卡:

root@DietPi:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         openwrt         0.0.0.0         UG    100    0        0 eth0
default         openwrt         0.0.0.0         UG    600    0        0 wlan0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 wlan0

解决方法是安装ifmetric软件包,但我们不需要用这个命令其手动设置metric,而是ifmetric会在接口启动时自动根据/etc/network/interface中的配置进行设置(软件包提供了/etc/network/if-up.d/ifmetric)。

随后重启网络服务,可以发现metric被正确设置了:

root@DietPi:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         openwrt         0.0.0.0         UG    100    0        0 eth0
default         openwrt         0.0.0.0         UG    600    0        0 wlan0
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     600    0        0 wlan0

为DietPi系统设置网卡优先级最先出现在WuSiYu Blog