Site icon Karneliuk

Tools 4. Checking bandwidth between your servers, VMs, containers or even PIs and Android/Apple phone using iperf

Hello my friend,

We hope you are doing well and staying safe during this COVID times. To make your stay a bit more pleasant, we are offering you and interesting read, which will give you ideas how to test network performance between your endpoints, which can be any Server, virtual machine (VM), container, or even Raspberry PI node. Yes, we continue our troubleshooting series. Take a brew, and get started.


1
2
3
4
5
No part of this blogpost could be reproduced, stored in a
retrieval system, or transmitted in any form or by any
means, electronic, mechanical or photocopying, recording,
or otherwise, for commercial purposes without the
prior permission of the author.

Can automation help with fixing your network issues?

Automation is your extra pair of hands. Or even more than that. Capability to create the network automation solutions, from a basic scripts for info collection or simple configuration to complicated logic, which takes into account exiting environment and is integrated with your other OSS/BSS, is one of the key skills, what allows you to build a successful career in the constantly changing network field.

We have created a new training, which is focused only on the Nornir and you can use it for the network (and not only) automation. It is an organic extension of our network automation training, which assumes you are already OK with Python and looking to learn new things, which can even more improve your automation skills to give you possibility to become the most efficient Engineer, who can automate networks and whole IT infrastructure.

Training includes the integration of Nornir with NetBox, configuration and validation of Cisco, Nokia, Arista, Cumulus Linux and CentOS Linux devices with CLI, NETCONF, RESTCONF, gNMI. In the same way as the original one, it is based on the real experience and real use cases, which will give you insights how to apply them for your networks and IT even during the training. Don’t loose your future.

Start your automation training today.

Brief description

In the first blogpost in this series we have listed the most important and useful to help you with the troubleshooting of your network problems, or to prove others that the problems are not network related :-). So far you have seen how to get your public IP and how to measure the bandwidth of your Internet connectivity. Today’s focus is to measure the bandwidth of the network connectivity between your two endpoints. Why do you want to measure the network performance (i.e. what are the use cases)?

Beware, the result of the iPerf tests are depend also on resources available on your compute node, drivers of the operating system and so on.

The endpoint is a broad term, which is related to any computing node, where you can install and run the corresponding application:

Those nodes are traditional for any cloud, data centre, service provider, and enterprise network. However, you may go even further and measure the bandwidth from/to the following nodes

Full list of the available tools you can find at the official website of the iPerf tool.

So, what exactly allows iPerf for you to measure? It allows you to measure the network throughput between any two your endpoints. There are quite a few parameters, which you can specify:

Besides the throughout figure itself you will also see the amount of the retransmits for TCP stream (if any) and packet loss for UDP (if any).

Usage

Let’s take a look how to use iPerf. By the way, the version you are about to see is the iPerf3, which is the latest available stable release. However, it is not the first version, and the iPerf2 was used in the industry for quite a while.

The documentation for both version are available at the official website of iPerf.

To give you better understand on what we are testing, take a look on the following diagram.

Lab topology

Despite you may think that this is not much use for it, we believe, it gives you some insights, how you can extrapolate this to your setup (e.g., public/private cloud, service provider 5G POD, campus network with WLAN and/or WAN links, etc).

#1. Installation

#1.1 CentOS

Depending on the operating system running on your endpoint, there will be different approaches for installation. On the CentOS Linux you can install using the official repository:


1
2
$ sudo dnf update -y
$ sudo dnf -y install iperf3

Use “yum” instead of “dnf” for CentOS 7.

After the installation is complete, you can check the installed version. It is important to know the version, as some features were added in 3.1 and were not available in 3.0 version of iPerf.


1
2
3
4
$ iperf3 --version
iperf 3.5 (cJSON 1.5.2)
Linux nnat.karneliuk.com 4.18.0-240.1.1.el8_3.x86_64 #1 SMP Thu Nov 19 17:20:08 UTC 2020 x86_64
Optional features available: CPU affinity setting, IPv6 flow label, SCTP, TCP congestion algorithm setting, sendfile / zerocopy, socket pacing, authentication

As you remember, the CentOS 8 is running as a VM.

#1.2. Raspberry PI OS (or Ubuntu/Debian)

Small and cheap Rasperry PI can be quite a powerful workhorse for the network monitoring and management. It OS is based on the Debian and, therefore, has the same package manager and approach to install the packages. As such, the installation of the iPerf there looks like that:


1
2
$ sudo apt-get update -y
$ sudo apt-get install -y iperf3

Despite the Raspberry PI run the “normal” Linux, it has different system architecture. It is ARM, rather than x86. As such, the corresponding packages should support ARM in order you can use them.

Once installed, check the version of iPerf:


