Normal view

There are new articles available, click to refresh the page.
Before yesterdayTimeForget

近两年基础设施的升级和更新

By: Erease
11 July 2023 at 08:00

正如About所描述的,希望在这里记录一些难以查找的信息:网络接入和局域网设备升级踩的坑

网络接入

OpenWrt + 4G 手机

历经多次宽带因为单一运营商垄断,价格高到离谱,之前在学校测过4G是可以跑到100Mbps的下行速率的,买过4G路由器做接入,后来因为SIM卡不够用就出掉了

在5G时代,闲置的4G手机完全可以用来作为网络接入设备,我用刷了OpenWrt的小米R3G有线连接退役的iPhone SE做了一个简单的4G路由器,找个4G信号好的地方固定,测速还行就可以开始用了

因为有部分模块依赖于内核,加上平时编译不太方便,所以采用官方固件,参考官网教程 Smartphone USB tethering

我记录的一些需要装的包

# 换源
sed -i 's_downloads\.openwrt\.org_mirrors.ustc.edu.cn/lede_' /etc/opkg/distfeeds.conf
# 装包
opkg install kmod-usb-net-ipheth kmod-usb-net kmod-usb-ohci kmod-usb-uhci kmod-usb2 libimobiledevice-utils libusbmuxd-utils usbmuxd 
opkg install luci-compat

用了一段时间后发现了如下问题,当然也还有其他的手机可以尝试,但是我觉得4G的问题更大:

  • 4G的信号不佳,经常达不到预期的100Mbps,这个和户型、运营商都有关
  • 4G的网速在不同时间段表现差别很大,高峰期几乎无法上网

ios更新14之后,以上教程提到的方法就失效了,后续就没有在ios上再尝试过了;随着第一代5G手机在2022年陆陆续续退役,5G手机USB共享网络给OpenWrt路由器却没有达到预想中的那么快,考虑到在手机上经过了一次NAT,存在硬件开销以及调度和功耗限制,这还是不适合作为一个长期方案

5G CPE

于是开始关注5G CPE,恰好就遇到了2020年刚上市的华为的5G CPE Pro 2 (型号H122-373,以下简称H122),幸好买的早,后来芯片荒价格一路水涨船高,直到后来智选的5G CPE铺货

当时刚好手上有可以跑千兆5G卡,至少在下载速率上可以超过绝大多数家庭宽带了,缺点也还是有的:

  • H122虽然可以放开防火墙,但是只是放开了入站的Input的流量(外部能够ping通CPE),会拒绝Forward的流量,即使下面的终端设备可以获取到IPv6地址,但是也无法从外网直接访问
  • 如果长时间高负载,即使内置了一个散热风扇,内部的温度还是比较高的,具体影响是SIM卡会热到变形,所以需要买一个SIM卡接口延长线
  • SIM卡不支持热插拔,经常需要换卡的话,要重启CPE,考虑到插槽寿命,SIM卡接口延长线必不可少
  • 最想吐槽的一点,CPE的桥模式在某次更新之后就没有了,桥模式可以使得下面的主路由可以自行控制防火墙,如果需要配置IPv6外网访问的话是必要的
  • WLAN to 2*LAN 最大只有千兆,让局域网内怎么都跑不满到160MHz WiFi6的速率(一般为实测1.2Gbps以上),充分说明了CPE还是以5G接入为主,5G to WLAN应该是能跑满的
  • 支持5G和有线WAN并发,但是实测效果一般,如果有线WAN只有IPv4的话,5G部分可以补充IPv6

写出来有点多,但不可否认的是在很长一段时间里H122就是能买到的最强的5G CPE,在我这稳定运行了三年,因为是价格低位购入,还能直接用天际通物联网卡(23年已经限速到200Mbps,没有了5G SA,只能用4G)

最后需要担心的其实是流量问题,因为5G的流量消耗速度非常快,实时监控流量消耗情况也是必要的,如用iOS小组件;因为华为5G CPE当前已经无法收到短信,流量告警只能自行编写脚本等方式实现

OpenWrt + 4G模块

这里使用的是DJI增强图传模块连接OpenWrt路由器USB接口接入的4G网络

  • 个人认为只能算是驱动了基础的QMI拨号上网功能,缺少产品本身完整功能及驱动的说明
  • 加了DIY的无人机上的天线,信号还是比手机略差,实测50Mbps-10Mbps传输的速率
  • 发热情况在28度的室内属于可以接受,上网基本是稳定的,游戏偶尔会跳ping,4G网络期望不能太高

2022年大疆在Mavic3发布之后发布了与之配套的4G图传模块(DJI Cellular),然而自带的增强图传服务只有一年的套餐,后续如果要继续使用就需要以每年99续费增强图传服务,对于只是想超视距飞行过把瘾的人来说,增强图传服务到期之后模块自然就闲置了(大疆2023年新品不兼容该模块),二手市场上挂出的非常多,感觉出手比较困难(原价699,2023.11二手大把的450),而全新的同规格的Cat4速率的4G USB网卡120可以买到,既然如此,还不如留着当4G网卡发挥余热

驱动的方法

该方法在ImmortalWrt 23.05.1的ARM和MT7621的路由器上测试成功

  1. 安装QMI拨号需要的包
    opkg install qmi-utils usb-modeswitch kmod-mii kmod-nls-base kmod-usb-core kmod-usb-ehci kmod-usb2 kmod-usb-net kmod-usb-wdm kmod-usb-net-qmi-wwan wwan uqmi luci-proto-qmi
    
  2. USB连接4G模块,执行识别驱动的命令,命令如果没有报错的话,ls /dev/应该看到cdc-wdm3这个设备了
    echo "2ca3 4006 0 2c7c 0125" > /sys/bus/usb/drivers/qmi_wwan/new_id
    
  3. 创建QMI拨号的接口,例如命名为DJI,在调制解调器设备一栏填入/dev/cdc-wdm3(最关键,下图是借用的其他教程的截图作为参考),其余的信息保持默认; 在防火墙设置,给这个接口分配防火墙区域为wan,保存设置即可

如果此时4G图传模块上的灯是绿色的,即模块正常连上了4G网络,很快能看到刚刚创建的接口已经获取到了IPv6的地址,并且系统自动生成了名为DJI_4的IPv4地址的虚拟接口,此时路由器应该就能通过4G模块访问互联网

第一次成功驱动并设置好QMI拨号的接口后,可以将命令

  echo "2ca3 4006 0 2c7c 0125" > /sys/bus/usb/drivers/qmi_wwan/new_id

添加到开机启动脚本中(网页LuCI界面->系统->启动项->本地启动脚本),添加到文本框中exit 0这一行之前即可,后续重启也无需任何的操作,随时插入4G模块后一段时间就能正常上网了

探索的过程

在大疆论坛上有用户尝试了Windows上驱动并成功让PC能接入4G网络,后续大疆又发布了模块的Windows驱动,其中主要提供了以下的信息:

  • PC直接识别的型号是EG25G-QDC507,其中EG25是移远(Quectel)的产品:一款Cat4速率的4G模组
  • 4G模块正常驱动后显示的生产商为Baiwang,查不到驱动和规格相关的信息

搜索OpenWrt上驱动模块的资料,发现在OpenWrt上移植EG25驱动的经验是空白的,主要都是移植EC2X的,其中《挂载移远EC20、EC21、EC25、AG35等4G模块》参考了官方的Linux驱动文档,EG25在文档发中和EC25的PID和VID是相同的(2C7C, 0125),但是与4G图传模块的(2CA3, 4006)不同,即使移植了EG25的驱动也未必能识别到4G图传模块

直到看到论坛里有人发了4G图传模块用于Linux系统上网尝试,用到了将USB设备的PID和VID写入/sys/bus/usb/drivers/…/new_id处理驱动识别的方法,另外又查到了23年11月的OpenWrt 下实现移远 4G 模块上网 中提到在OpenWrt 22.03在无需改内核代码就能驱动EC20

在运行echo "2ca3 4006 0 2c7c 0125" > /sys/bus/usb/drivers/qmi_wwan/new_id后,可以用cat /sys/kernel/debug/usb/devices查看到4G模块被qmi_wwan驱动(设备对应的信息出现Driver=qmi_wwan字样)

/dev目录下可以看到/dev/cdc-wdm[0-3]一共4个设备,最开始尝试了/dev/cdc-wdm0发现无法拨号就差点放弃,最后尝试了下/dev/cdc-wdm3发现拨号可以获取到IP了

查看信号及IPv6情况

uqmi命令可以与模块通信并输出一些状态的信息,其中个人比较关注的主要是信号

root@XDR6088:~# uqmi -d /dev/cdc-wdm3 --get-signal-info
{
	"type": "lte",
	"rssi": -55,
	"rsrq": -6,
	"rsrp": -79,
	"snr": 14.800000
}

4G模块的速率标准为Cat4(下行速率最高150Mbps,上行最高为50Mbps),实测在以上信号强度的电信4G上下行均为50Mbps左右,日常用这速率也算能接受吧,联想到我测试过最快的4G是2018年在iPhoneSE(4G Cat6最高下行速率300Mbps)上跑出了100Mbps的下行

关于IPv6,首先路由器时可以获取到公网IPv6地址的(以及64位前缀的PD),并且在LAN默认的IPv6设置下,可以向下分配地址,另外就是传入连接的连接性,实测发现有运营商的差异:移动的IPv6地址无法从外网访问路由器,联通和电信的IPv6地址则可以

CPE/4G模块下的二级路由

由于CPE和4G模块获取的IPv6地址是不含短于64位的前缀的,所以在使用二级路由的情况下,二级路由下的设备无法获取公网IPv6地址,这个时候需要配置“IPv6中继+NDP代理”,OpenWrt 23.05的LuCI界面的设置过程如下:

  1. 比如wan6接口已经获取到IPv6地址,下面都是在默认的设置上修改的,第一张图的设置不需要改
  2. wan6接口的设置勾选指定的主接口,接下来三个地址分配的选项选中继,学习路由要勾选
  3. lan接口的设置,三个地址分配的选项选中继,学习路由要勾选
  4. 删除ULA前缀(这里是经验之谈) 正常情况下,连接在路由器下面的设备就能获取到公网IPv6地址了,但是可能还打不开IPv6网站:http://test6.ustc.edu.cn,这个时候可能需要ping一下wan6接口的IPv6地址,让地址被NDP代理学习(可以用ip -6 neigh和LuCI上的系统->路由表->IPv6邻居看IPv6地址对应的接口来观察NDP代理的效果)

我的网络结构是CPE做一级路由,OpenWrt做二级路由,因为华为5G CPE本身防火墙的原因,二级路由下面的设备可以获取到IPv6地址,但是无法从外网访问

但是如果CPE或者4G模块支持桥模式,那么OpenWrt路由器大概率是不受CPE或者4G模块的防火墙影响的,放开OpenWrt的防火墙之后,只剩下运营商屏蔽了传入连接的可能性

局域网

局域网肯定还是要用一台OpenWrt路由器作为主路由,如果一台主路由能解决问题是最好,列出来的要求有点多:

  1. 网口足够多,早期的路由器一般是5个千兆口(1 x WAN + 4 x LAN),勉强够用(PC + NAS + xx),如果带USB口的话,还能额外扩展网口
  2. 最好有2.5G以上的网口,因为160MHz WiFi6已经可以跑到1.6Gbps以上了,当前NAS的机械硬盘读写大多能超过200MB/s,2.5G网口的设备会越来越多
  3. WiFi 4T4R(4x4 MIMO)信号更好,有MU-MIMO的情况下,当前主流2x2 MIMO的多台设备可以同时高速传输
  4. 有良好的OpenWrt支持,这里特指最好是有OpenWrt官方的支持,开源的固件能确保基本的功能正常(21年之前WiFi6的开源驱动很少有能用的)

在从2020年到2023年这一段时间里,涌现了一大批可以刷OpenWrt的WiFi6路由器:Qnap-301w、红米AX6,AX6000、中兴NX30 Pro,以及可能有QSDK固件的小米万兆路由,对比以上的要求有明显的短板,直到某一天看到B站上有人给TP-LINK XDR6088刷机的教程:TP-link路由器XDR6088、6086、4288刷openWRT,我终于发现了一台有潜力的机器:

  • 带2个2.5G网口 + 4个1G网口 + 一个USB3.0接口
  • 支持4T4R 160MHz的5G频段WiFi6
  • 4*A53@2.0GHz的CPU,128MB的闪存在2023年够路由器装常用插件了,看拆机散热算是比较好的

XDR6088刷OpenWrt

可以查到的获取终端操作权限刷入U-boot(bootloader)的方法源于:TP-LINK XDR6086/XDR6088 反弹 SHELL 并开启 SSH

综合亲手实践以及上面的视频教程,有几点需要特别注意

  • 实测在1.0.24版本到1.0.23都可以通过反弹shell注入命令,切记每次发完post请求之后,禁用用户触发反弹shell完成后,删除用户,这样下一个Post请求才能发送成功
  • 发Post请求的客户端软件有特别的要求,我试过OpenWrt,CentOS,群晖,Postman的curl命令/Post请求发送均无法创建VPN用户,最后还是重装了一个Ubuntu的WSL才成功:返回{"error_code":0}
  • 在Windows下使用nc导出路由器备份的mtdblock的时候,Windows上一定要用CMD运行nc并重定向nc -l -p 9995 > backup.img),不能用Powershell(备份传输完成后,校验的话就会发现用Powershell运行同样的命令会得到不一样的文件),因为这一条操作失误导致我刷OpenWrt后刷回原厂系统的过程中导致变砖
  • 视频教程中的UBoot刷完后,通过这个UBoot是无法直接刷入官方的OpenWrt固件的,原因是分区结构不一样,本文后面有记录刷到官方的方法

一些简单的测试

我只刷了视频教程的固件,基本上是截至到当时最新的R23.5.1,2.5G网口和WiFi稳定的运行两周,这里先放下收集到的参数的对比,至少CPU的参数在当前WiFi6末期可刷机硬路由中基本上是第一档的

路由器 CPU RAM ROM
Newifi Y1 MT7620 1C@580MHz 128MB 16MB
K2P MT7621AT 2C4T@880MHz 128MB 16MB
XDR6088 MT7986A 12nm 4*A53@2.0GHz 512MB DDR3 128MB
NX30 Pro MT7981B 12nm 2*A53@1.3GHz 256MB DDR3 128MB
Qnap-301w IPQ8072A 12nm 4*A53@2.2GHz 1GB DDR3-1600 4GB
K3 BCM4709 40nm 2*A9@1.4GHz 512MB DDR3-1600 128MB
N1 S905D 28nm 4*A53@1.5Ghz 2GB 8GB
  • 近距离WiFi6设备测速,用支持160MHz的小米13可以跑出1.6~1.8Gbps的速率,支持80MHz的iPad Pro能跑到900Mbps 同一房间,无遮挡用AX200也能跑到1.6Gbps左右
  • 中距离WiFi6设备测速,一堵墙的情况下,XDR6088能跑1Gbps,对比4T4R 80MHz的K3能跑400Mbps左右
  • 夏天室内29度左右,长时间开机运行,CPU温度不超过60度,机身有热感

救砖

上文提到Powershell下使用nc命令重定向的备份大小异常的问题,相关的原因查明在:Powershell与bash的重定向的差异,在搞清楚其中的原理后,我理解无法通过简单的操作使得备份还原,于是在论坛找到了别人的备份的mtdblock9尝试救砖,参考

