普通视图

发现新文章,点击刷新页面。
昨天以前WuSiYu Blog

Fedora + libvirt 下在宿主关机时安全关闭虚拟机

作者 WuSiYu
2025年7月29日 19:36

很简单的一个问题,但过程比较难绷,所以特此记录

为了能方便的既跑虚拟机,又跑Docker容器,我经常使用Fedora Server来作为宿主系统,配合红帽官方的Cockpit面板进行管理,其对虚拟机(基于libvirt/qemu/kvm)和容器(官方只支持Podman)的支持尚可。

但其在关机时虚拟机会直接被强制停止,并不安全。我们希望在直接对宿主机进行关机或重启时,其能够像PVE、EXSi等虚拟化系统一样发起并等待虚拟机的安全关机。

首先这个功能libvirt是提供了的,由libvirt-guests.service实现,但不知为何在Fedora并没有被默认启用。

进一步的,我们发现其配置文件/etc/sysconfig/libvirt-guests从某个版本起被移除了(你还能搜到关于这件事的相关讨论,暴躁用户 vs 倔强maintainer),更不方便我们配置了,因此首先恢复其内容:

# URIs to check for running guests
# example: URIS='default xen:/// vbox+tcp://host/system lxc:///'
#URIS=default

# action taken on host boot
# - start   all guests which were running on shutdown are started on boot
#           regardless on their autostart settings                                 
# - ignore  libvirt-guests init script won't start any guest on boot, however,     
#           guests marked as autostart will still be automatically started by      
#           libvirtd                                                               
#ON_BOOT=start                                                                     

# Number of seconds to wait between each guest start. Set to 0 to allow            
# parallel startup.
#START_DELAY=0

# action taken on host shutdown
# - suspend   all running guests are suspended using virsh managedsave
# - shutdown  all running guests are asked to shutdown. Please be careful with
#             this settings since there is no way to distinguish between a
#             guest which is stuck or ignores shutdown requests and a guest
#             which just needs a long time to shutdown. When setting
#             ON_SHUTDOWN=shutdown, you must also set SHUTDOWN_TIMEOUT to a
#             value suitable for your guests.
ON_SHUTDOWN=shutdown

# If set to non-zero, shutdown will suspend guests concurrently. Number of
# guests on shutdown at any time will not exceed number set in this variable.
#PARALLEL_SHUTDOWN=0

# Number of seconds we're willing to wait for a guest to shut down. If parallel
# shutdown is enabled, this timeout applies as a timeout for shutting down all
# guests on a single URI defined in the variable URIS. If this is 0, then there
# is no time out (use with caution, as guests might not respond to a shutdown
# request). The default value is 300 seconds (5 minutes).
#SHUTDOWN_TIMEOUT=300

# If non-zero, try to bypass the file system cache when saving and
# restoring guests, even though this may give slower operation for
# some file systems.
#BYPASS_CACHE=0

注意我这里设置的是ON_SHUTDOWN=shutdown,因为对于有PCIe设备直通的虚拟机suspend可能无法使用。

然后启用libvirt-guests.service服务:

sudo systemctl enable --now libvirt-guests

然后在虚拟机关机时(或libvirt-guests服务关闭时)正在运行的虚拟机应当能正常关机,并且这些虚拟机会在宿主机下次启动时自动启动(恢复状态)。

这里不得不吐槽一下红帽经常搞一些breaking change,之前升级就被Network UPS Tools (NUT)的服务配置坑过一次

Fedora + libvirt 下在宿主关机时安全关闭虚拟机最先出现在WuSiYu Blog

群晖ddrescue与暂时禁用USB外接硬盘自动挂载

作者 WuSiYu
2025年3月4日 11:23

来自每天一个没用的小知识

对一个挂掉SATA固态做数据恢复,症状大概是可以读,但一旦进行写入就会掉盘。在对数据做镜像时,直接通过USB3.0转SATA线插在群晖NAS机器上,并将镜像保存在其中的大容量硬盘上是个方便的做法。