1
2
3
4
$ iperf3 --version
iperf 3.6 (cJSON 1.5.2)
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l
Optional features available: CPU affinity setting, IPv6 flow label, SCTP, TCP congestion algorithm setting, sendfile / zerocopy, socket pacing, authentication
#1.3. Android smartphone

Originally we didn’t plan cover that part, as we even didn’t know about such a possibility. However, as we know about it now, we’ll try to add the smartphone part as well. To have it installed, go to the Google Play Store and search for “iperf3”.

Press the Install button and you will get it in a few minutes. Once it is installed you will launch it. Put the first switch in the position iperf3 just by pressing it (1). Afterwards, type in the cli part “-v” key and press the button stopped to run it (2).

As you can see, the Android smartphone is also ARM based device.

The installation is complete and we can progress with the tests.

#2. Simple tests

iPerf is a client-server application, where the server is listening for the connectivities from the customers on some port and the customer builds the session, which is in fact used to measure the performance. As such, the first task is to launch the server side (we do it at our Raspberry PI node) using the command “iperf3 -s“:


1
2
3
4
$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

You can see that server is listening for the connections on the default iperf3 port, which is 5201/TCP. The server is running in the foreground and you will immediately see any details of running tests

Now we can test the throughput from our VM running CentOS using the command “iperf3 -c server_ip“:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ iperf3 -c 192.168.1.75
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 49640 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   877 KBytes  7.17 Mbits/sec   44   34.2 KBytes      
[  5]   1.00-2.00   sec   376 KBytes  3.08 Mbits/sec   22   22.8 KBytes      
[  5]   2.00-3.00   sec   643 KBytes  5.27 Mbits/sec   42   4.28 KBytes      
[  5]   3.00-4.00   sec   847 KBytes  6.93 Mbits/sec   56   4.28 KBytes      
[  5]   4.00-5.00   sec   768 KBytes  6.30 Mbits/sec   44   31.4 KBytes      
[  5]   5.00-6.00   sec   361 KBytes  2.96 Mbits/sec   54   28.5 KBytes      
[  5]   6.00-7.00   sec   314 KBytes  2.57 Mbits/sec   40   4.28 KBytes      
[  5]   7.00-8.02   sec   408 KBytes  3.28 Mbits/sec   41   4.28 KBytes      
[  5]   8.02-9.01   sec   471 KBytes  3.92 Mbits/sec   32   14.3 KBytes      
[  5]   9.01-10.03  sec   157 KBytes  1.26 Mbits/sec   14   4.28 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.03  sec  5.10 MBytes  4.27 Mbits/sec  389             sender
[  5]   0.00-10.05  sec  4.94 MBytes  4.12 Mbits/sec                  receiver

iperf Done.

This output provides a lot of useful information, which explains how your network works:

As you can figure out, the connectivity from the client (VM with CentOS) to the server (Raspberry PI with PI OS) is not ideal.

The same results are also available on the server side :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Accepted connection from 192.168.1.66, port 63931
[  5] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 63932
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec   356 KBytes  2.92 Mbits/sec                  
[  5]   1.00-2.00   sec   710 KBytes  5.82 Mbits/sec                  
[  5]   2.00-3.00   sec   649 KBytes  5.31 Mbits/sec                  
[  5]   3.00-4.00   sec   870 KBytes  7.12 Mbits/sec                  
[  5]   4.00-5.00   sec   730 KBytes  5.98 Mbits/sec                  
[  5]   5.00-6.00   sec   405 KBytes  3.32 Mbits/sec                  
[  5]   6.00-7.00   sec   284 KBytes  2.32 Mbits/sec                  
[  5]   7.00-8.00   sec   456 KBytes  3.74 Mbits/sec                  
[  5]   8.00-9.00   sec   396 KBytes  3.24 Mbits/sec                  
[  5]   9.00-10.00  sec   203 KBytes  1.66 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.05  sec  4.94 MBytes  4.12 Mbits/sec                  receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

Wait, what? The TCP port is different to what you have seen on the client side (and IP as well). So the beauty of iPerf is that it works fine even if there is a NAT between the client and the server. That creates even more interesting opportunity to you…

How to measure the performance from the server to the client of the client is behind the dynamic NAT/PAT?

