把 VPN 的 UDP 端口标为高优先级是最常见的语音 QoS 改动,但它并不能把通话与共用同一条隧道的文件传输区分开。两条流从同一个加密封装套接字出去。标记是在告诉下一跳:所有东西同等重要,这等于什么都没说。真正保护通话的,是加密前可信的分类,加上一条你确实能控制的队列。

隧道藏起了你想分类的那条流

加密把内层报文头替换成每条隧道一个外层报文头。此后,语音和备份流量呈现相同的源、目的和传输端口,因此按隧道端口做的分类器 根本分不开它们。你抬高什么,都是整体抬高。

源端应用设置的 DSCP 值只有被某个环节向外复制时才会保留下来。OpenVPN 2.6 有 passtos,文档中限定在 IPv4 范围内;IPsec 则在隧道边界上执行自己的复制或映射策略。没有这一步,外层报文会按隧道接口使用的任意默认值打标,下游队列永远不知道里面有通话。

被复制的标记应该像任何客户端提供的值一样受到怀疑。一台工作站可以为一个备份任务声称加速转发,所以在信任这个标记之前,信任边界上的准入与重标记必须写进设计里。

优先级只在队列真正形成的地方才算数

把好编码器变成机器人声音的,是拥塞的上行链路,而填满的那条队列通常在接入设备或运营商的缓冲区里。把出向路径整形到可用速率(减去隧道与链路开销),才能让那条队列留在你自己管理的硬件上,而不是别人的缓冲区里。

公平排队和主动队列管理即使没有语音类别也有用,因为它们能阻止一条大流量填满缓冲区。Linux 上的 CAKE 把整形、按流的公平性和可选的 Diffserv 类别合并进一个 qdisc,已部署的网络管理器应当拥有这份配置,而不是再搞一套互相竞争的队列设置。没有整形时,比大流量更高的类别仍然要排在已经填满的缓冲区后面。

入向处理并非无用,但它是在报文越过接收链路之后才起作用。它能影响会响应的发送端,却无法退还已经在上游消耗掉的时延,所以它只是缓解,不是保证。

StageWhat you can controlWhat to verify
Application to clientWhich flows are trusted for markingThe marked packets are the ones you intended
Tunnel boundaryWhether the inner mark is copied outwardOuter header carries the expected value
Your uplinkShaping rate and class treatmentQueue counters move for the voice class
Provider pathAlmost nothingWhether the service enforces the marking at all
Receiving sideLocal policy after arrivalDelay that is already in the past

公网里能留下什么

Diffserv 架构描述的是管理域内部的处理方式,所以运营商可能在边界上忽略或改写标记。反过来声称每个网络都会一律清除,同样没有依据。诚实的问题是:这条具体路径在合同和监管下究竟承诺做什么。用带标记的探针去测,而不是重复一条你从别处读来的规则。

先问运营商如何处理这个类别,然后去测量。被保留却没有被调度的标记只是装饰;看不见标记却照常调度的路径是另一个问题,两者需要不同的修法。

一个能隔离环节的测量方案

打一通普通通话,同时施加可控的竞争上传,然后换到有线链路上重做一次。看看通话丢了多少、类别计数器记录了什么、接口离它真正的上限而不是套餐宣传速率有多近。

tc -s qdisc show dev eth0
tc -s class show dev eth0
mtr -rwzbc 50 voice.example.net

如果语音类别计数器始终为零,说明分类或标记复制出了问题,加多少优先级都没用。如果本地类别计数器在动而时延仍在上升,瓶颈就在网关之外。这两种结果都不是靠调高优先级数值能解决的。

相关文章