RTT, latencies and jitter

Task for week 48

In this exercise the task is to use code from the previous exercises and to measure RTT, latency and jitter with UDP, TCP and SCTP connections with various packet sizes. The measurements are collected to text files and plotted with gnuplot.

In some cases RTT = latency, but here we treat the RTT as it is defined, Round Trip Time - i.e. the time it takes for the packet to traverse from the source to destination and then back to the source. Latency is the one way trip time, i.e., approx. half of the RTT. Jitter is the variation of latency from one packet to the next.

Use a variable packet sizes, start with n=4 bytes and each round increment it with 2 (n+2) up to 1024 bytes (4,6,8,10,…,1020,1022,1024). Send each packet 10 times (from client to server) and calculate the averages (RTT, latency and jitter). Use a random payload for each packet.

A small hint, use a script to start clients (use chmod +x script_name to allow executing), such as:

#!/bin/bash
# Client executable name (remember, with scripts comment line starts with #)
CLIENTNAME="udpclient"
# Result file
RESFILE="udp"
# Server address
SERVER="lut1825.pc.lut.fi" 
# Server port
PORT="5656"
# Start with 4 bytes
BYTES=4
# Maximum length for packets
BYTES_MAX=1024
# How many times the measurement is done (can be hardcoded in your client)
COUNT=10
 
# Remove old results file
if [ -f "$RESFILE.dat" ] ; then rm "$RESFILE.dat" ; fi
 
# While $BYTES is less or equal to $BYTES_MAX
while [ $BYTES -le $BYTES_MAX ] ; do 
  ./$CLIENTNAME -b $BYTES -c $COUNT -h $SERVER -p $PORT >> "$RESFILE.dat"
  # On each round, increment by 2
  BYTES=$((BYTES+2))
done

It is expected here that:

  • The client is run with 4 parameters:
    • byte count (switch -b)
    • rounds (switch -c)
    • server address (switch -h)
    • server port (switch -p)
  • The client outputs only the byte count, rtt, latency and jitter, separated with spaces, e.g.,
    128 0.010 0.005 0.020

The measurements are required to be done in one way only, e.g., a client establishes connection to the server and after a small negotiation of the parameters (e.g. packet payload size, count, is nagle enabled, etc.), the client starts to send the packets which server echoes back and the client calculates the time difference. Jitter can be calculated from the differences between latencies.

1. UDP

Use a stop'n'wait approach (send-ack-send-ack) and sequence numbers in the packets to avoid data loss. Since packet boundaries are guaranteed length does not need to be sent, only BYTECOUNT-sizeof(seq_number_variable_type.

Save results to udp.dat

2. TCP

Measure with and without Nagle. This has to be reported to the server when initializing.

Use here a suitable payload variable and BYTECOUNT-sizeof(length_variable_type) amount of payload for each packet.

Save results to:

  • With Nagle: tcp_nagle.dat
  • Without Nagle: tcp.dat

An example how to disable/enable Nagle (remember to do this on both ends):

#include <netinet/in.h>
#include <netinet/tcp.h>
 
// Toggle nagle on given socket sock using value (0=NODELAY off,1=NODELAY on)
int toggle_nagle(int sock, int value) {
 
	int result = 0;		// Return value of setsockopt() function
 
        // Use setsockopt() function to toggle nagle.
	if ((value == 1)||(value == 0)) result = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
 
        // Return 1 in case value was invalid
        else result = 1;
 
	// Check, if there was an error. (setsockopt() returns 0 when successful, -1 when errors)
	if (result == -1) perror("Error! setsockopt (TCP_NODELAY)");
 
	return result;
}

3. SCTP

Since packet boundaries are guaranteed only the payload has to be sent. Use ordered data delivery - no sequence numbers are required.

Save results to sctp.dat

Timing functions

For timing you can use, e.g., gettimeofday() (microsecond resolution) or clock_gettime() (realtime use, nanosecond resolution). See following timer example , build it with make or make debug to see more details. The example uses both gettimeofday() and clock_gettime() functions. The example sleeps for 100ms (with usleep()) and shows the time in milliseconds and in microseconds. Run it with ./timer.

Plotting with gnuplot

Use e.g. gnuplot to plot diagrams from the results, if you decide to use some other feel free to do it. Instructions are given for gnuplot only.

  • For gnuplot you should use following format (note that this is just an example file):
    128 0.128 0.064 0.010
    256 0.256 0.128 0.020
    512 0.512 0.256 0.030
    • where one line is <packet size> <RTT in ms> <latency in ms> <jitter in ms>

Plotting:

  • THE EASY WAY: use the ready plotfile,
    • Download to the directory your code is and extract
      tar xzf plotfile.tar.gz
    • Your *.dat-files must be named as mentioned earlier (or otherwise you'll have to modify the plotfile by hand)
      • It is expected that the files follow the format defined earlier
    • To plot all diagrams, first start gnuplot and type
      load "plotfile"

      in gnuplot.


  • Or manually:
    • Run gnuplot with:
      gnuplot
    • To plot a content of udp.dat file with lines using 1st column as X-axis and 2nd column as Y-axis with title “UDP RTT”, type in gnuplot:
      plot "udp.dat" using 1:2 with lines title "UDP RTT"
      • which opens a new graphical window with the diagram
    • To plot multiple files, type in gnuplot'':
      plot "udp.dat" using 1:2 with lines, \
      "tcp_nagle.dat" using 1:2 with lines, \
      "tcp.dat" using 1:2 with lines
    • To set some basic things in gnuplot:
      • Labels:
        set xlabel "Packet size"
        set ylabel "time (ms)"
      • Range:
        set xrange [0:128]
        set yrange [0:1.5]
      • Tic intervals:
        set xtics 32
        set ytics 0.01
      • Apply changes made to parameters:
        replot

Task for next week (week 49): Server-client connection design #1