The iPerf3 is having an option, which allows you to signal from the client to the server, that the server shall send the data using the TCP session established by the client side. To do that, add the flag “-R“, when you run the test on the client:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ iperf3 -c 192.168.1.75 -R
Connecting to host 192.168.1.75, port 5201
Reverse mode, remote host 192.168.1.75 is sending
[  5] local 10.0.2.6 port 49670 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  5.80 MBytes  48.7 Mbits/sec                  
[  5]   1.00-2.00   sec  5.93 MBytes  49.8 Mbits/sec                  
[  5]   2.00-3.00   sec  3.17 MBytes  26.5 Mbits/sec                  
[  5]   3.00-4.00   sec  1.48 MBytes  12.4 Mbits/sec                  
[  5]   4.00-5.00   sec  1.35 MBytes  11.3 Mbits/sec                  
[  5]   5.00-6.01   sec  1.17 MBytes  9.76 Mbits/sec                  
[  5]   6.01-7.00   sec  3.44 MBytes  29.1 Mbits/sec                  
[  5]   7.00-8.00   sec  4.83 MBytes  40.5 Mbits/sec                  
[  5]   8.00-9.00   sec  3.14 MBytes  26.3 Mbits/sec                  
[  5]   9.00-10.00  sec  3.37 MBytes  28.3 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.03  sec  35.4 MBytes  29.7 Mbits/sec   38             sender
[  5]   0.00-10.00  sec  33.7 MBytes  28.3 Mbits/sec                  receiver

As you can see, the speed from our ARM PI 4 to VM with CentOS is 5-10 times higher and the amount of retransmits is 10 times less.

So iPerf gives you possibility to measure the network performance in both directions even if there are some complications to establish the direct connectivity (e.g., NAT).

Let’s try to run test from the Android phone to the Raspberry PI iPerf server:

It is exciting, isn’t it? The speed is way better than from VM running CentOS, however we are using the same WLAN connectivity for the uplink. So, you start seeing so that server running VM (in this case, that is my laptop, but still) can be a source of the troubles with the network performance, not the network itself.

Can we test the performance from the our ARM server (such a sound name for Raspberry PI 4, isn’t it? :-)) to the Android phone? Yes, we can:

Meanwhile, all the results are visible on the server side as explained above as well:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

Accepted connection from 192.168.1.66, port 63931
[  5] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 63932
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec   356 KBytes  2.92 Mbits/sec                  
[  5]   1.00-2.00   sec   710 KBytes  5.82 Mbits/sec                  
[  5]   2.00-3.00   sec   649 KBytes  5.31 Mbits/sec                  
[  5]   3.00-4.00   sec   870 KBytes  7.12 Mbits/sec                  
[  5]   4.00-5.00   sec   730 KBytes  5.98 Mbits/sec                  
[  5]   5.00-6.00   sec   405 KBytes  3.32 Mbits/sec                  
[  5]   6.00-7.00   sec   284 KBytes  2.32 Mbits/sec                  
[  5]   7.00-8.00   sec   456 KBytes  3.74 Mbits/sec                  
[  5]   8.00-9.00   sec   396 KBytes  3.24 Mbits/sec                  
[  5]   9.00-10.00  sec   203 KBytes  1.66 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.05  sec  4.94 MBytes  4.12 Mbits/sec                  receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.1.66, port 64300
[  5] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 64301
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  6.36 MBytes  53.4 Mbits/sec    0    387 KBytes      
[  5]   1.00-2.00   sec  6.96 MBytes  58.4 Mbits/sec    0    650 KBytes      
[  5]   2.00-3.00   sec  3.29 MBytes  27.6 Mbits/sec    0    764 KBytes      
[  5]   3.00-4.00   sec  1.18 MBytes  9.91 Mbits/sec   12    543 KBytes      
[  5]   4.00-5.00   sec  1.74 MBytes  14.6 Mbits/sec    8    411 KBytes      
[  5]   5.00-6.00   sec   954 KBytes  7.82 Mbits/sec   18    298 KBytes      
[  5]   6.00-7.00   sec  3.23 MBytes  27.1 Mbits/sec    0    328 KBytes      
[  5]   7.00-8.00   sec  4.97 MBytes  41.7 Mbits/sec    0    346 KBytes      
[  5]   8.00-9.00   sec  3.48 MBytes  29.2 Mbits/sec    0    355 KBytes      
[  5]   9.00-10.00  sec  3.29 MBytes  27.6 Mbits/sec    0    356 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.03  sec  35.4 MBytes  29.7 Mbits/sec   38             sender
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.1.67, port 52516
[  5] local 192.168.1.75 port 5201 connected to 192.168.1.67 port 52518
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  3.58 MBytes  30.0 Mbits/sec                  
[  5]   1.00-2.00   sec  4.11 MBytes  34.5 Mbits/sec                  
[  5]   2.00-3.00   sec  5.65 MBytes  47.4 Mbits/sec                  
[  5]   3.00-4.00   sec  4.98 MBytes  41.8 Mbits/sec                  
[  5]   4.00-5.00   sec  4.99 MBytes  41.9 Mbits/sec                  
[  5]   5.00-6.00   sec  4.21 MBytes  35.3 Mbits/sec                  
[  5]   6.00-7.00   sec  3.79 MBytes  31.8 Mbits/sec                  
[  5]   7.00-8.00   sec  3.23 MBytes  27.1 Mbits/sec                  
[  5]   8.00-9.00   sec  3.41 MBytes  28.6 Mbits/sec                  
[  5]   9.00-10.00  sec  3.43 MBytes  28.8 Mbits/sec                  
[  5]  10.00-10.09  sec   221 KBytes  20.9 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.09  sec  41.6 MBytes  34.6 Mbits/sec                  receiver
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.1.67, port 52520
[  5] local 192.168.1.75 port 5201 connected to 192.168.1.67 port 52522
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec  5.73 MBytes  48.1 Mbits/sec    0    267 KBytes      
[  5]   1.00-2.00   sec  6.21 MBytes  52.1 Mbits/sec    0    489 KBytes      
[  5]   2.00-3.00   sec  5.65 MBytes  47.4 Mbits/sec    0    735 KBytes      
[  5]   3.00-4.00   sec  5.53 MBytes  46.4 Mbits/sec    0    993 KBytes      
[  5]   4.00-5.00   sec  4.47 MBytes  37.5 Mbits/sec   90    281 KBytes      
[  5]   5.00-6.00   sec  4.48 MBytes  37.6 Mbits/sec   49    107 KBytes      
[  5]   6.00-7.00   sec  4.72 MBytes  39.6 Mbits/sec   63   1.00 MBytes      
[  5]   7.00-8.00   sec  3.35 MBytes  28.1 Mbits/sec  101    666 KBytes      
[  5]   8.00-9.00   sec  4.78 MBytes  40.1 Mbits/sec   21    154 KBytes      
[  5]   9.00-10.00  sec  4.60 MBytes  38.6 Mbits/sec  104    462 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.10  sec  49.5 MBytes  41.2 Mbits/sec  428             sender
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