因为我之前给T440s修改BIOS买了CH341A编程器和8pin的夹子,所以就鼓起勇气拆机,经过艰难的掰卡口后,很快就遇到了问题:

  • 红米AX6000救砖中提到建议改CH341的输出电压为3.3v,这个要飞线,我没有工具:

  • 我查了下ThinkPad BIOS芯片W25Q32V的datasheet,发现支持的也是2.7~3.6V,之前成功刷上了BIOS,通过不严谨的推测,不修改CH341的输出电压也能刷2.7~3.6V的F50L1G41LB

  • 店家给的CH341的编程器刷写软件不支持F50L1G41LB,红米AX6000救砖中提到“NeoProgrammer不知道如何写入单独分区,我选择了SNANDer”:

    • SNANDer大概是缺少说明,我这里用的不太顺利,最后还是选了NeoProgrammer,因为后者能成功识别到芯片并读写
  • 最棘手的问题在于,F50L1G41LB相比W25Q32V,夹子的触点难以夹到芯片的针脚,无法稳定连接就无法写入,红米AX6000救砖中用的漆包线飞线

    • 我买了电烙铁,尝试飞线,但是实在是不会用锡焊,意识到用力过猛可能会损坏芯片,遂另寻他路
    • 最后在网上看到了生产用的治具,有一个工作台能将探针垂直于主板放置,探针尖直接接触芯片针脚,然而治具带工作台价格上百,WSON8探针(匹配芯片尺寸8*6mm)比CH341编程器加上夹子还贵一些,自己拼凑了一个固定探针的框,如图:

刷入官方OpenWrt

在OpenWrt官方23.05正式版支持XDR-6088的固件后,参考了TL-XDR6088/6086 刷入官方 Openwrt/Immortalwrt,原文已经记录的相当的详细,此处仅摘录用到的步骤(因为独立博客的域名过期之后就很可能找不到原文了)

本文写作时,最新的是23.05.0-rc3版。将来请用更新的稳定版本,目前Immortalwrt官方固件已经支持:

  • 双 2.5Gb 网口的正常驱动(但LED灯还不亮)
  • WiFi6 160Mhz
  • 硬件流量分载
  • WED (Wireless Ethernet Dispatch) 无线加速
  • 硬件 NAT 加速
  • Fullcone NAT

4.2 如果路由器已经刷了其它版本的 Openwrt

在 Openwrt 中运行cat /proc/mtd,得到mtd设备的真实命名,再用命令来写入(将下面的BL2或FIP改成你在上面看到的名字,注意大小写)

md5sum /tmp/preloader.bin
mtd erase BL2
mtd write /tmp/preloader.bin BL2
mtd verify /tmp/preloader.bin BL2

md5sum /tmp/bl31-uboot.fip
mtd erase FIP
mtd write /tmp/bl31-uboot.fip FIP
mtd verify /tmp/bl31-uboot.fip FIP

注意查看上传的两个文件 md5 并和本地文件对比,查看两次 mtd verify 最后是否输出输出 Success,没问题才可进行下一步。

5. 通过 tftp 载入 recovery 镜像

这时候你可以拔掉路由器的电源,然后插上。直接拔电源可能是最安全的,因为如果你用 reboot 命令,可能会有一些后台程序运行(包括可能你之前在慌乱中没有杀掉的误操作了的 dd)导致路由器变砖。别问我是怎么知道的。

此时 tftp 服务器上应该已经有提示了,路由器在请求的文件名为 openwrt-mediatek-filogic-tplink_tl-xdr6088-initramfs-recovery.itb 。你只需要把结尾为 recovery.itb 的文件,改名为这个就行了。

如果没动静,你可以拔下电源,然后顶住 reset 孔不放,同时插入电源,应该会看到 LAN 口的灯齐闪一下。大约10秒钟,应该就会进入 recovery 模式。确保网线插在 1Gb LAN 口上,网口的灯应该会亮的。

NAS加装万兆网卡

前面提到了WiFi6 160MHz普及之后,局域网传输的瓶颈主要在千兆的有线网口上,考虑到外置USB网卡(USB 3.0外置网卡最大速率为5Gbps)可能因为发热等因素不稳定,首选的话还是PCIe的网卡,而且由于数据中心万兆网卡下架,市面上有较多的低成本的选择,在网络讨论的最多的是浪潮X540-T2拆机卡,价格大概70左右,特别之处在于PCIE插槽是X8+X1,如果要用的话x1要绝缘屏蔽,我实际使用发现卡兼容性不太好:

  • 铝制的小面积散热片,只要插上PCIe插槽就非常烫
  • 插在群晖的NAS上发现无法识别
  • 插在z370主板上,概率性无法识别,或者iperf3测速不稳定
  • 最后是X540本身,由于年代久远,不支持协商以太网的2.5G速率

最后捡到一张180的带华为物料编码的x540,有几乎覆盖整个卡面的黑色散热片,插上群晖DS1621可以直接用,对于装了驱动的Z370-I也是

简单测了下,这张x540的空载功耗大约是8w,看卡背面的便签写着silicom PE210G2I40E,查到了silicom官网关于电口万兆网卡的功耗,找到了“电口功耗高”的依据:

PE开头的NIC(网卡)均为silicom官网上的网卡的功耗数据(均为所有端口Link/Idel 的功耗的整卡功耗),可以看到x540的功耗一骑绝尘,考虑到网卡的成本以及长期电费,最后我找了一张AQC107的网卡LREC6880BT,也把数据列到了下面:

NIC Controller 无Link GE XGE  
PE310G2I50-T X550-AT2 4.62W 5.4W 8.16W x4 PCIe 3.0
PE210G2I40-T X540 7.23W 7.92W 14.28W x8 PCIe 2.1
PE310G2I71-T X710-AT2 3.6W 5.52w 8.28W x8 PCIe 3.0
PE310G2I71 X710BM2 3~4W   4.6~4.8W x8 PCIe 3.0
PE210G2SPI9A 82599ES 4~6W   6W x8 PCIe 2.0
LREC6880BT AQC 107     网卡4.7W x4 PCIe v2.1

数据中心下架的卡基本上都有些年头了,关于网卡的控制器、发布时间、制程、TDP,2022年末的二手价如下:

NIC Controller TDP Release Process Price
华为SP230电 X540-AT2 12.5W 12Q1 40nm 250左右
Intel X550 X550-AT2 11W 15Q4 28nm 1200左右
Intel X710-T4 XL710-BM1 7W 15Q4 28nm 2450
X520-DA1 82599ES   09Q2 65nm  
LREC6880BT AQC107 6W 17Q4 28nm  

在网上看到说Intel的X540和X550在群晖的DSM系统中是免驱的(其实是DSM的Linux带了驱动),因为X550太贵,所以把目光投向了价格和功耗都合适的AQC107,因为群晖E10G18-T1 10G等群晖官方的万兆电口卡也是用的AQC107,我天真的以为第三方AQC107也是免驱的

群晖DSM7.1编译AQC107网卡驱动

网上我能找到两个中文的经验:

详细的要二次编译成功再补充,大概是下次DSM系统版本/内核版本更新

Z370-ITX使用64GB内存

因为不涉及到后面的修改BIOS文件就能上64GB内存,这里直接上结论:

  • 实测在华硕Z370-I的1410版本的BIOS,可以识别到64GB内存并开机正常使用,使用的内存是2条金士顿Fury DDR4 32GB 3200MHz

在我的平台上,用最新的3005的BIOS反而会导致莫名其妙的自动重启

  • 关于CMD运行命令“wmic memphysical get maxcapacity会显示最大支持的内存”,实测是不准确的
  • 华硕这块ITX的主板的BIOS文件的 最大内存限制的二进制位 与 已有经验反馈的ATX主板BIOS文件的不同,所以最后还是实践出真理

因为在互联网上找不到Z370-I成功实践的经验,所以这里留个记录:

Asus Z370-I是一块ITX主板,只有两个内存插槽,装机的时候切好碰上DDR4内存天价,所以很长一段时间里只有双通道16GB 3000MHz,这块主板在官网上参数写着最大支持32GB内存,也就是2X16GB,然而随着内存降价,发现23年单条32GB的内存已经很便宜了,想着直接上到双通道64GB,以后这台机器退役也能当服务器用

32G单条内存的颗粒检索

因为是捡垃圾买到的“Fury DDR4 32GB 3200MHz”,想要知道超频情况,无法在thaiphoon burner中识别出具体的镁光颗粒,所以只能通过拆内存条散热马甲查看颗粒的FBGA Code(或者叫Market Code:颗粒第二行的编码,例如比较流行的镁光超频内存条C9BJZ),然后在官网Micron FBGA and component marking decoder查询,然而如下的丝印代码在官网是查不到的:

3CE22 
Z9XJP

最后是在电子元器件网站上检索到了颗粒的型号(Part Number):MT40A4G8VNE-062H ES:B;根据镁光的PART NUMBER命名规则表,可以获取到如下信息:

  • 频率:062对应3200MHz
  • 内存条单面八颗粒,叠die颗粒(4G8 4Gb*8 为2Gb的2G8的叠die版本)MT40A4G8 这个是叠die的颗粒
  • 然后是ES是工程样片,对应Market Code第一位为Z

然后因为网上搜索不到相同的颗粒,所以超频抄作业可以不用想了,只能搜索到酷兽银甲单条32g 颗粒分析和超频也是叠die颗粒超频:“3200频率下1.45V时序可压c14-18-18-34,这里简单调了下一二时序,能效可以达到4.8w左右”,我看到了这个之后就按照文中提到的时序调整,实测不需要以上那样的参数,1.35v c14-18-18-32即可,其他的时序参考网上的超频教程进一步收紧,TM5跑不过就放开一点(tRFC为500),最后时延能控制在52ns左右(收紧的话可以49ns但是TM5报错)

修改BIOS提升内存支持上限

我搜到了CHH的帖子:首发!Z170/Z370 突破内存64g可用的上限限制,精华在评论里,总结如下:

如何使 H310C/B365/Z370 的 BIOS 支持最大 128G 内存:

1.UEFITool提取SiInitPreMem模块,GUID为A8499E65-A6F6-48B0-96DB-45C266030D83 2.UEFITool搜索“C786….000000….00”,其中“..”为任意HEX值 3.第一处“….”不用理会,第二处“….”如果是“8000”那么就是最大64G,如果是“0001”就是最大128G 4.将“8000”修改为“0001”可破除64G限制 5.100/200系BIOS内也有此内容,理论上6-9代的IMC支持的内存没差,6700+Z170也能128G内存(已测试可行) 6.我这边看,MSI的Z370,18年底的BIOS还是8000,19年4月的BIOS就是0001了,ASUS的BIOS一水的都还是8000 7.ME 需要禁用(修改Flash Descriptor的HAP Bit,但要注意部分主板有校验不允许这么改,改后无法开机) 8.部分BIOS需设置 Chipset->System Agent (SA) Configuration->Above 4GB MMIO BIOS assignment->Disabled 不同 BIOS 位置不同,且可能被隐藏,无法直接修改

注:参考后面的引用,第七步为:将 0x102h的位置 +1

Z370-I的BIOS的修改追踪

限制内存大小的字段,在我的主板上看到的是

# 3005 BIOS (2000 我觉得是单条16G,或者单DIMM 32G)
#Hex pattern "C786....000000....00" found as "C7866F25000000200000" in TE image section at header-offset 388FCh
C7 86 6F 25 00 00 00 20 00 00 EB 20
6A 00 56 E8 B4 E0 FE FF 59 59 0F B6

# 纯血的370ROG已经提供了128G的bios( 2021-2-15 )
# 3004 BIOS 2021-04-16 发生了变化,没有了老版的第二行
C7 86 6F 25 00 00 00 20 00 00 EB 20

# 1802 BIOS
C7 86 6F 25 00 00 00 20 00 00 EB 0A 
C7 86 6F 25 00 00 00 80 00 00

# 1410 BIOS
Hex pattern "C786....000000800000" found as "C7866F25000000800000" in TE image section at header-offset 384ACh
C7 86 6F 25 00 00 00 20 00 00 EB 0A 
C7 86 6F 25 00 00 00 80 00 00 8B C3

“18年底的BIOS还是8000,19年4月的BIOS就是0001了”的这一行去掉发生3004(更新日志:主要是添加了Win11的支持,没有提内存上线变化),我找了M10H ROG MAXIMUS X HERO BIOS变更日志中有内存上限修改(Support Max DRAM Total Capacity up to 128 GB.)的新老BIOS看了下,也是去掉了8000这一行

恩杰H1自带140水冷老化

这个问题能搜索到公开的文字信息不多,主要的问题是用了一段时间之后散热能力迅速衰减,比如新购入可以压制170w发热的CPU(已经开盖换液态金属),然而老化之后散热能力在CPU功耗80w左右温度就冲击100度,网上能搜索到的维修和拆解分析的经验:

我拆开水冷头之后,果然如上面引用所述是杂志堵塞了水冷头的微水道,用蒸馏水冲洗了几轮水路,最后换了蒸馏水之后散热能力重回170w,另外水冷的大风扇,对内存散热也要更友好(换用了一段时间的AXP100,内吹的时候内存太烫了)

折腾两台Haswell时代的设备

By: Erease
30 May 2021 at 08:00

Haswell架构是Intel在2013年推出的“酷睿第四代”CPU架构,Haswell刚推出那年配了自己第一台台式机,后来上大学又捡了一台Haswell的笔记本T440s,毕业后又凑了一台M73小主机…台式机至今还在家用,笔记本已到垂暮之年,修改BIOS之后装上AX200依旧是顺手的全能笔电,M73目前主要是作为Linux环境主机

T440s刷BIOS

之所以要刷BIOS,是因为T440s大部分的BIOS有网卡白名单,基本完全限制住了自行升级网卡,自带的AC7260是Intel最早的2x2 AC网卡,信号和速度已经远远落后如今的AX网卡,T440s现在主要是处理器跟不上了,其他方面放到现在也是非常优秀的:

  • 接口丰富(主要是有RJ45),有廉价的拓展坞
  • 1.4KG的重量,同重量下优秀的键盘键程
  • 支持2242和2.5inch的共两块SSD
  • 使用PD转方口可以使用PD充电头

另外还有几个比较有意思的地方:

  • i7-4600U处理器可以在XTU拉4倍频,本来最高3.3GHz可以拉高到3.7GHz(实测还是要手动加些电压,加太多功耗高,容易死机,实际只见过3.6GHz)
  • 可以换装72WH的外置电池
  • 没有不耐用的类肤质涂层

在如今是市场里确实很难找到合适自己用的笔记本(定位高,接口丰富,不用拓展坞),所以还是想多延续下T440s的使用期,一直比较头痛的就是更换网卡的问题,之前并非没有查过刷BIOS,但是教程太复杂,时过境迁,2020年搜到有不少人都能自己刷了,下面进入正题

参考教程

虽然写的是T440p,但是实测对T440s基本适用,本文对以上的材料做下补充:

  • BIOS芯片的位置

  • 夹上编程器的样子

  • 用工具读取到的BIOS芯片型号和教程可能不同,以卖家附赠的工具为准

  • 教程还带有解锁高级菜单的部分,但是实测貌似没什么用(主要想解锁功耗,15w下散热还是压得住的)

黑苹果

换了AX200的网卡之后在160MHz下实测无线可以跑满1000Mbps,另外一个在2020年的新闻就是Intel的网卡在MacOS下终于可以日常使用了:itlwm,因为手头空闲的机器不多,所以就尝试给T440s上黑苹果试一试,好在Clover的EFI不难找

实测黑苹果日常使用确实比Win10流畅不少(主要是少了一些莫名其妙的高占用),但是多开还是有些吃力的

M73

