Building a test setup for load testing with Tsung

Multiple IPs for using different sources and destinations for web requests

Posted by Emre Bastuz on August 4, 2015

Overview

From time to time it is necessary to create multiple network sessions in a testing environment, to see how a component handles those sessions.

The following description will show a testing setup to create multiple TCP sessions by using a combination of techniques:

  • Tsung as a load generator to create many many TCP sessions
  • Apache 2 as a webserver to answer every request that arrives
  • The Linux operating system with the "ip" command to add whole network ranges with hundreds or thousands of IPs to a system, without using subinterfaces,
  • SNMP to query involved components for their status

What is somewhat special about this setup is the configuration of the network part: While one might assume that it is necessary to spawn many many agent nodes to make request or add tons of subinterfaces to a system to have the capability of receiving requests and creating requests with many different IPs, I found using the "ip" command to put a network segment on the loopback interface quite straight forward.

The Components

For this setup Debian Linux is used. The software compoents should be available in any other decent distro.

All instructions below will show how to create the testbed with virtualization techology.

Prerequisites

Created two host-only networks in the virtualization technology of your choice, one being "receiver" and the other being "sender".

The following IP addresses will be used tor the environment:

  • 10.0.0.0/24 - source IPs for requests
  • 10.0.1.0/24 - destination addresses for requests
  • 172.16.66.0/30 - transfer link router-to-sender
  • 172.16.77.0/30 - transfer link router-to-receiver

Modify your file /etc/apt/sources.list to contain "contrib" and "non-free":

deb http://ftp.de.debian.org/debian/ jessie main contrib non-free
deb http://security.debian.org/ jessie/updates main contrib non-free
deb http://ftp.de.debian.org/debian/ jessie-updates main contrib non-free

Do an apt-get update after modifying the sources file.

Further more, every machine should have a network interface for Internet connectivity - a NAT/bridged interface for instance.

The result will look like in the picture below: Overall setup

To continue, let's create the three virtual machines with the details as described in the following section.

System 1: The Traffic Receiver

Minimal system for Debian (1 CPU, 512 Megabytes of RAM) Two network interfaces Bridged (to "the Internet" on eth0) and "receiver" (on eth1).

Assuming that the bridged network is providing IP addresses via DHCP, the config file /etc/network/interfaces might look as follows:

# The loopback network interface
auto lo
iface lo inet loopback
  post-up /sbin/ip addr add dev lo 10.0.1.0/24 scope host

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
  address 172.16.77.2
  netmask 255.255.255.252
  post-up /sbin/route add -net 10.0.0.0/24 gw 172.16.66.1

Tweaking the system with some sysctl settings is also recommended:

# cat /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
fs.file-max = 65000

After a reboot, the network configuration and the sysctl settings should be active, the network config looking like as follows:

# ifconfig -a
...
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet 10.0.1.0/24 scope host lo
...       
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:fe:5c:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.16.77.2/30 brd 172.16.77.3 scope global eth1

Install the following additional software packages: apt-get -y install apache2 curl snmpd snmp snmp-mibs-downloader.

Once Apache 2 is installed, modify the logging of the default virtual host as follows (/etc/apache2/sites-enabled/000-default.conf):

#CustomLog ${APACHE_LOG_DIR}/access.log combined
LogFormat "%h %l %u %t \"%r\" %>s %b - TSUNG: src: %a - dst: %A" TSUNG
CustomLog ${APACHE_LOG_DIR}/access.log TSUNG

Restart Apache 2 to make the changes take effect with service apache2 restart.

Once Apache is restarted, a test can be make to see the logging in action:

# curl --interface 10.0.1.22 --silent http://localhost/ > /dev/null
...
# tail /var/log/apache2/access.log
10.0.1.22 - - [04/Aug/2015:00:58:17 +0200] "GET / HTTP/1.1" 200 11104 - TSUNG: src: 10.0.1.22 - dst: 127.0.0.1

Modify the snmpd to listen on the system IP. In file /etc/snmp/snmpd.conf:

#agentAddress  udp:127.0.0.1:161
agentAddress  udp:0.0.0.0:161

Modify the snmp config /etc/snmp/snmp.conf:

#mibs :

After restarting the snmpd with service restart snmpd, verify that the monitoring works as expected:

# snmpwalk -v2c -c public 172.16.66.2 SNMPv2-MIB::sysContact.0
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>

System 2: The Traffic Router

Minimal system for Debian (1 CPU, 512 Megabytes of RAM) Three network interfaces Bridged to "the Internet" on eth0, "receiver" on eth1 and "sender" on eth2.

Assuming that the bridged network is providing IP addresses via DHCP, create the following entries in /etc/network/interfaces:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
  address 172.16.77.1
  netmask 255.255.255.252
  post-up /sbin/route add -net 10.0.0.0/24 gw 172.16.77.1

auto eth2
iface eth2 inet static
  address 172.16.66.1
  netmask 255.255.255.252
  post-up /sbin/route add -net 10.0.0.0/24 gw 172.16.66.1

After a reboot verify the the interface configuration and routing configuration is OK.

Interfaces:

# ifconfig -a
eth0      Link encap:Ethernet  Hardware Adresse 00:0c:29:0d:bf:f4  
          inet Adresse:<some-ip>  