As you can see, there are no limits in scenarious to measure your network performance. Now it is time to do some more advanced tests.

#3. Advanced tests

#3.1. Client side tricks

There are quite a few parameters you might want to modify in the test, which is depending on what exactly you are going to troubleshoot. For example, you are not sure about the long term stability of the network performance. To observe the possible deviations over the time, you can run the iPerf test for a longer period (e.g., 1 minute, 5 minute, 60 minutes, etc). To do that, you need to use key “-t X“, where X is duration in seconds:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[aaa@nnat ~]$ iperf3 -c 192.168.1.75 -t 30
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 45562 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   639 KBytes  5.23 Mbits/sec   39   14.3 KBytes      
!
! SOME OUTPUT IS TRUNCATED FOR BREVITY
!  
[  5]  29.00-30.00  sec   816 KBytes  6.68 Mbits/sec   58   32.8 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-30.00  sec  17.2 MBytes  4.80 Mbits/sec  1242             sender
[  5]   0.00-30.01  sec  16.9 MBytes  4.73 Mbits/sec                  receiver

iperf Done.

So far you see that performance is poor, to be frank. That could be related to the network condition (e.g., there is no more free capacity, some links are congested or having errors causing some streams to be dropped) or the operating system issues.

Based on the experience, we’ve seen that sometimes if you have multiple links in your network, where ECMP may happen (data centre fabric, service provider network, etc), you may have sporadic traffic drop for certain flows, what typically means that some one the interface is having issues. One of the ideas, how you can start such a troubleshooting, is to run iPerf measurement simultaneously for several streams in parallel using the “-P X” key, where X is the amount of the parallel streams:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[aaa@nnat ~]$ iperf3 -c 192.168.1.75 -P 5
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 45566 connected to 192.168.1.75 port 5201
[  7] local 10.0.2.6 port 45568 connected to 192.168.1.75 port 5201
[  9] local 10.0.2.6 port 45570 connected to 192.168.1.75 port 5201
[ 11] local 10.0.2.6 port 45572 connected to 192.168.1.75 port 5201
[ 13] local 10.0.2.6 port 45574 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.01   sec   401 KBytes  3.24 Mbits/sec   22   4.28 KBytes      
[  7]   0.00-1.01   sec   412 KBytes  3.33 Mbits/sec   22   4.28 KBytes      
[  9]   0.00-1.01   sec   630 KBytes  5.10 Mbits/sec   42   27.1 KBytes      
[ 11]   0.00-1.01   sec   907 KBytes  7.34 Mbits/sec   39   34.2 KBytes      
[ 13]   0.00-1.01   sec   519 KBytes  4.20 Mbits/sec   25   4.28 KBytes      
[SUM]   0.00-1.01   sec  2.80 MBytes  23.2 Mbits/sec  150            
- - - - - - - - - - - - - - - - - - - - - - - - -
!
! SOME OUTPUT IS TRUNCATED FOR BREVITY
!          
- - - - - - - - - - - - - - - - - - - - - - - - -
[  5]   9.00-10.00  sec   110 KBytes   898 Kbits/sec   15   1.43 KBytes      
[  7]   9.00-10.00  sec   125 KBytes  1.03 Mbits/sec   17   1.43 KBytes      
[  9]   9.00-10.00  sec  2.02 MBytes  16.9 Mbits/sec   32   34.2 KBytes      
[ 11]   9.00-10.00  sec  1.04 MBytes  8.72 Mbits/sec   48   4.28 KBytes      
[ 13]   9.00-10.00  sec   925 KBytes  7.57 Mbits/sec   40   35.6 KBytes      
[SUM]   9.00-10.00  sec  4.20 MBytes  35.1 Mbits/sec  152            
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  2.20 MBytes  1.84 Mbits/sec  181             sender
[  5]   0.00-10.33  sec  2.04 MBytes  1.66 Mbits/sec                  receiver
[  7]   0.00-10.00  sec  2.12 MBytes  1.78 Mbits/sec  192             sender
[  7]   0.00-10.33  sec  1.98 MBytes  1.60 Mbits/sec                  receiver
[  9]   0.00-10.00  sec  8.70 MBytes  7.30 Mbits/sec  345             sender
[  9]   0.00-10.33  sec  8.50 MBytes  6.90 Mbits/sec                  receiver
[ 11]   0.00-10.00  sec  9.45 MBytes  7.93 Mbits/sec  346             sender
[ 11]   0.00-10.33  sec  9.31 MBytes  7.56 Mbits/sec                  receiver
[ 13]   0.00-10.00  sec  9.29 MBytes  7.79 Mbits/sec  350             sender
[ 13]   0.00-10.33  sec  8.90 MBytes  7.22 Mbits/sec                  receiver
[SUM]   0.00-10.00  sec  31.8 MBytes  26.6 Mbits/sec  1414             sender
[SUM]   0.00-10.33  sec  30.7 MBytes  24.9 Mbits/sec                  receiver

