为什么我的Linux prio基于tc没有改善networking延迟?

我正在构build一个具有各种networkingstream量的实时embedded式Linux应用程序。 在这组交通中,两个连接对时间至关重要。 一个是input数据,另一个是输出数据。 我的应用程序需要此stream量优先于其他非时间关键stream量。

我关心两件事情:

  1. 最大限度地减less由于这两个连接过载而丢弃的数据包数量。
  2. 在这两个连接上最小化通过设备(input到输出)的延迟。

我已经(稍微!)加快了Linuxstream量控制的速度,并且明白它主要适用于出口stream量,因为远程设备负责发送给我的数据的优先级。 我已经将应用程序设置为实时进程,并且已经完成了与运行它的优先级相关的问题。

我现在着手build立TC。 对于我的testing用例,下面是我使用的:

tc qdisc add dev eth0 root handle 1: prio bands 3 priomap 2 2 2 2 2 2 2 0 2 2 2 2 2 2 2 2 tc qdisc add dev eth0 parent 1:1 handle 10: pfifo tc qdisc add dev eth0 parent 1:2 handle 20: pfifo tc qdisc add dev eth0 parent 1:3 handle 30: pfifo 

基本上我是这样说的:发送所有优先级为7的stream量通过带0, 所有其他stream量通过带2.一旦我有这个简单的testing工作,我会做得更好,处理其他stream量。

首先让我们来validation一下我的期望:我期望的是,任何优先级为7的stream量应该在具有任何其他优先级的stream量之前总是出去。 这应该使这种stream量上的延迟相对不受其他stream量的影响,不是吗? 我的MTU设置为1500,通过界面我获得了大约10 MB /秒。 由带2stream量引起的带0上的最大附加等待时间是一个分组(<= 1500字节)或150us(1500字节/ 10MBytes / sec = 150us)。

这是我的testing设置:

两个Linux的盒子。 方框1运行一个回应input数据的TCP服务器。 方框2连接到方框1,通过TCP发送分组并测量延迟(发送到接收时间的时间)。

我使用相同的tc设置框Linux的盒子。

在应用程序(包括服务器和客户端)中,我在套接字上设置了SO_PRIORITY,如下所示:

 int so_priority = 7; setsockopt(m_socket.native(), SOL_SOCKET, SO_PRIORITY, &so_priority, sizeof(so_priority)); 

我使用tc来validation我的stream量超过了频段0,而频段2上的所有其他stream量:

 tc -s qdisc ls dev eth0 

这里是蹭的:当没有其他交通时,我看到500 us范围内的延迟。 当我有其他stream量时(例如,复制100 MB文件的scp作业),延迟时间会跳到10+ ms。 真奇怪的是,我所做的任何工作都没有任何影响。 事实上,如果我交换频段(所以我所有的stream量都经过了较低优先级的频段2,而频段1上的其他stream量),我看不到任何延迟。

我期望的是,当networking上有其他stream量时,我会看到150 us的延迟增加,而不是10 ms! 顺便说一下,我已经validation了,使用其他(非实时优先级)进程加载框不会影响延迟,也不会影响其他接口上的stream量。

还有一点需要注意的是,如果我把mtu降到500字节,等待时间就会缩短到5毫秒左右。 不过,这比空载的情况要严重得多。 另外 – 为什么改变mtu影响这么多,但使用TC设置优先队列没有影响?

为什么TC不帮我? 我错过了什么?

谢谢!

埃里克

你没有对网络的其他部分做任何说明,但是我猜测你正在上游路由器上进行排队,通常有很长的队列来优化吞吐量。 解决这个问题的最好方法是把你的优先级队列送入一个带宽正好低于上行带宽的整形器。 这样,你的批量优先级数据包就会排队到你的盒子里,而不是在外部路由器上,这样你的高优先级的数据包就可以像你期望的那样跳到队列的前面了。

prio工具只是在发送数据包的时候发送可用的最高优先级数据包(通常只要前一个数据包已经发送,除非没有数据包在等待出去)。

你的测试依赖于在每台机器上通过适当的程序进程放入队列中的数据包,并接收到来自每台机器端口的数据包。

任何影响进程在任一机器上运行的时间的调度延迟都可能影响进程将消息放入队列或从队列中检索和处理消息的能力。 这听起来像你已经加载了至少一个机器来测试这个,但我的经验是,机器加载肯定会影响测量延迟这样(毫秒级,而不是几微秒),所以这可能是值得重复这两个机器加载具有高度优先的任务。

另一件要检查的是用于衡量延迟的时间戳 – 是在客户端机器上实际接收到回显消息的时间,还是程序处理该消息的时间。 如果是后者,那么你不仅测量网络延迟,而且还测量接收到的消息和你的程序之间的时间,得到处理器的一部分,并进入你检查时间的时间 – 参见http://wiki.wireshark .org /时间戳 。

顺便说一句,我不认为你将能够得到保证微秒级别的响应能力,而没有像机制一样的实时操作系统。 另一方面,如果您的应用程序是VoIP,那么通常情况下您的应用程序的延迟时间可达200​​毫秒。

您是否尝试捕获数据包,并检查IP标头的TOS值是否已更改?

您需要linux 2.6.39或更高版本才能使用SO_PRIORITY。

你应该改变IP_TOS。

你应该设置:

 int iptos_precedence = 0xc0; if (setsockopt(sock_fd, IPPROTO_IP, IP_TOS, &iptos_precedence, sizeof(iptos_precedence)) < 0) { //print errno (or something like that) }