6

I'm trying to simply delay traffic targeted for certain IP address on Ubuntu 16.06 box with no luck. There are plenty of resources as this this this or this that I studied. I ended up with these two sets of commands, neither of those work:

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

-- or --

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

After executing them, all traffic is blocked - i.e. nothings comes out, host unreachable:

$ 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

It even does it right after I execute just the very first line.

Does anyone have an idea of what's wrong with the approach I'm taking?

peetonn
  • 231
  • 2
  • 4

1 Answers1

7

I finally figured it out. After careful studying of this and this chapters I have much better understanding of how it is supposed to work and how tc processes packets.

So basically, what I need to do, is to build this kind of tree:

          1:   root qdisc
         / | \ 
       /   |   \
       /   |   \
     1:1  1:2  1:3    classes
      |    |    |
     10:  20:  30:    qdiscs    qdiscs
    netem sfq  ---
band  0    1    2

Which means, that apart from adding netem qdisc I needed to add sfq to the second band and add a filter for "catch-all" case. Here are all the commands I'm using:

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

Here are explanations for every line above:

  1. Add prio queueing discipline to the root with handle (id) 1:0 (0 is not mandatory) on interface eth0. prio qdisc has three classes by default - 1:1 1:2 and 1:3. These classes will be assigned filters on the next three lines (order matters!). It is important to understand how outgoing packets are processed - they enter tree from the root and exit it from the root as well (not falling off the leaves!).

  2. Add filter for the traffic we want to slow down (it's the traffic going to 172.19.0.2 on port 6363 in my case). Filter attaches to the root node (parent 1:) - it means that all outgoing packets will be checked by this filter. Filter checks for ip and port (ip dst ... ip dport ...) and redirects to class 1:1 (flowid 1:1).

  3. In similar fashion to the above, this is how "catch-all" filter is set (thanks this post), redirects to class 1:2.

  4. Similarly, this filter is a "catch-all" for ICMP packets (ping packets), also redirects to 1:2.

  5. Attach qdisc to class 1:1, give it a handle of 10:0 and let it be netem qdisc with delay 10ms.

  6. Attach sfq qdisc to class 1:2 - this qdisc will handle all other packets that matched "catch-all" filter in a "stochastic fairness" fashion.

I highly recommend reading those chapters I gave links to as they clarify a lot of things and allow you to stop desperately googling for a solution and start designing network shaping on your own.

Also, I found these commands extremely useful for debugging/examining:

tc -s qdisc ls dev eth0
tc -s filter ls dev eth0
peetonn
  • 231
  • 2
  • 4
  • I get 404 on both links to chapters you refer to. – ae6rt Sep 28 '18 at 20:33
  • 1
    Thanks it works well and cleaner than the [solution](https://serverfault.com/a/964387/382373) I was previously using – Nicolas Henneaux Jun 20 '19 at 08:17
  • Another reference that helps understand where the prio qdisc bands actually come from: https://linux.die.net/man/8/tc-prio – ae6rt Dec 20 '19 at 13:33
  • Maybe someone reading this who uses etcd can comment on this issue https://github.com/etcd-io/etcd/issues/11469. I don't know if the etcd docs are in error, but I can't see my way to saying they are correct, either. – ae6rt Dec 20 '19 at 13:40