In the beginning of the output you may see that each stream has obtained its own source port, what in case of multiple paths available in the network will work as a variable for hashing of load-balancing mechanism.

Available from your phone as well

Once you nail down some streams, which are working good or bad, you can retest that using the option to provide a specific port for the TCP session with “–cport X” key, where X is a port number:


1
2
3
4
5
6
$ iperf3 -c 192.168.1.75 --cport 33333
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 33333 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   921 KBytes  7.54 Mbits/sec   41   14.3 !
! FURTHER OUTPUT IS TRUNCATED

In case you have multiple IP addresses (e.g. some secondary IP or just multiple interfaces), you can specify the source IP explicitly using the key “-B X“, where X is a corresponding IP address.


1
2
3
4
5
6
7
$ iperf3 -c 192.168.1.75 --cport 33333 -B  10.0.2.6
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 33333 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   921 KBytes  7.54 Mbits/sec   41   14.3
!
! FURTHER OUTPUT IS TRUNCATED
Available from your phone as well

It could be that you are interested in measuring the performance of UDP traffic and the packet loss, if your application in question is UDP based. iPerf gives you such possibility as well, just 2 flags are needed:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[aaa@nnat ~]$ iperf3 -c 192.168.1.75 -u -b 10000000
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 44093 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Total Datagrams
[  5]   0.00-1.00   sec  1.19 MBytes  9.97 Mbits/sec  855  
!
! SOME OUTPUT IS TRUNCATED BY BREVITY
!
[  5]   9.00-10.22  sec   870 KBytes  5.85 Mbits/sec  610  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  5]   0.00-10.22  sec  11.6 MBytes  9.50 Mbits/sec  0.000 ms  0/8315 (0%)  sender
[  5]   0.00-10.26  sec  11.5 MBytes  9.39 Mbits/sec  1.057 ms  74/8315 (0.89%)  receiver

iperf Done.
Available from your phone as well

The important point about the UDP is the fact that the packets are sent doesn’t mean they are received (everyone knows UDP joke, right? :-). Therefore, you should check the server side to validate what was received exactly and how big the packet loss is:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.1.66, port 63979
[  6] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 55725
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  6]   0.00-1.00   sec  1.06 MBytes  8.86 Mbits/sec  0.311 ms  0/759 (0%)  
!
! SOME OUTPUT IS TRUNCATED BY BREVITY
!
[  6]  10.00-10.26  sec  0.00 Bytes  0.00 bits/sec  1.057 ms  0/0 (0%)  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  6]   0.00-10.26  sec  11.5 MBytes  9.39 Mbits/sec  1.057 ms  74/8315 (0.89%)  receiver

There are few more things, which you may use depending on your use case:

Now, it is time to take a look on the server side, what you can do differently there.

#3.2. Server tricks