缘起于之前为了收一个小机箱和MATX主板,被学长捆绑了一颗ES版的CPU,最开始说是E3,用CPU-Z看也是志强,但是根据顶盖上的四位编号QEDH,在某宝上搜索指向的是i7-4770s的ES版本,4c8t @ 3.0GHz,TDP 83W,并且带核显;尝试过作为家用win10主机使用过,但是核显实在太鸡肋,单核心主频低导致部分应用速度比较慢

最后我还是决定装一台低功耗的Mini Server,准系统选择了Haswell时代的M73(相比戴尔的9020散热更好),M73可以用ThinkPad系的方口电源也是一大优势(家里方口电源多…)

装机及散热测试

准系统的安装很简单,但是这里有些插曲,一个是CPU的散热问题,相比带T后缀的45W的低功耗CPU,以及家用台式机的65W标压处理器,QEDH的83W还是很吓人的,之前在B85 ATX主板上实测,解锁功耗烤机满载也确实可以跑到80W以上,所以对于65W以下的准系统M73,我选择了把顶盖到Die的导热材料换成液金,然后测试下M73能否在编译时跑满这颗CPU

这里选择CentOS下,初次编译OpenWrt作为负载,编译时,温度抵近90度,基本上就是达到默认风扇下的上限了,如果把风扇转速拉满,温度大概80左右,但是噪音太大了;使用s-tui可以在软件层面查看功耗和频率信息,CPU功耗接近60W,主频2.8GHz,因为可以用Type-C的方口诱骗线供电,所以也顺带看了下整机的功耗,基本在65W以下(用95W的电源);编译的时间对比win10下使用WSL2的i7-8700K,M73这套平台耗时是其两倍,可以接受的水平;另外日常待机功耗12W左右

Docker下载机

之前用NAS时,用的比较多的就是Docker版本的qBittorrent以及网络共享功能,其实在Linux下实现这些并不难,M73用这一套的优势是相比传统NAS噪音很小,且小体型放置随意;这里使用和NAS上一样的容器镜像源,主要是qBittorrent作为下载软件

以下设置仅针对CentOS 7.9,其他发行版可能不同,其中Docker启动命令如下(记得建立挂卷的目录):


docker run -d \
  --name=qbittorrent \
  --network=host \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Europe/London \
  -e WEBUI_PORT=8080 \
  -v /home/qbittorrent/config:/config \
  -v /home/downloads:/downloads \
  --restart unless-stopped \
  linuxserver/qbittorrent

可能遇到的问题

  1. 3.1X的内核可能存在qbt启动异常的问题,/usr/bin/qbittorrent-nox: error while loading shared libraries: libQt5Core.so.5: cannot open shared object file: No such file or directory参考群晖

  2. Linux的防火墙可能会阻止访问8080端口

    firewall-cmd --zone=public --add-port=8080/tcp --permanent
    firewall-cmd --reload
    

    部分运营商的家用宽带也会在上游阻隔8080端口的访问,此时建议将Docker启动命令的监听端口修改为8081

  3. 添加证书设置开启HTTPS访问后无法打开网页

    需要修改证书的key的权限为所有人可读

    chmod +044 keyfilepath
    

    这个在使用供应商的证书 对比 通过ACME申请的Let’s Ecrypt证书发现的差异,因为ps -ef | grep -i qbit可以看到实际使用证书的程序的UID是abc而不是root,acme在使用root权限执行申请到的证书key对abc用户是不可读的

    root       255     1  0 18:26 ?        00:00:00 s6-supervise qbittorrent
    abc        333   255  1 19:15 ?        00:00:00 /usr/bin/qbittorrent-nox --webui-port=8081
    

文件服务

SMB共享

  1. 基于系统的用户创建SMB用户

  2. 设置SMB共享目录

  3. 关闭SELinux(否则只能看到目录而看不到文件)

    临时关闭(不用重启机器)
    setenforce 0  
       
    修改/etc/selinux/config 文件
    将SELINUX=enforcing改为SELINUX=disabled
    重启机器即可
    

