使用`tc netem` 的网络整形似乎不起作用

pee*_*onn 5 networking linux ubuntu tc

我试图在 Ubuntu 16.06 机器上简单地延迟针对特定 IP 地址的流量,但没有运气。有丰富的资源为这个 这个 这个是我研究。我最终得到了这两组命令,这些命令都不起作用:

tc qdisc add dev eth0 root handle 1: prio
tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 100ms
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 172.19.0.2/32 flowid 1:1
Run Code Online (Sandbox Code Playgroud)

- 或者 -

tc qdisc add dev eth0 root handle 1: prio priomap 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 100ms
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 172.19.0.2/32 flowid 1:1
Run Code Online (Sandbox Code Playgroud)

执行它们后,所有流量都被阻止 - 即什么都没有出现,主机无法访问:

$ ping pingserver2
PING pingserver2 (172.19.0.4) 56(84) bytes of data.
From 14d25a894559 (172.19.0.3) icmp_seq=1 Destination Host Unreachable
From 14d25a894559 (172.19.0.3) icmp_seq=2 Destination Host Unreachable

$ ping pingserver
PING pingserver (172.19.0.2) 56(84) bytes of data.
From 14d25a894559 (172.19.0.3) icmp_seq=1 Destination Host Unreachable
From 14d25a894559 (172.19.0.3) icmp_seq=2 Destination Host Unreachable
Run Code Online (Sandbox Code Playgroud)

它甚至在我只执行第一行之后就立即执行了。

有没有人知道我采取的方法有什么问题?

pee*_*onn 6

我终于弄明白了。经过仔细研究的这个这个章节我有更好的理解它是如何工作的,以及如何tc处理封包。

所以基本上,我需要做的是构建这种树:

          1:   root qdisc
         / | \ 
       /   |   \
       /   |   \
     1:1  1:2  1:3    classes
      |    |    |
     10:  20:  30:    qdiscs    qdiscs
    netem sfq  ---
band  0    1    2
Run Code Online (Sandbox Code Playgroud)

这意味着,除了添加netemqdisc之外,我还需要添加sfq到第二个频段并为“全能”情况添加一个过滤器。这是我正在使用的所有命令:

tc qdisc add dev eth0 root handle 1: prio
tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 172.19.0.2 match ip dport 6363 0xffff flowid 1:1
tc filter add dev eth0 protocol all parent 1: prio 2 u32 match ip dst 0.0.0.0/0 flowid 1:2
tc filter add dev eth0 protocol all parent 1: prio 2 u32 match ip protocol 1 0xff flowid 1:2
tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 10ms
tc qdisc add dev eth0 parent 1:2 handle 20: sfq
Run Code Online (Sandbox Code Playgroud)

以下是对上面每一行的解释:

  1. 在 interface 上prio使用句柄 (id) 1:0(0 不是必需的)向根添加排队规则eth0prioqdisc 默认有三个类 - 1:1 1:2 和 1:3。这些类将在接下来的三行中分配过滤器(顺序很重要!)。了解传出数据包的处理方式很重要——它们从根进入树并从根退出(不会从叶子上掉下来!)。

  2. 为我们想要减慢的流量添加过滤器(在我的情况下172.19.0.2是端口上的流量6363)。过滤器附加到根节点 ( parent 1:) - 这意味着该过滤器将检查所有传出的数据包。过滤器检查 ip 和端口 ( ip dst ... ip dport ...) 并重定向到类1:1( flowid 1:1)。

  3. 以与上述类似的方式,这就是“全能”过滤器的设置方式(感谢这篇文章),重定向到 class 1:2

  4. 同样,此过滤器是 ICMP 数据包(ping 数据包)的“包罗万象”,也重定向到1:2.

  5. 附加qdisc到 class 1:1,给它一个句柄,10:0让它成为netem延迟 10ms 的 qdisc。

  6. sfqqdisc附加到类1:2- 该 qdisc 将以“随机公平”的方式处理与“全能”过滤器匹配的所有其他数据包。

我强烈建议阅读我提供链接的那些章节,因为它们阐明了很多事情,让您不再拼命地在谷歌上搜索解决方案,而是开始自己设计网络整形。

此外,我发现这些命令对于调试/检查非常有用:

tc -s qdisc ls dev eth0
tc -s filter ls dev eth0
Run Code Online (Sandbox Code Playgroud)