In certain cases, you may have a default port (5201 TCP or UDP) not available for you to test (e.g., it is not allowed in the firewall or access-list somewhere, or you want to simulate the performance test for a specific application to take into account load sharing). That’s not a problem, you need start the server part of iperf with the key “-p X“, where X is the port number to be used by TCP or UDP:


1
2
3
4
iperf3 -s -p 11111
-----------------------------------------------------------
Server listening on 11111
-----------------------------------------------------------

Then, on the customer side you need to specify the port the server is listening to using the same key:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ iperf3 -c 192.168.1.75 -p 11111
Connecting to host 192.168.1.75, port 11111
[  5] local 10.0.2.6 port 49184 connected to 192.168.1.75 port 11111
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.00   sec   449 KBytes  3.68 Mbits/sec   18   4.28 KBytes      
!
! SOME OUTPUT IS TRUNCATED BY BREVITY
!          
[  5]   9.00-10.00  sec   863 KBytes  7.06 Mbits/sec   57   34.2 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  9.63 MBytes  8.08 Mbits/sec  394             sender
[  5]   0.00-10.05  sec  9.42 MBytes  7.86 Mbits/sec                  receiver

iperf Done.

The second useful tweak you can do on the server is to change mode of the operation of the iPerf server side so that it runs as a daemon in background rather than in foreground. That allows you to create a multipurpose monitoring server, where the iperf could be one of the servers it offers. In the same time, you would like to see the tests run against that and the results of the measurements. As such, you need 2 more keys:

Run the following commands on the server side:


1
2
$ iperf3 -s -D --logfile test.txt
$

You are getting the CLI back, so you can carry on with any further job you need to do at this server. Meanwhile, you can run the tests from your client:


1
2
3
4
5
6
7
8
9
10
11
12
13
$ iperf3 -c 192.168.1.75
Connecting to host 192.168.1.75, port 5201
[  5] local 10.0.2.6 port 45670 connected to 192.168.1.75 port 5201
[ ID] Interval           Transfer     Bitrate         Retr  Cwnd
[  5]   0.00-1.01   sec   609 KBytes  4.96 Mbits/sec   16   4.28 KBytes      
!
! SOME OUTPUT IS TRUNCATED BY BREVITY
!      
[  5]   9.00-10.00  sec  1.26 MBytes  10.5 Mbits/sec   38   1.43 KBytes      
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  13.3 MBytes  11.2 Mbits/sec  345             sender
[  5]   0.00-10.04  sec  13.2 MBytes  11.0 Mbits/sec                  receiver

Once the tests are done, you can check on the server side all the details in the log file, which was identified during the launch:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat test.txt
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.1.66, port 49857
[  6] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 49858
[  9] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 49859
[ 11] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 49860
[ 13] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 49861
[ 15] local 192.168.1.75 port 5201 connected to 192.168.1.66 port 49862
[ ID] Interval           Transfer     Bitrate
[  6]   0.00-1.00   sec   401 KBytes  3.28 Mbits/sec
!
! FURTHER OUTPUT IS TRUNCATED

If you decide to switch off the server, you just need to find the corresponding process using the PID and kill it:


1
2
3
4
5
6
$ ps aux | grep 'iperf3'
pi        1529  0.1  0.0   5556  1568 ?        Ss   14:02   0:00 iperf3 -s -D --logfile test.txt
pi        1545  0.0  0.0   7348   548 pts/1    S+   14:12   0:00 grep --color=auto iperf3
$ kill -9 1529
$ ps aux | grep 'iperf3'
pi        1547  0.0  0.0   7348   556 pts/1    S+   14:13   0:00 grep --color=auto iperf3

As said earlier for the client part, you may add the strict authentication on the server side to make sure that only legitimate clients can perform the measurements, what is particularly useful if you do the test over the public network.

#4. Changing the output format

Finally, after we have covered a lot of various testing scenarios you might be interested into, let’s try to figure out, what are the possible outputs. By default we get the information into the human readable format, but what if we want to build any automated pipeline, where the iPerf tests are conducted automatically and their results are published to dashboard or are analysed by network analytics?

