在 Linux 系统中,qdisc(Queueing Discipline,排队规则)模块是网络子系统中的一个重要组件,主要用于管理和控制网络数据包的排队和调度行为。以下是 qdisc 模块的主要作用和功能:
-
数据包排队管理
-
流量控制和调度
-
拥塞控制
-
分类和过滤
-
支持多种调度算法
-
网络性能优化
-
模拟网络故障
2. 如何模拟网络故障
在 Linux 中,可以使用 tc(Traffic Control)工具结合 netem(Network Emulator)队列规则来模拟各种网络故障。以下是一些常见网络故障的模拟方法:
tc qdisc netem 是 Linux 中用于网络仿真和故障注入的工具,可以模拟各种网络问题,如延迟、丢包、乱序、重复等。以下是 netem 的主要参数及其用途:
- 延迟(Delay)
-
参数:
delay TIME [JITTER [CORRELATION]] [distribution TYPE] -
作用:
-
TIME:指定延迟时间,单位为毫秒(ms)。所有经过该队列的数据包都会被延迟指定的时间。
-
JITTER:抖动时间,表示延迟的随机变化范围。例如,
delay 100ms 20ms表示延迟时间在 80ms 到 120ms 之间随机变化。 -
CORRELATION:相关性,表示相邻数据包延迟的相关系数(百分比)。例如,
50%表示当前数据包的延迟受前一个数据包延迟的影响程度。 -
distribution:延迟分布模式,可选值包括:
-
uniform:均匀分布。
-
normal:正态分布。
-
pareto:帕累托分布,适合模拟长尾分布。
-
paretonormal:帕累托与正态分布的混合。
- 丢包(Loss)
-
参数:
loss MODEL [PERCENT] -
作用:
-
PERCENT:指定丢包率,单位为百分比。例如,
loss 5%表示丢弃 5% 的数据包。 -
MODEL:丢包模型,可选值包括:
-
random:随机丢包。
-
state:基于马尔可夫链的丢包模型。
-
gemodel:基于 Gilbert-Elliot 模型的丢包。
- 数据包损坏(Corrupt)
-
参数:
corrupt PERCENT -
作用:以指定的概率(
PERCENT)随机修改数据包的内容。
- 数据包重复(Duplicate)
-
参数:
duplicate PERCENT -
作用:以指定的概率(
PERCENT)复制数据包。
- 数据包乱序(Reorder)
-
参数:
reorder PERCENT [CORRELATION]或gap DISTANCE -
作用:
-
PERCENT:指定乱序的概率。
-
CORRELATION:乱序的相关性。
-
gap:每隔
DISTANCE个数据包,将一个数据包提前发送。
- 限速(Rate)
-
参数:
rate RATE [PACKETOVERHEAD] [CELLSIZE [CELLOVERHEAD]] -
作用:
-
RATE:限制数据包的发送速率。
-
PACKETOVERHEAD:每包的额外开销(字节)。
-
CELLSIZE
和CELLOVERHEAD:用于模拟链路层的单元化。
- 队列限制(Limit)
-
参数:
limit COUNT -
作用:限制队列中可持有的最大数据包数量。
- 显式拥塞通知(ECN)
-
参数:
ecn -
作用:使用显式拥塞通知(ECN)标记数据包,而不是直接丢弃。
- 时间槽(Slot)
-
参数:
slot MIN_DELAY [MAX_DELAY] [distribution] -
作用:模拟时隙化网络,将数据包延迟到指定的时间槽内发送。
示例
以下是一些常见的使用示例:
-
添加固定延迟:
tc qdisc add dev eth0 root netem delay 100ms。 -
添加抖动和相关性:
tc qdisc add dev eth0 root netem delay 100ms 20ms 50%。 -
丢包:
tc qdisc add dev eth0 root netem loss 5%。 -
乱序:
tc qdisc add dev eth0 root netem delay 10ms reorder 25%。
通过这些参数,tc qdisc netem 可以模拟各种复杂的网络环境,帮助开发和测试人员验证应用程序在网络问题下的表现。
3. 注入时延导致丢包
现象描述
网卡:云芯/E810(25Gb)
在有业务流量(网口有流量500~600MB/s)的情况下,使用qdisc对一个网口注入netem 90ms~100ms的时延,流经此网口数据报文存在少量的丢包。
丢包率:使用ping进行测试,大概有1%的丢包
根因分析
- 先确认链路上是否真的有丢包
停掉业务流量,注入时延,ping不产生丢包;重新打开业务流量,注入时延,ping产生丢包。
结论:链路正常
- 确认ping包丢在哪里
发包测抓取ping包,接收测同时也抓取ping包,此时复现ping包丢失的场景。
丢包时发包测可以抓到icmp request,无icmp reply;接收测可以抓到icmp request,无icmp reply
结论:数据包丢失产生在接收测
- tc qdisc netem的参数调整
tc qdisc netem的参数中,有个limit,用来限制队列长度。调整队列长度测试
默认参数中limit为1000(iproute2/src/q_netem.c),固测试1000和100000
使用1000,复现出ping丢包的场景,使用tc qdisc change修改limit到100000,丢包消失。
- 复现测试
在netem_enqueue中丢包的位置添加日志打印
注入900ms + 5 limit的故障,使用ping进行测试
发现ping丢包50%(个数50),netem丢包150
- 流程总结
初始化:tc qdisc(iproute2) -> netem delay limit -> sch_netem.ko(netem_init)
-> sch_netem.ko(netem_change)
使用:sch_netem.ko(netem_enqueue) –> qlen > limit -> loss
处理方案
Limit值增大,相当于增大了队列长度,会增加内存占用,可能会对某些时间敏感的数据包造成更大的影响。
| 方案 | 方案简介 | 缺点 |
|---|---|---|
| iproute2源码调整 | 将limit默认值改大 | 需要修改基础模块源码默认值大小不好定 |
| 使用ethtool获取Speed,计算limit值 | 需要修改基础模块源码 | |
| 驱动源码调整 | 将limit值改大 | 需要修改内核源码默认值大小不好定 |
| tc命令套壳计算limit | tc命令套壳,发现delay/latency关键字,则使用ethtool获取Speed,计算limit值,以参数形式加入 | 套壳命令管理困难若limit值增大引起其他问题,定位困难 |