模拟 Linux 上延迟和丢失数据包

290

我想在Linux上模拟UDPTCP数据包的延迟和丢失,以衡量应用程序的性能。是否有一种简单的方法来实现这个目标?


这个关于网络物理模拟的教程包含了C++类在示例代码中,用于模拟UDP连接中的延迟和数据包丢失,并可能对您有所指导。请参见可下载源代码中Connection.h文件中的Connection类的公共latencypacketLoss变量。 - Judge Maygarden
参见/重复:模拟缓慢网络连接的网络工具 - blahdiblah
1
对于OS X,请参见:https://superuser.com/questions/173882/netem-for-mac-os-x-to-emulate-network-latency-and-dropped-packets - Lenar Hoyt
6个回答

370

netem 利用已经内置在Linux和用户空间工具中的功能来模拟网络。这实际上就是Mark答案所指的内容,只是使用了另一个名称。

他们网站上的示例已经展示了如何实现您所要求的内容:

示例

仿真广域网延迟

这是最简单的示例,它只是对所有从本地以太网出去的数据包添加了固定数量的延迟。

# tc qdisc add dev eth0 root netem delay 100ms

现在,对本地网络上的主机进行简单的ping测试应该会显示100毫秒的增加。延迟受内核时钟分辨率(Hz)的限制。在大多数2.4系统中,系统时钟运行在100 Hz,这允许以10ms的增量产生延迟。在2.6中,该值是一个配置参数,范围从1000到100 Hz。

后面的例子只是改变参数而不重新加载qdisc。

真实的广域网展示了可变性,因此可以添加随机变化。

# tc qdisc change dev eth0 root netem delay 100ms 10ms

这会导致额外的延迟为100±10ms。网络延迟变化并非纯随机,为了模拟这种情况,还有一个相关值。

# tc qdisc change dev eth0 root netem delay 100ms 10ms 25%

这将导致添加的延迟为100±10毫秒,下一个随机元素取决于上一个元素的25%。这并不是真正的统计相关性,而是一种近似。

延迟分布

通常,网络延迟不是均匀的。更常见的做法是使用类似正态分布的东西来描述延迟的变化。netem disipline可以采用表格来指定非均匀分布。

# tc qdisc change dev eth0 root netem delay 100ms 20ms distribution normal

实际的表格(normal、pareto、paretonormal)是作为iproute2编译的一部分生成并放置在/usr/lib/tc中的;因此,可以通过一些努力基于实验数据制作自己的发行版。

数据包丢失

在“tc”命令中以百分比指定随机数据包丢失。最小可能的非零值为:

2−32 = 0.0000000232%

# tc qdisc change dev eth0 root netem loss 0.1%

这会导致随机丢弃1/10个百分点的数据包(即1000个数据包中有1个被丢弃)。

还可以添加可选关联。这会使随机数生成器不太随机,并可用于模拟数据包突发性丢失。

# tc qdisc change dev eth0 root netem loss 0.3% 25%

这会导致 0.3% 的数据包丢失,并且每个连续的概率都依赖于上一个概率的四分之一。

Probn = 0.25 × Probn-1 + 0.75 × Random

请注意,如果您在该接口上没有规则,则应使用tc qdisc add,如果您已经为该接口设置了规则,则应使用tc qdisc change。试图在没有规则的接口上使用tc qdisc change将会出现错误RTNETLINK answers: No such file or directory


2
原始网站有那个错误,我只是直接复制了那段文字。但是没错,2^(-32)=2.33e-10。 - ephemient
44
请注意,tc -p qdisc ls dev eth0将列出当前定义的规则,而tc qdisc del dev eth0 root将删除它们。 - Quamis
1
因为尝试更改不存在的条目而指出错误,已被点赞。 - Neo
2
@ephemient,IP级别上是否可以做类似的事情?例如,针对单个IP地址丢弃和延迟数据包?https://stackoverflow.com/questions/46945705 - Greg
1
这只适用于出站数据包,不适合模拟网络丢失。 iptables 对传入流量应用正确。 - Phuah Yee Keat
显示剩余9条评论

110

对于丢弃的数据包,我会简单地使用iptables和统计模块

iptables -A INPUT -m statistic --mode random --probability 0.01 -j DROP

以上代码将有1%的概率丢弃一个入站数据包。请注意,如果超过0.14,大多数TCP连接很可能会完全停顿。

使用-D命令撤销:

iptables -D INPUT -m statistic --mode random --probability 0.01 -j DROP 

查看 man iptables 命令并搜索“statistic”以获取更多信息。


7
为什么TCP连接在超过14%后会停顿? - David Wolever
3
因为 TCP 滑动窗口大小的调整方式。但是那个14%只是经验值,你可以自己试一下,会发现当丢包率达到14%及以上时,SSH基本上无法使用,而在更低的丢包率下则表现得非常好。 - Bjarke Freund-Hansen
18
为了安全起见,最好将规则限制在你想测试的端口上:iptables -A INPUT --dport FOO -m statistics .... 这样,你的 SSH 和其他连接将保持不变,你可以增加感兴趣服务的丢包率,以便更快地重现任何问题。 - Mikhail T.
8
请注意,在出站连接上使用DROP命令可能会让send()操作返回EPERM,而不是像本应该做的那样丢弃数据包。 - Fake Name
5
需要撤销这个命令,只需要运行以下命令即可:iptables -D INPUT -m statistic --mode random --probability 0.01 -j DROP - jcalfee314
显示剩余3条评论

6

iptables(8)有一个统计匹配模块,可以用来匹配每第n个数据包。要丢弃此数据包,只需添加-j DROP


3

科学界中用于这一目的最常用的工具之一是DummyNet。一旦您安装了ipfw内核模块,只需运行以下命令即可在两台计算机之间引入50ms的传播延迟:

./ipfw pipe 1 config delay 50ms
./ipfw add 1000 pipe 1 ip from $IP_MACHINE_1 to $IP_MACHINE_2

为了引入50%的数据包丢失,您需要运行以下命令:
./ipfw pipe 1 config plr 0.5

这里有更多细节。


1
一个易于使用的网络故障注入工具是Saboteur。它可以模拟以下情况:
  • 完全的网络分区
  • 远程服务停止(未在预期端口上侦听)
  • 延迟
  • 数据包丢失 -TCP连接超时(通常在两个系统由有状态防火墙分开时发生)

2
遗憾的是,该项目的最后一次提交是在2015年8月28日,也就是将近4年前。未解决的问题现在已经有5年了。 - Ali

1
我自己没有尝试过,但这个页面列出了在Linux内置的iptables IP过滤系统中运行的插件模块列表。其中一个模块叫做“nth”,允许您设置一个规则来丢弃可配置速率的数据包。至少可能是一个好的起点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接