The iPerf has a possibility to provide the result in a JSON format. To do that, you need to add key “-J” on the client side:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
$ iperf3 -c 192.168.1.75 -J
{
    "start":    {
        "connected":    [{
                "socket":   5,
                "local_host":   "10.0.2.6",
                "local_port":   49678,
                "remote_host":  "192.168.1.75",
                "remote_port":  5201
            }],
        "version":  "iperf 3.5",
        "system_info":  "Linux nnat.karneliuk.com 4.18.0-240.1.1.el8_3.x86_64 #1 SMP Thu Nov 19 17:20:08 UTC 2020 x86_64",
        "timestamp":    {
            "time": "Sun, 17 Jan 2021 21:51:50 GMT",
            "timesecs": 1610920310
        },
        "connecting_to":    {
            "host": "192.168.1.75",
            "port": 5201
        },
        "cookie":   "zwrypqz36a2qoqnvv7oan5zef2jsfma2bwi3",
        "tcp_mss_default":  1460,
        "sock_bufsize": 0,
        "sndbuf_actual":    16384,
        "rcvbuf_actual":    87380,
        "test_start":   {
            "protocol": "TCP",
            "num_streams":  1,
            "blksize":  131072,
            "omit": 0,
            "duration": 10,
            "bytes":    0,
            "blocks":   0,
            "reverse":  0,
            "tos":  0
        }
    },
    "intervals":    [{
            "streams":  [{
                    "socket":   5,
                    "start":    0,
                    "end":  1.0023031234741211,
                    "seconds":  1.0023031234741211,
                    "bytes":    523328,
                    "bits_per_second":  4177003.8443944808,
                    "retransmits":  27,
                    "snd_cwnd": 5840,
                    "rtt":  697,
                    "rttvar":   122,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    0,
                "end":  1.0023031234741211,
                "seconds":  1.0023031234741211,
                "bytes":    523328,
                "bits_per_second":  4177003.8443944808,
                "retransmits":  27,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    1.0023031234741211,
                    "end":  2.0015499591827393,
                    "seconds":  0.99924683570861816,
                    "bytes":    578160,
                    "bits_per_second":  4628766.2214311361,
                    "retransmits":  39,
                    "snd_cwnd": 4380,
                    "rtt":  695,
                    "rttvar":   117,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    1.0023031234741211,
                "end":  2.0015499591827393,
                "seconds":  0.99924683570861816,
                "bytes":    578160,
                "bits_per_second":  4628766.2214311361,
                "retransmits":  39,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    2.0015499591827393,
                    "end":  3.0012469291687012,
                    "seconds":  0.99969696998596191,
                    "bytes":    1236620,
                    "bits_per_second":  9895958.77252576,
                    "retransmits":  62,
                    "snd_cwnd": 4380,
                    "rtt":  635,
                    "rttvar":   264,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    2.0015499591827393,
                "end":  3.0012469291687012,
                "seconds":  0.99969696998596191,
                "bytes":    1236620,
                "bits_per_second":  9895958.77252576,
                "retransmits":  62,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    3.0012469291687012,
                    "end":  4.0016889572143555,
                    "seconds":  1.0004420280456543,
                    "bytes":    433620,
                    "bits_per_second":  3467427.2998871827,
                    "retransmits":  42,
                    "snd_cwnd": 20440,
                    "rtt":  577,
                    "rttvar":   293,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    3.0012469291687012,
                "end":  4.0016889572143555,
                "seconds":  1.0004420280456543,
                "bytes":    433620,
                "bits_per_second":  3467427.2998871827,
                "retransmits":  42,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    4.0016889572143555,
                    "end":  5.0018069744110107,
                    "seconds":  1.0001180171966553,
                    "bytes":    321200,
                    "bits_per_second":  2569296.7787967911,
                    "retransmits":  27,
                    "snd_cwnd": 18980,
                    "rtt":  375,
                    "rttvar":   126,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    4.0016889572143555,
                "end":  5.0018069744110107,
                "seconds":  1.0001180171966553,
                "bytes":    321200,
                "bits_per_second":  2569296.7787967911,
                "retransmits":  27,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    5.0018069744110107,
                    "end":  6.0002789497375488,
                    "seconds":  0.99847197532653809,
                    "bytes":    562100,
                    "bits_per_second":  4503681.7368152738,
                    "retransmits":  43,
                    "snd_cwnd": 18980,
                    "rtt":  603,
                    "rttvar":   284,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    5.0018069744110107,
                "end":  6.0002789497375488,
                "seconds":  0.99847197532653809,
                "bytes":    562100,
                "bits_per_second":  4503681.7368152738,
                "retransmits":  43,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    6.0002789497375488,
                    "end":  7.0003120899200439,
                    "seconds":  1.0000331401824951,
                    "bytes":    497860,
                    "bits_per_second":  3982748.0110040833,
                    "retransmits":  47,
                    "snd_cwnd": 18980,
                    "rtt":  328,
                    "rttvar":   32,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    6.0002789497375488,
                "end":  7.0003120899200439,
                "seconds":  1.0000331401824951,
                "bytes":    497860,
                "bits_per_second":  3982748.0110040833,
                "retransmits":  47,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    7.0003120899200439,
                    "end":  8.0023720264434814,
                    "seconds":  1.0020599365234375,
                    "bytes":    481800,
                    "bits_per_second":  3846476.5025658207,
                    "retransmits":  37,
                    "snd_cwnd": 20440,
                    "rtt":  401,
                    "rttvar":   113,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    7.0003120899200439,
                "end":  8.0023720264434814,
                "seconds":  1.0020599365234375,
                "bytes":    481800,
                "bits_per_second":  3846476.5025658207,
                "retransmits":  37,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    8.0023720264434814,
                    "end":  9.0017809867858887,
                    "seconds":  0.99940896034240723,
                    "bytes":    562100,
                    "bits_per_second":  4499459.3589188484,
                    "retransmits":  45,
                    "snd_cwnd": 18980,
                    "rtt":  367,
                    "rttvar":   72,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    8.0023720264434814,
                "end":  9.0017809867858887,
                "seconds":  0.99940896034240723,
                "bytes":    562100,
                "bits_per_second":  4499459.3589188484,
                "retransmits":  45,
                "omitted":  false
            }
        }, {
            "streams":  [{
                    "socket":   5,
                    "start":    9.0017809867858887,
                    "end":  10.000101089477539,
                    "seconds":  0.99832010269165039,
                    "bytes":    449680,
                    "bits_per_second":  3603493.4990296755,
                    "retransmits":  35,
                    "snd_cwnd": 20440,
                    "rtt":  512,
                    "rttvar":   324,
                    "pmtu": 1500,
                    "omitted":  false
                }],
            "sum":  {
                "start":    9.0017809867858887,
                "end":  10.000101089477539,
                "seconds":  0.99832010269165039,
                "bytes":    449680,
                "bits_per_second":  3603493.4990296755,
                "retransmits":  35,
                "omitted":  false
            }
        }],
    "end":  {
        "streams":  [{
                "sender":   {
                    "socket":   5,
                    "start":    0,
                    "end":  10.000101089477539,
                    "seconds":  10.000101089477539,
                    "bytes":    5646468,
                    "bits_per_second":  4517128.736581604,
                    "retransmits":  404,
                    "max_snd_cwnd": 20440,
                    "max_rtt":  697,
                    "min_rtt":  328,
                    "mean_rtt": 519
                },
                "receiver": {
                    "socket":   5,
                    "start":    0,
                    "end":  10.016968965530396,
                    "seconds":  10.000101089477539,
                    "bytes":    5488788,
                    "bits_per_second":  4383591.898018321
                }
            }],
        "sum_sent": {
            "start":    0,
            "end":  10.000101089477539,
            "seconds":  10.000101089477539,
            "bytes":    5646468,
            "bits_per_second":  4517128.736581604,
            "retransmits":  404
        },
        "sum_received": {
            "start":    0,
            "end":  10.016968965530396,
            "seconds":  10.016968965530396,
            "bytes":    5488788,
            "bits_per_second":  4383591.898018321
        },
        "cpu_utilization_percent":  {
            "host_total":   0.49001790646860094,
            "host_user":    0.097042513412793963,
            "host_system":  0.39299488733331056,
            "remote_total": 0.019121696299913209,
            "remote_user":  0.00078453336250969687,
            "remote_system":    0.018337280850285832
        },
        "sender_tcp_congestion":    "cubic",
        "receiver_tcp_congestion":  "cubic"
    }
}

The major difference here is in the way, how the results are published:

Despite it may have little impact on short-term tests (e.g., 10 seconds), but it will significantly impact the tool you define if you are measuring the performance for a long period of time (e.g. 5 minutes), as the results for JSON encoding will be available after the test is complete.

Learn more about Asible, Python, JSON for the network configuration and troubleshooting in our Network Automation Training.

#5. Ideas for automation

There are few things, you may want to automate with the respect to the iPerf. For example, you may want to run the iPerf regularly each hour and store the results in the form of the JSON files, which names includes the date and timeframe of the execution? If that sounds interesting to you, look for the example below.

Take me to the examples

Lessons learned

When we have started creation of this blogpost, we were not even aware that it is possible to install the iperf on the mobile phone and run the performance test using it as a client or even as a service. Despite, for sure, it is just another compute node, quite powerful in all honesty, it was still a bit unexpected. On the other hand, it makes test of the WLAN performance super simple, as all you need to test the speed is literally just in your hand.

Conclusion

We hope we have fulfil our promise and gave you some interesting read about testing the network performance with iperf. The current state of the application allows you to test it in quite a mixed environment with various endpoints. Iperf is a good tool, which allows you to quickly get some insights about the status of your network and could serve as benchmarking to establish the baseline of network health and during troubleshooting to validate the performance and check how your network changes impacts the performance. Take care and good bye.

Support us






P.S.

If you have further questions or you need help with your networks, I’m happy to assist you, just send me message. Also don’t forget to share the article on your social media, if you like it.

BR,

Anton Karneliuk

Exit mobile version