我想模拟以下场景:假设我有 4 台 ubuntu 服务器机器 A、B、C 和 D。我想将机器 A 和机器 C 之间的网络带宽减少 20%,将 A 和 B 之间的网络带宽减少 10%。如何使用网络模拟/节流工具来实现这一点?
答案1
为此,您可以使用tc
独自一人u32
过滤器或与iptables 标记(如果您不想学习复杂的过滤器语法,也许更简单)。我将在下一篇文章中详细介绍前一种解决方案。
模拟您的设置
举个例子,假设 A、B、C 和 D 正在运行 10兆位/秒虚拟接口。
你基本上想要:
- A <==> B:9兆比特/秒出口整形
- A <==> C:8兆位/秒出口整形
为了模拟这一点,我将创建 4 个网络命名空间和插入网桥的虚拟以太网接口。
当然,在您的情况下,您将使用真正的 NIC,并且网桥将是您的网关或交换机,具体取决于您的基础设施。
因此在我的模拟中我们将在 10.0.0.0/24 网络中进行以下设置:
10.0.0.254
+-------+
| |
| br0 |
| |
+---+---+
|
| veth{A..D}.peer
|
+------------+------+-----+------------+
| | | |
vethA | vethB | vethC | vethD |
+---+---+ +---+---+ +---+---+ +---+---+
| | | | | | | |
| A | | B | | C | | D |
| | | | | | | |
+-------+ +-------+ +-------+ +-------+
10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4
首先,设置阶段,这样您就可以了解它是由什么构成的,如果您不熟悉它,请跳过它,没什么大不了的。但是您必须知道的是,该命令ip netns exec <namespace> <command>
允许在网络命名空间中执行命令(即在上一个绘制的框中)。这也将在下一节中使用。
# Create the bridge
ip link add br0 type bridge
# Create network namespaces and veth interfaces and plug them into the bridge
for host in {A..D} ; do
ip link netns add ${host}
ip link add veth${host} type veth peer name veth${host}.peer
ip link set dev veth${host}.peer master br0
ip link set dev veth${host} netns ${host}
ip netns exec ${host} ip link set veth${host} up
done
# Assign IPs
ip addr add 10.0.0.254/24 dev br0
ip netns exec A ip addr add 10.0.0.1/24 dev vethA
ip netns exec B ip addr add 10.0.0.2/24 dev vethB
ip netns exec C ip addr add 10.0.0.3/24 dev vethC
ip netns exec D ip addr add 10.0.0.4/24 dev vethD
此时我们已经有了之前描述的设置。
调整流量
现在是时候进入交通管制状态以获得您想要的东西了。该tc
工具允许您添加排队规则:
- 对于出口:一旦内核需要发送数据包并且在访问 NIC 驱动程序之前。
- 对于入口:在访问 NIC 驱动程序之后和内核例程对接收到的数据包运行之前。
它包含三个概念:队列规定,类和过滤器。这些概念可用于设置复杂的数据包流管理,并根据您想要的任何标准对流量进行优先排序。
简而言之 :
- Qdiscs 是数据包最终入队/出队的结构。
- 类别是具有特定行为的 qdisc 的容器。
- 过滤器是在类别之间路由数据包的方式,可以在同一个入口点上定义多个过滤器,并在处理过程中具有优先级。
所有这些通常以树的形式工作,其中叶子是 qdisc,类是节点。树或子树的根将被声明为<id>:
,子节点将被声明为<parent_id>:<children_id>
。请记住此语法。
对于您的情况,让我们取 A 并渲染您想要设置的树tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
解释 :
1:
是附加到设备 vethA 的根 qdisc,它将被明确地用作htb
层次结构令牌桶(设备的默认 qdisc 是pfifo
或pfifo_fast
取决于操作系统)。它特别适合带宽管理。不匹配此级别定义的过滤器的数据包将进入1:30
类。1:1
将是一个htb
将设备整个流量限制为 10 Mbit/s 的类。1:10
将是一个htb
限制输出流量为 9 Mbit/s(10 Mbit/s 的 90%)的类。1:20
将是一个htb
限制输出流量为 8 Mbit/s(10 Mbit/s 的 80%)的类。1:30
将会是一个htb
限制流量为 10 Mbit/s (回退) 的类。:10, :20, :30
是sfq
随机公平排队的 qdisc。换句话说,这些 qdisc 将确保基于流的传输调度的公平性。
整个过程由以下命令设置:
ip netns exec A tc qdisc add dev vethA root handle 1: htb default 30
ip netns exec A tc class add dev vethA parent 1: classid 1:1 htb rate 10mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:10 htb rate 9mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:20 htb rate 8mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:30 htb rate 10mbit burst 15k
ip netns exec A tc qdsic add dev vethA parent 1:10 handle 10: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:20 handle 20: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:30 handle 30: sfq perturb 10
我们最后需要做的是添加过滤器,以便目标 IP 等于 B 的 IP 数据包将进入1:10
类,而目标 IP 等于 C 的 IP 数据包将进入1:20
类:
ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 1 u32 match ip dst 10.0.0.2/32 flowid 1:10
ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 2 u32 match ip dst 10.0.0.3/32 flowid 1:20
现在您已经明白了,您将需要tc
向 B 和 C 添加类似的规则,以便这些钻机向 A 的传输也能成形。
测试
现在让我们测试一下。我个人习惯使用iperf
,它仅由一个二进制文件组成,可以作为客户端或服务器运行,并将自动在两个主机之间发送尽可能多的流量。
A 和 B 之间:
$ ip netns exec B iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.2 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.2, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[ 5] local 10.0.0.1 port 58191 connected with 10.0.0.2 port 8001
[ ID] Interval Transfer Bandwidth
[ 5] 0.0- 2.0 sec 2.38 MBytes 9.96 Mbits/sec
[ 5] 2.0- 4.0 sec 2.12 MBytes 8.91 Mbits/sec
[ 5] 4.0- 6.0 sec 2.00 MBytes 8.39 Mbits/sec
[ 5] 6.0- 8.0 sec 2.12 MBytes 8.91 Mbits/sec
[ 5] 8.0-10.0 sec 2.00 MBytes 8.39 Mbits/sec
[ 5] 0.0-10.1 sec 10.8 MBytes 8.91 Mbits/sec
我们得到我们的9兆比特/秒带宽限制。
A 和 C 之间:
$ ip netns exec C iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.3 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.3, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[ 5] local 10.0.0.1 port 58522 connected with 10.0.0.3 port 8001
[ ID] Interval Transfer Bandwidth
[ 5] 0.0- 2.0 sec 2.25 MBytes 9.44 Mbits/sec
[ 5] 2.0- 4.0 sec 1.75 MBytes 7.34 Mbits/sec
[ 5] 4.0- 6.0 sec 1.88 MBytes 7.86 Mbits/sec
[ 5] 6.0- 8.0 sec 1.88 MBytes 7.86 Mbits/sec
[ 5] 8.0-10.0 sec 1.75 MBytes 7.34 Mbits/sec
[ 5] 0.0-10.1 sec 9.62 MBytes 7.98 Mbits/sec
我们得到我们的8兆位/秒带宽限制。
A 和 D 之间:
$ ip netns exec D iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.4 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.4, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[ 5] local 10.0.0.1 port 40614 connected with 10.0.0.4 port 8001
[ ID] Interval Transfer Bandwidth
[ 5] 0.0- 2.0 sec 2.62 MBytes 11.0 Mbits/sec
[ 5] 2.0- 4.0 sec 2.25 MBytes 9.44 Mbits/sec
[ 5] 4.0- 6.0 sec 2.38 MBytes 9.96 Mbits/sec
[ 5] 6.0- 8.0 sec 2.25 MBytes 9.44 Mbits/sec
[ 5] 8.0-10.0 sec 2.38 MBytes 9.96 Mbits/sec
[ 5] 0.0-10.2 sec 12.0 MBytes 9.89 Mbits/sec
这里我们有全速的虚拟接口10兆位/秒到达。
htb
请注意,通过调整适当的参数,可以在课堂上更好地处理每次运行的第一个小节的爆发。
打扫干净
去除 :
- 优先级 1 的过滤器
1:
:tc filter del dev vethA parent 1: prio 1 u32
。 - 所有过滤器均开启
1:
:tc filter del dev vethA parent 1:
。 - 类别
1:20
及其子类:tc class del dev vethA parent 1:1 classid 1:20
。 - 整棵树:
tc qdisc del dev vethA
。
清理模拟集:
# Remove veth pairs and network namespaces
for host in {A..D} ; do
ip link del dev veth${host}.peer
ip netns del ${host}
done
# Remove the bridge
ip link del dev br0
答案2
Ubuntu 有从 FreeBSD 移植的 IPFW,并且 IPFW 有 DUMMYNET,可以管理各种网络参数 - 带宽、延迟、数据包丢失率等。
答案3
最好的方法是使用 tc 工具和现在集成的 netem 模块(至少在 Ubuntu 服务器上)。你可以在以下位置找到更多信息这篇文章来自 Stackoverflow。