eth1      Link encap:Ethernet  Hardware Adresse 00:0c:29:0d:bf:fe  
          inet Adresse:172.16.77.1  Bcast:172.16.77.3  Maske:255.255.255.252

eth2      Link encap:Ethernet  Hardware Adresse 00:0c:29:0d:bf:08  
          inet Adresse:172.16.66.1  Bcast:172.16.66.3  Maske:255.255.255.252

Routing:

# netstat -ran
Kernel-IP-Routentabelle
Ziel            Router          Genmask         Flags   MSS Fenster irtt Iface
0.0.0.0         <some-other-ip> 0.0.0.0         UG        0 0          0 eth0
10.0.0.0        172.16.66.1     255.255.255.0   UG        0 0          0 eth2
10.0.1.0        172.16.77.1     255.255.255.0   UG        0 0          0 eth1

Install the following additional software packages: apt-get -y install tsung snmp snmpd snmp-mibs-downloader.

Modify the snmpd to listen on the system IP. In file /etc/snmp/snmpd.conf:

#agentAddress  udp:127.0.0.1:161
agentAddress  udp:0.0.0.0:161

Modify the snmp config /etc/snmp/snmp.conf:

#mibs :

After restarting the snmpd with service restart snmpd, verify that the monitoring works as expected:

# snmpwalk -v2c -c public 172.16.66.1 SNMPv2-MIB::sysContact.0
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>

System 3: The Traffic Sender

Minimal system for Debian (1 CPU, 512 Megabytes of RAM) Two network interfaces Bridged (to "the Internet" on eth0) and "sender" (on eth1).

Assuming that the bridged network is providing IP addresses via DHCP, the config file /etc/network/interfaces might look as follows:

# The loopback network interface
auto lo
iface lo inet loopback
  post-up /sbin/ip addr add dev lo 10.0.0.0/24 scope host

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
  address 172.16.66.2
  netmask 255.255.255.252
  post-up /sbin/route add -net 10.0.1.0/24 gw 172.16.66.1

Tweaking the system with some sysctl settings is also recommended:

# cat /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
fs.file-max = 65000

After a reboot, the network configuration and the sysctl settings should be active, the network config looking like as follows:

# ifconfig -a
...
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet 10.0.0.0/24 scope host lo
...       
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:aa:bb:c6 brd ff:ff:ff:ff:ff:ff
    inet 172.16.66.2/30 brd 172.16.77.3 scope global eth1

Install the following additional software packages: apt-get -y install tsung snmp snmpd snmp-mibs-downloader.

Modify the snmpd to listen on the system IP. In file /etc/snmp/snmpd.conf:

#agentAddress  udp:127.0.0.1:161
agentAddress  udp:0.0.0.0:161

Modify the snmp config /etc/snmp/snmp.conf:

#mibs :

After restarting the snmpd with service restart snmpd, verify that the monitoring works as expected:

# snmpwalk -v2c -c public 172.16.77.2 SNMPv2-MIB::sysContact.0
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>

Now it's time to configure Tsung.

Create a subdirectory in your user's home folder with mkdir ~/.tsung.

Create the tsung config file with the following content as ~/.tsung/tsung.xml:

<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
 
<clients>
  <client host="localhost" use_controller_vm="true">
    <ip value="10.0.0.1"></ip>
    <ip value="10.0.0.2"></ip>
    <ip value="10.0.0.3"></ip>
    <ip value="10.0.0.4"></ip>
    <ip value="10.0.0.5"></ip>
    <ip value="10.0.0.6"></ip>
    <ip value="10.0.0.7"></ip>
    <ip value="10.0.0.8"></ip>
    <ip value="10.0.0.9"></ip>
  </client>
</clients>
 
<servers>
  <server host="10.0.1.1" port="80" type="tcp"></server>
  <server host="10.0.1.2" port="80" type="tcp"></server>
  <server host="10.0.1.3" port="80" type="tcp"></server>
  <server host="10.0.1.4" port="80" type="tcp"></server>
  <server host="10.0.1.5" port="80" type="tcp"></server>
  <server host="10.0.1.6" port="80" type="tcp"></server>
  <server host="10.0.1.7" port="80" type="tcp"></server>
  <server host="10.0.1.8" port="80" type="tcp"></server>
  <server host="10.0.1.9" port="80" type="tcp"></server>
</servers>
 
<monitoring>
  <monitor host="172.16.66.1" type="snmp">
    <snmp version="v2" community="public" port="161">
      <oid value="1.3.6.1.2.1.2.2.1.10.0" name="ifInOctets" type="counter"/>
      <oid value="1.3.6.1.2.1.2.2.1.14.0" name="ifInErrors" type="counter"/>
    </snmp>
  </monitor>
</monitoring>
 
<load>
  <arrivalphase phase="1" duration="10" unit="second">
    <users arrivalrate="1" unit="second"></users>
  </arrivalphase>

  <arrivalphase phase="2" duration="10" unit="second">
    <users arrivalrate="10" unit="second"></users>
  </arrivalphase>

  <arrivalphase phase="3" duration="10" unit="second">
    <users arrivalrate="20" unit="second"></users>
  </arrivalphase>

 </load>
 
<sessions>
  <session name="http-example" probability="100" type="ts_http">
    <request> <http url="/" method="GET" version="1.0"></http> </request>
    <thinktime min="1" max="3" random="true"></thinktime>
  </session>
</sessions>
</tsung>

Fire up tsung with tsung start.