aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJörgen Karlsson <jorgen.w.karlsson@ericsson.com>2015-06-04 09:11:46 +0200
committerJörgen Karlsson <jorgen.w.karlsson@ericsson.com>2015-06-09 13:03:20 +0000
commit508e01d81a96c8ede773e6d0dd332892e9600ea7 (patch)
treefae75cc00148d3dbc2f814353b470af4e7cb6bf3
parent662efbb518793a268fb7e82057ccd9b8c197b386 (diff)
add pktgen scenario and sample
Supports measuring network throughput UDP. SLA can be verified for packet lost per million packets (ppm) Change-Id: Ie5972f189bbe58b39a2fae98630b2f117c176ae5 JIRA: YARDSTICK-5 Signed-off-by: Jorgen Karlsson <jorgen.w.karlsson@ericsson.com>
-rw-r--r--samples/pktgen.yaml14
-rw-r--r--yardstick/benchmark/runners/arithmetic.py2
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen.py135
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash158
4 files changed, 305 insertions, 4 deletions
diff --git a/samples/pktgen.yaml b/samples/pktgen.yaml
index a17cffd76..000a7cd92 100644
--- a/samples/pktgen.yaml
+++ b/samples/pktgen.yaml
@@ -17,11 +17,13 @@ scenarios:
runner:
type: Arithmetic
name: number_of_ports
- stop: 100
+ # run twice with values 10 and 20
+ stop: 20
step: 10
sla:
- max_ppm: 1
+ max_ppm: 1000
+ action: monitor
context:
name: demo
@@ -29,15 +31,21 @@ context:
flavor: yardstick-flavor
user: ec2-user
+ placement_groups:
+ pgrp1:
+ policy: "availability"
+
servers:
client:
- instances: 1
floating_ip: true
+ placement: "pgrp1"
server:
floating_ip: true
+ placement: "pgrp1"
networks:
test:
cidr: '10.0.1.0/24'
external_network: "net04_ext"
+
diff --git a/yardstick/benchmark/runners/arithmetic.py b/yardstick/benchmark/runners/arithmetic.py
index a3aceb35d..acf14d08a 100644
--- a/yardstick/benchmark/runners/arithmetic.py
+++ b/yardstick/benchmark/runners/arithmetic.py
@@ -49,7 +49,7 @@ def _worker_process(queue, cls, method_name, context, scenario_args):
if "sla" in scenario_args:
sla_action = scenario_args["sla"].get("action", "assert")
- for value in range(start, stop, step):
+ for value in range(start, stop+step, step):
options[arg_name] = value
diff --git a/yardstick/benchmark/scenarios/networking/pktgen.py b/yardstick/benchmark/scenarios/networking/pktgen.py
new file mode 100644
index 000000000..8038cad60
--- /dev/null
+++ b/yardstick/benchmark/scenarios/networking/pktgen.py
@@ -0,0 +1,135 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import pkg_resources
+import logging
+import json
+
+import yardstick.ssh as ssh
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+LOG.setLevel(logging.DEBUG)
+
+
+class Pktgen(base.Scenario):
+ """Executes a pktgen benchmark between two hosts"""
+ __scenario_type__ = "Pktgen"
+
+ TARGET_SCRIPT = 'pktgen_benchmark.bash'
+
+ def __init__(self, context):
+ self.context = context
+ self.setup_done = False
+
+ def setup(self):
+ '''scenario setup'''
+ self.target_script = pkg_resources.resource_filename(
+ 'yardstick.benchmark.scenarios.networking',
+ Pktgen.TARGET_SCRIPT)
+ user = self.context.get('user', 'ubuntu')
+ host = self.context.get('host', None)
+ target = self.context.get('target', None)
+ key_filename = self.context.get('key_filename', '~/.ssh/id_rsa')
+
+ LOG.debug("user:%s, target:%s", user, target)
+ self.server = ssh.SSH(user, target, key_filename=key_filename)
+ self.server.wait(timeout=600)
+
+ LOG.debug("user:%s, host:%s", user, host)
+ self.client = ssh.SSH(user, host, key_filename=key_filename)
+ self.client.wait(timeout=600)
+
+ # copy script to host
+ self.client.run("cat > ~/pktgen.sh",
+ stdin=open(self.target_script, "rb"))
+
+ self.setup_done = True
+
+ def _iptables_setup(self):
+ """Setup iptables on server to monitor for received packets"""
+ cmd = "sudo iptables -F; " \
+ "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP" \
+ % (1000 + self.number_of_ports)
+ LOG.debug("Executing command: %s", cmd)
+ status, _, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _iptables_get_result(self):
+ """Get packet statistics from server"""
+ cmd = "sudo iptables -L INPUT -vnx |" \
+ "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'" \
+ % (1000 + self.number_of_ports)
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def run(self, args):
+ """execute the benchmark"""
+
+ if not self.setup_done:
+ self.setup()
+
+ ipaddr = args.get("ipaddr", '127.0.0.1')
+
+ options = args['options']
+ packetsize = options.get("packetsize", 60)
+ self.number_of_ports = options.get("number_of_ports", 10)
+
+ self._iptables_setup()
+
+ cmd = "sudo bash pktgen.sh %s %s %s" \
+ % (ipaddr, self.number_of_ports, packetsize)
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+
+ if status:
+ raise RuntimeError(stderr)
+
+ data = json.loads(stdout)
+
+ data['packets_received'] = self._iptables_get_result()
+
+ if "sla" in args:
+ sent = data['packets_sent']
+ received = data['packets_received']
+ ppm = 1000000 * (sent - received) / sent
+ sla_max_ppm = int(args["sla"]["max_ppm"])
+ assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d" \
+ % (ppm, sla_max_ppm)
+
+ return data
+
+
+def _test():
+ '''internal test function'''
+ key_filename = pkg_resources.resource_filename('yardstick.resources',
+ 'files/yardstick_key')
+ ctx = {'host': '172.16.0.137',
+ 'target': '172.16.0.138',
+ 'user': 'ubuntu',
+ 'key_filename': key_filename
+ }
+
+ logger = logging.getLogger('yardstick')
+ logger.setLevel(logging.DEBUG)
+
+ p = Pktgen(ctx)
+
+ options = {'packetsize': 120}
+
+ args = {'options': options,
+ 'ipaddr': '192.168.111.31'}
+ result = p.run(args)
+ print result
+
+if __name__ == '__main__':
+ _test()
diff --git a/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
new file mode 100644
index 000000000..f5df50f0f
--- /dev/null
+++ b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
@@ -0,0 +1,158 @@
+#!/bin/sh
+
+##############################################################################
+# Copyright (c) 2015 Ericsson AB and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+set -e
+
+# Commandline arguments
+DST_IP=$1 # destination IP address
+shift
+NUM_PORTS=$1 # number of source ports
+shift
+PKT_SIZE=$1 # packet size
+
+# Configuration
+UDP_SRC_MIN=1000 # UDP source port min
+UDP_SRC_MAX=$(( UDP_SRC_MIN + NUM_PORTS - 1 )) # UDP source port max
+UDP_DST_MIN=1000 # UDP destination port min
+UDP_DST_MAX=$(( UDP_DST_MIN + NUM_PORTS )) # UDP destination port max
+DURATION=20 # test duration (seconds)
+
+# helper function to send commands to pktgen
+pgset()
+{
+ local result
+
+ echo $1 > $PGDEV
+
+ result=$(cat $PGDEV | fgrep "Result: OK:")
+ if [ "$result" = "" ]; then
+ cat $PGDEV | fgrep "Result:" >/dev/stderr
+ exit 1
+ fi
+}
+
+# configure pktgen (see pktgen doc for details)
+pgconfig()
+{
+ #
+ # Thread commands
+ #
+
+ PGDEV=/proc/net/pktgen/kpktgend_0
+
+ # Remove all devices from this thread
+ pgset "rem_device_all"
+
+ # Add device to thread
+ pgset "add_device $DEV"
+
+ #
+ # Device commands
+ #
+
+ PGDEV=/proc/net/pktgen/$DEV
+
+ # 0 means continious sends untill explicitly stopped
+ pgset "count 0"
+
+ # use single SKB for all transmits
+ pgset "clone_skb 0"
+
+ # packet size, NIC adds 4 bytes CRC
+ pgset "pkt_size $PKT_SIZE"
+
+ # random address within the min-max range
+ pgset "flag IPDST_RND UDPSRC_RND UDPDST_RND"
+
+ # destination IP
+ pgset "dst_min $DST_IP"
+ pgset "dst_max $DST_IP"
+
+ # destination MAC address
+ pgset "dst_mac $MAC"
+
+ # source UDP port range
+ pgset "udp_src_min $UDP_SRC_MIN"
+ pgset "udp_src_max $UDP_SRC_MAX"
+
+ # destination UDP port range
+ pgset "udp_dst_min $UDP_DST_MIN"
+ pgset "udp_dst_max $UDP_DST_MAX"
+}
+
+# run pktgen
+pgrun()
+{
+ # Time to run, result can be vieved in /proc/net/pktgen/$DEV
+ PGDEV=/proc/net/pktgen/pgctrl
+ # Will hang, Ctrl-C or SIGINT to stop
+ pgset "start" start
+}
+
+# run pktgen for ${DURATION} seconds
+run_test()
+{
+ pgrun &
+ pid=$!
+
+ sleep $DURATION
+
+ kill -INT $pid
+
+ wait; sleep 1
+}
+
+# write the result to stdout in json format
+output_json()
+{
+ sent=$(awk '/^Result:/{print $5}' <$PGDEV)
+ pps=$(awk 'match($0,/'\([0-9]+\)pps'/, a) {print a[1]}' <$PGDEV)
+ errors=$(awk '/errors:/{print $5}' <$PGDEV)
+
+ flows=$(( NUM_PORTS * (NUM_PORTS + 1) ))
+
+ echo { '"packets_sent"':$sent , '"packets_per_second"':$pps, '"flows"':$flows, '"errors"':$errors }
+}
+
+# main entry
+main()
+{
+ modprobe pktgen
+
+ ping -c 3 $DST_IP >/dev/null
+
+ # destination MAC address
+ MAC=`arp -n | grep -w $DST_IP | awk '{print $3}'`
+
+ # outgoing interface
+ DEV=`arp -n | grep -w $DST_IP | awk '{print $5}'`
+
+ # setup the test
+ pgconfig
+
+ # run the test
+ run_test >/dev/null
+
+ PGDEV=/proc/net/pktgen/$DEV
+
+ # check result
+ result=$(cat $PGDEV | fgrep "Result: OK:")
+ if [ "$result" = "" ]; then
+ cat $PGDEV | fgrep Result: >/dev/stderr
+ exit 1
+ fi
+
+ # output result
+ output_json
+}
+
+main
+