Auteur Sujet: How does IPerf3 exactly work - I can't reproduce the results  (Lu 8925 fois)

0 Membres et 1 Invité sur ce sujet

0x2a

  • Abonné FAI autre
  • *
  • Messages: 2
  • Wien (AT-1030)
Hi,

sorry for writing in English but I'm not capable of speaking or writing French. Hopefully someone will answer me ... :(

I've an unconventional problem with IPerf3: I measured my 1000BASE-T network and got a result with around 55,625 MByte/s (using "iperf3 -c 10.0.0.2 -l xxx" and different sizes for xxx from 256 Byte up to 1MB). Then I wrote an echo server in C and a client measuring the transfer time and calculating the MByte/s. But I only get around 20 MByte/s every time I run it. I've attached the source code - it's pretty straight forward. I thought that I take a look into the source code to find the difference. But this is a little bit like looking for a needle in a haystack. So my last idea was to ask here for help, hoping that somebody knows whats going on.

Could you help me?

Regards!

kgersen

  • Modérateur
  • Abonné Bbox fibre
  • *
  • Messages: 9 078
  • Paris (75)
How does IPerf3 exactly work - I can't reproduce the results
« Réponse #1 le: 15 mars 2016 à 18:50:32 »
you're doing an echo (both way traffic) for too short periods. Iperf3 is doing a one way, single tcp stream over 10 seconds. that's not the same thing.

try coding just sending data from client to server for 10 seconds.

For instance, I've an old code here:

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <arpa/inet.h>
#include <stdio.h>

#define PORT 8192
#define TIMEOUT 10

int client;
void sendReply();
void closeConnection();

int main()
{
signal(SIGCHLD, SIG_IGN);

//

struct sockaddr_in6 serverInfo;
memset(&serverInfo, 0, sizeof serverInfo);

serverInfo.sin6_family = AF_INET6;
serverInfo.sin6_addr = in6addr_any;
serverInfo.sin6_port = htons(PORT);

// socket creation

int server = socket(AF_INET6, SOCK_STREAM, 0);

int yes = 1;
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);

bind(server, (struct sockaddr *) &serverInfo, sizeof serverInfo);
listen(server, 20);
printf("listening on port %d\n",PORT);
    char clientip[INET6_ADDRSTRLEN];
   
for(;;)
{
struct sockaddr_in6 clientInfo;
int clientInfoSize = sizeof clientInfo;
client = accept(server, (struct sockaddr *) &clientInfo, &clientInfoSize);
       
        inet_ntop(clientInfo.sin6_family, &clientInfo.sin6_addr, clientip, sizeof(clientip));
printf("incoming request from %s\n",clientip);

 
if (fork() == 0)
{
sendReply(client);
}
}

return 0;
}

void sendReply()
{
// stop after TIMEOUT seconds

signal(SIGALRM, closeConnection);
alarm(TIMEOUT);

// send HTTP headers

char headers[] =
"HTTP/1.1 200 OK\r\n"
"Content-Type: octet-stream\r\n"
"Cache-Control: no-cache, no-transform\r\n"
"\r\n";

ssize_t rc = write(client, headers, strlen(headers));

// send random data

#define BUFFSIZE (4096)
char buffer[BUFFSIZE];
memset(&buffer, 0, sizeof buffer);
srand(time(NULL));

// Get buffer size
int sendbuff;
socklen_t optlen = sizeof(sendbuff);
  int res = getsockopt(client, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);
if(res == -1)
printf("Error getsockopt one");
else
printf("send buffer size = %d\n", sendbuff);
     
for(;;)
{
    //  uncomment to send random data, cpu might affect performance
// int i;
// for(i = 0; i < BUFFSIZE; i++)
// {
// buffer[i] = rand() & 255;
// }

if(write(client, buffer, sizeof buffer) < 0)
{
closeConnection();
}
}
}

void closeConnection()
{

shutdown(client, 2);
//close(client);
exit(0);
}

this is a small http server that will send data during 10 seconds then stop.

on the client do:

wget -o /dev/null http://ip_of_server:8192or use curl

this should yield results similar to iperf3.

0x2a

  • Abonné FAI autre
  • *
  • Messages: 2
  • Wien (AT-1030)
How does IPerf3 exactly work - I can't reproduce the results
« Réponse #2 le: 16 mars 2016 à 17:06:39 »
Thank you for your reply, kgersen!

try coding just sending data from client to server for 10 seconds.
And who measures then the time to calculate the MB/s from? The sending node or the receiving node?

For instance, I've an old code here:

wget -o /dev/null http://ip_of_server:8192or use curl

this should yield results similar to iperf3.

I tested it and came to 29.4 MB/s for a send buffer size of 21480 bytes. Directly after that I re-run iperf with the same buffer size and got 42.5 MB/s. So there seems to be a gap of 13-odd MB/s.

you're doing an echo (both way traffic) for too short periods. Iperf3 is doing a one way, single tcp stream over 10 seconds. that's not the same thing.
If I do an echo over 10 seconds I only get 11.8 MB/s for a buffer size of 21480 bytes.

Regards!

kgersen

  • Modérateur
  • Abonné Bbox fibre
  • *
  • Messages: 9 078
  • Paris (75)
How does IPerf3 exactly work - I can't reproduce the results
« Réponse #3 le: 16 mars 2016 à 19:21:52 »
Thank you for your reply, kgersen!
And who measures then the time to calculate the MB/s from? The sending node or the receiving node?

in that case, it's  the receiving node (wget).

I tested it and came to 29.4 MB/s for a send buffer size of 21480 bytes. Directly after that I re-run iperf with the same buffer size and got 42.5 MB/s. So there seems to be a gap of 13-odd MB/s.
If I do an echo over 10 seconds I only get 11.8 MB/s for a buffer size of 21480 bytes.

is there any latency between the client and the server ?

Max throughput can be affected by latency and cpu limitation.

It's frequent that a lot of older PC or other 'small' devices that have a gigabit Ethernet interface cannot achieve gigabit speed because of some limitation elsewhere (most of the time it's the CPU).

Be aware too that IPerf3 doesn't work the expected way: by default it's the client that send data to the server.

"iperf3 -c ip_of_server" will send data to ip_of_server for 10 seconds.

add -R to reverse the test:

"iperf3 -R -c ip_of_server" will receive data from ip_of_server for 10 seconds.

corrector

  • Invité
How does IPerf3 exactly work - I can't reproduce the results
« Réponse #4 le: 27 mars 2016 à 01:31:54 »
Your code is wrong.