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

时间:2010-09-20 23:25:38

标签: linux networking tcp ip qos

我正在构建一个具有各种网络流量的实时嵌入式Linux应用程序。在这组流量中,两个连接是时间关键的。一个是输入数据,另一个是输出数据。我的应用程序需要此流量优先于其他非时间关键流量。

我关心两件事:

  1. 最大限度地减少因这两个连接过载导致丢弃的数据包数量。
  2. 最大限度地减少这两个连接上的设备延迟(输入到输出)。
  3. 我(有点!)加快了Linux流量控制的速度,并了解它主要适用于出口流量,因为远程设备负责发送给我的数据的优先级。我已将我的应用程序设置为实时流程,并已完成与运行它的优先级相关的问题。

    我现在开始设置tc。对于我的测试用例,这是我使用的:

    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
    

    基本上我要说的是:在频段0上发送所有优先级7流量,并在频段2上发送所有其他流量。一旦我完成了这个简单的测试,我将会更好地处理其他流量。 / p>

    首先让我们来验证我的期望: 我期望的是,任何具有优先级7的流量应该总是在具有任何其他优先级的流量之前消失。这应该使这种流量的延迟相对不受盒子上其他流量的影响,不是吗?我的mtu设置为1500,我通过界面获得大约10 MB /秒。由频带2业务引起的频带0上的最大附加延迟是一个分组(<= 1500字节),或150us(1500字节/ 10MBytes / sec = 150us)。

    这是我的测试设置:

    两个Linux Box。框1运行回送输入数据的TCP服务器。方框2连接到方框1,通过TCP发送数据包并测量延迟(发送到收到时间的时间)。

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

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

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

    我使用tc来验证我的流量超过0频段,以及所有其他流量超过频段2:

    tc -s qdisc ls dev eth0
    

    这就是问题:当没有其他流量时,我会看到500美元范围内的延迟。当我有其他流量(例如,复制100 MB文件的scp作业)时,延迟会跳到10毫秒。真正奇怪的是,我所做的任何工作都没有任何影响。事实上,如果我交换频段(所以我的所有流量都超过优先级较低的频段2,其他流量超过频段1),我认为延迟没有任何差异。

    我所期待的是,当网络上有其他流量时,我会看到延迟增加约150 us,而不是10 ms!顺便说一句,我已经验证了加载具有其他(非实时优先级)进程的盒子不会影响延迟,也不会影响其他接口上的流量。

    另一个需要注意的事项是,如果我将mtu降为500字节,则延迟会降低到大约5毫秒。不过,这比卸载的情况要糟糕一个数量级。另外 - 为什么更改mtu对它影响如此之大,但使用tc设置优先级排队没有效果???

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

    谢谢!

    埃里克

3 个答案:

答案 0 :(得分:0)

你没有对网络的其他部分说什么,但我猜你在上游路由器上遇到了一个队列,它通常有很长的队列来优化吞吐量。解决此问题的最佳方法是将优先级队列提供给一个带有上行带宽的带宽的整形器。这样,您的批量优先级数据包将在您的盒子内而不是外部路由器中排队,从而允许您的高优先级数据包按预期跳转到队列的前面。

答案 1 :(得分:0)

prio工具只会在发送数据包时发送可用的最高优先级数据包(通常在上一个数据包发送后立即发送,除非没有数据包等待熄灭)。

您的测试依赖于每台计算机上相应程序进程放入队列的数据包,以及从每台计算机上的端口检索到的数据包。

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

要检查的另一件事是用于衡量延迟的时间戳 - 是在客户端计算机上实际接收回显消息的时间还是程序处理它的时间。如果是后者,那么您不仅要测量网络延迟,还要测量接收消息和程序获得处理器片段之间的时间,并达到检查时间的程度 - 请参阅http://wiki.wireshark.org/Timestamps。< / p>

顺便说一句,我认为如果没有像机制这样的实时操作系统,你将无法获得有保证的微秒级响应能力。另一方面,如果您的应用程序是像那样的VoIP,那么通常可以达到大约200毫秒的延迟。

答案 2 :(得分:0)

您是否尝试捕获数据包并检查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)
}