Simulate Network Latency » History » Version 9
neels, 08/31/2021 01:40 PM
1 | 1 | neels | h1. Simulate Network Latency |
---|---|---|---|
2 | |||
3 | This describes how to virtually introduce network latency on a specific ethernet link, |
||
4 | based on the practical example of introducing latency on the Abis link (between BSC and BTS). |
||
5 | All of this on a single machine using the loopback interface. |
||
6 | |||
7 | {{graphviz_link() |
||
8 | digraph G { |
||
9 | rankdir = LR; |
||
10 | |||
11 | subgraph cluster_abis { |
||
12 | label="namespace: abis";style=dotted |
||
13 | 3 | neels | TRX [rank="min"] |
14 | 1 | neels | BTS [rank="min"] |
15 | abisin [label="link: abis-in\n10.9.8.2/24";shape=box] |
||
16 | } |
||
17 | |||
18 | subgraph cluster_root { |
||
19 | label="namespace: root";style=dotted |
||
20 | abisout [label="link: abis-out\n10.9.8.1/24";shape=box] |
||
21 | BSC |
||
22 | MSC |
||
23 | } |
||
24 | |||
25 | 3 | neels | TRX -> BTS -> abisin [dir=both] |
26 | 1 | neels | abisin -> abisout [label="netem delay"] |
27 | abisout -> abisin [label="netem delay"] |
||
28 | abisout -> BSC -> MSC [dir=both] |
||
29 | } |
||
30 | |||
31 | }} |
||
32 | |||
33 | 4 | neels | h2. setup virtual ethernet link |
34 | 1 | neels | |
35 | 6 | neels | The following setup is volatile, i.e. a reboot of the operating system will wipe out all of it. |
36 | 1 | neels | |
37 | 6 | neels | (Perform the following steps as root user.) |
38 | |||
39 | 1 | neels | create network namespace "abis", |
40 | create a virtual ethernet link "abis-in" <-> "abis-out" |
||
41 | and put "abis-in" in the new network namespace: |
||
42 | |||
43 | <pre> |
||
44 | ip netns add abis |
||
45 | ip link add abis-in type veth peer name abis-out |
||
46 | ip link set abis-in netns abis |
||
47 | </pre> |
||
48 | |||
49 | make up a new local IP subnet, here 10.9.8.0/24, |
||
50 | and give each link an address in that subnet. |
||
51 | First for "abis-out" in the root namespace: |
||
52 | |||
53 | <pre> |
||
54 | ip link set abis-out up |
||
55 | ip addr add 10.9.8.1/24 dev abis-out |
||
56 | </pre> |
||
57 | |||
58 | And for "abis-in" within the "abis" namespace, |
||
59 | first opening a shell in that namespace: |
||
60 | |||
61 | <pre> |
||
62 | ip netns exec abis bash |
||
63 | ip link set abis-in up |
||
64 | ip addr add 10.9.8.2/24 dev abis-in |
||
65 | </pre> |
||
66 | |||
67 | 4 | neels | h2. verify the link |
68 | 1 | neels | |
69 | Any shell within the "abis" namespace should show only the "abis-in" and loopback links, |
||
70 | and the "abis-in" link should be in state UP: |
||
71 | |||
72 | 2 | neels | (I repeat the 'ip netns exec' step below just to clarify, of course it suffices to keep one shell within the "abis" namespace open) |
73 | |||
74 | 1 | neels | <pre> |
75 | # ip netns exec abis bash |
||
76 | # ip link |
||
77 | 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000 |
||
78 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
||
79 | 6: abis-in@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 |
||
80 | link/ether f6:c6:b5:47:46:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 |
||
81 | |||
82 | # ip a |
||
83 | 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 |
||
84 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
||
85 | 6: abis-in@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 |
||
86 | link/ether f6:c6:b5:47:46:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 |
||
87 | inet 10.9.8.2/24 scope global abis-in |
||
88 | valid_lft forever preferred_lft forever |
||
89 | inet6 fe80::f4c6:b5ff:fe47:464f/64 scope link |
||
90 | valid_lft forever preferred_lft forever |
||
91 | </pre> |
||
92 | |||
93 | A shell running in the "root" namespace should show the "abis-out" link |
||
94 | and any other links your machine may have configured: |
||
95 | |||
96 | <pre> |
||
97 | # ip link |
||
98 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 |
||
99 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
||
100 | [...] |
||
101 | 5: abis-out@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc netem state UP mode DEFAULT group default qlen 1000 |
||
102 | link/ether be:49:d6:ef:35:38 brd ff:ff:ff:ff:ff:ff link-netns abis |
||
103 | |||
104 | # ip a |
||
105 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 |
||
106 | link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
||
107 | inet 127.0.0.1/8 scope host lo |
||
108 | valid_lft forever preferred_lft forever |
||
109 | inet6 ::1/128 scope host |
||
110 | valid_lft forever preferred_lft forever |
||
111 | [...] |
||
112 | 5: abis-out@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc netem state UP group default qlen 1000 |
||
113 | link/ether be:49:d6:ef:35:38 brd ff:ff:ff:ff:ff:ff link-netns abis |
||
114 | inet 10.9.8.1/24 scope global abis-out |
||
115 | valid_lft forever preferred_lft forever |
||
116 | inet6 fe80::bc49:d6ff:feef:3538/64 scope link |
||
117 | valid_lft forever preferred_lft forever |
||
118 | 2 | neels | </pre> |
119 | |||
120 | A shell run within the "abis" namespace should be able to ping the "root" namespace: |
||
121 | |||
122 | <pre> |
||
123 | # ip netns exec abis bash |
||
124 | # ping 10.9.8.1 |
||
125 | PING 10.9.8.1 (10.9.8.1) 56(84) bytes of data. |
||
126 | 64 bytes from 10.9.8.1: icmp_seq=1 ttl=64 time=0.133 ms |
||
127 | 64 bytes from 10.9.8.1: icmp_seq=2 ttl=64 time=0.059 ms |
||
128 | 64 bytes from 10.9.8.1: icmp_seq=3 ttl=64 time=0.059 ms |
||
129 | 64 bytes from 10.9.8.1: icmp_seq=4 ttl=64 time=0.058 ms |
||
130 | ^C |
||
131 | </pre> |
||
132 | |||
133 | And a running in the "root" namespace should be able to ping into the "abis" namespace: |
||
134 | <pre> |
||
135 | # ping 10.9.8.2 |
||
136 | PING 10.9.8.2 (10.9.8.2) 56(84) bytes of data. |
||
137 | 64 bytes from 10.9.8.2: icmp_seq=1 ttl=64 time=0.133 ms |
||
138 | 64 bytes from 10.9.8.2: icmp_seq=2 ttl=64 time=0.059 ms |
||
139 | 64 bytes from 10.9.8.2: icmp_seq=3 ttl=64 time=0.059 ms |
||
140 | 64 bytes from 10.9.8.2: icmp_seq=4 ttl=64 time=0.058 ms |
||
141 | ^C |
||
142 | </pre> |
||
143 | |||
144 | h2. add latency |
||
145 | |||
146 | In a shell running in the "root" namespace, add a netem delay, for example: |
||
147 | |||
148 | <pre> |
||
149 | tc qdisc add dev abis-out root handle 1:0 netem delay 200ms 50ms 50% |
||
150 | </pre> |
||
151 | |||
152 | From here on, there is latency in *only one* direction on the virtual ethernet. |
||
153 | It already shows in the ping time on both sides, because ping always includes the entire roundtrip. |
||
154 | |||
155 | Also add similar latency in the other direction: |
||
156 | |||
157 | <pre> |
||
158 | ip netns exec abis bash |
||
159 | tc qdisc add dev abis-in root handle 1:0 netem delay 200ms 50ms 50% |
||
160 | </pre> |
||
161 | |||
162 | At this point there is latency in both directions between "abis-in" and "abis-out" |
||
163 | |||
164 | 4 | neels | h2. use the link |
165 | 2 | neels | |
166 | 5 | neels | In my specific example, I configure the BSC to listen for Abis on 10.9.8.1. |
167 | I am running osmo-bsc in a normal shell in the "root" namespace, as usual. |
||
168 | 1 | neels | |
169 | 5 | neels | The other side of Abis, osmo-bts-trx and osmo-trx-uhd, shall run within the "abis" namespace. |
170 | In my specific case, I am running osmo-trx-uhd as root user to allow it to set realtime priority: |
||
171 | |||
172 | 1 | neels | <pre> |
173 | 5 | neels | sudo ip netns exec abis bash |
174 | 1 | neels | osmo-trx-uhd -C osmo-trx.cfg |
175 | 2 | neels | </pre> |
176 | |||
177 | 5 | neels | osmo-bts-trx should run as my normal user, but I need to enter the "abis" netns first and su back to my user: |
178 | 2 | neels | |
179 | <pre> |
||
180 | 5 | neels | sudo ip netns exec abis bash |
181 | 2 | neels | su - neels |
182 | osmo-bts-trx -c osmo-bts.cfg |
||
183 | 1 | neels | </pre> |
184 | 6 | neels | |
185 | 7 | neels | h2. troubleshooting |
186 | |||
187 | 9 | neels | h3. loopback 127.0.0.1 not working |
188 | |||
189 | 7 | neels | In the new netns, the loopback interface will still be in state DOWN. |
190 | To be able to use loopback addresses like 127.0.0.1, set the lo link to UP: |
||
191 | |||
192 | ip link set lo up |
||
193 | 9 | neels | |
194 | h3. modify the latency |
||
195 | |||
196 | To add a new network latency while the interface is running, |
||
197 | you may first want to delete the previously set latency: |
||
198 | |||
199 | <pre> |
||
200 | ip netns exec abis tc qdisc del dev abis-in root handle 1:0 |
||
201 | tc qdisc del dev abis-out root handle 1:0 |
||
202 | </pre> |
||
203 | 7 | neels | |
204 | 6 | neels | h2. Clean up |
205 | |||
206 | When done using the virtual latency link, it suffices to remove the "abis" namespace: |
||
207 | |||
208 | ip netns delete abis |
||
209 | |||
210 | It will still be functional until the last shell running in the namespace exits. |
||
211 | 8 | neels | |
212 | h2. Script |
||
213 | |||
214 | Attached is a script that works well to set up a network namespace with latency on a link to/from it: |
||
215 | attachment:virtual-link.sh |