Simulate Network Latency¶
This describes how to virtually introduce network latency on a specific ethernet link,
based on the practical example of introducing latency on the Abis link (between BSC and BTS).
All of this on a single machine using the loopback interface.
setup virtual ethernet link¶
The following setup is volatile, i.e. a reboot of the operating system will wipe out all of it.
(Perform the following steps as root user.)
create network namespace "abis",
create a virtual ethernet link "abis-in" <-> "abis-out"
and put "abis-in" in the new network namespace:
ip netns add abis ip link add abis-in type veth peer name abis-out ip link set abis-in netns abis
make up a new local IP subnet, here 10.9.8.0/24,
and give each link an address in that subnet.
First for "abis-out" in the root namespace:
ip link set abis-out up ip addr add 10.9.8.1/24 dev abis-out
And for "abis-in" within the "abis" namespace,
first opening a shell in that namespace:
ip netns exec abis bash ip link set abis-in up ip addr add 10.9.8.2/24 dev abis-in
verify the link¶
Any shell within the "abis" namespace should show only the "abis-in" and loopback links,
and the "abis-in" link should be in state UP:
(I repeat the 'ip netns exec' step below just to clarify, of course it suffices to keep one shell within the "abis" namespace open)
# ip netns exec abis bash # ip link 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 6: abis-in@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether f6:c6:b5:47:46:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 # ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 6: abis-in@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether f6:c6:b5:47:46:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 10.9.8.2/24 scope global abis-in valid_lft forever preferred_lft forever inet6 fe80::f4c6:b5ff:fe47:464f/64 scope link valid_lft forever preferred_lft forever
A shell running in the "root" namespace should show the "abis-out" link
and any other links your machine may have configured:
# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 [...] 5: abis-out@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc netem state UP mode DEFAULT group default qlen 1000 link/ether be:49:d6:ef:35:38 brd ff:ff:ff:ff:ff:ff link-netns abis # ip a 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever [...] 5: abis-out@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc netem state UP group default qlen 1000 link/ether be:49:d6:ef:35:38 brd ff:ff:ff:ff:ff:ff link-netns abis inet 10.9.8.1/24 scope global abis-out valid_lft forever preferred_lft forever inet6 fe80::bc49:d6ff:feef:3538/64 scope link valid_lft forever preferred_lft forever
A shell run within the "abis" namespace should be able to ping the "root" namespace:
# ip netns exec abis bash # ping 10.9.8.1 PING 10.9.8.1 (10.9.8.1) 56(84) bytes of data. 64 bytes from 10.9.8.1: icmp_seq=1 ttl=64 time=0.133 ms 64 bytes from 10.9.8.1: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 10.9.8.1: icmp_seq=3 ttl=64 time=0.059 ms 64 bytes from 10.9.8.1: icmp_seq=4 ttl=64 time=0.058 ms ^C
And a running in the "root" namespace should be able to ping into the "abis" namespace:
# ping 10.9.8.2 PING 10.9.8.2 (10.9.8.2) 56(84) bytes of data. 64 bytes from 10.9.8.2: icmp_seq=1 ttl=64 time=0.133 ms 64 bytes from 10.9.8.2: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 10.9.8.2: icmp_seq=3 ttl=64 time=0.059 ms 64 bytes from 10.9.8.2: icmp_seq=4 ttl=64 time=0.058 ms ^C
add latency¶
In a shell running in the "root" namespace, add a netem delay, for example:
tc qdisc add dev abis-out root handle 1:0 netem delay 200ms 50ms 50%
From here on, there is latency in only one direction on the virtual ethernet.
It already shows in the ping time on both sides, because ping always includes the entire roundtrip.
Also add similar latency in the other direction:
ip netns exec abis bash tc qdisc add dev abis-in root handle 1:0 netem delay 200ms 50ms 50%
At this point there is latency in both directions between "abis-in" and "abis-out"
use the link¶
In my specific example, I configure the BSC to listen for Abis on 10.9.8.1.
I am running osmo-bsc in a normal shell in the "root" namespace, as usual.
The other side of Abis, osmo-bts-trx and osmo-trx-uhd, shall run within the "abis" namespace.
In my specific case, I am running osmo-trx-uhd as root user to allow it to set realtime priority:
sudo ip netns exec abis bash osmo-trx-uhd -C osmo-trx.cfg
osmo-bts-trx should run as my normal user, but I need to enter the "abis" netns first and su back to my user:
sudo ip netns exec abis bash su - neels osmo-bts-trx -c osmo-bts.cfg
troubleshooting¶
loopback 127.0.0.1 not working¶
In the new netns, the loopback interface will still be in state DOWN.
To be able to use loopback addresses like 127.0.0.1, set the lo link to UP:
ip link set lo up
modify the latency¶
To add a new network latency while the interface is running,
you may first want to delete the previously set latency:
ip netns exec abis tc qdisc del dev abis-in root handle 1:0 tc qdisc del dev abis-out root handle 1:0
Clean up¶
When done using the virtual latency link, it suffices to remove the "abis" namespace:
ip netns delete abis
It will still be functional until the last shell running in the namespace exits.
Script¶
Attached is a script that works well to set up a network namespace with latency on a link to/from it:
virtual-link.sh
Updated by neels about 2 years ago · 9 revisions