在使用SMB作为局域网内的文件共享方式有以下的缺点:

  • Android和IOS的播放器软件使用SMB协议播放视频时,无法达到带宽的上限(据说是受限于移动端的APP的SMB协议版本
  • SMB协议基本上只能用于局域网内的文件传输,无法作为一种安全的公网传输方式

优点:

  • 兼容性较好,Windows,MacOS自带的文件浏览器支持直接访问
  • SMB3在NAS上支持多路径,可以使用普通的千兆路由器路由器达到较快的网速

Alist

首先说WebDav协议,这个最早在群晖的NAS上只要安装就能使用,主要就是用于公网访问文件,然而我在很长一段时间,都没有在Linux上寻找一款配置简单,易用的服务端,在此期间用gohttpserver作为多端访问服务器文件的方式

之前听闻Alist可以挂载云盘后对外提供WebDav协议的访问,所以就看了下文档,其简介为:“一个支持多种存储的文件列表程序”,打开发现其实也是支持挂载本地存储的,又有网页端,完全可以实现gohttpserver的功能,初次之外页面上的分享功能也方便将Alist本身作为网盘分享文件

这里因为考虑到方便的挂载本地目录(主要是qbittorrent的下载目录)以及使用HTTPS(证书周期性的需要更换),所以使用了本地直接部署的方式,采用官网的一键脚本

curl -fsSL "https://alist.nn.ci/v3.sh" | bash -s install

特别留意首次安装后,日志会显示默认的随机密码

之后就是用nPlayer等播放器挂载webdav目录了,留意url的路径http[s]://domain:port/dav/中的dav,如果是Android的话,nPlayer可能常年没有更新了,推荐Reex

NextCloud

Nextcloud挂载SMB提供多种外部访问方式,体验下来还是SMB为主,Nextcloud的优势在于有完善的移动APP,2022年发现还是Alist更轻量好用

docker run -d \
  --name=nextcloud \
  --network=host \
  -e PUID=1000 \
  -e PGID=1000 \
  -e TZ=Asia/Shanghai \
  -v /home/nextcloud/config:/config \
  -v /home/nextcloud/data:/data \
  --restart unless-stopped \
  linuxserver/nextcloud

可能遇到的问题:nextcloud会识别首次登陆的IP之类的信息,导致无法二次访问

解决办法:需要到docker指定的config目录下修改才可以换用域名或者新的IP访问

vi ./nextcloud/config/www/nextcloud/config/config.php
<?php
$CONFIG = array (
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'datadirectory' => '/data',
  'instanceid' => 'xxx',
  'passwordsalt' => 'xxx',
  'secret' => 'xxx',
  'trusted_domains' =>
  array (
    0 => '192.168.8.114',
    1 => preg_match('/cli/i',php_sapi_name())?'127.0.0.1':$_SERVER['SERVER_NAME'],
  ),
  'dbtype' => 'sqlite3',
  'version' => '21.0.0.18',
  'overwrite.cli.url' => 'https://192.168.8.114',
  'installed' => true,
);

注册美区Apple ID

By: Erease
18 December 2019 at 08:00

因为想要下载一个软件体验,所以参考了下网络上的教程尝试了下,有种水到渠成的感觉,这里留个记录,另外就是记录下折腾黑苹果的一段经历

注册Apple ID

主要就是网络环境,之后的所有工作是围绕网络环境来的

网络环境:这里用的是Google Cloud Platform(GCP)的VPS,DigitalOcean的打开注册页面为502(可能是用的人太多了,Do类似的情况很常见)

为了复制粘贴方便用的PC端的浏览器(必要的话开无痕模式),不同的平台流程可能不一样

注册过程

  • 检查下当前的IP,这里用的IPIP.net,页面上的地理位置以及经纬度信息在后面有用
  • 打开Apple ID,语言是英文的
  • 填写邮箱,姓名等与地理位置无关的信息
  • 付款方法暂时选的None

地理位置

网络上有那种地址身份信息生成器,据说地址,注册IP以及验证的电话在相关的时候比较省事,所以这里就从网络到地址一步步来

首先是根据之前的IP得到的经纬度信息,在Google地图中找到具体的位置,可以得到申请需要的:州,城市,街道,邮编

之后再在经纬度周边找到一个有提供电话信息的位置,后面需要用到其区号

电话

据说会用短信验证(我并没有走这个流程),这里选择用TextNow提供的虚拟电话号码,提供地理位置(区号)就行

充值

我手上的双币卡是无法直接做为支付方式的,但是据说可以买官网上的礼品卡,然而面额都有些大,所以就在淘宝上找小面额的礼品卡,这里要注意的是,因为盗刷信用卡情况的比较多,网上不乏有那种特别便宜的软件激活码和充值方式,切记不能贪小便宜(据说重则封号)

其他设置

设置密保问题,完善个人信息之类的,之后登陆就可以看到英文的Apple Store,貌似下载软件的速度有点慢

黑苹果

之前也是试过好几次,但是搞不清楚的问题实在是太多了,一时半会处理不完

  • 之前只有一台电脑,如果翻车会影响日常生活
  • 之前能够找到的EFI不多,也没有看到那种特别基础的教程
  • 这个学期MacOS 10.15发布,想要体验下新功能
  • 某些开发环境在MacOS下配置更加方便
  • 忘了在哪里看到的言论:八代处理器的台式机安装黑苹果非常简单
  • 最关键的是,我的Win10又开始出现各种小问题,翻车顺带重装

于是假期花点时间尝试一下

摘要

这里先要提一下配置情况:

  • Asus Z370-I主板搭配的八代UHD630核显的CPU
  • 因为10.14起,N卡不再有可以用的驱动,所以这里使用核显输出,用的家里的HDMI线(估计是遇到困难的主要原因)
  • 自带无线网卡是RTL8822BE,黑苹果无驱动,暂时不更换,暂用USB连接手机热点上网
  • 在windows下制作安装U盘

目前来看最终的效果还是要回到学校,换DP输出和无线网卡,测试一段时间

下面来梳理安装的思路

  1. 在远景或者黑果小兵下载10.15.2的镜像
  2. 寻找对应主板和系统版本的EFI,主要在:
    • tonymacx86,黑苹果首屈一指的论坛
    • Github,相对来说readme写的比较清楚
    • 远景,大量的说不清楚的资源以及过期的百度云链接,有效信息密度较低但是最贴合实际
  3. 将镜像以及替换的EFI写入启动U盘,设置BIOS
  4. 无法启动~开始遍历相关资料

后续解决的问题:

  • 核显HDMI输出时无法启动
  • 找到的EFI无法直接安装或升级10.15.2
  • USB3.0无法接入3.0设备
  • 电脑传感器无法正常读取数据,风扇无法控制
  • 睡眠唤醒问题

引导

最主流的应该还是Clover,OpenCore是未来的趋势,但是现在可以找到的即用的资料比较少;在黑果小兵或者远景可以下载到带有Clover的安装镜像,之后使用Etcher写到U盘,再在上面提到的站点搜索EFI做替换就好,然而这里会遇到一些问题:

  • 与系统版本和硬件情况完全匹配的EFI较为难找,部分经验贴没有给出具体的系统版本与实际的硬件情况,例如HDMI输出问题
  • 10.15系统发布的时间不长,发出来的资源较少
  • Clover的具体定制需要用到MacOS平台下的Clover Configurator
  • 在与已有资源与实际情况稍有出入时,EFI应该如何替换

所以这里第一步就是要收集EFI,既然10.15的相对难找,我找了10.14.x的EFI,先安装上再说,毕竟有了Clover Configurator配置起来会方便很多,这里又遇到了无法进入安装界面的问题,根据-v的启动参数都没查到确切的原因,直到把HDMI接到独显上才成功进入了安装界面

独显自然是无法完美驱动的,显而易见的有顶栏和底栏无法开启透明效果,而且移动鼠标都可以感受到卡顿;于是可以大致锁定是HDMI输出的问题,之后就搜索到了黑苹果需要调整下才能输出HDMI,我自己探知的方法是在Clover Configurator->Device中勾选UseIntelHDMI,之后显示器接主板的HDMI,重启即可(Clover Configurator居然有中文,部分选项还有提示)

排查

升级

按照网络上的说法,升级10.15.x需要:升级Clover,更新Kext到比较高的版本,然而我并没有这么一帆风顺,然后又找了一些EFI,反复对比和修改了下,最后对黑果小兵的EFI分区的driver和kext做了删减,把10.14的config修改了下放了进去,终于成功安装了10.15.2,因为之前的文件系统是HFS,所以直接重新抹盘安装了

推测是Clover以及kext还有driver需要高度适配才行,config可以从外部导入

USB定制

之前10.14可以正常识别和使用USB 3.0,然而10.15只认2.0了,查了下得知是需要定制USB,按照网络上的教程尝试了下,又没有成功,之后把10.14的SSDT-UIAC-ALL.aml直接替换了过来就好了

传感器与风扇

风扇的声音和在BIOS界面一样,因为接了一个风扇在主板的水泵接口上,所以在此之前都是全速运转,然后按照查到的结果,安装了Macs Fan Control以及HWmonitor,然而什么都没有,之后发现需要安装VirtualSMC或者FakeSMC的一系列kext才行,貌似前者维护得更好,但是只有后者能用,吸取前面的教训,这次依然从镜像配套的EFI里提取文件

其他问题

  • 短时间睡眠需要一段时间准备,唤醒绿屏,长时间睡眠之后就关机或者重启了,这个暂时没有找到相关的材料,对比也没有发现是哪里的差别
  • 偶尔会顿卡(在播放视频的时候非常频繁),卡住一段时间没有反应,这些问题都只有回到学校再说
  • 期间出现过频繁的花屏问题,调整CPU电压到自动就正常了
  • 无法通过主板的显示接口同时连接两台显示器,并且在连接BenQ的显示器时出现了黑屏无法唤醒的情况

小结

确实是只要硬件OK,找到合适的EFI的情况下,黑苹果安装几乎没有什么难度,我算是走了一套流程,和大部分装黑苹果的人差不多,对Clover这些配置依然是一头雾水,记录也是为了留下一点信息

进一步完善

最后还是走到了这一步,按照惯例,回馈下已知的信息

下面做的主要是:

  • 加装网卡:DW1820A,驱动蓝牙(支持AirDrop隔空投送)
  • 生成序列号,使用iMassage
  • 使用iCloud打通设备,主要是支持SideCar

必要的配置信息:i7 8700K UHD630 Asus Z370-I,原装的网卡RTL8822BE在黑苹果下无法驱动,加上我一直觉得瑞昱的网卡不太可靠(尽管这块已经是其比较好的网卡了),最后还是决定换为博通以支持黑苹果

加装网卡

Asus Z370-I的网卡插在主板背板边缘,网卡拆开WiFi Go的盒子才看得见,规格为m.2 2230 NGFF E key,盒子有两个可拆卸的天线的接口,网卡必须是2X2的,拆卸网卡具体情况看:我的 ITX Hackintosh / PC 购买、组装、安装系统心得

弄清楚规格之后就是选网卡了,主要的网卡可以看攒了一台 4K 视频剪辑黑苹果中的表格和参考文章

大多数人会选择BCM94360CS2这块免驱的网卡(150+),但是最后我还是相中了DW1820A,一方面是因为规格,再一个就是价格(90+),最重要的是经过查阅资料,这块网卡被研究的差不多了,另外黑果小兵也有相关文章:

DW1820A(BCM94350ZAE) 的子型号说明和一些研究,19年8月终极更新,看99楼

按照上面的教程就可以把Win10以及MacOS下的驱动都装好了,然而我测试的时候发现,这张网卡在win10下,5G有1%的丢包,主要是上传丢包,这显然是有点难以接受的,但是暂时就这样吧(因为我把之前的8822BE拆坏了一个天线引脚),最后发现是网卡的抗干扰能力不行(信号差)

序列号问题

有人称这个为黑苹果洗白,来看下B站的可以在黑苹果登录AppleID吗?怎么激活iMessage

在浏览黑苹果相关问题的过程中,发现序列号其实是很重要的东西,这里的序列号还和机型有关,我选的机型是Mac Mini 18,据说这样就可以打开核显加速,序列号不宜频繁更换,会导致Apple ID设置出问题(一个序列号就是账号下的一台设备),进而导致后续的SideCar无法使用

多系统下的时间不同步问题

这个问题困扰了我很久,网上能查到的解释和解决办法比较杂乱,具体的表现是Windows关机一段时间后,再开机发现时间停留在上次关机的时间点,以及开机状态下休眠,时间会停止在休眠的时间点;历经多次搜索终于从RTC综述-RTC的问题表现:电脑时钟不走,或者睡眠唤醒后时钟不走找到了答案,我从文档中主要获得的信息是:

Apple公司使用自己定义的Apple RTC,Apple RTC记录的内存范围可能不被我们普通的主板所支持

这让我想起了OS是可以写时间信息到主板的,如果格式不一样确实可能导致Windows无法写入主板上的时间,文档中的解决办法主要是针对OpenCore引导的黑苹果的,我还停留在Clover而且没有动力去折腾了,最终找到的解决办法是启动一次Ubuntu之后再启动Windows就正常了

SideCar

之前怎么也没想到使用SideCar居然和iCloud有关,最开始我觉得只要有线能用就行,之后换好网卡之后发现SideCar居然还是不能用:出现了连接超时还有只能有线连接的情况(远景上有各种问题的讨论)

最后在苹果的官网Sidecar的其他要求找到了答案,主要就是要开二重认证,经过一番倒腾之后,终于可以用了,我也这才发现:副屏居然不能触摸!!还需要Apple Pencil??

不过多一块屏幕还是方便很多,具体MacOS还是不太会用,这就当体验一下吧

How to VLAN

By: Erease
10 November 2019 at 08:00

介绍VLAN的基本概念和几种场景下的应用,而OpenWrt下VLAN处理机制和一般交换机有些不同,这里做了一个对比并给出了一种两台路由器之间的单线复用的方案

问题

计算机网络的教材对VLAN一笔带过,作业的却要用到交换机互联,之前看的VLAN的文章貌似都对应不到OpenWrt上去,也就很难有实践的机会;下面根据个人在宿舍组网上遇到的问题,一步步来探究VLAN的用法

后面又看到了N1盒子基于VLAN的单臂路由,又做了一些补充

多线接入

宿舍是上床下桌,每一张桌子下面有一个百兆的网口,通过负载均衡,很早就可以把网速跑到100Mbps了,这显然不够啊,因为宿舍WiFi是共用的,自然而然想到连接相邻的两个床位的网口,这样就有300Mbps了,这也是多线拨号的第一步

上图就是将LAN3与LAN4作双线接入,通过VLAN分别对应到eth0.3和eth0.4

此时LAN4与WAN是“直通”的,效果上来说,就是LAN4也可以插网线用电脑拨号了,如果是要给路由器做双线接入的话,则需要添加VLAN,再把一个LAN口添加到新VLAN中,最后建立接口拨号即可

交换

然而舍友还是需要网口拨号的,所以如果需要长期占用的话偶尔肯定是不太方便的,所以需要交换机来扩展一下网口,这一步已经可以通过简单的修改下OpenWrt路由器的Switch来实现,將LAN4和WAN划到同一个VLAN,两个接口就相当于在同一交换机下:

单线复用

然而,仅仅通过untagged只能实现多条线路的“汇聚”,能够达到100Mbps+的只有一台路由器而已,并没有实现“互通”,即每一台路由器都可以上到100Mbps+;不仅如此,还要实现相邻床位的路由器之间只用一根线连接就可以达到同样的网速,更具体的就是在一根网线传输不同的来源(网口)的数据

而VLAN的一个重要的功能恰好就是实现交换机之间的互通

单臂路由

这个需求源于有一台N1,之前看过VLAN的接入网络的方法,觉得网络结构更清晰,以此可以解决主路由算力不足的问题,但之前一直没有刷上OpenWrt,刷完之后发现居然没有交换机的Switch选项,赶紧翻出了之前看到的帖子:N1做主路由,新3做AP的最正统vlan连法教程,想起之前文档刚好有部分没看懂,刚好可以补充上

概念

首先还是OpenWrt的文档:VLAN,很早就读过,但是因为缺少具体的有解释的例子,当时没弄清楚VLAN tagged的机制

所以这里先结合华为的文档了解下基础的概念

VLAN Tag

首先需要理解VLAN标签是被添加到以太帧内部的一个4个字节的片段,其中VID也就是常说的VLAN ID

在一个VLAN交换网络中,以太网帧主要有以下两种形式:

  • 有标记帧(Tagged帧):加入了4字节VLAN标签的帧
  • 无标记帧(Untagged帧):原始的、未加入4字节VLAN标签的帧

常用设备中:

  • 用户主机、服务器、Hub只能收发Untagged帧(Linux系统可以通过安装软件实现收发Tagged帧)
  • 交换机、路由器和AC既能收发Tagged帧,也能收发Untagged帧
  • 语音终端、AP等设备可以同时收发一个Tagged帧和一个Untagged帧

VID & PVID

VID也就是数据帧中的12bit的VLAN ID,表示该数据帧所属VLAN的编号,而PVID(Port Default VLAN ID)又称为缺省VLAN,可以用于和VID做比较来判断Tag的情况

应用

最主要的应用是划分广播域,这部分可以参考图文并茂VLAN详解,然而和本文的关系不是很大

为了提高处理效率,设备内部处理的数据帧一律都是Tagged帧,例如在交换机内部的,在数据帧进入交换机的时候可能会按照一定的规则被打上VLAN Tag以方便下一步的处理,OpenWrt的Old Wiki的一张图很好地体现了这一点:

以太帧进入端口后被打上VLAN Tag,之后在传输的CPU的线路内(Port5-CPU),就同时传输带两种VLAN Tag的包

另外在交换机之间,可以在一条链路上使用两个VLAN也叫做Ethernet trunking,也有人称作单线复用,常见的应用:

  • 单臂路由(只有一个网口的路由器)
  • 使用一根网线同时传输IPTV和宽带的数据

交换机

这里参考的是上面的华为的交换机的文档,不同交换机可能有些不一样

Incoming & Outgoing

以收发的设备作为主体,指的是数据帧到达接口而没有完全进出交换机内部,举个例子:

  • 数据帧到达某一个接口时,路由器会对数据帧的VLAN情况做判断
  • 如果符合通过的规则,则放行做后续处理,不符合则丢弃
  • 后续处理可能就是剥离或者打上标签

链路类型和接口类型

配置VLAN:为了适应不同的连接和组网,设备定义了Access接口、Trunk接口和Hybrid接口3种接口类型,以及接入链路(Access Link)和干道链路(Trunk Link)两种链路类型,如下图所示

根据接口连接对象以及对收发数据帧处理的不同,以太网接口分为:

  • Access接口

Access接口一般用于和不能识别Tag的用户终端相连,只能收发Untagged帧,且只能为Untagged帧添加唯一VLAN的Tag

  • Trunk接口

Trunk接口一般用于连接交换机、路由器、AP以及可同时收发Tagged帧和Untagged帧的语音终端。它可以允许多个VLAN的帧带Tag通过,但只允许一个VLAN的帧从该类接口上发出时不带Tag(即剥除Tag)

  • Hybrid接口

Hybrid接口可以允许多个VLAN的帧带Tag通过,且允许从该类接口发出的帧根据需要配置某些VLAN的帧带Tag(即不剥除Tag)、某些VLAN的帧不带Tag(即剥除Tag)

Hybrid接口和Trunk接口在很多应用场景下可以通用,但在某些应用场景下,必须使用Hybrid接口。比如一个接口连接不同VLAN网段的场景(如图所示的Router连接Hub的接口)中,因为一个接口需要给多个Untagged报文添加Tag,所以必须使用Hybrid接口。

  • 接入链路只可以承载1个VLAN的数据帧,用于连接设备和用户终端
  • 干道链路可以承载多个不同VLAN的数据帧,用于设备间互连

处理机制

OpenWrt对VLAN Tag的处理机制见后文引用文档的加粗部分,此处暂作为理解的参考

  • Access端口

  • Trunk端口

  • Hybird端口

OpenWrt VLAN

OpenWrt的文档没怎么提及接口类型的概念,OpenWrt对VLAN设置的组织形式和普通的交换机有所不同,从机制介绍来看是比较接近Trunk端口的:发出的数据帧只有一个VLAN的数据帧不带Tag

OpenWrt文档所提到的:An untagged port can have only 1 VLAN ID 反映在:OpenWrt中的Switch设置VLAN时单个untagged Port无法再再其他VLAN上为Untagged,否则回提示:LAN 1 is untagged in multiple VLANs!

故抛开之前的端口类型,遵守VLAN的规则,兼容且实用就行

另外,不是所有OpenWrt设备都有Switch这个LuCI的配置选项,比如N1就没有,但是照样可以配置VLAN,位置在Interface的接口物理配置部分,由于无法像Switch那样有Tag之类的选项,

Tag机制

官方文档对Tag机制的介绍如下(散落在两处):

  • Tagged on “CPU (eth0)” means that the two VLAN ID tags used in this example (1, 2) are sent to the router CPU “as tagged data”. Remember: you can only send Tagged data to VLAN-aware devices configured to deal with it properly.
  • Untagged means that on these ports the switch will accept only the incoming traffic without any VLAN IDs (i.e. normal ethernet traffic). The switch will remove VLAN IDs on outgoing data in such ports. Each port can only be assigned as “untagged” to exactly one VLAN ID.
  • Off: no traffic to or from the tagged ports of this VLAN ID will reach these ports.

Ports can be tagged or untagged:

  • The tagged port (t is appended to the port number) is the one that forces usage of VLAN tags, i.e. when the packet is outgoing, the VLAN ID tag with vlan value is added to the packet, and when the packet is incoming, the VLAN ID tag has to be present and match the configured vlan value(s).
  • The untagged port is removing the VLAN ID tag when leaving the port – this is used for communication with ordinary devices that does not have any clue about VLANs. When the untagged packet arrives to the port, the default port VLAN ID (called pvid) is assigned to the packet automatically. The pvid value can be selected by the switch_port section.

特别指出,但是一般也用不上,在LuCI界面上看不到的PVID设置,设置具体在uci network switch_port部分:

Port PVID; the VLAN tag to assign to untagged ingress packets

无Switch配置

官方文档的位置在 Creating driver-level VLANs 一节,配置方式是通过在接口设置,选择自定义接口,在名称在做文章:如在物理网卡eth1上,通过自定义eth1.2接口的方式建立一个VLAN ID为2的接口,在使用Switch设置VLAN,如添加VLAN ID为3的VLAN之后,接口处也会出现eth0.3,逻辑上还是统一的;下面来看下文档对处理机制的描述:

If the incoming packet arrives to the interface with software VLANs (incoming packet to eth1) and has a VLAN ID tag set, it appears on the respective software-VLAN-interface instead (VLAN ID 2 tag arrives on eth1.2) – if it exists in the configuration! Otherwise the packet is dropped. Non-tagged packets are deliveded to non-VLAN interface (eth1) as usual.

即处理流入的包:接口只接收有相应Tag的包,相当于Switch中的VLAN在该接口设置为Tag

这样一来,一个物理网口可以同时收发带Untagged帧和Tagged帧,故使用VLAN来实现单臂路由也就很好理解了,配置的方式也不唯一

解决方案

回到本文开头提到的问题,仿照上面的Switch内部VLAN机制的图的形式,画了一张两台OpenWrt路由器通过VLAN互通,进而实现让两台路由器可以得到宿舍三个网口合计300Mbps的接入

需要说明的是:

  • 因为所有的VLAN都需要为拨号服务,所以这里略去了VLAN到CPU的一段
  • 格式为了照顾LuCI的设置界面显示,可能看起来有些不寻常
  • VLAN ID的外层意义就是接入的网口的标识,中间的TRUNK链路如何并不重要
  • 对WAN Interface的命名就相对随意了,例如Router 1的WAN_1应该命名为WAN_21更合适一点

最后的在宿舍的书桌背后的路由器如图

路由负载均衡:ECMP

By: Erease
3 November 2019 at 08:00

介绍了Linux系统中等效多径路由(ECMP)及其在网络负载均衡上的应用,给出了OpenWrt下的启用的方法

参考

因为偶然发现了Linux内核中的ECMP这种负载均衡的方法,然后查了些资料,这里整理下(业余水平);文末留下了当时发现ECMP的记录

ECMP在工程方面用的很多,能找到的多是说明文档,介绍特性和成套的解决方案,但是基础的材料并不是那么好找,个人也是刚刚接触到ECMP,水平有限,这里先给出本文的主要参考文献

关于负载均衡,[译] 现代网络负载均衡与代理导论(2017)有一个较为全面的介绍,其中作者提到

关于现代网络负载均衡和代理的入门级教学材料非常稀少(dearth)。我问自己:为什么会这样呢?负载均衡是构建可靠的分布式系统最核心的概念之一。因此网上一定有高质量的相关材料?我做了大量搜索,结果发现信息确实相当稀少。 Wikipedia 上面负载均衡 和代理服务器 词条只介绍了一些概念,但并没有深入 、这些主题,尤其是和当代的微服务架构相关的部分。Google 搜索负载均衡看到的大部分都 是厂商页面,堆砌大量热门的技术词汇,而无实质细节。本文将给读者一个关于现代负载均衡和代理的中等程度介绍,希望以此弥补这一领域的信息缺失。

对此个人在经历一番搜索之后也是感同身受,所以才有了总结的想法;如果觉得上文过于“导论”(和本文的关系不大),华为的文档更贴近本文的主题一些,尽量看英文:Introduction to Load Balancing

Jakub Sitnicki’s Blog的系列博文:对Linux内核中的ECMP的实现深入浅出地做了介绍,如果感兴趣的话可以看看

最后是一篇相对详尽的中文资料,重点是ECMP在内核中的变更历史:ECMP在Linux内核的实现

原理及概念

ECMP也就是下面的路由表的情形,就是到某一个目的地址可以有多个下一跳路径可选

root@K2P:~# ip r
default metric 1
        nexthop via 10.170.72.254 dev pppoe-VWAN21 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN22 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN31 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN32 weight 1
root@K2P:~# ip -6 r default
default metric 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN21 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN22 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN31 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN32 weight 1 pref medium

看起来很简单,要弄清楚这个具体能做到什么程度就需要了解下具体的实现,这里一步一步来看

Packet/Flow

Packet对应的是IP分组(数据报、数据包),是数据在L3上传输的单元

对路由器而言,流(Flow)是共享某些特性的packet序列,比如同一个请求(连接)的packets有相同的路由路径

根据负载均衡的对象分:有Per-Packet和Per-Flow两种方式,文档中的两张图对此有个直观的对比

自然而然的会想到L4 Per-Packet负载均衡:每一个的Flow的Packets会被分流,可以实现多拨对看直播都可以加速的效果,然而本文并不会涉及:

Existing Multipath Routing implementation in Linux is designed to distribute flows of packets over multiple paths, not individual packets. Selecting route in a per-packet manner does not play well with TCP, IP fragments, or Path MTU Discovery.

故默认下文都是Per-Flow负载均衡,这就需要利用Packet的header fields信息把一个个的Packet和Flow联系起来,再进行下一跳的路由选择:

  • IPv4 L3 hash

     { Source Address, Destination Address }
    
  • IPv4 L4 hash

    { Source Address, Destination Address, Protocol, Source Port, Destination Port }
    
  • IPv6 L3 hash

    { Source Address, Destination Address, Flow Label, Next Header (protocol) }
    

    IPv6分组因为有Flow Label的存在,IPv6即使只用到L3 Hash也可以实现L4负载均衡

IPv6 Flowlabel IPv6数据报(packet)中有一个20字节的字段:流标号(流标签);进而可以用流标号取代路由表来处理流的路由,加速路由器对分组的处理;在ECMP中却提供了Flow的信息,故IPv6 ECMP是比较容易做的

L3/L4

更关键的还是负载均衡的层级,比如在多拨的情况下使用策略路由也可以做“负载均衡”,下面的命令往往提高BT的速度,这属于L3 Per-Flow负载均衡(左图):只在IP地址层级分流

ip rule add table 916
ip route add 10.173.0.0/16 via 10.170.72.254 dev pppoe-VWAN31 table 916
ip route add 10.170.0.0/16 via 10.170.72.254 dev pppoe-VWAN32 table 916

类似的方法对HTTP多线程下载并没有加速作用,对连接分流,需要L4负载均衡:多线程下载的请求之间source port不同,故L4 hash值基本不同,故会被分到不同的路径上,这样一来L4负载均衡是面向连接的就很好理解了,而内核在IPv4/IPv6上实现到一步有一段很长的历史:

Linux内核中ECMP

Linux内核的Git Commit,对发展历程感兴趣的还可以参考博文Celebrating ECMP in Linux,其中还讨论了设备的出站流量和转发流量的ECMP效果的不同,这里把ECMP的变更历史整理到一张表格中,以及对应时间的OpenWrt的内核版本信息:

Linux Kernel OpenWrt 内核版本 ECMP变更 ECMP形式
1997 | 2.1.68   IPv4 ECMP 加入内核 L3 Per-packet + route cache -> L3 Per-flow
2007 | 2.6.23   IPv4 multipath cached 移除 L3 Per-packet + route cache -> L3 Per-flow
2012.9 | 3.6   IPv4 route cache 被移除 L3 Per-packet -> L3 Per-packet
2012.10 | 3.8   IPv6 ECMP 加入内核 IPv6 Flowlabel -> IPv6 L4 Per-flow
2015.9 | 4.4 15.05 | 3.18 IPv4 ECMP:使用L3 Hash L3 Per-packet + L3 hash -> L3 Per-flow
2016.4 | 4.7   IPv4 ECMP: 增加邻居健康检查  
2017.2 17.01 | 4.4    
2017.3 | 4.12   IPv4 ECMP: 增加 L4 Hash L3 Per-packet + L3/L4 hash -> L3/L4 Per-flow
2017.11 | 4.14   IPv6 ECMP: ICMPv6 修复  
2018.1 | 4.16   IPv6 ECMP: 支持指定权重  
2018.4 | 4.17   IPv6 ECMP: 增加 L4 Hash  
2018.7 18.06 | 4.9/4.14    
2018.10 | 4.19      
2019.11 19.07 | 4.14.151    

这里可以推出(实际早期版本我也没有测试过),在默认的编译选项和内核版本下,较为实用的L4负载均衡,IPv4需要在18.06及之后的版本

IPv6由于使用了Flowlabel作为Hash的对象,根据表格,OpenWrt在15.05之后的版本就可以启用L4负载均衡

本文考虑更多的还是OpenWrt中的应用,更多信息参考本博客中的Speed_Up

启用ECMP

准备部分是从排查问题的角度来看的

在启用之前可以确认下编译内核时的下面选项,即IP: equal cost multipath,ECMP支持,较新版本的OpenWrt默认是打开的

  • CONFIG_IP_ROUTE_MULTIPATH=y

暂时不清楚使用下面的多个nexthop命令添加ECMP路由的依赖,只知道命令ip route的源于iproute2,如果出现如下报错:

Error: either “to” is a duplicate, or “nexthop” is a garbage.

可以尝试:

  • 安装ip-full再尝试,OpenWrt默认是ip-tiny,某些情况下也能使用多个nexthop命令添加ECMP路由
  • 使用route命令多次添加静态路由,可以启用IPv6的ECMP(详见文末的后记),实测在原版的OpenWrt可行
    route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2
    route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3
    

添加ECMP路由

这里直接引用iproute2的user Guide的Multipath routing部分:

ip route add ${addresss}/${mask} nexthop via ${gateway 1} weight ${number} nexthop via ${gateway 2} weight ${number}

Multipath routes make the system balance packets across several links according to the weight (higher weight is preferred, so gateway/interface with weight of 2 will get roughly two times more traffic than another one with weight of 1). You can have as many gateways as you want and mix gateway and interface routes, like:

ip route add default nexthop via 192.168.1.1 weight 1 nexthop dev ppp0 weight 10

Warning: the downside of this type of balancing is that packets are not guaranteed to be sent back through the same link they came in. This is called “asymmetric routing”. For routers that simply forward packets and don’t do any local traffic processing such as NAT, this is usually normal, and in some cases even unavoidable.

If your system does anything but forwarding packets between interfaces, this may cause problems with incoming connections and some measures should be taken to prevent it.

可以补充的是如果用的多个等带宽的PPPoE Interface的话,可以使用多个nexthop dev ${pppoe-dev}

修改内核运行参数

仅仅是上一步的话,可以见到在使用P2P下载时已经有负载均衡了,但是对HTTP的多线程下载并没有加速效果,因为一些Linux内核对IPv4的ECMP默认设置到L3 Hash,而且也没有开启邻居健康检查,所以需要修改下内核的运行参数,相关的具体的参数说明如下:

fib_multipath_hash_policy - INTEGER Controls which hash policy to use for multipath routes. Only valid for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled. Default: 0 (Layer 3) Possible values: 0 - Layer 3 1 - Layer 4 2 - Layer 3 or inner Layer 3 if present

fib_multipath_use_neigh - BOOLEAN Use status of existing neighbor entry when determining nexthop for multipath routes. If disabled, neighbor information is not used and packets could be directed to a failed nexthop. Only valid for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled. Default: 0 (disabled) Possible values: 0 - disabled 1 - enabled

echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf
echo "net.ipv4.fib_multipath_use_neigh=1" >> /etc/sysctl.conf
sysctl -p

其他相关的内核运行参数(IPv6 Flowlabel等)可以参考ip-sysctl.txt

OpenWrt上启用ECMP

熟练的话完全根据上面的方法做了,以下是在校园网PPPoE接入下实践的,如果PPPoE拨号多播数量较多可以参考如何提高网速

准备

  • 在启用之前可以确认下编译内核时的选项CONFIG_IP_ROUTE_MULTIPATH=y(OpenWrt 18.06之后的版本默认已经开启)
  • IPv6 ECMP只在IPv6 NAT下测试过,受限于当前OpenWrt正式版的内核版本,未对内核参数做进一步测试
  • 加速的前提是下多拨可以加速(ISP限制)

添加虚拟网卡

OpenWrt安装kmod-macvlan后就可以添加虚拟网卡到不同的VLAN上

opkg update && opkg install macvlan

路由器上的RJ45网口是绑定到VLAN上的,如果是添加虚拟网卡到一个VLAN上就是单线多拨,添加到多个VLAN上就可以做多线多拨了

这里的eth0.2对应于WAN口(在Interface -> Switch可以看到WAN绑定在VLAN 2上),不同的设备可能有些许不同,这里在eth0.2上添加两个虚拟网卡

for i in  `seq 1 2`
do
  ip link add link eth0.2 name veth$i type macvlan
done

拨号

还是用脚本省事,填上用户名和密码即可,拨数为2,填下账号密码

#!/bin/sh
username=
password=
for i in  `seq 1 2`
do
  uci set network.VWAN$i=interface
  uci set network.VWAN$i.proto='pppoe'
  uci set network.VWAN$i.username="$username"
  uci set network.VWAN$i.password="$password"
  uci set network.VWAN$i.metric="$((i+1))"  
  uci set network.VWAN$i.ifname="veth$i"
  uci set network.VWAN$i.ipv6='1'
done
uci commit network

添加所有PPPoE接口到wan zone(担心影响到其他的网络环境的话手动也可以)

for i in `uci show network | grep pppoe | awk -F. '{print $2}'`
do
  uci add_list firewall.@zone[2].network=$i
done
uci commit firewall

添加ECMP路由

只用nexthop dev ${pppoe-dev}:

#IPv4
ip route replace default metric 1 nexthop dev  pppoe-VWAN1 nexthop dev  pppoe-VWAN2
#IPv6
ip -6 route replace default metric 1 nexthop dev  pppoe-VWAN1 nexthop dev pppoe-VWAN2

做完这一步就可以使用ip rip -6 r命令检查下路由表

修改内核运行参数

echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf
echo "net.ipv4.fib_multipath_use_neigh=1" >> /etc/sysctl.conf
sysctl -p

测试

通过东北大学IPv6测速以及IPv4测速测试负载均衡的速度叠加效果,或者使用iftop命令查看各个接口上路由的实时速率

传入连接的问题

添加ECMP路由之后传入连接偶尔连的上,偶尔连不上,但是PT的上传之类的貌似又没有问题(可能因为上传也可以是主动发出的连接),如果有这方面需求的话需要添加策略路由,为某一接口上的地址指定路由规则,下面是IPv4的,完成之后可以从外部访问之类的,但是对其他的影响就不太清楚了,IPv6部分暂时没有测试条件…

ip rule add perf 20 from IP table 20
ip route add default table 20 dev INTERFACE

此处参考自Linux 平台上之 Multipath Routing 應用,非常难得的详细的文章,还是2001年的

后记:偶然发现的ECMP

这里保留当时的发现过程:(当时发现了这个功能非常开心,现在来看部分内容不准确,但是文末的脚本的效果要好于ECMP默认的方法)

只在K2P OpenWrt 18.06上面实践过,对LEDE 17.01无效

下面是在操作一番之后的路由表,对IPv6的测速显示网速翻了四倍

root@OpenWrt:~# ip -6 route | grep pppoe
default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN4 proto static metric 512 pref medium
2000:::/3 dev pppoe-VWAN4 proto static metric 256 pref medium
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-wan weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN4 weight 1

大致可以看出这已经是做了负载均衡,需要的只是安装好luci-app-mwan3,简单操作一下路由表,这里的网关地址和dev需要看具体情况

2000::/3 就是IPv6的单播(Unicast)地址了,在不做任何操纵的情况下,无PD的路由表(单拨)

default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 proto static metric 512 pref medium
2001:250:1006:dff0::/64 dev pppoe-VWAN3 proto static metric 256 pref medium
...

之后通过下面两条常规的添加路由表条目的命令:

route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2
route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3

发现路由表就出现了nexthup和负载均衡中的weight标记

root@OpenWrt:~# ip -6 route | grep pppoe
default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 proto static metric 512 pref medium
2000::/3 dev pppoe-VWAN3 proto static metric 256 pref medium
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 weight 1
...

类似的网关添加过程对IPv4效果并不好,这里稍后再细说

之后还需要修改一下防火墙,这里用的还是NAT6中的那条命令

因为对路由表的修改在路由器重启之后会重置,所以还是要添加到开机的启动脚本或者添加到自定的防火墙规则之中,如果已经在NAT6配置过程中配置好了的话这一步就可以忽略了

ip6tables -t nat -I POSTROUTING -s `uci get network.globals.ula_prefix` -j MASQUERADE

实测的峰值速度可以到达双网口的满速,但是一样的问题,在UT,IDM,Thunder这种多线程下载软件下轻松满速,而在YouTube视频应用下,只有半速(甚至包括用IDM下载的情况下)

目前最新版本的mwan3也开始支持IPv6多拨了,但是个人还是觉得日常使用的话用以上的方法更加快捷,不过需要对网络有一定的了解,下面是一段针对IPv6 NAT的多拨hotplug脚本,用了一些OpenWrt开发时推荐的写法,比较实验性

#!/bin/sh
[ "$ACTION" = ifup ] || exit 0
ifaces=$(ubus call network.interface dump | jsonfilter -e '$.interface[@.proto="dhcpv6" && @.up=true].interface')
for iface_6 in $ifaces
do
  [ "$INTERFACE" = $iface_6 ]  || continue
  devices=$(ubus call network.interface dump | jsonfilter -e '$.interface[@.proto="dhcpv6" && @.up=true].device')
  ipv6_gw=$(ifstatus $iface_6 | jsonfilter -e '$.route[1].nexthop')
  for ipv6_dev in $devices
  do
    status=$(route -A inet6 add 2000::/3 gw $ipv6_gw dev $ipv6_dev 2>&1)
    logger -t NAT6 "Gateway: $ipv6_dev: Done $status"
  done
  exit 0
done

TTRNN论文的UCF11实验复现

By: Erease
21 October 2019 at 08:00

对ICML2017上的使用TTRNN做视频分类的论文中的UCF11实验做了复现,作者在Github上公开了Python2代码,这里使用工具转换到Python3;另外代码缺少了预处理步骤,个人参考注释做了补充;在复现的过程中遇到并解决了部分问题:OpenCV提取视频帧序列,简单的并行处理,Tensorflow在Linux下CPU调度设置

Paper With code

Tensor-Train Recurrent Neural Networks for Video Classification

需要复现的部分是使用TT_RNN处理UCF11的数据集(使用新版本的UCF11数据集,旧版本的文件有点乱)

最开始还是梳理下论文和代码的逻辑

代码修改

通过注释和前后文猜测作者的想法…

2to3代码转换

本来在Linux环境下使用Python2是没什么问题的:

  • Windows下的Conda没有Python2的Tensorflow,而平时用Windows的居多
  • Python2和Python3的pickel导出的对象之间不兼容
  • 而在同一个Conda环境中,OpenCV和Keras之间也不兼容,所以运行代码的时候需要了两个Python2.7的环境,一个用于OpenCV处理视频,一个用于Keras
  • Github的Readme所提及的运行环境难以配置(版本问题,Conda的锅?)
  • Linux下计算只用了一个核心,这是不能接受的(训练到天荒地老)

这些显然是无故添加了很多麻烦的,在Conda环境下使用Python2成功运行后就尝试使用Pyhton3配置环境,尽管有些warning,但是一次性就解决了上述问题

2to3 - 自动将 Python 2 代码转为 Python 3 代码主要是转换TTRNN.py,其他的手动改就好(真的只转换了print…)

后端

默认使用了Tensorflow作为了Keras的后端,然而在Linux下默认只用了一个核心,还好使用Python3时给出了提示,按照提示找到了:Tips to Improve Performance for Popular Deep Learning Frameworks on CPUs

如果您有一个可以在内部并行化的操作,例如矩阵乘法(tf.matmul())或归约(例如tf.reduce_sum()),TensorFlow将通过在具有线程的线程池中调度任务来执行该intra_op_parallelism_threads操作。因此,此配置选项控制单个操作的最大并行加速。请注意,如果并行运行多个操作,则这些操作将共享此线程池。

如果TensorFlow图中有很多独立的操作-因为在数据流图中它们之间没有直接的路径-TensorFlow将尝试使用带有线程的线程池并发运行它们inter_op_parallelism_threads。如果这些操作具有多线程实现,则它们(在大多数情况下)将共享同一线程池以进行操作内并行操作。 这两个参数在Tensorflow的性能指南也有说明,其中提到了默认设置往往就有比较好的训练效果,但是为了缩短训练时间,经过几次测试之后选择调高:

#some option to improve performance in linux
import tensorflow as tf
from keras import backend as K

config = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=18, inter_op_parallelism_threads=36, allow_soft_placement=True)
session = tf.compat.v1.Session(config=config)
K.set_session(session)

