模拟两台ubuntu服务器机器之间的慢速连接

Yah*_*hia 9 networking ubuntu bandwidth tcp linux-networking

我想模拟以下场景:假设我有 4 台 ubuntu 服务器机器 A、B、C 和 D。我想将机器 A 和机器 C 之间的网络带宽减少 20%,将 A 和 B 之间的网络带宽减少 10%。如何使用网络模拟/节流工具来做到这一点吗?

Xav*_*cas 15

为此,您可以tc单独使用u32过滤器或与iptables 标记结合使用(如果您不想学习复杂的过滤器语法,可能更简单)。我将在下面的帖子中详细介绍以前的解决方案。


模拟您的设置

例如,让我们考虑运行10 Mbit/s虚拟接口的 A、B、C 和 D。

你基本上想要:

  • A <==> B : 9 Mbit/s出口整形
  • A <==> C : 8 Mbit/s出口整形

为了模拟这一点,我将创建 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           
Run Code Online (Sandbox Code Playgroud)

首先是设置阶段,这样您就可以了解它的构成,如果您不熟悉它,请跳过它,没什么大不了的。然而,您必须知道的是,该命令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
Run Code Online (Sandbox Code Playgroud)

所以在这一点上,我们有前面描述的设置。


塑造交通

是时候进入交通管制以获得你想要的东西了。该tc工具允许您添加排队规则:

  • 对于出口:一旦内核需要发送数据包并且在访问 NIC 驱动程序之前。
  • 对于入口:在访问 NIC 驱动程序之后和内核例程运行接收到的数据包之前。

它带有 3 个概念:qdisc过滤器。这些概念可用于设置复杂的数据包流管理并根据您想要的任何标准/标准对流量进行优先级排序。

简而言之 :

  • Qdiscs 是数据包最终将入队/出队的结构。
  • 类是执行特定行为的 qdisc 的容器。
  • 过滤器是在类之间路由数据包的方法,在处理过程中可以在具有优先级的同一入口点上定义多个过滤器。

所有这些通常作为一棵树工作,其中叶子是 qdiscs,类是节点。树或子树的根将声明为<id>:,子节点将声明为<parent_id>:<children_id>。记住这个语法。

对于您的情况,让我们取 A 并渲染您想要设置的树tc

                                     1:
                                      |
                                      |
                                      |
                                     1:1
                                   /  |  \
                                  /   |   \
                                 /    |    \
                               1:10  1:20  1:30
                                |     |     |
                                |     |     |
                               :10   :20   :30
Run Code Online (Sandbox Code Playgroud)

解释 :

  • 1:是附加到设备 vethA 的根 qdisc,它将被明确地视为htb层次令牌桶(设备的默认 qdisc 是pfifopfifo_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, :30sfq随机公平排队的 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
Run Code Online (Sandbox Code Playgroud)

我们需要做的最后一件事是添加过滤器,因此目标 IP 等于 B 的1:10IP 数据包将进入class ,目标 IP 等于 C 的 IP 数据包将进入1:20class :

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
Run Code Online (Sandbox Code Playgroud)

现在您明白了,您将需要向tcB 和 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
Run Code Online (Sandbox Code Playgroud)

我们得到了9 Mbit/s 的带宽限制。

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
Run Code Online (Sandbox Code Playgroud)

我们得到了8 Mbit/s 的带宽限制。

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
Run Code Online (Sandbox Code Playgroud)

在这里,我们达到了10 Mbit/s的虚拟接口全速。

请注意,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
Run Code Online (Sandbox Code Playgroud)