Reputation: 21
I am trying to use the tcconfig package (a python wrapper for tc module) and tc commands to set up netem delay between 2 docker containers within a Ubuntu distro in WSL2
However I didn't manage to make it work as the tc commands can not be applied to the correct address.
What I have tried is:
# create and start 3 docker containers:
sudo docker run --name dc1 -itd --cap-add NET_ADMIN archlinux bash
sudo docker run --name dc2 -itd --cap-add NET_ADMIN archlinux bash
sudo docker run --name dc3 -itd --cap-add NET_ADMIN archlinux bash
# use tcconfig to set up 100ms delay between container dc1 and dc2
sudo tcset dc1 --src-container dc1 --dst-container dc2 --docker --delay 100ms
With the above commands I expect to be able to see 100ms delay when I ping dc1 from dc2 and vice versa.
However I cannot see the delay applied.
When I look into the veth of container dc1, I can see the following rules applied with the tcshow command from tcconfig:
(.venv) johnsmith@AP-HYB-AmXNp8wl:~/python-scripts$ sudo tcshow veth605f18a
{
"veth605f18a": {
"outgoing": {
"src-network=172.17.0.2/32, dst-network=172.17.0.3/32, protocol=ip": {
"filter_id": "800::800",
"delay": "100ms",
"rate": "10Gbps"
}
},
"incoming": {}
}
}
I figure the reason that it's not working might be because the rules is somehow applied to 172.17.0.2/32 and 172.17.0.3/32 instead of 172.17.0.2/16 and 172.17.0.3/16, which is the correct address + subnet of the containers. To validate the address of container dc1:
[root@7cee5e6f43bc /]# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet **172.17.0.2/16** brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
If I dive deeper into the tc commands that are behind the scene, I can get the following commands with the --tc-script option:
/usr/sbin/tc qdisc add dev veth605f18a root handle 17e0: htb default 1
/usr/sbin/tc class add dev veth605f18a parent 17e0: classid 17e0:1 htb rate 10000000.0kbit
/usr/sbin/tc class add dev veth605f18a parent 17e0: classid 17e0:76 htb rate 10000000.0Kbit ceil 10000000.0Kbit
/usr/sbin/tc qdisc add dev veth605f18a parent 17e0:76 handle 22d8: netem delay 100.0ms
/usr/sbin/tc filter add dev veth605f18a protocol ip parent 17e0: prio 5 u32 match ip src 172.17.0.2/32 match ip dst 172.17.0.3/32 flowid 17e0:76
As I thought the problem was the subnet mask /32 not being correct, I attempted to run the above tc commands as follow, with only the subnet masks updated to /16:
/usr/sbin/tc qdisc add dev veth605f18a root handle 17e0: htb default 1
/usr/sbin/tc class add dev veth605f18a parent 17e0: classid 17e0:1 htb rate 10000000.0kbit
/usr/sbin/tc class add dev veth605f18a parent 17e0: classid 17e0:76 htb rate 10000000.0Kbit ceil 10000000.0Kbit
/usr/sbin/tc qdisc add dev veth605f18a parent 17e0:76 handle 22d8: netem delay 100.0ms
/usr/sbin/tc filter add dev veth605f18a protocol ip parent 17e0: prio 5 u32 match ip src 172.17.0.2/16 match ip dst 172.17.0.3/16 flowid 17e0:76
I still fail to make this work as I found out the set of tc rules eventually set the filters on the entire subnet of 172.17.0.0/16 instead of these 2 specific ip addresses:
(.venv) johnsmith@AP-HYB-AmXNp8wl:~/python-scripts$ tcshow veth605f18a
{
"veth605f18a": {
"outgoing": {
"src-network=172.17.0.0/16, dst-network=172.17.0.0/16, protocol=ip": {
"filter_id": "800::800",
"delay": "100ms",
"rate": "10Gbps"
}
},
"incoming": {}
}
}
I am very new to network shaping with tc, does anyone have some idea of what did I do wrong here and how can I apply the delay between the docker contaienrs? Many thanks!
Upvotes: 0
Views: 360
Reputation: 21
After some struggling I managed to find out what was going wrong: I didn't set the src-container and dst-container correctly:
The correct command with tcconfig to set up delay between container dc1 and dc2 should be:
sudo tcset dc1 --src-container dc2 --dst-container dc1 --docker --delay 100ms
instead of
sudo tcset dc1 --src-container dc1 --dst-container dc2 --docker --delay 100ms
Incorrect assignment of src/dst container will result in a false tc filter getting applied to the qdisc:
/usr/sbin/tc qdisc add dev vethf83016b root handle 1da0: htb default 1
/usr/sbin/tc class add dev vethf83016b parent 1da0: classid 1da0:1 htb rate 10000000.0kbit
/usr/sbin/tc class add dev vethf83016b parent 1da0: classid 1da0:192 htb rate 10000000.0Kbit ceil 10000000.0Kbit
/usr/sbin/tc qdisc add dev vethf83016b parent 1da0:192 handle 2c9e: netem delay 200.0ms 10ms loss 20% 10%
/usr/sbin/tc filter add dev vethf83016b protocol ip parent 1da0: prio 5 u32 match ip dst 172.17.0.3 match ip src 172.17.0.2 flowid 1da0:192
In the case dc1 has the virtual interface of vethf83016b and ip address of 172.17.0.2 While dc2 has an ip address of 172.17.0.3
From my understanding, with the above tc settings, the virtual ethernet of dc1 should be able to apply the delay to all the packets sent to dc2. However, it only works the other way around when I set it up with dc1 as destination and dc2 as source where a simulated 2-way delay can be achieved:
However I don't fully understand how the veth work with the outgoing traffic, does anyone have any idea why is
sudo tcset dc1 --src-container dc1 --dst-container dc2 --docker --delay 100ms
not delaying the outgoing packets from dc1 to dc2?
Upvotes: 1