视频预处理

使用OpenCV提取视频帧序列,基本上做视频处理都要做这一步,因为逐个读写文件需要几分钟有点不太方便,看for循环部分可以设置并行就试了下,可以缩短运行时间到几秒(看硬盘速度~)

训练的代码Experiment_UCF11.py根据预处理的代码做了相应的修改,在导入训练和测试数据部分,因为导出视频帧使用的是list结构,而原作者的做法是导出的array,故在导入后多了一步list转array的操作

另外论文中提到的输入是RGB的通道矩阵,而OpenCV默认读取BGR,这里还用了matplot查看了下

最后导出的数据大小是16.4G

import os
import pickle
from multiprocessing.dummy import Pool as ThreadPool

import matplotlib.pyplot as plt
import numpy as np

import cv2

workspace ='./'
clips_path = workspace+'Datasets/UCF11_updated_mpg/'
frames_path =  workspace+'processed_data/'

if not os.path.isdir(frames_path):
    os.mkdir(frames_path)

classes = ['basketball', 'biking', 'diving', 'golf_swing', 'horse_riding', 'soccer_juggling',
           'swing', 'tennis_swing', 'trampoline_jumping', 'volleyball_spiking', 'walking']

def get_clips(class_name):
    files = os.listdir(clips_path + class_name)
    files.sort()
    clip_list = []
    for this_file in files:
        if '.DS_Store' not in this_file and 'Annotation' not in this_file:
            clips = os.listdir(clips_path + class_name + '/' + this_file)
            clips.sort()
            for this_clip in clips:
                if '.DS_Store' not in this_clip and 'Annotation' not in this_file:
                    clip_list.append( clips_path + class_name + '/' + this_file + '/' + this_clip )
    return clip_list

