如果我的设备有 3 个蜂窝模组,接入三大运营商网络,如何设置动态加权 ECMP 路由,排除掉信号不可用的那路呢,这个机制对于频繁出入运营商网络覆盖不规律的场所非常重要。
Linux 本身并没有这种机制,需要一个脚本动态刷新,为了保证网络被剔除后,相关连接的 NAT 重置,需要 conntrack -F:
bash
while true; do
# 1. 读信号
rssi0=$(at_cmd /dev/ttyUSB0 AT+CSQ)
rssi1=$(at_cmd /dev/ttyUSB1 AT+CSQ)
rssi2=$(at_cmd /dev/ttyUSB2 AT+CSQ)
# 2. 计算权重(简单线性映射:rssi 越大 weight 越高)
w0=$((rssi0 + 100))
w1=$((rssi1 + 100))
w2=$((rssi2 + 100))
# 3. 更新路由
ip route replace default \
nexthop dev wwan0 weight $w0 \
nexthop dev wwan1 weight $w1 \
nexthop dev wwan2 weight $w2
# 4. 重置连接。此举可清理 conntrack,让新路由 NAT 生效,旧连接新 NAT 会被高层机制 reset
conntrack -F
# 5. 等待信号低于阈值的中断 or 简单间隔轮询 sleep 2(不支持 INT 时)
SLEEP_for_INT
done
我觉得 Linux 很无趣了,即使修改了内核,增加路由子系统 metric 与物理层的交互接口,也没什么大不了的,不会再从这种事中获得乐趣。
但有趣的是,w0,w1,w2 如何归类。
即时的 w 值会造成路由震荡,连接跟着乒乓,那么就必须对 rssi 做处理,而且容易看到,1,2,3 的区分和 101,102,103 的区分并不一样,前三者属于不同类别,后三者显然属于同一类,100,800 属于不同类,但 10100,10899 就属于同类。
我需要小数值具有高区分度,大数值差值不敏感,区间随数值增大逐步变宽,仅此而已。
韦伯-费希纳定律说人的感觉是对数的,自然界的无线信号衰减也是对数的,所以区分信号类别的函数就是对树的,而不必搞什么阶梯式分段函数来故弄玄虚,就像手机厂商把一段 dBm 区间直接映射成几格一样。
以下是我调教的三个备选函数:
f 1 ( x ) = ⌊ log α x ⌋ , α = 2 ( 首选 ) , 3 , ⋯ f_1(x)=\lfloor\log_\alpha x\rfloor,\quad \alpha=2(首选),3,\cdots f1(x)=⌊logαx⌋,α=2(首选),3,⋯
f 2 ( x ) = ⌊ ln x k ⌋ , k = 0.8 , 1 , 1.2 f_2(x)=\lfloor\dfrac{\ln x}{k}\rfloor,\quad k=0.8,1,1.2 f2(x)=⌊klnx⌋,k=0.8,1,1.2
f 3 ( x ) = β arctan ( ln x ) f_3(x)=\beta\arctan{(\ln x)} f3(x)=βarctan(lnx)
这几个都挺好。
还有一个事,昨天我在 网络长尾延时的重尾本质 提到流量分类,流长是自相似的,因此分类也是对数关系,也能用这几个函数。
浙江温州皮鞋湿,下雨进水不会胖。