首先安装ddrescue,添加SynoCommunity软件源,并安装SynoCli Disk Tools软件包即可。(如果你的网不是很好,也可以从这里手动下载:https://synocommunity.com/package/synocli-disk

接下来,由于群晖会自动挂载USB外接硬盘等设备,会对其产生写入,这是我们不希望发生的。群晖没有选项可以关闭自动挂载功能,但经过一些尝试发现,我们可以通过暂停(SIGSTOP)/usr/syno/sbin/hotplugd进程的方法暂时阻止其自动挂载的行为。

登入SSH后执行:

sudo pkill -STOP -f /usr/syno/sbin/hotplugd

注意不要直接将其杀死,否则其会自动重启。若再去阻止其自启就太过麻烦了,我们只需要暂时用SIGSTOP信号暂停其执行,让其失去功能即可。之后使用sudo pkill -CONT ...或直接重启机器后便可恢复。

而后便可以接入硬盘并使用ddrescue进行数据恢复。

群晖ddrescue与暂时禁用USB外接硬盘自动挂载最先出现在WuSiYu Blog

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

作者 WuSiYu
2024年4月8日 05:49

(更新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

为DietPi系统设置网卡优先级

作者 WuSiYu
2023年7月9日 22:29

当你的设备同时带有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

RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址

作者 WuSiYu
2023年6月17日 22:16

Update:较新的RouterOS v7.11已经带有了此功能(未测试),或许无需再使用该脚本

摘要:这篇文章给出了一种对于Router OS的更“优雅“的WireGuard Peer Endpoint(动态)域名自动刷新脚本,提出了一种在配置项的COMMENT中填写变量(比如域名)的方法,而不是hardcode在脚本中。这种思想也可用于其他对于RouterOS功能扩展的脚本。

背景:这个需求来源于Router OS的一个bug或者毛病,即当配置WireGuard Peer的连接地址(Endpoint)时,你虽然可以使用域名,但其仅会在启动时被解析,之后如果域名的IP发生变化,是不回重新解析的。这就导致如果你使用DDNS域名作为Endpoint,那在其IP变化后连接就会丢失,不会自动恢复,直到你重启接口或者机器。

解决上述问题的方式就是编写一个Router OS的脚本来解析域名,并将其IP更新到WireGuard Peer的Endpoint项中,然后将这个脚本添加在Schedule中,定时自动执行。由于Endpoint项会被脚本填写的IP覆盖,因此要在别的地方记录其域名。这个脚本目前网络上流传的版本如下:

# 网络上流传的版本,灵活性较差
:local wgInterface
:local wgPeerDns

:set wgInterface "wireguard1"
:set wgPeerDns "xxxxxxx.xxx-ddns.net"

:if ([interface wireguard peers get number=[find interface="$wgInterface"] value-name=endpoint-address] != [resolve $wgPeerDns]) do={
  interface wireguard peers set number=[find interface="$wgInterface"] endpoint-address=[/resolve $wgPeerDns]
}

可以看出其WireGuard的接口和域名都hardcode(写死)在了脚本中,并且其默认一个接口只有一个Peer,无法适用于一个接口有多个Peer的情况。虽然我们很容易就能对其进行修改让其支持,但仍是繁琐的,比如要根据pubkey或设置特定的Comment用于区分不同Peer,并在脚本中对照配置项进行填写,带来了维护上的繁琐。

方法:既然这类脚本的目的是对Router OS本身的功能进行扩展,那么对于配置时最自然的方式,就是可以在配置项原有的界面中一并填写相关的变量(比如此处的域名),虽然Router OS中我们不能给配置项再添加一个字段,但我们其实可以充分利用Comment字段来存放我们的变量,有点像加在linux命令前的环境变量。并且Comment本身就和每个配置项直接关联,不需要我们再去维护其对应关系。

例如,我们就可以在Comment里写上DOMAIN_ENDPOINT=xxxxxxx.xxx-ddns.net来表示域名,像下面这样:

相应的这种更优雅一些的脚本如下:

/interface/wireguard/peers

:local CommentPrefix "DOMAIN_ENDPOINT="

:foreach i in=[find where comment~"^$CommentPrefix.*\$"] do={
    :local comment [get number=$i comment]
    :local ip [:resolve [:pick $comment [:len $CommentPrefix] [:len $comment]]]
    
    :if ([get number=$i endpoint-address] != $ip) do={
        set number=$i endpoint-address=$ip
    }
}

由于所有配置相关的信息都在Comment中填写了,哪怕之后还需要修改Peer的地址或者添加新的Peer和接口,也不需要对脚本进行任何更新。同时,如果Comment中没有“DOMAIN_ENDPOINT=”这样的字符串,脚本不回对其做任何操作;比起直接将整个Comment区域作为特定的变量值,这样不会有任何副作用,并且对于维护时该变量的含义是“自解释”的。

结论:这是对于WireGuard Peer动态域名的一个实用的脚本,但对于这种“通过Comment区的特定语法来配合一个通用的脚本来对Router OS的功能进行扩展”的思想,这只是一个简单的例子。实际上,还可以实现如:兼容与普通Comment一起使用,可以填写多个变量等,就“交给读者作为练习”了。

RouterOS脚本之更优雅的使用(动态)域名作为WireGuard Peer地址最先出现在WuSiYu Blog

解决更新Fedora 37后新版NUT(Network UPS Tools)无法连接UPS设备的问题

作者 WuSiYu
2023年1月22日 06:33

在Fedora老版本上配置了NUT,每次开机后NUT服务均能正常与UPS连接;但在将系统更新至Fedora 37后,开机后NUT服务提示无法连接UPS,会周期性在终端广播报错,如果通过upsc指令查询UPS状态就会报错,如题图所示。

这个原因是因为在新版的nut软件包中,对于nut-driver服务的systemd配置文件发生了变化,旧的nut-driver.service被移除了[1],取而代之的是nut-driver-enumerator.service,后者再去启动nut-driver@<ups_name>.service(其中<ups_name>为配置文件中的UPS名称)[2]

由于原本配置时enable的是nut-driver.service,现已不存在,而更新后nut-driver-enumerator.service并未被enable,因此nut-driver服务没有启动,导致nut-server、upsd和upsc等组件无法连接UPS。

解决方法也很简单,执行以下命令把nut-driver-enumerator.service启用即可:

systemctl enable --now nut-driver-enumerator.service

不得不说这个更新有点坑,但这也是系统跨版本更新时没办法的事情。

[1] https://packages.fedoraproject.org/pkgs/nut/nut/fedora-36.html
[2] https://packages.fedoraproject.org/pkgs/nut/nut/fedora-37.html

解决更新Fedora 37后新版NUT(Network UPS Tools)无法连接UPS设备的问题最先出现在WuSiYu Blog

适合树莓派/SBC的MLC长寿命sd卡?SanDisk Max Endurance 32G tf卡简单测试

作者 WuSiYu
2023年1月16日 03:50

自从读研之后好久没更新了,正巧前几天树莓派上用的tf卡(micro SD card)又双叒叕挂了一张,启动后出现写I/O错误,文件系统变为只读(fsck没有效果),这次挂的还是Kingston CANVAS Go! Plus,这卡指标有V30 A2,也不算便宜货了,但还是挂的很突然。

普通的tf卡本就是用分级最差的一档NAND颗粒制作的,据一些资料说目前流行的tf卡采用的都是QLC模式,毫无疑问寿命很差。同时,市场上也有一些长寿命(Endurance)类型的tf卡,但其中一些仅仅是换个名字,寿命没有本质区别,比如之前买过的banq high endurance系列,同样挂了一两个,而且是突然不认盘的那种。

不过这次测试的SanDisk Max Endurance系列似乎是更靠谱些的,其给出了在行车记录仪场景下的寿命内可录制时间,写入标准为26Mbps,即3.25MB/s速度写入。32G版本的寿命为15000小时(其他版本根据容量成比例),换算成P/E和TBW如下:

P/E = 3.25/1024*15000*3600/32 = 5355.8349609375 (cycle)

TBW = 3.25/1024/1024*15000*3600 = 167.3698425293 (TB)

可以说达到了TLC企业级固态和一些MLC固态的水平,另外根据外网的逆向工程(链接:https://ripitapart.com/2020/07/16/reverse-engineering-and-analysis-of-sandisk-high-endurance-microsdxc-card/),这个tf卡使用了3D TLC NAND,并工作在MLC模式下(pMLC)。

类似的产品还有Samsung PRO Endurance,32G版本的寿命为17520小时,还要更长些,但在64G及以下的版本写入速度不佳,不足30MB/s,32G版本的性价比也不高,因此没有选择。如果需要128G或以上容量可以考虑这个。

同时SanDisk还有一个SanDisk High Endurance的系列,略微便宜,但寿命低很多,32G版本的寿命仅为2500小时,虽然应该也比普通tf卡高不少了,但不如MAX系列一步到位。

下面简单在树莓派4B上测试一下性能,这张卡标称读100MB/s,写40MB/s,不过在树莓派上受硬件限制,任何tf卡的连续读的上限都只有30MB/s左右(树莓派4B),也是正常现象了,测试是Raspbian自带的sdcard 测试项目,结果如下:

顺序读4k随机读4k随机写
30.354 MB/s2461 IOPS911 IOPS

可以看到,它的随机性能可以达到A1标准,但离A2标准还比较远(卡本身没有给出随机性能的指标),但也可能是树莓派硬件限制了。

这个性能在树莓派上是能达到这个项目的“通过”标准的(10M/1500/500IOPS),由于其吊打普通tf卡的长寿命的优点,我认为这是最适合树莓派或者其他SBC的tf卡类型,说不定卡都能把板子送走。当然代价则是同等容量下相对便宜tf卡近4倍的价格。

适合树莓派/SBC的MLC长寿命sd卡?SanDisk Max Endurance 32G tf卡简单测试最先出现在WuSiYu Blog

Mikrotik CCR2004-1G-2XS-PCIe 简单带宽测试

作者 WuSiYu
2022年6月21日 18:01

CCR2004-1G-2XS-PCIe是一个有趣的设备,准确的讲它是一个“PCIe网卡形式的路由器”,与普通路由器不同的是,它除了挡板上的两个SFP28 25G网口和一个RJ45千兆管理口这些“物理网口”,其还通过PCIe 3.0 x8有着4个直连主机的25G虚拟网络接口,在主机看来,这相当于4个固定直连到路由器上的“普通”网络接口;而与一些Smart NIC不同的是,CCR2004-1G-2XS-PCIe并不能为主机提供任何offload功能,RDMA和sr-iov等功能应该也是不支持的,它也没有内置交换机芯片,所有从主机到物理网口的数据都需要CCR2004-1G-2XS-PCIe的CPU来转发,换句话说,如果你只是把它当网卡用,那它还不如普通网卡,它的合理用途应当是组成一个服务器和路由器的All-in-one方案。不过无论是作为“集成路由器”还是“普通网卡”的用途都值得我们实践测试一下,这便是这篇文章接下来的部分。

由于没有25G环境,本文在10G内网下测试,CCR2004-1G-2XS-PCIe通过SFP+ DAC连接至CRS305 10G交换机上,交换机上的另一台机器使用x540双万兆电口网卡。CCR2004-1G-2XS-PCIe被安装在一台Core i9-10850k迷你主机(以下简称为host)的PCIe 3.0 x16槽上(CPU直连通道),系统为Fedora Workstation 36。

在host上的一些关于此设备的信息节选:

# lspci
01:00.0 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
01:00.1 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
01:00.2 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet
01:00.3 Ethernet controller: Qualcomm Atheros AR8151 v2.0 Gigabit Ethernet

# dmesg
[    1.971577] atl1c 0000:01:00.0: enabling device (0000 -> 0002)
[    1.994014] atl1c 0000:01:00.1: enabling device (0000 -> 0002)
[    2.014003] atl1c 0000:01:00.2: enabling device (0000 -> 0002)
[    2.034983] atl1c 0000:01:00.3: enabling device (0000 -> 0002)
[    2.057479] atl1c 0000:01:00.1 enp1s0f1: renamed from eth1
[    2.073979] atl1c 0000:01:00.0 enp1s0f0: renamed from eth0
[    2.090921] atl1c 0000:01:00.2 enp1s0f2: renamed from eth2
[    2.105991] atl1c 0000:01:00.3 enp1s0f3: renamed from eth3
[    8.700933] atl1c 0000:01:00.0: atl1c: enp1s0f0 NIC Link is Up<25000 Mbps Full Duplex>
[    8.703098] atl1c 0000:01:00.1: atl1c: enp1s0f1 NIC Link is Up<25000 Mbps Full Duplex>
[    8.705370] atl1c 0000:01:00.2: atl1c: enp1s0f2 NIC Link is Up<25000 Mbps Full Duplex>
[    8.707589] atl1c 0000:01:00.3: atl1c: enp1s0f3 NIC Link is Up<25000 Mbps Full Duplex>

# ethtool enp1s0f0
Settings for enp1s0f0:
	Supported ports: [ TP ]
	Supported link modes:   10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	Supported pause frame use: No
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  Not reported
	Advertised pause frame use: No
	Advertised auto-negotiation: Yes
	Advertised FEC modes: Not reported
	Speed: 25000Mb/s
	Duplex: Full
	Auto-negotiation: on
	Port: Twisted Pair
	PHYAD: 0
	Transceiver: internal
	MDI-X: Unknown
	Supports Wake-on: pg
	Wake-on: d
        Current message level: 0x0000003f (63)
                               drv probe link timer ifdown ifup
	Link detected: yes

# ethtool -i enp1s0f0
driver: atl1c
version: 5.17.9-300.fc36.x86_64
firmware-version:
expansion-rom-version:
bus-info: 0000:01:00.0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: yes
supports-priv-flags: no

可以看出其在Linux下使用atl1c驱动,连接速度和功能正常,但lspci下型号识别是有问题的。

交换性能测试(“软交换机”模式)

这个模式下所有接口都在一个bridge中,在host上只启用第一个虚拟网口,一个SFP28口接入房间交换机。remote为房间交换机上的主机。测试线路的带宽上限是10G,这里使用iperf3进行测试,也就是大包测试,RouterOS的Fast Forward为默认的开启状态。

测试描述带宽CPU占用
#1单向host -> remote9.39 Gbits/sec15%
#2单向remote -> host9.41 Gbits/sec30%

表格中的CPU占用指CCR2004-1G-2XS-PCIe的,默认RouterOS是开启bridge的Fast Forward,手动关闭后的结果没有明显变化。

路由+NAT性能测试(“集成路由器”模式)

这个模式下,模拟常见的家用路由器环境,但WAN侧使用DHCP,通过一个SFP28接口接入房间交换机,从上级路由器获得地址,remote主机也在房间交换机上。其余接口在一个bridge中,为LAN侧。像普通家用路由器一样,LAN侧有自己的地址段,打开DHCP服务器,开启WAN上的NAT masquerade。

首先是开启Fast Path时的性能:

测试描述带宽CPU占用
#1单向host -> remote9.35 Gbits/sec21%
#2单向remote -> host9.37 Gbits/sec31%

然后是关闭Fast Path时的性能:

测试描述带宽CPU占用
#1单向host -> remote9.37 Gbits/sec28%
#2单向remote -> host2.80 Gbits/sec29%

可以看到在关闭Fast Path后,remote -> host,也就是WAN to LAN方向的性能不佳。虽然此时CPU占用率并未达到100%,但一共4个核心中,仅有一个核心使用率接近100%,估计是有单核瓶颈,此时的CPU占用情况如下:

Mikrotik CCR2004-1G-2XS-PCIe 简单带宽测试最先出现在WuSiYu Blog

MacBook的高速网卡(>1000Mbps)方案踩坑

作者 WuSiYu
2022年6月21日 11:48

本文是MacBook超过千兆网络的连接(比如2.5G/5G/10G)方案的探索,我的设备是MacBook Pro 13,2020年,M1芯片,系统为macOS Monterey 12.4。其他MacBook也可参考,主要的坑在于macOS。

首先是MacBook自带的网络方案:内置Wi-Fi,但目前MacBook的WiFi6仅为2×2,且不支持160M频宽,PHY速度只能到1200M,实测在中高端路由器下,实际速度最大也仅为800Mbps左右,无法超过千兆。

工作:常见的2.5G USB有线网卡(RTL8156芯片)

示意图

目前市场上有很多2.5G USB网卡,通常都是RTL8156芯片,这种芯片在macOS下工作良好,开箱即用(免驱)

实测速度(iperf3):TX:2.35Gbps,RX:2.35Gbps,双向TX+RX:2.26Gbps+2.26Gbps,能跑满2.5G。

还测试了长时间跑满2.5G,网卡外壳仅为温热,未出现明显降速,效能挺不错的。

不工作:QNA-UC5G1T等5G USB有线网卡(AQC111u芯片)

QNAP QNA-UC5G1T

这里的5G指5Gbps,而不是5GHz WiFi的无线网卡,这基本是USB 3.x gen1(5Gbps)的最快速度,也是目前市面上最快的USB协议网卡(不包括雷电),USB 3.x gen2的USB网卡还未出现。

不幸的是,AQC111u的官方驱动仅支持“macOS Catalina 10.15 or older”,在较新的MacBook上至少都是BigSur(11.x)以后的版本,无法使用。

在较新的macOS版本下,虽然QNA-UC5G1T可以被识别,但仅能工作在1Gbps下,实际使用体验和满大街的千兆USB网卡没区别,没有意义,也不够稳定,有时甚至会握手为100Mbps。

同时这种网卡在其他系统下也不建议使用,实测在Windows和Linux下也只能达到3Gbps左右的速度,比2.5G网卡强不了多少,考虑到其价格,完全没有性价比。

大概率不工作:雷电硬盘盒转接普通PCIe万兆网卡

市面上有售雷电3的万兆网卡,但都价格昂贵(1000+),使用几百块的雷电m2硬盘盒+普通PCIe万兆网卡似乎是更有性价比的方案,但实际并不能工作。通过雷电m2硬盘盒+m2转pcie座+外置12v电源,MacBook是可以实际识别到PCIe设备,但都因为驱动问题无法使用。我尝试了AQC107和Intel x540两种网卡,均无法使用。

对于普通AQC107 PCIe万兆网卡,macOS虽然有AQC107的驱动,但其是仅为Mac Mini的内置网卡服务的,对于ID不同的普通AQC107网卡,macOS会拒绝加载驱动,虽然有破解方案,但对于白苹果繁琐且不值得。

对于Intel x540PCIe万兆网卡,根本没有驱动,无法识别。

因此市售的成品雷电3的万兆网卡,或许是MacBook万兆的唯一方案了,但因不是很值得(笔记本用个2.5G也够用,10G不是刚需),我没有购买测试。

MacBook的高速网卡(>1000Mbps)方案踩坑最先出现在WuSiYu Blog

2022年,对于爱快(iKuai)路由系统本身网络活动的简单抓包分析

作者 WuSiYu
2022年5月18日 02:49

iKuai路由系统,一个基于Linux的国产路由系统,特点是带有DPI流控并且免费,有一定审计功能,目前在国内似乎是除OpenWrt外最常用的软路由系统。

不过和部分其他的专用路由系统类似,iKuai本身相对封闭,不开放Linux shell,甚至rootfs也是加密的,在商业上这自然无可厚非,但iKuai系统在几年前曾被爆出有过劫持用户网络的DNS和HTTP请求用于广告盈利的行为,虽然据传言已被去除,但仍然令人担忧其“私货”。

所以这次,我将iKuai路由系统作为二级路由,连接到RouterOS主路由上。RouterOS有着方便的防火墙配置和抓包功能,可以设置filter进行抓包并保存到文件,然后导入Wireshark中查看。

所用iKuai系统为“免费版3.6.0 x64 Build202202101800 体验版”,与目前的3.5.4正式版在网络活动行为上应该区别不大。在iKuai中并未开启“爱快云”和SD-WAN功能,仅打开默认的自动更新,意味爱快自身着其除了“download.ikuai8.com”外,理应不去访问任何外网。

截止2022.02,iKuai系统在“爱快云”页面有一个隐私政策文档的链接,但其只描述了爱快云的隐私政策,并未说明在不使用“爱快云”的情况下iKuai路由系统本身会上传哪些信息。

DNS抓包

截取DNS请求是用于发现其试图访问哪些域名的方便方法,本次首先禁止了iKuai对除了“download.ikuai8.com”和114.114.114.114 DNS外的任何连接,然后截取了其开机几十分钟内的所有DNS请求:

经过整理,其查询的所有域名如下:

NTP服务,正常行为:
0.centos.pool.ntp.org
1.centos.pool.ntp.org
2.centos.pool.ntp.org
ntp.aliyun.com

软件更新,正常行为:
download.ikuai8.com

意义不明的名字,但IP与download.ikuai8.com相同:
302.ikuai8.com

爱快云:
yun.ikuai8.com.w.kunlungr.com (CNAME自 yun.ikuai8.com)

疑似使用情况上报,存在疑问(如:上传了哪些信息?):
report.ikuai8.com.w.kunluncan.com (CNAME自 report.ikuai8.com)

阿里云-日志服务SLS,存在疑问(如:上传了哪些信息?):
alpha-cloud-log.cn-hangzhou.log.aliyuncs.com

疑似阿里广告服务(友盟),存在疑问:
secgw-na61-na62.wagbridge.alibaba.alibabacorp.com (CNAME自 umdc.aliapp.org)

用途未知,存在疑问,对应IP都属于阿里的AS37963:
as1.ikuai8.com
as2.ikuai8.com
dis.ikuai8.com
pkgmanager.ikuai8.com

江苏电信的IP,疑似用于宽带加速服务,存在疑问:
fastgame.ikuai8.com

可能用于网络检测:
baidu.com
qq.com

注:以上为单次简单实验收集到的域名查询和个人的主观推测,不为其正确性负责,不做出任何评价。若官方或第三方能提供更多信息,欢迎在评论区留言。

在上级路由中使用的规则如下(192.168.88.2为iKuai的IP):

未完待续,等有空时准备进行一次全天抓包。

2022年,对于爱快(iKuai)路由系统本身网络活动的简单抓包分析最先出现在WuSiYu Blog

Mikrotik CCR2004-1G-2XS-PCIe 实际CPU型号及拆解分析

作者 WuSiYu
2022年5月16日 19:51

CCR2004-1G-2XS-PCIe时Mikrotik在2022年初发布的“网卡形态的路由器”,是一个网卡+路由器二合一的产品。

关于CCR2004-1G-2XS-PCIe的CPU型号,Mikrotik的宣传手册上写的是AL32400,这与其他CCR2004系列路由器上的型号一致。但官网产品页面中写的却是AL52400,让人困惑,RouterOS中也没显示其CPU型号。

这周正好我订的那个也到货了,直接拆开一探究竟,发现确实是AL32400,后缀1700,应该表示1.7GHz频率版本,与其他CCR2004系列路由器一致,同样这个CPU也被用在了QNAP的一款NAS上。其内核规格为4核A57(ARM Cortex-A57 1.7GHz x4),A57是A72的上一代架构,与A53、A55不同,A57是同属于A7x系列的高性能核,因此可以认为AL32400的CPU性能与树莓派4的BCM2711较为类似,后者为4核A72,1.5GHz或1.8GHz(新版arm_boost),对于路由器而言性能比较不错。

下面为详细的拆解图(点击图片查看原始尺寸)

说是拆解,但其实这就是一个PCIe卡,拆下PCIe档片后,在拧下背面的5个螺丝拆下散热器,即可露出全貌:

背面:

CPU,或者说SOC,型号AL32400(-1700):

拆掉散热风扇,其规格为12v 0.13A 4线,直径44mm,孔距39mm,厚度约1cm:

PCB全貌:

可以看出其布局和普通的高速网卡是非常类似的,不同的是中央的芯片是一个SoC,而不是网卡芯片,并且上方还有其内存,内存大小为4GB,但内存颗粒为5个,可能是有ECC。

关于其实际使用的体验,我会在后续发布新的文章。

其他附属芯片

SoC左侧,SFP28接口周围

红色:德州仪器TI DS250DF410,25Gbps 多速率 4 通道重定时器,以太网重定时器、转接驱动器和多路复用器缓冲器

具有集成信号调节功能的四通道多速率重定时器,最大速度25.8Gbps,支持协议:IEEE802.3bj, 100GbE, Infiniband EDR, OIF-CEi-25G-LR/MR/SR/VSR, QSFP28, CFP2/CFP4, CDFP

DS250DF410 是一款具有集成信号调节功能的四通道多速率重定时器。该器件用于扩展有损且存在串扰的远距离高速串行链路的延伸长度并提升稳定性,同时实现不高于 10-15 的比特误码率 (BER)。

黄色:德州仪器TI CDCM61002,1:2 超低抖动晶振时钟发生器

CDCM61002是一种高度通用的低抖动频率合成器,可以产生两个低抖动时钟输出,可以在低压正发射器耦合逻辑(LVPECL)、低压差分信令(LVDS)或低压互补金属氧化物半导体(LVCMOS)输出之间进行选择,来自低频晶体或LVCMOS输入,用于各种有线和数据通信应用。CDCM61002具有板载PLL,只能通过控制引脚轻松配置。整体输出随机抖动性能小于1ps,RMS(从10 kHz到20 MHz),使该设备成为SONET、以太网、光纤通道和SAN等苛刻应用程序的完美选择。CDCM61002有一个小体积的32pin、5mm×5mm QFN封装可供选择。

绿色:Atheros AR8035 集成10/100/1000千兆以太网收发器

AR8035是Atheros的第4代 单口 10/100/1000 Mbps Tri-speed Ethernet PHY,支持RGMII接口的MAC。

紫色:74HC595,串行输入、并行输出的8位移位缓存器

蓝色:NT5AD512M16A4-HR,DDR4 8Gb(1GB)内存颗粒,支持速率:2933、2666、2400

SoC右侧

红色:铠侠(原东芝)Kioxia TC58BYG0S3HBAI6,Built-in ECC SLCNAND,1Gb(128MB)SLC NAND 闪存,1.8v,x8位宽

黄色:意法半导体ST STM32F030C6T6,主流ARM Cortex-M0超值系列MCU,具有32 KB Flash和48 MHz CPU

绿色:德州仪器TI TPS51362,具有超低静态电流的 3V 至 22V、10A 同步降压转换器,输入3~22v,输出0.6v ~ 2v

蓝色:德州仪器TI TPS548B22 具有差分遥感功能的 1.5V 至 18V、25A 同步 SWIFT™ 降压转换器,输入1.5~18v,输出0.6v ~ 5.5v

紫色:德州仪器TI SN74GTL2003 (丝印GK2003)3片,双向电平转换器,双向0.95v~5v

棕色:LITE-ON LSP5523,3A 27V 同步降压转换器,输入4.5v~27v,输出0.925v~0.8Vin

白色:意法半导体ST M24C64-F(丝印464FT),64-Kbit(8KB)串行I2C总线EEPROM

背面

红色:winbond W25Q128JWS,128Mb(16MB) SPI Flash,128M-bit Serial Flash Memory with uniform 4KB sectors and Dual/Quad SPI

黄色:德州仪器TI TCA9546A(丝印PW546A),具有复位功能的低压 4 通道 I2C 和系统管理总线 (SMbus) 开关

蓝色:德州仪器TI TCA9555 (丝印PW555),具有中断、弱上拉和配置寄存器的 16 位 1.65V 至 5.5V I2C/SMBus I/O 扩展器

Mikrotik CCR2004-1G-2XS-PCIe 实际CPU型号及拆解分析最先出现在WuSiYu Blog

“双网线”旁路由之“完美”解决IPv6和千兆瓶颈问题

作者 WuSiYu
2022年1月30日 22:22

旁路由是一种homelab常见的需求,主路由用硬路由确保稳定,比如用Mikrotik的RouterOS路由器作为主路由,旁路由使用OpenWrt作为软路由,实现广告过滤和隧道等高级功能,这些功能往往都无法硬件加速,需要消耗大量CPU完成,x86的高性能软路由是很合适的选择。比起使用二级路由,可以减少在旁路由上的一次NAT(仅对于IPv4),提高利率,也便于主路由进行管理。

本文提出了一种整活之余有些实用性的特殊旁路由方案,或者也可称为IPv4不NAT的二级路由方案。

本文环境信息:

  • 主路由RouterOS,旁路由OpenWrt,需要主路由具有3个网口(对于硬路由很容易满足),旁路由至少具备双网口,假设其都为千兆网口;
  • 为了使用IPv6二级路由,运营商给的IPv6前缀至少需要为/63;
    • (常见的/56、/60都可满足,但如果给的是/64,虽然或许也能实现功能,但需要不同的设置)
  • 主内网(全功能)网段:192.168.10.0/24,辅助内网(备用/直连)网段:192.168.88.0/24

0x01 传统旁路由设置

传统的旁路由设置只针对IPv4,旁路由只需要一根网线连接内网和旁路由的LAN,旁路由的WAN空置。主路由LAN口IP为192.168.10.1/24,旁路由LAN口IP为192.168.10.2/24,在内网DHCP服务器设置中设置网关为192.168.10.2(DHCP服务器可运行在主路由或旁路由上,但只能有一个),然后在旁路由中设置网关为192.168.10.1。

这样所有客户端都会使用192.168.10.2作为网关,将出口的IP封包发到旁路由上,旁路由因为开启了ip_forward(路由器都会开启),会对这些封包进行转发:由于在旁路由上设置了192.168.10.1作为网关,于是旁路由就会将这些封包直接转发到192.168.10.1的主路由上(传统旁路由的关键就在于,由于是LAN to LAN转发,所以不会匹配防火墙中LAN to WAN的masquerade规则,即不会进行我们常说的路由器NAT)。由于封包在旁路由上进行了转发,隧道软件就可以通过防火墙NAT表中的规则对这些封包进行处理(比如redirect和tproxy),满足我们使用旁路由的需求。

在一般链接的回程(下载)时,经过主路由NAT后的入口封包的目标IP为客户端的内网IP,直接通过交换机到达客户端,无需再经过旁路由,所以理论上是可以对外网跑满双向千兆的。

0x02 传统旁路由的问题

第一个问题就是IPv6,IPv6没有单独的网关选项,对于SLAAC而言(至今Android只支持SLAAC,不支持DHCPv6),如果一台机器进行了RA(路由宣告),让客户端获得了前缀,那么客户端就会认为其是网关。由于公网IPv6前缀由PPPoE获得,所以必然是主路由进行RA,也就自动成为了所有客户端的IPv6网关,无法再指定旁路由为网关。

一个常规的IPv6 RA包

从另一个角度讲,IPv6要求所有设备(Node)必须从Router和Host这两种角色中二选一,而旁路由就恰恰是一个设备既作为Router,又作为Host。

实际上,IPv6也没必要使用旁路由,由于通常情况下IPv6不使用NAT,路由器在这里做的仅仅是转发而已,我们可以放心的使用IPv6二级路由。

另一个问题是千兆瓶颈的问题,这个千兆瓶颈只对于非直连流量(比如隧道流量)存在,即经过隧道的流量,上行和下行的速度总和无法超过1Gbps,这是因为隧道流量返程也需要经过旁路由。对于直连流量而言,如文章第一节所述,由于返程不需要经过旁路由,所以不存在千兆瓶颈,上下行速度总和可以达到2Gbps,即跑满。不过这个问题通常不会带来影响(啥公网隧道能千兆对等),但若能一并解决了也好。

0x03 本文的魔改二级路由方案

为避免混淆,以下使用「软路由」代指我们原本逻辑中的旁路由(即那台OpenWrt的软路由)

这是一种双网口、IPv4旁路由+IPv6二级路由的方案,这种方案实际上更接近于标准的二级路由,但通过一些魔改,让IPv4变成旁路由模式。

拓扑如下:

图中主路由bridge代表主内网,具有软路由提供的高级功能;bridge_alt代表辅助内网,此处仅用于软路由与主路由间的通信,也可接入一个交换机作为直连/备用内网,其不具有软路由提供的高级功能,但能在软路由故障时继续提供标准(直连)的上网功能。如果主路由上不需要扩展辅助内网,也可不为辅助内网创建bridge,使用一接口代替。

这里只列出了IPv4部分的参数。IPv6部分同标准的IPv6二级路由,但要注意,IPv6的RA和DHCP Server要运行在bridge_alt接口上(见下文)。

如果你的主路由的具有硬件交换机且还有很多未用端口,那便可以省掉“主内网 交换机”,这样旁路由就是通过两根线连接了主路由,但并不会成环。

下面开始IPv4部分的详细配置介绍:

在主路由上,基于路由器模式的出厂设置(如Home AP Dual等),进行以下修改:

  1. 首先新建个Bridge,名称为“bridge_alt”:

2. 添加需要的接口到bridge_alt中,这里我除了必要的有线端口ether1外,还添加了机器自带的两个wlan,作为备用网络热点(主内网的wlan由独立的AP提供):

3. 为bridge设置IP:192.168.10.1/24;为bridge_alt设置IP:192.168.88.1/24

4. 为bridge_alt设置分配192.168.88.0/24的DHCP服务器;如果主内网也由主路由提供DHCP服务,则为bridge设置分配192.168.10.0/24的DHCP服务器,并设置网关为192.168.10.2(下图未展示):

5. 在Interface list中,将bridge_alt设置为LAN

然后将软路由WAN口与bridge_alt的接口通过网线连接(本文中为ether0),然后你应该能看到软路由的WAN口从主路由获取了IP:

(你可能会疑惑:这不是二级路由的状态吗?别急,下面我们就关闭它的NAT)

下面我们在软路由中进行设置(类似的,基于OpenWrt的默认设置)

6. 设置软路由的LAN口IP为192.168.10.2;如果在主路由上设置了主内网的DHCP服务,则要关闭软路由LAN的DHCP服务(下图未展示)

7. 最为关键的一步,到防火墙中关闭WAN区域的“IP动态伪装”,也就是masquerade,即我们常说的NAT:

然后将根据拓扑图,将软路由的LAN主路由的bridge主内网的设备都接到交换机上,IPv4的设置就完成了。

关于IPv6的配置,和标准的IPv6二级路由相似,只是RA和DHCPv6 Server的接口设置有所不同,这部分网上有非常多很好的教程,比如:https://wu.renjie.im/blog/network/ros-dhcpv6/zh-cn/,下面仅写出在本文设置中需要注意的点。

主路由上,IPv6的地址设置(包括了RA)和DHCPv6的设置中,需要在且仅在bridge_alt接口上进行设置,而不应对bridge进行任何设置。换句话说,在IPv6下,主路由不会使用主内网bridgebridge的IPv6 RA和路由完全由软路由负责,bridge作为bridge_alt的下级路由,形成标准的IPv6二级路由。

0x04 后记

本文的方法与普通二级路由的最大区别,其实就是对于IPv4:①在二级路由器(本文中的软路由)上关闭了LAN to WAN的masquerade NAT;②在主路由上连通了二级路由的LAN。从而达到了类似旁路由的效果(旁路由就是为了少一层NAT)。

至于为什么可以在关闭二级路由器的NAT,不妨思考一下我们为什么在路由器上需要NAT:如果我们有一个连接上级网络的普通路由器,并关闭了NAT,那么我们发出的包其实还是可以正常的被送到远端的服务器,但由于包中的源IP地址还是我们客户端的内网IP地址,无法通过我们的内网IP向我们回应(其实通常直接就不会被远端服务器的防火墙接受)。而masquerade NAT就是一种特殊的src nat,其永远都会使用路由器本机地址,作为IP封包源地址的替换,从而让远端服务器的回应包能被正确发到路由器上,再由路由器转发给客户端。

但在本文的方法中,首先在我们的包通过二级路由器直接转发给主路由后,由于主路由是带有NAT的,远端服务器的回应包会正常的到达主路由,然后主路由在转发回应包时,由于我们配置了上面的,回应包可以直接发给客户端,无需经过二级路由器,也就无需二级路由器的NAT,正常的完成了一次往返的通信。

最后,本文的方法更多是整活向的。无论是直接使用单路由,还是普通的二级路由,甚至用传统旁路由方式并直接关闭IPv6,其实也没什么不好(毕竟2022年目前ISP和CDN的优化还是针对IPv4为主,很多地方依然是“关闭IPv6以提升上网体验”)。不过homelab的一大乐趣之一就是折腾各种非标准的方案和配置,本文也算是提出了一种旁路由+正常IPv6的解决方案,如果各位读者认为有改进的地方或漏洞,也欢迎在下面留言。

“双网线”旁路由之“完美”解决IPv6和千兆瓶颈问题最先出现在WuSiYu Blog

❌
❌