# iterate through all clips and store the length of each:
def process(par_input):
    item=par_input[1:]
    classes_name=par_input[0]
    for l in range(len(item)):
        #print(str(item[l]))
        cap = cv2.VideoCapture(item[l])
        ret = True
        clip_frames = []
        count = 0
        while(ret):
            k
            ret, frame = cap.read()
            if ret:
                #if count%2==0:
                rgb_frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
                frame_resized = cv2.resize(rgb_frame,(160,120))
                clip_frames.append(frame_resized)
                count = count + 1
        #data.append(clip_frames)
        class_index=classes.index(classes_name)
        clip_index_in_class=clips[class_index].index(item[l])
        head_index_of_class=int(sum(class_sizes[:class_index]))
        length_array_index=head_index_of_class+clip_index_in_class
        length_of_frames[length_array_index]=count
        save_name = str(classes_name) + '/' + str(l)
        if not os.path.isdir(frames_path + str(classes_name)):
            os.mkdir(frames_path +  str(classes_name))
        write_out = open(frames_path + save_name +'.pkl', 'wb')
        pickle.dump(clip_frames, write_out)
        write_out.close()

clips = [None]*11
#labels = [None]*11
class_sizes = np.zeros(11)
for k in range(11):
    class_clip_paths = get_clips(classes[k])
    clips[k] = class_clip_paths
    class_sizes[k] = len(class_clip_paths)
    #labels[k] = np.repeat([k], class_sizes[k])

n_all_clips=int(class_sizes.sum())
length_of_frames = np.zeros(n_all_clips)

par_input=[]
for i in range(11):
    temp_list=[]
    temp_list.append(classes[i])
    temp_list.extend(clips[i])
    par_input.append(temp_list)

pool = ThreadPool()
pool.map(process,par_input)
pool.close()
pool.join()

print("total "+str(length_of_frames.shape[0])+" clips")
print("The lengths of frame sequences is vary from: "+str(length_of_frames.min())+" to "+str(length_of_frames.max()))
print("The average length is:"+str(length_of_frames.mean()))

其中还统计了每个片段的长度,用于训练做截断用,大大减少训练的数据量(内存占用)和运算量(训练时间)

参数修改

a resolution of 320 X 240. We generate a sequence of RGB frames of size 160 X 120 from each clip at an fps(frame per second) of 24, corresponding to the standard value in film and television production. The lengths of frame sequences vary therefore between 204 to 1492 with an average of 483.7.

片段的帧序列长度和论文中的陈述有些出入,比实际统计的最大值900要大得多,论文使用的片段转换到24FPS,貌似需要使用ffmpeg做插值,感觉必要性不大(OpenCV可以跳帧,但是训练的结果不太好看)

源代码中默认的统一的输入长度是GLOBAL_MAX_LEN=1492,前面提到实际只有900,却给计算带了些希望,设置成900,内存占用只需要110G+,如果参考平均200左右将输入长度减半到450的话,仅仅需要50G+的内存就足够了,训练时间也可以缩短到一天左右

为了复现TTRNN在UCF11上的出彩的性能,选择使用TT,GRU是默认的

use_TT = 1      # 0 for non-TT, 1 for TT

速度最快的TT_MLP的帧提取部分貌似不太清楚,这里就不做了

迭代次数按照论文提到的100 epochs把iter_range设置为101(初始代码写的1001?),论文的结果,一个Epoch需要30分钟,一百个也就是50小时,两天,这个速度和输入长度为900的情形是接近的

运行

环境

Linux和Windows下都使用了Anaconda构建的Python3.7环境,主要安装最近版本的Keras,OpenCV,scikit-learn,其他的倚赖都会自动安装,windows下跑小数据集用于测试(内存太小了),Linux使用VSCode的SSH-Remote调试和运行(Tmux居然会随着VSCode断开而终止?)

论文貌似使用CPU跑的,这里也一样,把后端从Theano换成了Tensorflow,主要的瓶颈在于内存

命令

还是用Tmux挂在init进程下运行:tmux new -s UCF11_L450

python ***.py | tee UCF11.out

运行代码之后再切出来,从文件查看输出或者使用tmux a -t UCF11_L450切入

结果

个人不太了解调参,仅仅是让代码可以运行,半天时间可以跑完的一个设置:以隔帧采样的帧序列作为输入,取截断长度为200

运行情况

运行了几次,给出一个参数,占用,训练时长和效果的参考表格

  内存占用(GB) epoch_time(s) 100 Epochs(about) Epochs - Accuracy
跳帧-L200 30 120 4hour 99 - 0.4
L450 60 400 12hour 77 - 0.38
L900 130 1700 2days 14 - 0.25

关于PT站的零零碎碎

By: Erease
17 October 2019 at 08:00

遇到的问题,读过的文章,一点总结,希望能节约些时间的同时把事情做好

前言

初次接触到PT的概念是在初中,EACDY论坛的站长在115网盘链接失效后毅然决定要开办PT站,但是因为那是家里的带宽极为有限,没能提供多少的上传量;之后偶然在东南大学的虎踞龙盘PT见识到了教育网PT的繁荣,于是定了一个之后要去一所有PT的大学的目标,最后如愿以偿,却发现IPv6才是打通教育网和公网PT的关键;之后又是一次偶然的机会,接触到了PT站的一些技巧后…决定把本文放到博客上(仅涉及国内的PT站)

个人的PT站账号不多,数据仅仅是咸鱼水平,对公网PT知之甚少,内容多是引用以及摸索的经验,仅供参考

引用与推荐

文章

rhilip对国内的PT站数据有一个详细的统计分析,可以作为发展PT的参考:

PT实用工具&脚本分享:感谢给我发过邀请的yezi1000,顺着简介找到了博客,下面这篇文章介绍了搭建PT盒子的一些经验(和普通的娱乐用户关系不大)

torrentinvites.org:据说是一个卖PT邀请码的网站,该网页有PT站的数据统计及站点的分析,可以为进入某个公网PT提供了部分参考

ipv6 NAT后配置端口转发:使用IPv6 NAT的可以看下,说不定可以改善连接性,进而大大提高上传速度

这里还有一个用得上但是有些古老的软件,v6speed,类似于某种P2P点播软件:使用种子利用P2P传输就可以观看电影,一时半会还真的没找到同类型的软件,据说有解码能力有限的问题,最后一次更新在2015年

工具

PT站最关注的点:保种以及搜索下载

reseed:方便的跨站辅种工具,进到新的PT站,一个个搜索辅种往往需要花掉相当多的时间,这个几分钟就解决了,天津大学的同学开发的,注册账号需要北洋的Passkey,国内的部分站点可用

PT-Plugin-Plus:支持Chrome和Firefox的插件,提供站点数据概览,搜索聚合以及辅助下载功能;向往PT的一大原因就是简单且高质量,这个插件对此贡献也很大,比如在网页上看到有人推荐某个纪录片,右键搜索,下载一气呵成

如果要发电影(转种可能也用得上),PT Gen可以帮助生成信息

遇到的问题

PT的生存性

如果网络通畅的话下载热门的种子即可,但是如果上传速度很糟心的话,还是选择大量的保种路线,使用保种得到的积分换上传量比较好,所以打听好PT站点的生存策略和弄清楚自身的网络状况是很关键的

资源的发布时间

首先要搞清楚0day资源的概念,自行搜索,这里说下蓝光电影的发布时间的一个参考:blu-ray.com中的电影详情页面中可以看到蓝光碟片的发布时间,一般PT站可以提前一点点发出资源,不同的站点的一个区别就在于首发的速度,但顶级站点往往转种都是很快的

至于更普遍的WEB版或者TV版资源,看首播的时间就好,可以留意的是:

  • 有WEB录制组的站点,可以查看历史资源确定是否有录制计划
  • 电影录制比较特殊的地方在于版权,有些站点可能不让发
  • Auto Seed的存在,主要是对欧美剧集,可以第一时间转种,具体那些站点有可以参考Pt-Board

特别一点的是动漫,动漫资源的发布往往依赖于字幕组,就我所在的大部分PT站动漫更新都不是很及时,BT站 动漫花园,部分动漫字幕组出资源会第一时间放出来

代理与盒子

因为学校往往带宽比较贵,学生购置大容量硬盘也不太划算(刷数据和看电影是两回事),随意挂代理和购置盒子可以提高速度和节约流量,需要注意的事部分站点是限制这种方式的,尤其是刚进入站点的时候,如果一不小心被识别为盒子(挂代理的VPS供应商有时候会被识别),可能上去下载免费资源就会出现分享率爆炸的情况,所以此处需格外谨慎(尤其是路由器上挂透明代理)

NAS

因为电脑上没有安装3.5寸盘的空间,在经历过路由器挂BT的初等玩法后,还是组建了一台NAS用于个人的数据存储和下载管理

下载软件

NAS自带的下载软件源于Transmission:

  • 有配套的APP:DS Get,但是不太好用…
  • 支持订阅,规则也比较好写
  • 结合上Download Station Extension可以在Chrome,safari,Opera浏览器中使用右键直接下载,缺点是最多只能显示100个种子
  • 缺点之一就是默认是强制校验资源的完整性的,以至于添加资源特别麻烦
  • 缺点之二,种子太多容易卡顿

于是就转而使用了Docker的linuxserver\qBittorrent

  • 终于可以跳过校验了,结合之前的reseed工具,可以迅速添加几百个种子
  • 开源软件,自带开源的气质,各种选项,信息都会呈现出来
  • 需要结合后面的FlexGet实现订阅
  • 轻量化的Web界面反而成为了远程跨平台访问的优势

默认设置需要修改的主要是下载任务数量和连接数

IPv6问题

docker如果使用桥接网络是默认不支持IPv6的,个人安装网上的修改参数之类的方法最终也失败了,最后还是使用了hosts网络多尝试了几次成功了

订阅

比如说在0day资源出来之前可以先写好订阅,待到资源出种就可以第一时间自动下载好,查看下载列表就可以得知已经出种而不需要再去反复的检索

RSS

一般的NexusPHP架构的PT站都在搜索栏的右侧有个订阅的icon,设置好筛选就可以通过RSS获取种子的信息进而实现自动的下载

FlexGet

主要是弥补自带RSS的设置自由度不足以及给Docker的qBittorrent提供自动下载支持,为了省事,采用了Docker:wiserain-flexget,挂载一个qbittorrent可以访问的文件夹作为qbittorrent的种子监测文件夹,运行后就可以从网页打开FlexGet的界面,填写config即可

网络

若是用户之前都是公网IP且防火墙规则开放的情况就不多说了,主要是做种的时候看到有人在下载而本地的种子又没有上传就很折磨

传入连接

Tracker是PT用户都可以访问,用于上传BT客户端的IP及端口信息以方便用户之间的相互连接,试想一下这样的一个过程,当一个客户端A,得知客户端B正在做种,于是A直接向B发起了一个连接请求,也就是对B而言,该连接是一个传入连接,然而残酷的现实是:

  • 防火墙默认阻止了传入连接,在以校园网的IPv6防火墙和设备的默认防火墙策略为代表
  • 路由器的NAT类型默认阻止了传入连接

阻止传入连接不会影响正常的上网,因为日常的上网连接都是由内网的设备发起或是请求,好比开门发快递和收快递,而PT的传入连接呢?就好比一个陌生的快递突然送了过来,现实中可能是“来者不拒”,但是网络的世界往往要危险的多

至于防火墙这一级,如果可以管理的话,开放UT的监听端口即可,如果不行的话可以尝试设置uPnP做自动端口转发

PT站上显示的“可连接”仅仅是可以连接到Tracker服务器,实际的效果可以靠UT、qbittorrent的用户标识(Flag)判断

Flag所代表的意义:

D = 当前正在下载 (感兴趣且没有被阻塞)
d = 本级客户端需要下载, 但是对方没有发送 (感兴趣但是被阻塞)
U = 当前正在上传 (感兴趣且没有被阻塞)
u = 对方需要本机客户端进行上传, 但是本机客户端没有发送 (感兴趣但是被阻塞)
O = 开放式未阻塞
P = 使用μTP协议连接,兼具TCP的可靠性及UDP的连接性
S = 对方被置于等待状态
I = 对方为一个连入连接
K = 对方没有阻塞本机客户端, 但是本机客户端不感兴趣
? = 本机客户端没有阻塞对方, 但是对方不敢兴趣
X = 对方位于通过来源交换获取到的用户列表中 (PEX)
H = 对方已被通过 DHT 获取.
E = 对方使用了协议加密功能 (所有流量)
e = 对方使用了协议加密功能 (握手时)
L = 对方为本地/内网用户 (通过网络广播发现或位于同一网段中)

NAT类型

NAT类型概述以及提升NAT类型的方法对NAT类型做了简要的介绍

NAT对PT的影响是很大的,如基于OpenWrt的Linux路由使用netfilter的MASQUERADE实现的NAT的默认类型是Symmetric NAT,或者称为NAT4,是对传入连接最不友好的一种NAT,IPv4的解决办法:

Chion82/netfilter-full-cone-nat写了从DNAT到netfilter内核子系统,浅谈Linux的Full Cone NAT实现,而LGA1150为OpenWrt做了Netfilter and iptables extension

然而,教育网主要还是IPv6,IPv6的Full Cone NAT还没见过,暂时只有ipv6 NAT后配置端口转发

How to VSCode

By: Erease
19 September 2019 at 08:00

还记得初见Atom的惊艳以及日久感受到的速度慢和占用高,记得VSCode刚推出时的“难用”,现已今非昔比,本文主要介绍VSCode的一些简单的应用:部分实用的插件以及调试C,Python代码的方法

最初为了写LaTeX而使用 Atom + 插件 来作为代码编辑器(积累了些经验之后转而使用TeXStudio),之后也就顺其自然的用Atom写了作业的大部分代码(装插件还要看网络环境),之后就是遇到了幽灵和熔断漏洞的影响,笔记本的性能越来越力不从心,使用Atom打开大文件特别慢,运行也并不流畅,才发现Atom的性能问题被诟病已久,有人推荐了微软的VSCode —— 和Atom的主题、插件基本通用,但是性能好太多,于是我就换下了Atom,一直用到了现在

现代代码编辑器最基本的功能:Git,多语言支持,丰富的效率插件,VSCode都是有的,而它出彩的地方还是在于开发方面(其实我就是写下作业)

准备

安装VSCode的时候记得勾选使用VSCode打开文件夹,因为VSCode的对工作空间要求比较严格的,另外对于Atom迁移而来的,可以选择Atom主题“One Dark Pro”以实现一个“平缓的过渡”

在调试代码和使用方面,常用的插件有:

  • Code Runner
  • Terminal
  • Resource Monitor

考虑到配置繁杂,重装或者有多台电脑迁移配置不便,可以用Setting Sync插件通过Github提供的服务以实现配置的同步

Remote-SSH

常规插件其实各大代码编辑器都差不多,对于VSCode来说,个人接触到的,最惊艳的插件当属Remote-SSH:

开发环境或者说代码运行的环境在远程或者其他的系统上,需要使用SSH客户端连接到远程,使用SCP或者SFTP来传输文件,这里面SSH客户端是一个重要的角色,最开始使用Atom编辑加上脚本完成“本地编辑,远程调试”的过程,后面遇到了一度让我觉得“相见恨晚”的FinalShell,解决了SSH时的一些列问题,但是作为一个独立开发者维护的闭源软件,稳定性和安全性是一般般的

而Remote-SSH相当于把VSCod搬到了服务器上,同时解决了运行环境和文件传输两个问题,尽管类似的问题可能早就有成熟的方案,但是在常用的代码编辑器中就能实现还是相当感动的,安装完成本地的客户端之后在VSCode的左下角有一个蓝色的标记,点击之后按照提示添加服务器就好(遇到SSH的config文件权限的问题,换用另外一个ssh的config文件就好),初次使用连接服务器之后会在服务器端自动下载和安装VSCode的相关组件(常用的LInux发行版没什么问题,也不需要root权限,ARM架构也支持),之后再手动把需要的插件安装下就好

初次连接时打开文件夹需要重连,直接打开另外一个文件夹也会重连,感觉不方便的话,可以在打开文件夹之后再添加另外一个文件夹到工作空间中(会重新连接),文件夹一栏会变成了工作空间,之后添加文件夹就不需要重连了,工作空间的配置可以保存以便下次使用;文件的上传下载分别是拖拽和右键菜单,体验算是很好了

如果在远程跑代码可以安装Resource Monitor用于监测CPU和内存占用,其他的细枝末节的部分搜索下就有

WSL支持

这里就不造轮子了,已经有人做的很好了,Dev on Windows with WSL,其中主要使用了Remote-WSL插件,虽然个人一度觉得WSL是未来,但是使用了一段时间之后还是觉得不如Docker或虚拟机来得方便,尤其是和Remote-WSL一起推出的Remote-SSH诞生之后

Docker支持

无意中又看到Remote插件多了一个Docker,之前的docker插件在VSCode侧边栏可以方便的查看镜像容器的情况,而Remote插件可以直接把VSCode的运行环境放到容器内,并且可以直接接入正在运行的容器(也就是不需要预先安装SSH和开放端口),尤其对编译环境下修改代码比较方便

另外还有个有趣的地方,可以让Win下的Docker支持图形化界面(勉强可用)

  • 安装vcxsrv,运行xlanuch,设置勾选最后一页的最后一项(Disable Access Control)
  • 获取本机的一个让容器可以到的IP,可取宿主机的WAN IP

这里直接把IP保存为变量了:

$DISPLAY=(ipconfig|findstr "IPv4")[1].split(" ")[-1]+":0.0";
docker run -it --net=host -e DISPLAY=$DISPLAY ....

调试代码

VSCode全称Visual Studio Code,调试代码方面算是对得起Visual Studio之名了,权威的配置过程还是参考VSCode官方文档,本文介绍的是个人配置在Windows下的配置尝试,点几下就配置好了,故分享出来,仅供参考

C语言

有些作业要求用C语言写,最开始追求新奇,用的Visual Studio 2015以及Clang,看中的是强大的调试功能,但是对于写个简单的作业来说太费事,Clang的报错常常不理解

之后转而使用了更常见的Dev C++,基于GCC,照抄书上的代码也不会莫名报错了,在很长一段时间里都是用Atom写代码,Dev C++做运行和调试,

到了VSCode当然会想要接近Visual Studio的体验,编译器肯定不用Clang了,至于GCC,WSL里有,Win上的GCC的版本不知道用哪个好,看网上的博客配置tasks.json (build instructions),launch.json (debugger settings)依然颇为繁琐

直到后面遇到了Scoop,安装就很简单了:scoop install gcc,查看版本后发现是MinGW的GCC,安装CodeRunner扩展后就可以运行代码了

注:代码及工作目录的路径不要有中文

调试功能则需要C/C++扩展,Debug功能在VSCode的左侧应该是自带的,对新目录来说Debug一栏的左上角绿色三角形旁边会显示”No COnfiguration”,Debug时配置gcc.exe作为代码的编译器,GDB作为代码的调试器的关键就在这里了:

  • Add Configuration的时候选C++(GDB/LLDB),之后再选gcc.exe build and debug active file设置完成后会在工作目录下生成一个.vscode/launch.json的文件,文件定义了gdb作为exe的调试器,需要注意的是这里的preLaunchTask,定义了在执行调试在前需要使用gcc对代码进行编译,也就是下一步

  • 回到C的源文件,点击Debug一栏的左上角绿色三角形开始调试,会提示Could not find the task ‘gcc.exe build active file’ ,点击Configure Task,再选gcc.exe debug active file,软件就会创建并打开.vscode/task.json,其中定义了gcc.exe编译的过程,也就是上一步的preLaunchTask

  • 以上的文件在做了选择之后就自动生成好了,之后该文件夹内的C代码都可以透过VSCode的Debug来调试了,设置断点,查看变量体验还是比较现代的~

已知问题

自带的运行代码和调试的terminal窗口对部分编码支持的不太好,调试的时候会闪退

使用WSL GCC可以参考下面的链接(和上个链接的WSL Remote还是有些不同的): VSCode使用WSL环境开发C语言配置

Python

首先在VSCode窗口的左下角,可以设置当前使用的Python解释器,运行依然是CodeRunner,在代码编辑窗口右键选择各种运行方式包括交互式。重点还是调试,这个时候可以选择创建一个新文件夹了(平时把Python代码都放到一个文件夹…),在新文件夹的情况下,点击调试会提示选择Debug Configuration:包括了Python File和Module以及其他没见过的类型

显然对于只会用调试Python File的情况,每次都做一次选择显然不太方便,那么可以选择Add Configuration,工作目录下会生成一个.vscode/launch.json的文件:

        {
            "name": "Python: 当前文件",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }

在Debug的选项中也就有“Python: 当前文件”的选项了,如果想要在已经有launch.json的文件夹中调试,添加这一段到其中即可

调试Python文件的时候比较慢,比如调用Python还需要先激活Conda环境(选择Python解释器)

在编辑器窗口的右键选项中还有使用Jupyter-notebook作为交互式运行的选项,需要在Conda环境中准备:

conda install ipykernel
python -m ipykernel install --user --name 环境名称 --display-name "Python (环境名称)"

网页版

有上面的Remote-SSH,加上VSCode也是基于electron的,自然会想到能不能在浏览器中使用,偶然的一次机会还真的看到了这样的一个项目:Code-Server

这样一来,只要有一台配置OK的Linux的服务器,使用iPad之类的设备也可以在VSCode中看/写代码(随着iPad逐渐强调生产力,对键鼠支持的越来越好)

主题

Name: Vibrancy
Id: eyhn.vscode-vibrancy
Description: Vibrancy Effect for Visual Studio Code

拖动有些卡顿,打开的时候窗口大小有些异常,不过,不影响代码体验~(笔记本上可能对GPU负担太大从而影响续航)

最近发现有个网站收集了很多微软的壁纸:Wallpaper Hub

最重要的是,网站有一些Fluent Design的元素,最明显的就是Acrylic的效果了

其他插件

  • markmap,将Markdown转换为树状的思维导图
  • drawio,对于常见的流程图和框图,往往不需要特别重量级的工具,只需要创建.drawio的新文件就可以VSCode内画框图了
  • Marp,由Markdown生成slide,写slide也可以轻松地专注内容

从WiFi速率到无线通信

By: Erease
9 September 2019 at 08:00

各种WiFi的速率是怎么来的?WiFi的速度靠什么提高?如何理解和应用相关理论来改善网络质量?业余理解

缘起于Win10显示的图书馆的WiFi信息

1568137490504

5GHz,165信道,WiFi 4???这个是什么情况呢,是不是有哪里显示错了?然后就是速率最高只有144MHz,这个速率又是怎么来的?

从网络协商速率开始

tnext wifi linkspeed

这里以802.11AC 1T1R MCS9 HT80 带宽Short GI为例计算网络连接速率,由上面的公式以及下面的引用可以知道:

\[Rate HT80 = (234MHz* 8bit *5/6 )/(3.2us + 0.4us)= 433.33Mbps\]

这个也就是最常见的单天线的5G WiFi速率,大概的解释如下

80MHz中一个符号有234个数据子载波,使用256QAM时每个子载波每次传输8bits数据,编码率为5/6,而传输时间等于符号持续时间加上保护间隔

802.11ax子载波带宽

从OpenWrt主页的Associated Stations右侧的字段的含义又是什么呢?

650.0 Mbit/s, 80MHz, VHT-MCS 7, VHT-NSS 2, Short GI
650.0 Mbit/s, 80MHz, VHT-MCS 7, VHT-NSS 2, Short GI

我按照个人理解的通信流程整理下,水平有限…

通信部分的概念

把速率计算公式根据后面的原理部分化简一下: \(\begin{align}Rate & =(N_{sub}\times log(N_{QAM}) \times R_{coding})/(N_{sub}/N_{HT}+GI) \\& =\frac{log(N_{QAM}) \times R_{coding}}{1/N_{HT}+GI/N_{sub}}\end{align} \\\) 其中$N_{sub}$为子载波数,$N_{HT}$为频宽

提高网络速率的方法可以粗略的归结到各个子项上面

物理层

频段与频宽

WiFi所用的频段主要是三个,下图也列出了不同的频宽下选择某个信道对频段的占用情况

802.11n: 2.4G频段

img

每相邻的2个信道之间的频宽就是5Mhz,最大频宽为40MHz,对于国内的2.4G只有1-13信道可以用,用1信道,频宽为20Mhz,则信道2,3,4,5都被占用了;如果是40Mhz,侧信道2,3,4,5,6,7,8,9也被占用了,当然只在传输数据时才会占用的。这就为什么在家附近因有大量wifi造成网络堵塞缓慢的原因了。

802.11ac: 5G频段

1568145613985

中国WIFI设备在5GHz下可以使用的信道有36,40, 44, 48, 52, 56, 60, 64, 149,153, 157, 161, 165。而每个信道频宽为20Mhz,如果信道为149,当要用80Mhz时,则153,157,161都要被占用了

802.11ad: 60G频段,近距离高速无线传输专用,现在基本上见不到了

802.11ax: WiFi 6的频段依然是之前的2.4G和5G频段,主要是把最大频宽定在了160MHz

比较有趣的是某个WiFi对频宽的占用越大,有效的传输距离越短,对环境的干扰越小,最后又作用与可以占用更大的频宽来做近距离的高速传输,故各种规格的WiFi是可以和谐共处的

MIMO技术

通过多条通道来发送数据,常用 nTnR,或者 n x n 来表示,比如说2T2R也就是2x2 MIMO,以及OpenWrt上用的NSS:Number of spatial streams后接数字表示空间流的数目

看起来是最简单粗暴的提高无线速率的方式,然而实际上会遇到多径效应导致高误码率,最终还是采取了一系列的措施来尽量克服多径效应

FEC:QAM

FEC (Forward Error Correction):按照无线通信的基本原理,为了使信息适合在无线信道这样不可靠的媒介中传递,发射端将把信息进行编码并携带冗余信息,以提高系统的纠错能力,使接收端能够恢复原始信息。

正交幅度调制QAMQuadrature Amplitude Modulation)是一种在两个正交载波上进行幅度调制调制方式。这两个载波通常是相位差为90(π/2)的正弦波,因此被称作正交载波,这种调制方式因此而得名

802.11n所采用的QAM-64的编码机制可以将编码率(有效信息和整个编码的比率)从3/4 提高到5/6。所以,对于一条空间流,在MIMO-OFDM基础之上,物理速率从58.5提高到了65Mbps(即58.5乘5/6除以3/4)

QAM编码是用星座图(点阵图)来做数据的调制解调,实际应用中是2的N次方的关系。比如说16-QAM ,16是2的4次方,一次就可以传输4个bit的数据;802.11n是64-QAM ,是2的6次方,因此在64个点阵的一个星座集合里面,用任意一个点可以携带六个bit的数据信息

到了802.11ac,就变成了256-QAM,是2的8次方,802.11ac相对于802.11n在编码上面的速率提升了33%。802.11ax之后引入了更高阶的编码,就是2的10次方,1024-QAM

我们都知道从8到10的提升是25%,也就是相对于802.11ac来说,802.11ax的性能又提高了25%,变成了1024-QAM,一个符号可以携带10个bit的数据

img

MIMO-OFDM

在室内等典型应用环境下,由于多径效应的影响,信号在接收侧很容易发生(ISI),从而导致高误码率。OFDM调制技术是将一个物理信道划分为多个子载体(sub-carrier),将高速率的数据流调制成多个较低速率的子数据流,通过这些子载体进行通讯,从而减少ISI机会,提高物理层吞吐。

用于Wi-Fi通信的有OFDM和OFDMA技术:802.11a/g/n/ac无线电当前使用正交频分复用(OFDM)用于802.11频率上的单用户传输,将比特串流对应到QAM调制的符号

子载波的分类

OFDM有三种类型的子载波,如下所示:

数据子载波:这些子载波将使用与802.11ac相同的调制和编码方案(MCS)以及两个新的MCS,并添加1024-QAM

导频子载波:导频子载波不携带调制数据;它们用于接收器和发射器之间的同步

未使用的子载波:剩余的未使用的子载波主要用作保护载波或空子载波以抵抗来自相邻信道或子信道的干扰

例如:20 MHz 802.11n/ac 信道由64个子载波组成——52个子载波用于承载调制数据; 4个子载波用作导频载波;8个子载波用作保护频带;每个OFDM子载波的宽度是20MHz/64=312.5KHz。

TNEXT 802.11 OFDM

不同频宽的数据子载波的数量(第三列)关系见下表

802.11ac 子载波数参数

OFDM符号持续时间

把每个子载波传输的内容是一个符号(比如QAM调制的结果),由于把一个载波分为了多个子载波并行处理,符号持续时间隔也就是处理单个子载波的时间, 为实现最大频谱效率,一般取符号持续时间=1/子载波间隔 ,对802.11 n/ac,符号持续时间为 3.2us=1/312.5

保护间隔

Short Guard Interval (GI),由于多径效应(即使单路传输也存在)的影响,信息符号(Information Symbol)将通过多条路径传递,可能会发生彼此碰撞,导致ISI干扰。为此,802.11a/g标准要求在发送信息符号时,必须保证在信息符号之间存在800 ns的时间间隔,这个间隔被称为Guard Interval (GI)。802.11n仍然使用缺省使用800 ns GI

当多径效应不是很严重时,用户可以将该间隔配置为400ns(=0.4us即Short GI),对于一条空间流,可以将吞吐提高近10%,即从65Mbps提高到72.2 Mbps。对于多径效应较明显的环境,不建议使用Short Guard Interval (Short GI)

预设的调制和编码方案

HT/VHT/HEW

分别对应802.11 n/ac/ax,指的是高、超高吞吐,高效无线网络(High-Efficiency Wireless - HEW),后接数字指示频宽

MCS

MCS (Modulation Coding Scheme)调制和编码方案

在802.11a/b/g时代,配置AP工作的速率非常简单,只要指定特定radio类型(802.11a/b/g)所使用的速率集,速率范围从1Mbps到54Mbps,一共有12种可能的物理速率。

到了802.11n时代,由于物理速率依赖于调制方法、编码率、空间流数量、是否40MHz绑定等多个因素。这些影响吞吐的因素组合在一起,将产生非常多的物理速率供选择使用。比如基于Short GI,40MHz绑定等技术,在4条空间流的条件下,物理速率可以达到600Mbps(即4*150)

为此,802.11n提出了MCS的概念。MCS可以理解为这些影响速率因素的完整组合,每种组合用整数来唯一标示,于是就有了下表

ieee-802-11n-ac-modulation-coding-schemes

至于802.11ax暂时作为上面的补充,添加了MCS10,11

TNEXT 802.11ax速率表

回到最开始的问题

把本文最开始的OpenWrt的截图中的VHT-MCS 9对应过来就可以很方便的查到是866.7Mbps的速率

对于斐讯K3的5G速率可以由 256-QAM 4ss 80MHz SGI来计算1024QAM的速率,即由8bit到10bit,增加25%的速率,大约2100Mbps

144Mbps的由来,可以在Spatial Streams = 2的几行中找到对应的HT20-MCS 15 SGI以及VHT20-MCS 7 SGI,也就是说两种都有可能,后面我还是拿专业点的软件测试了下,确实是5G的WiFi,参考下表就有该5G WiFi不符合WiFi 5的标准,降为WiFi 4情有可原,只是后面那个802.11n就有些尴尬了

1568200987531

学校的AP是双频的,因为AP数量比较多,组网的时候几乎全频段都有,所以每个频段的频宽都设置的比较低以避免互相干扰,144Mpbs的协商速率对单设备限制50Mbps的情况足够了

另外有了上面的一些基础概念之后,方便选择合适的路由器和网卡,尤其是在当前这个向WiFi 6 过渡的阶段

WiFi 6的新特性

img

▲802.11ax技术构成模块示意图

TP-LINK的官网已经有比较简洁美观的介绍了,本文就接着上文提到的部分加以延伸

MU-MIMO

MU-MIMO 即Multi-User Multiple-Input Multiple-Output 的缩写,直译为“多用户 多输入 多输出”, 是最新Wi-Fi技术标准802.11ac Wave 2(即802.11ac 2.0标准)的最重要特性之一

802.11ax设备借鉴了802.11ac的部署经验,将使用波束成形技术同步将数据包发送至不同空间的用户。 换言之,AP会计算每个用户的信道矩阵,并同时将波束导向不同的用户——每路波束包含针对其目标用户的特定数据包。 802.11ax一次可支持8个多用户MIMO传输包的发送,而802.11ac一次可支持4个MIMO数据包。 而且,每次MU-MIMO传输都可能有自己的调制和解码集(MCS)和不同数量的空间串流。 以此类推,当使用MU-MIMO空间复用时,接入点会与以太网交换机进行比较,将冲突域从大型计算机网络缩小至单个端口。

作为MU-MIMO上行方向的新增功能,AP将通过一个触发帧从每个STA发起上行同步传输。 当多个用户及其数据包同时响应时,AP将信道矩阵应用于所接收的波束并将每个上行波束包含的信息分开, 同时它还可能发起上行多用户传输,从而接收来自所有参与STA的波束形成反馈信息

img

至于MU-MIMO的实际情况可以参考有关的测试:ACWIFI

OFDMA

802.11ax无线电可以利用正交频分多址(OFDMA) ,其是OFDM数字调制技术的多用户版本。OFDMA将信道细分为较小的频率分配,称为资源单元(RU)。

OFDM和OFDMA都通过称为逆快速傅立叶变换(IFFT)的数学函数将信道划分为子载波。子载波的间隔是正交的,因此尽管它们之间缺少保护带,它们也不会相互干扰。

img

通过细分信道,可以同时发生小帧到多个用户的并行传输。每个资源单元内的数据和导频子载波在OFDMA信道内都是相邻且连续的

802.11 OFDMA

802.11ax引入了更长的12.8μs的OFDM符号时间,这是传统符号时间3.2μs的四倍。子载波间隔等于符号时间的倒数。由于符号时间较长,子载波大小和间隔从312.5KHz降低到78.125KHz。窄子载波间隔允许更好的均衡并因此增强信道鲁棒性。

上面提到的OFDMA规格对理论速率提升约为10%

MU-OFDMA

802.11ax标准借鉴4G蜂窝技术的技术进步,在相同信道带宽中服务更多用户的另一技术是: 正交频分多址(OFDMA)。 基于802.11ac已经使用的现有正交频分多路复用(OFDM)数字调制方案,802.11ax标准进一步将特定的子载波集分配给个体用户, 即,它将现有的802.11信道(20、40、80和160MHz频宽)分为带有预定义数量的副载波的更小子信道。 802.11ax标准还借用现代LTE术语,将最小子信道称为资源单元(RU),最少包含26个副载波。

密集用户环境下,许多用户通常无力争夺信道的使用机会,现在正交频分多址使用更小巧——但更具专用性的子信道同时服务多个用户,因此提升了每个用户的平均数据吞吐量。 802.11ax系统可能通过不同的资源单元规模实现信道的多路复用。注意,对于每20MHz带宽,信道的最小部分可容纳9个用户

img

imgimg

AP依据多个用户的通信需求决定如何分配信道,始终在下行方向分配所有可用的资源单元。 它可能一次将整个信道仅分配给一个用户——与802.11ac当前功能相同——或者它可能对其进行分区,以便同时服务多个用户。

img

BSS Color

BBS(Base Service Station) Color, 基于色码的空间复用,为了改善密集部署场景中的系统层级性能以及频谱资源的使用效率,802.11ax标准实现了空间重用技术。 STA可以识别来自重叠基本服务集(BSS)的信号,并根据这项信息来做出媒体竞争和干扰管理决策。

这部分和速率关系不大

信号质量与无线速率

信号的衡量标准

一般我们都会有个信号强弱的标准,比如常用的WiFi和Cellular的Icon上被填满的图标面积,然而打开一些调试工具看到的是dbm这个单位,例如在OpenWrt的Wireless详情中有: Tx-Power: 23 dBm Signal: -64 dBm | Noise: 0 dBm Tx-Power指的是路由器信号的发射功率,无线功率一般以mw为单位,但是因为WiFi信号的能量通常为mw级,因此业界将WIFI信号大小表示为与1mw的强度比,用dbm来表示,对应关系是 \(signal=10log(\frac{P}{1mw})\) 这就有个非常方便的计算方式:

降低3dBm,是指信号强度降低到原先的1/2(二分之一)。

降低10dBm,是指信号强度降低到原先的1/10(十分之一)。

降低30dBm,是指信号强度降低到原先的1/1000(千分之一)。

有了这个之后,可以对信号的强度做一个大致的判断: 下图来自RSSI等级和信号强度

使用上图来源的网站提供的软件可以绘制出一个大致的信号强度分布图,可以参考来的调整AP的位置

除了dbm表示无线的收发功率之外,还要考虑到信道中的信噪比(SNR),噪声也可以使用dbm为单位,所以计算dbm为SNR单位的时候把二者相减即可

与无线速率的关系

首先是会影响到协商速率,在发射端的信号到接收端,中间存在衰减和损失,其对通信的影响就是会产生高误码率,故为了达到可靠通信的需求需要采取高纠错性能的编码和调制方式,也就是影响到MCS,进而影响到协商速率和实际传输速率,而调整的标准就看设备的厂商的调教了

应用

有了上述的铺垫,就有了一些改善无线网络质量的途径,但是最重要的还是认清现实,理性对待

频段

因为某一个频段内的信道容量有限,在拥挤的时候噪声也多,故在选择频段的时候,尽可能的避开当前区域拥挤的信道,可以使用路由器的无线桥接功能(wireless scan)工具,查看路由器附近的信道占用的情况,或者用Netspot工具检测当前区域网络情况

特别说明的是2.4G频段已经相当的拥挤了,对于有高可靠性网络环境要求的情况,建议还是网线或者使用5G频段

提高发射功率

这里可以说是个经验上的技巧,首先,路由器的发射功率是受到国家标准的严格限制的,但是对于某些可以切换无线地区的路由器来说,可以通过该途径来提高发射功率,或者使用某些频段进而提高发射功率

使用高增益的天线,使用内置信号放大器的AP也是同样的逻辑

增加AP

Mesh,信号放大器,主路由+AP,无线漫游都是类似的途径,高端的设备往往配备了更好的硬件和算法,这点也是毋庸置疑的

参考

802.11 WiFi协议浅析

802.11ax高效率无线标准介绍-National Instruments

第七代无线技术802.11ax详解

02.11ax 11ac 11n WiFi全速率表

简说各种wifi无线协议的传输速率

IEEE 802.11理论速率计算

How to Scoop

By: Erease
5 September 2019 at 08:00

Scoop作为Windows下的命令行包管理工具,在之前的文章里用到的非常多,最近又看了下Scoop的说明,这里简要的介绍下更新后的特性,附带一些常用的命令行工具

Github:lukesampson/scoop的README对Scoop有了大概的介绍,我初次接触到是读到了 再谈谈 Scoop 这个 Windows 下的软件包管理器

缘由

  • 安装常见命令行工具
  • 自带配置环境变量,方便配置简易的开发环境
  • 有脚本自动化执行的优势,方便快速部署(比如重装系统的时候)

需要注意的是如果Scoop安装的软件和Powershell的命令或者别名重合,Powershell的命令依然被优先使用

安装

可以使用管理员模式打开powershell运行

Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
# or shorter
iwr -useb get.scoop.sh | iex

多线程下载支持

部分软件源在Github之类的连接性不太好的地方,偶尔下载很慢而且易报错,现在Scoop推荐默认使用aria2进行多线程下载,只需要安装aira2即可开启多线程下载

scoop install aria2

添加额外的仓库

参考SpencerWoo的文章添加的软件仓库基本上够用了

scoop bucket add extras
scoop bucket add java
scoop bucket add dorado https://github.com/h404bi/dorado
  • 默认的main仓库以命令行工具为主(比如收录的cmder是个有GUI的终端软件),例如Linux常用的sed, grep, gawk,vim可以大大方便Powershell的日常使用
  • extra仓库收录的高质量的gui软件比较多,比如说googlechrome,typora,vscode
  • java仓库收录了多种多版本的JDK,结合下文的scoop reset,可以便捷的切换环境变量下的JDK
  • dorado仓库收录了相当一部分国内常用的软件如微信,网易云,besttrace,因为下载源在国内下载速度很OK

常用软件

除去上面介绍的一些,其实想得到软件都可以在Scoop中使用scoop search找下看看

$ scoop list
Installed apps:

  7zip 19.00
  chromedriver 76.0.3809.126
  cmder-full 1.3.11
  concfg 0.2019.03.09
  ffmpeg 4.1.3 #编码工具
  gawk 3.1.7
  gcc 8.1.0
  gdrive 
  git 2.21.0.windows.1
  grep 2.5.4
  innounp 0.48
  iperf3 3.1.3 #网速测试工具
  nodejs 12.5.0
  pshazz 0.2019.04.02
  R 3.6.0
  sed 4.2.1
  tesseract 4.1.0.20190314 #OCR工具
  vim 8.1.1302 
  youtube-dl 2019.05.20 #偶尔下载视频
  trafficmonitor #任务栏网速,CPU内存占用监测
  screentogif #Gif录屏软件
  ntop #类似htop的的终端下的资源监视器(但是做不到htop那么强大)
  glow #终端下的Markdown Render
  openjdk #添加java仓库后,默认安装最新版的openjdk
  openjdk9 #java9

sudo

部分命令是无法在普通模式下运行的,一般的方法是打开一个新的管理员模式的窗口,相对来说不太方便,scoop可以安装sudo来实现对单一命令的赋权

比如设置禁用eth0接口的别名

scoop alias add ethd 'sudo netsh interface set interface eth0 disabled' 'disable eth0' 

输入scoop ethd之后就会弹出用户账户控制的弹窗,提示需要管理员权限,用键盘确认就好,省去了再开一个窗口的麻烦(如果是长串命令都需要管理员权限的话还是开一个吧)

ffmpeg

只介绍常用的简单指令

录制直播

面对没有加密的m3u8直播录制,IPTV用的较多,m3u8的地址可以通过浏览器的检查工具找到

ffmpeg -i m3u8 'test.ts'  

合并音频和视频

现在越来越多的网站选择把音频和视频分开,使用IDM下载两个文件可以直接用ffmpeg做快速的合并(复制)

ffmpeg -i v.mp4 -i a.mp4 -c copy output.mkv

当然如果youtube-dl支持视频网站的话使用youtube-dl更方便

提取视频中的音轨

常用于提取BGM,不做重编码的情况

ffmpeg -i input-video.avi -vn -acodec copy output-audio.aac

-vn没有视频 -acodec copy说使用已经存在的相同的音频流

注意事项

scoop依然有许多不成熟的地方,在高可靠性要求的环境下依然是不推荐的,最经常遇到的莫非是软件安装因为网络等问题终端,安装状态会返回成功,如果需要重新安装的话需要先进行卸载

再一个就是环境变量的问题,scoop可以在安装的时候配置好一些环境变量,但是卸载却不一定会移除,这就导致一些重要的软件在Scoop卸载之后再在其他位置安装会出现环境变量错误的问题

部分高度依赖于安装目录,权限以及关联众多的软件不推荐使用scoop安装,如Chrome

使用Scoop提供的别名

Powershell的别名设置不方便,直接使用WSL的自定义别名(.bashrc)调用Windows下的程序又不能直接在Powershell中运行,直到发现Scoop可以自由的添加“环境变量”,想起来Scoop alias来设置程序运行的scoop别名

本来的用法应该是为Scoop内的操作添加别名:

# Install app
scoop alias add i 'scoop install $args[0]' 'Innstall app'
scoop alias add add 'scoop install $args[0]' 'Install app'

# Uninstall app
scoop alias add rm 'scoop uninstall $args[0]' 'Uninstall an app'
scoop alias add remove 'scoop uninstall $args[0]' 'Uninstall an app'

# List apps
scoop alias add ls 'scoop list' 'List installed apps'

# Update
scoop alias add u 'scoop update $args[0]' 'Update apps, or Scoop itself'
scoop alias add upgrade 'scoop update $args[0]' 'Update apps, or Scoop itself'

但是这个格式看起来就很自由:

比如说给WinMTRCmd添加一个scoop mtr的别名

scoop alias add mtr '~/winMTRCmd $args[0]' 'MTR tools for Win CMD'

之后使用scoop mtr [host]就可以愉快的使用mtr工具了

使用Scoop切换软件版本

这里以切换Java版本为例,例如在安装了openjdk和openjdk9之后,从默认的openjdk9切换到openjdk16

$ java -version
openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+11)
OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)

$ scoop reset openjdk
Resetting openjdk (16.0.1-9).
Linking ~\scoop\apps\openjdk\current => ~\scoop\apps\openjdk\16.0.1-9

$ java -version
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment (build 16.0.1+9-24)
OpenJDK 64-Bit Server VM (build 16.0.1+9-24, mixed mode, sharing)
❌
❌