aboutsummaryrefslogtreecommitdiffstats
path: root/docs/userguide
diff options
context:
space:
mode:
Diffstat (limited to 'docs/userguide')
-rw-r--r--docs/userguide/index.rst1
-rwxr-xr-xdocs/userguide/integration.rst573
-rw-r--r--docs/userguide/teststeps.rst651
3 files changed, 652 insertions, 573 deletions
diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst
index 1a796dbf..a1cce262 100644
--- a/docs/userguide/index.rst
+++ b/docs/userguide/index.rst
@@ -11,5 +11,6 @@ VSPERF User Guide
:maxdepth: 3
testusage.rst
+ teststeps.rst
integration.rst
yardstick.rst
diff --git a/docs/userguide/integration.rst b/docs/userguide/integration.rst
index 20d6b70c..5b26a716 100755
--- a/docs/userguide/integration.rst
+++ b/docs/userguide/integration.rst
@@ -33,579 +33,6 @@ view the current test list simply execute the following command:
The standard tests included are defined inside the
``conf/integration/01_testcases.conf`` file.
-Test Steps
-----------
-
-Execution of integration tests are done on a step by step work flow starting
-with step 0 as defined inside the test case. Each step of the test increments
-the step number by one which is indicated in the log.
-
-.. code-block:: console
-
- (testcases.integration) - Step 1 - 'vswitch add_switch ['int_br1']' ... OK
-
-Each step in the test case is validated. If a step does not pass validation the
-test will fail and terminate. The test will continue until a failure is detected
-or all steps pass. A csv report file is generated after a test completes with an
-OK or FAIL result.
-
-Test objects and their functions
---------------------------------
-
-Every test step can call a function of one of the supported test objects. The list
-of supported objects and their most common functions follows:
-
- * ``vswitch`` - provides functions for vSwitch configuration
-
- List of supported functions:
-
- * ``add_switch br_name`` - creates a new switch (bridge) with given ``br_name``
- * ``del_switch br_name`` - deletes switch (bridge) with given ``br_name``
- * ``add_phy_port br_name`` - adds a physical port into bridge specified by ``br_name``
- * ``add_vport br_name`` - adds a virtual port into bridge specified by ``br_name``
- * ``del_port br_name port_name`` - removes physical or virtual port specified by
- ``port_name`` from bridge ``br_name``
- * ``add_flow br_name flow`` - adds flow specified by ``flow`` dictionary into
- the bridge ``br_name``; Content of flow dictionary will be passed to the vSwitch.
- In case of Open vSwitch it will be passed to the ``ovs-ofctl add-flow`` command.
- Please see Open vSwitch documentation for the list of supported flow parameters.
- * ``del_flow br_name [flow]`` - deletes flow specified by ``flow`` dictionary from
- bridge ``br_name``; In case that optional parameter ``flow`` is not specified
- or set to an empty dictionary ``{}``, then all flows from bridge ``br_name``
- will be deleted.
- * ``dump_flows br_name`` - dumps all flows from bridge specified by ``br_name``
- * ``enable_stp br_name`` - enables Spanning Tree Protocol for bridge ``br_name``
- * ``disable_stp br_name`` - disables Spanning Tree Protocol for bridge ``br_name``
- * ``enable_rstp br_name`` - enables Rapid Spanning Tree Protocol for bridge ``br_name``
- * ``disable_rstp br_name`` - disables Rapid Spanning Tree Protocol for bridge ``br_name``
-
- Examples:
-
- .. code-block:: python
-
- ['vswitch', 'add_switch', 'int_br0']
-
- ['vswitch', 'del_switch', 'int_br0']
-
- ['vswitch', 'add_phy_port', 'int_br0']
-
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]']
-
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '1', 'actions': ['output:2'],
- 'idle_timeout': '0'}],
-
- ['vswitch', 'enable_rstp', 'int_br0']
-
- * ``vnf[ID]`` - provides functions for deployment and termination of VNFs; Optional
- alfanumerical ``ID`` is used for VNF identification in case that testcase
- deploys multiple VNFs.
-
- List of supported functions:
-
- * ``start`` - starts a VNF based on VSPERF configuration
- * ``stop`` - gracefully terminates given VNF
-
- Examples:
-
- .. code-block:: python
-
- ['vnf1', 'start']
- ['vnf2', 'start']
- ['vnf2', 'stop']
- ['vnf1', 'stop']
-
- * ``trafficgen`` - triggers traffic generation
-
- List of supported functions:
-
- * ``send_traffic traffic`` - starts a traffic based on the vsperf configuration
- and given ``traffic`` dictionary. More details about ``traffic`` dictionary
- and its possible values are available at `Traffic Generator Integration Guide
- <http://artifacts.opnfv.org/vswitchperf/docs/design/trafficgen_integration_guide.html#step-5-supported-traffic-types>`__
-
- Examples:
-
- .. code-block:: python
-
- ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput'}]
-
- ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}]
-
- * ``settings`` - reads or modifies VSPERF configuration
-
- List of supported functions:
-
- * ``getValue param`` - returns value of given ``param``
- * ``setValue param value`` - sets value of ``param`` to given ``value``
-
- Examples:
-
- .. code-block:: python
-
- ['settings', 'getValue', 'TOOLS']
-
- ['settings', 'setValue', 'GUEST_USERNAME', ['root']]
-
- * ``namespace`` - creates or modifies network namespaces
-
- List of supported functions:
-
- * ``create_namespace name`` - creates new namespace with given ``name``
- * ``delete_namespace name`` - deletes namespace specified by its ``name``
- * ``assign_port_to_namespace port name [port_up]`` - assigns NIC specified by ``port``
- into given namespace ``name``; If optional parameter ``port_up`` is set to ``True``,
- then port will be brought up.
- * ``add_ip_to_namespace_eth port name addr cidr`` - assigns an IP address ``addr``/``cidr``
- to the NIC specified by ``port`` within namespace ``name``
- * ``reset_port_to_root port name`` - returns given ``port`` from namespace ``name`` back
- to the root namespace
-
- Examples:
-
- .. code-block:: python
-
- ['namespace', 'create_namespace', 'testns']
-
- ['namespace', 'assign_port_to_namespace', 'eth0', 'testns']
-
- * ``veth`` - manipulates with eth and veth devices
-
- List of supported functions:
-
- * ``add_veth_port port peer_port`` - adds a pair of veth ports named ``port`` and
- ``peer_port``
- * ``del_veth_port port peer_port`` - deletes a veth port pair specified by ``port``
- and ``peer_port``
- * ``bring_up_eth_port eth_port [namespace]`` - brings up ``eth_port`` in (optional)
- ``namespace``
-
- Examples:
-
- .. code-block:: python
-
- ['veth', 'add_veth_port', 'veth', 'veth1']
-
- ['veth', 'bring_up_eth_port', 'eth1']
-
- * ``tools`` - provides a set of helper functions
-
- List of supported functions:
-
- * ``Assert condition`` - evaluates given ``condition`` and raises ``AssertionError``
- in case that condition is not ``True``
- * ``Eval expression`` - evaluates given expression as a python code and returns
- its result
- * ``Exec command [regex]`` - executes a shell command and filters its output by
- (optional) regular expression
-
- Examples:
-
- .. code-block:: python
-
- ['tools', 'exec', 'numactl -H', 'available: ([0-9]+)']
- ['tools', 'assert', '#STEP[-1][0]>1']
-
- * ``wait`` - is used for test case interruption. This object doesn't have
- any functions. Once reached, vsperf will pause test execution and waits
- for press of ``Enter key``. It can be used during testcase design
- for debugging purposes.
-
- Examples:
-
- .. code-block:: python
-
- ['wait']
-
-Test Macros
------------
-
-Test profiles can include macros as part of the test step. Each step in the
-profile may return a value such as a port name. Recall macros use #STEP to
-indicate the recalled value inside the return structure. If the method the
-test step calls returns a value it can be later recalled, for example:
-
-.. code-block:: python
-
- {
- "Name": "vswitch_add_del_vport",
- "Deployment": "clean",
- "Description": "vSwitch - add and delete virtual port",
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_vport', 'int_br0'], # STEP 1
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], # STEP 2
- ['vswitch', 'del_switch', 'int_br0'], # STEP 3
- ]
- }
-
-This test profile uses the vswitch add_vport method which returns a string
-value of the port added. This is later called by the del_port method using the
-name from step 1.
-
-It is also possible to use negative indexes in step macros. In that case
-``#STEP[-1]`` will refer to the result from previous step, ``#STEP[-2]``
-will refer to result of step called before previous step, etc. It means,
-that you could change ``STEP 2`` from previous example to achieve the same
-functionality:
-
-.. code-block:: python
-
- ['vswitch', 'del_port', 'int_br0', '#STEP[-1][0]'], # STEP 2
-
-Also commonly used steps can be created as a separate profile.
-
-.. code-block:: python
-
- STEP_VSWITCH_PVP_INIT = [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 3
- ['vswitch', 'add_vport', 'int_br0'], # STEP 4
- ]
-
-This profile can then be used inside other testcases
-
-.. code-block:: python
-
- {
- "Name": "vswitch_pvp",
- "Deployment": "clean",
- "Description": "vSwitch - configure switch and one vnf",
- "TestSteps": STEP_VSWITCH_PVP_INIT +
- [
- ['vnf', 'start'],
- ['vnf', 'stop'],
- ] +
- STEP_VSWITCH_PVP_FINIT
- }
-
-HelloWorld and other basic Testcases
-------------------------------------
-
-The following examples are for demonstration purposes.
-You can run them by copying and pasting into the
-conf/integration/01_testcases.conf file.
-A command-line instruction is shown at the end of each
-example.
-
-HelloWorld
-^^^^^^^^^^
-
-The first example is a HelloWorld testcase.
-It simply creates a bridge with 2 physical ports, then sets up a flow to drop
-incoming packets from the port that was instantiated at the STEP #1.
-There's no interaction with the traffic generator.
-Then the flow, the 2 ports and the bridge are deleted.
-'add_phy_port' method creates a 'dpdk' type interface that will manage the
-physical port. The string value returned is the port name that will be referred
-by 'del_port' later on.
-
-.. code-block:: python
-
- {
- "Name": "HelloWorld",
- "Description": "My first testcase",
- "Deployment": "clean",
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'actions': ['drop'], 'idle_timeout': '0'}],
- ['vswitch', 'del_flow', 'int_br0'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
-
- }
-
-To run HelloWorld test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --integration HelloWorld
-
-Specify a Flow by the IP address
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The next example shows how to explicitly set up a flow by specifying a
-destination IP address.
-All packets received from the port created at STEP #1 that have a destination
-IP address = 90.90.90.90 will be forwarded to the port created at the STEP #2.
-
-.. code-block:: python
-
- {
- "Name": "p2p_rule_l3da",
- "Description": "Phy2Phy with rule on L3 Dest Addr",
- "Deployment": "clean",
- "biDirectional": "False",
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_dst': '90.90.90.90', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous'}],
- ['vswitch', 'dump_flows', 'int_br0'], # STEP 5
- ['vswitch', 'del_flow', 'int_br0'], # STEP 7 == del-flows
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
- },
-
-To run the test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --integration p2p_rule_l3da
-
-Multistream feature
-^^^^^^^^^^^^^^^^^^^
-
-The next testcase uses the multistream feature.
-The traffic generator will send packets with different UDP ports.
-That is accomplished by using "Stream Type" and "MultiStream" keywords.
-4 different flows are set to forward all incoming packets.
-
-.. code-block:: python
-
- {
- "Name": "multistream_l4",
- "Description": "Multistream on UDP ports",
- "Deployment": "clean",
- "Stream Type": "L4",
- "MultiStream": 4,
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- # Setup Flows
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '2', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '3', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- # Send mono-dir traffic
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
- 'bidir' : 'False'}],
- # Clean up
- ['vswitch', 'del_flow', 'int_br0'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
- },
-
-To run the test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --integration multistream_l4
-
-PVP with a VM Replacement
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-This example launches a 1st VM in a PVP topology, then the VM is replaced
-by another VM.
-When VNF setup parameter in ./conf/04_vnf.conf is "QemuDpdkVhostUser"
-'add_vport' method creates a 'dpdkvhostuser' type port to connect a VM.
-
-.. code-block:: python
-
- {
- "Name": "ex_replace_vm",
- "Description": "PVP with VM replacement",
- "Deployment": "clean",
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
- ['vswitch', 'add_vport', 'int_br0'], # STEP 4
-
- # Setup Flows
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[2][1]', \
- 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[3][1]', \
- 'actions': ['output:#STEP[1][1]'], 'idle_timeout': '0'}],
-
- # Start VM 1
- ['vnf1', 'start'],
- # Now we want to replace VM 1 with another VM
- ['vnf1', 'stop'],
-
- ['vswitch', 'add_vport', 'int_br0'], # STEP 11 vm2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 12
- ['vswitch', 'del_flow', 'int_br0'],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[12][1]', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
-
- # Start VM 2
- ['vnf2', 'start'],
- ['vnf2', 'stop'],
- ['vswitch', 'dump_flows', 'int_br0'],
-
- # Clean up
- ['vswitch', 'del_flow', 'int_br0'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1
- ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[11][0]'], # vm2
- ['vswitch', 'del_port', 'int_br0', '#STEP[12][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
- },
-
-To run the test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --integration ex_replace_vm
-
-VM with a Linux bridge
-^^^^^^^^^^^^^^^^^^^^^^
-
-In this example a command-line parameter allows to set up a Linux bridge into
-the guest VM.
-That's one of the available ways to specify the guest application.
-Packets matching the flow will be forwarded to the VM.
-
-.. code-block:: python
-
- {
- "Name": "ex_pvp_rule_l3da",
- "Description": "PVP with flow on L3 Dest Addr",
- "Deployment": "clean",
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
- ['vswitch', 'add_vport', 'int_br0'], # STEP 4
- # Setup Flows
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_dst': '90.90.90.90', \
- 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
- # Each pkt from the VM is forwarded to the 2nd dpdk port
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- # Start VMs
- ['vnf1', 'start'],
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
- 'bidir' : 'False'}],
- ['vnf1', 'stop'],
- # Clean up
- ['vswitch', 'dump_flows', 'int_br0'], # STEP 10
- ['vswitch', 'del_flow', 'int_br0'], # STEP 11
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1 ports
- ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
- },
-
-To run the test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --test-params
- "guest_loopback=linux_bridge" --integration ex_pvp_rule_l3da
-
-Forward packets based on UDP port
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-This examples launches 2 VMs connected in parallel.
-Incoming packets will be forwarded to one specific VM depending on the
-destination UDP port.
-
-.. code-block:: python
-
- {
- "Name": "ex_2pvp_rule_l4dp",
- "Description": "2 PVP with flows on L4 Dest Port",
- "Deployment": "clean",
- "Stream Type": "L4", # loop UDP ports
- "MultiStream": 2,
- "TestSteps": [
- ['vswitch', 'add_switch', 'int_br0'], # STEP 0
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
- ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
- ['vswitch', 'add_vport', 'int_br0'], # STEP 4
- ['vswitch', 'add_vport', 'int_br0'], # STEP 5 vm2
- ['vswitch', 'add_vport', 'int_br0'], # STEP 6
- # Setup Flows to reply ICMPv6 and similar packets, so to
- # avoid flooding internal port with their re-transmissions
- ['vswitch', 'add_flow', 'int_br0', \
- {'priority': '1', 'dl_src': '00:00:00:00:00:01', \
- 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', \
- {'priority': '1', 'dl_src': '00:00:00:00:00:02', \
- 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', \
- {'priority': '1', 'dl_src': '00:00:00:00:00:03', \
- 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', \
- {'priority': '1', 'dl_src': '00:00:00:00:00:04', \
- 'actions': ['output:#STEP[6][1]'], 'idle_timeout': '0'}],
- # Forward UDP packets depending on dest port
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \
- 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
- 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \
- 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}],
- # Send VM output to phy port #2
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[6][1]', \
- 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
- # Start VMs
- ['vnf1', 'start'], # STEP 16
- ['vnf2', 'start'], # STEP 17
- ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
- 'bidir' : 'False'}],
- ['vnf1', 'stop'],
- ['vnf2', 'stop'],
- ['vswitch', 'dump_flows', 'int_br0'],
- # Clean up
- ['vswitch', 'del_flow', 'int_br0'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1 ports
- ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
- ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'], # vm2 ports
- ['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'],
- ['vswitch', 'del_switch', 'int_br0'],
- ]
- },
-
-To run the test:
-
- .. code-block:: console
-
- ./vsperf --conf-file user_settings.py --integration ex_2pvp_rule_l4dp
-
Executing Tunnel encapsulation tests
------------------------------------
diff --git a/docs/userguide/teststeps.rst b/docs/userguide/teststeps.rst
new file mode 100644
index 00000000..51e62020
--- /dev/null
+++ b/docs/userguide/teststeps.rst
@@ -0,0 +1,651 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) OPNFV, Intel Corporation, AT&T and others.
+
+Step driven tests
+=================
+
+In general, test scenarios are defined by a ``deployment`` used in the particular
+test case definition. The chosen deployment scenario will take care of the vSwitch
+configuration, deployment of VNFs and it can also affect configuration of a traffic
+generator. In order to allow a more flexible way of testcase scripting, VSPERF supports
+a detailed step driven testcase definition. It can be used to configure and
+program vSwitch, deploy and terminate VNFs, execute a traffic generator,
+modify a VSPERF configuration, execute external commands, etc.
+
+Execution of step driven tests is done on a step by step work flow starting
+with step 0 as defined inside the test case. Each step of the test increments
+the step number by one which is indicated in the log.
+
+.. code-block:: console
+
+ (testcases.integration) - Step 0 'vswitch add_vport ['br0']' start
+
+Step driven tests can be used for both performance and integration testing.
+In case of integration test, each step in the test case is validated. If a step
+does not pass validation the test will fail and terminate. The test will continue
+until a failure is detected or all steps pass. A csv report file is generated after
+a test completes with an OK or FAIL result.
+
+In case of performance test, the validation of steps is not performed and
+standard output files with results from traffic generator and underlying OS
+details are generated by vsperf.
+
+Step driven testcases can be used in two different ways:
+
+ # description of full testcase - in this case ``clean`` deployment is used
+ to indicate that vsperf should neither configure vSwitch nor deploy any VNF.
+ Test shall perform all required vSwitch configuration and programming and
+ deploy required number of VNFs.
+
+ # modification of existing deployment - in this case, any of supported
+ deployments can be used to perform initial vSwitch configuration and
+ deployment of VNFs. Additional actions defined by TestSteps can be used
+ to alter vSwitch configuration or deploy additional VNFs. After the last
+ step is processed, the test execution will continue with traffic execution.
+
+Test objects and their functions
+--------------------------------
+
+Every test step can call a function of one of the supported test objects. The list
+of supported objects and their most common functions follows:
+
+ * ``vswitch`` - provides functions for vSwitch configuration
+
+ List of supported functions:
+
+ * ``add_switch br_name`` - creates a new switch (bridge) with given ``br_name``
+ * ``del_switch br_name`` - deletes switch (bridge) with given ``br_name``
+ * ``add_phy_port br_name`` - adds a physical port into bridge specified by ``br_name``
+ * ``add_vport br_name`` - adds a virtual port into bridge specified by ``br_name``
+ * ``del_port br_name port_name`` - removes physical or virtual port specified by
+ ``port_name`` from bridge ``br_name``
+ * ``add_flow br_name flow`` - adds flow specified by ``flow`` dictionary into
+ the bridge ``br_name``; Content of flow dictionary will be passed to the vSwitch.
+ In case of Open vSwitch it will be passed to the ``ovs-ofctl add-flow`` command.
+ Please see Open vSwitch documentation for the list of supported flow parameters.
+ * ``del_flow br_name [flow]`` - deletes flow specified by ``flow`` dictionary from
+ bridge ``br_name``; In case that optional parameter ``flow`` is not specified
+ or set to an empty dictionary ``{}``, then all flows from bridge ``br_name``
+ will be deleted.
+ * ``dump_flows br_name`` - dumps all flows from bridge specified by ``br_name``
+ * ``enable_stp br_name`` - enables Spanning Tree Protocol for bridge ``br_name``
+ * ``disable_stp br_name`` - disables Spanning Tree Protocol for bridge ``br_name``
+ * ``enable_rstp br_name`` - enables Rapid Spanning Tree Protocol for bridge ``br_name``
+ * ``disable_rstp br_name`` - disables Rapid Spanning Tree Protocol for bridge ``br_name``
+
+ Examples:
+
+ .. code-block:: python
+
+ ['vswitch', 'add_switch', 'int_br0']
+
+ ['vswitch', 'del_switch', 'int_br0']
+
+ ['vswitch', 'add_phy_port', 'int_br0']
+
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]']
+
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '1', 'actions': ['output:2'],
+ 'idle_timeout': '0'}],
+
+ ['vswitch', 'enable_rstp', 'int_br0']
+
+ * ``vnf[ID]`` - provides functions for deployment and termination of VNFs; Optional
+ alfanumerical ``ID`` is used for VNF identification in case that testcase
+ deploys multiple VNFs.
+
+ List of supported functions:
+
+ * ``start`` - starts a VNF based on VSPERF configuration
+ * ``stop`` - gracefully terminates given VNF
+
+ Examples:
+
+ .. code-block:: python
+
+ ['vnf1', 'start']
+ ['vnf2', 'start']
+ ['vnf2', 'stop']
+ ['vnf1', 'stop']
+
+ * ``trafficgen`` - triggers traffic generation
+
+ List of supported functions:
+
+ * ``send_traffic traffic`` - starts a traffic based on the vsperf configuration
+ and given ``traffic`` dictionary. More details about ``traffic`` dictionary
+ and its possible values are available at `Traffic Generator Integration Guide
+ <http://artifacts.opnfv.org/vswitchperf/docs/design/trafficgen_integration_guide.html#step-5-supported-traffic-types>`__
+
+ Examples:
+
+ .. code-block:: python
+
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'throughput'}]
+
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'back2back', 'bidir' : 'True'}]
+
+ * ``settings`` - reads or modifies VSPERF configuration
+
+ List of supported functions:
+
+ * ``getValue param`` - returns value of given ``param``
+ * ``setValue param value`` - sets value of ``param`` to given ``value``
+
+ Examples:
+
+ .. code-block:: python
+
+ ['settings', 'getValue', 'TOOLS']
+
+ ['settings', 'setValue', 'GUEST_USERNAME', ['root']]
+
+ * ``namespace`` - creates or modifies network namespaces
+
+ List of supported functions:
+
+ * ``create_namespace name`` - creates new namespace with given ``name``
+ * ``delete_namespace name`` - deletes namespace specified by its ``name``
+ * ``assign_port_to_namespace port name [port_up]`` - assigns NIC specified by ``port``
+ into given namespace ``name``; If optional parameter ``port_up`` is set to ``True``,
+ then port will be brought up.
+ * ``add_ip_to_namespace_eth port name addr cidr`` - assigns an IP address ``addr``/``cidr``
+ to the NIC specified by ``port`` within namespace ``name``
+ * ``reset_port_to_root port name`` - returns given ``port`` from namespace ``name`` back
+ to the root namespace
+
+ Examples:
+
+ .. code-block:: python
+
+ ['namespace', 'create_namespace', 'testns']
+
+ ['namespace', 'assign_port_to_namespace', 'eth0', 'testns']
+
+ * ``veth`` - manipulates with eth and veth devices
+
+ List of supported functions:
+
+ * ``add_veth_port port peer_port`` - adds a pair of veth ports named ``port`` and
+ ``peer_port``
+ * ``del_veth_port port peer_port`` - deletes a veth port pair specified by ``port``
+ and ``peer_port``
+ * ``bring_up_eth_port eth_port [namespace]`` - brings up ``eth_port`` in (optional)
+ ``namespace``
+
+ Examples:
+
+ .. code-block:: python
+
+ ['veth', 'add_veth_port', 'veth', 'veth1']
+
+ ['veth', 'bring_up_eth_port', 'eth1']
+
+ * ``tools`` - provides a set of helper functions
+
+ List of supported functions:
+
+ * ``Assert condition`` - evaluates given ``condition`` and raises ``AssertionError``
+ in case that condition is not ``True``
+ * ``Eval expression`` - evaluates given expression as a python code and returns
+ its result
+ * ``Exec command [regex]`` - executes a shell command and filters its output by
+ (optional) regular expression
+
+ Examples:
+
+ .. code-block:: python
+
+ ['tools', 'exec', 'numactl -H', 'available: ([0-9]+)']
+ ['tools', 'assert', '#STEP[-1][0]>1']
+
+ * ``wait`` - is used for test case interruption. This object doesn't have
+ any functions. Once reached, vsperf will pause test execution and waits
+ for press of ``Enter key``. It can be used during testcase design
+ for debugging purposes.
+
+ Examples:
+
+ .. code-block:: python
+
+ ['wait']
+
+Test Macros
+-----------
+
+Test profiles can include macros as part of the test step. Each step in the
+profile may return a value such as a port name. Recall macros use #STEP to
+indicate the recalled value inside the return structure. If the method the
+test step calls returns a value it can be later recalled, for example:
+
+.. code-block:: python
+
+ {
+ "Name": "vswitch_add_del_vport",
+ "Deployment": "clean",
+ "Description": "vSwitch - add and delete virtual port",
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 1
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], # STEP 2
+ ['vswitch', 'del_switch', 'int_br0'], # STEP 3
+ ]
+ }
+
+This test profile uses the vswitch add_vport method which returns a string
+value of the port added. This is later called by the del_port method using the
+name from step 1.
+
+It is also possible to use negative indexes in step macros. In that case
+``#STEP[-1]`` will refer to the result from previous step, ``#STEP[-2]``
+will refer to result of step called before previous step, etc. It means,
+that you could change ``STEP 2`` from previous example to achieve the same
+functionality:
+
+.. code-block:: python
+
+ ['vswitch', 'del_port', 'int_br0', '#STEP[-1][0]'], # STEP 2
+
+Also commonly used steps can be created as a separate profile.
+
+.. code-block:: python
+
+ STEP_VSWITCH_PVP_INIT = [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 3
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 4
+ ]
+
+This profile can then be used inside other testcases
+
+.. code-block:: python
+
+ {
+ "Name": "vswitch_pvp",
+ "Deployment": "clean",
+ "Description": "vSwitch - configure switch and one vnf",
+ "TestSteps": STEP_VSWITCH_PVP_INIT +
+ [
+ ['vnf', 'start'],
+ ['vnf', 'stop'],
+ ] +
+ STEP_VSWITCH_PVP_FINIT
+ }
+
+HelloWorld and other basic Testcases
+------------------------------------
+
+The following examples are for demonstration purposes.
+You can run them by copying and pasting into the
+conf/integration/01_testcases.conf file.
+A command-line instruction is shown at the end of each
+example.
+
+HelloWorld
+^^^^^^^^^^
+
+The first example is a HelloWorld testcase.
+It simply creates a bridge with 2 physical ports, then sets up a flow to drop
+incoming packets from the port that was instantiated at the STEP #1.
+There's no interaction with the traffic generator.
+Then the flow, the 2 ports and the bridge are deleted.
+'add_phy_port' method creates a 'dpdk' type interface that will manage the
+physical port. The string value returned is the port name that will be referred
+by 'del_port' later on.
+
+.. code-block:: python
+
+ {
+ "Name": "HelloWorld",
+ "Description": "My first testcase",
+ "Deployment": "clean",
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'actions': ['drop'], 'idle_timeout': '0'}],
+ ['vswitch', 'del_flow', 'int_br0'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+
+ },
+
+To run HelloWorld test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration HelloWorld
+
+Specify a Flow by the IP address
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The next example shows how to explicitly set up a flow by specifying a
+destination IP address.
+All packets received from the port created at STEP #1 that have a destination
+IP address = 90.90.90.90 will be forwarded to the port created at the STEP #2.
+
+.. code-block:: python
+
+ {
+ "Name": "p2p_rule_l3da",
+ "Description": "Phy2Phy with rule on L3 Dest Addr",
+ "Deployment": "clean",
+ "biDirectional": "False",
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_dst': '90.90.90.90', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous'}],
+ ['vswitch', 'dump_flows', 'int_br0'], # STEP 5
+ ['vswitch', 'del_flow', 'int_br0'], # STEP 7 == del-flows
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration p2p_rule_l3da
+
+Multistream feature
+^^^^^^^^^^^^^^^^^^^
+
+The next testcase uses the multistream feature.
+The traffic generator will send packets with different UDP ports.
+That is accomplished by using "Stream Type" and "MultiStream" keywords.
+4 different flows are set to forward all incoming packets.
+
+.. code-block:: python
+
+ {
+ "Name": "multistream_l4",
+ "Description": "Multistream on UDP ports",
+ "Deployment": "clean",
+ "Stream Type": "L4",
+ "MultiStream": 4,
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ # Setup Flows
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '2', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '3', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ # Send mono-dir traffic
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
+ 'bidir' : 'False'}],
+ # Clean up
+ ['vswitch', 'del_flow', 'int_br0'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration multistream_l4
+
+PVP with a VM Replacement
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This example launches a 1st VM in a PVP topology, then the VM is replaced
+by another VM.
+When VNF setup parameter in ./conf/04_vnf.conf is "QemuDpdkVhostUser"
+'add_vport' method creates a 'dpdkvhostuser' type port to connect a VM.
+
+.. code-block:: python
+
+ {
+ "Name": "ex_replace_vm",
+ "Description": "PVP with VM replacement",
+ "Deployment": "clean",
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 4
+
+ # Setup Flows
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[2][1]', \
+ 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[3][1]', \
+ 'actions': ['output:#STEP[1][1]'], 'idle_timeout': '0'}],
+
+ # Start VM 1
+ ['vnf1', 'start'],
+ # Now we want to replace VM 1 with another VM
+ ['vnf1', 'stop'],
+
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 11 vm2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 12
+ ['vswitch', 'del_flow', 'int_br0'],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[12][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+
+ # Start VM 2
+ ['vnf2', 'start'],
+ ['vnf2', 'stop'],
+ ['vswitch', 'dump_flows', 'int_br0'],
+
+ # Clean up
+ ['vswitch', 'del_flow', 'int_br0'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1
+ ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[11][0]'], # vm2
+ ['vswitch', 'del_port', 'int_br0', '#STEP[12][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration ex_replace_vm
+
+VM with a Linux bridge
+^^^^^^^^^^^^^^^^^^^^^^
+
+This example setups a PVP topology and routes traffic to the VM based on
+the destination IP address. A command-line parameter is used to select a Linux
+bridge as a guest loopback application. It is also possible to select a guest
+loopback application by a configuration option ``GUEST_LOOPBACK``.
+
+.. code-block:: python
+
+ {
+ "Name": "ex_pvp_rule_l3da",
+ "Description": "PVP with flow on L3 Dest Addr",
+ "Deployment": "clean",
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 4
+ # Setup Flows
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_dst': '90.90.90.90', \
+ 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
+ # Each pkt from the VM is forwarded to the 2nd dpdk port
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ # Start VMs
+ ['vnf1', 'start'],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
+ 'bidir' : 'False'}],
+ ['vnf1', 'stop'],
+ # Clean up
+ ['vswitch', 'dump_flows', 'int_br0'], # STEP 10
+ ['vswitch', 'del_flow', 'int_br0'], # STEP 11
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --test-params
+ "guest_loopback=linux_bridge" --integration ex_pvp_rule_l3da
+
+Forward packets based on UDP port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This examples launches 2 VMs connected in parallel.
+Incoming packets will be forwarded to one specific VM depending on the
+destination UDP port.
+
+.. code-block:: python
+
+ {
+ "Name": "ex_2pvp_rule_l4dp",
+ "Description": "2 PVP with flows on L4 Dest Port",
+ "Deployment": "clean",
+ "Stream Type": "L4", # loop UDP ports
+ "MultiStream": 2,
+ "TestSteps": [
+ ['vswitch', 'add_switch', 'int_br0'], # STEP 0
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1
+ ['vswitch', 'add_phy_port', 'int_br0'], # STEP 2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 4
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 5 vm2
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 6
+ # Setup Flows to reply ICMPv6 and similar packets, so to
+ # avoid flooding internal port with their re-transmissions
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:01', \
+ 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:02', \
+ 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:03', \
+ 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:04', \
+ 'actions': ['output:#STEP[6][1]'], 'idle_timeout': '0'}],
+ # Forward UDP packets depending on dest port
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \
+ 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \
+ 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}],
+ # Send VM output to phy port #2
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[6][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ # Start VMs
+ ['vnf1', 'start'], # STEP 16
+ ['vnf2', 'start'], # STEP 17
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', \
+ 'bidir' : 'False'}],
+ ['vnf1', 'stop'],
+ ['vnf2', 'stop'],
+ ['vswitch', 'dump_flows', 'int_br0'],
+ # Clean up
+ ['vswitch', 'del_flow', 'int_br0'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], # vm1 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'], # vm2 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'],
+ ['vswitch', 'del_switch', 'int_br0'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration ex_2pvp_rule_l4dp
+
+Modification of existing PVVP deployment
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This is an example of modification of a standard deployment scenario with additional TestSteps.
+Standard PVVP scenario is used to configure a vSwitch and to deploy two VNFs connected
+in series. Additional TestSteps will deploy a 3rd VNF and connect it in parallel to
+already configured VNFs. Traffic generator is instructed (by Multistream feature) to send
+two separate traffic streams. One stream will be sent to the standalone VNF and second
+to two chained VNFs.
+
+In case, that test is defined as a performance test, then traffic results will be collected
+and available in both csv and rst report files.
+
+.. code-block:: python
+
+ {
+ "Name": "pvvp_pvp_cont",
+ "Traffic Type": "continuous",
+ "Deployment": "pvvp",
+ "Description": "PVVP and PVP in parallel with Continuous Stream",
+ "biDirectional": "True",
+ "iLoad": "100",
+ "MultiStream": "2",
+ "TestSteps": [
+ ['vswitch', 'add_vport', 'br0'],
+ ['vswitch', 'add_vport', 'br0'],
+ # priority must be higher than default 32768, otherwise flows won't match
+ ['vswitch', 'add_flow', 'br0',
+ {'in_port': '1', 'actions': ['output:#STEP[-2][1]'], 'idle_timeout': '0', 'dl_type':'0x800',
+ 'nw_proto':'17', 'tp_dst':'0', 'priority': '33000'}],
+ ['vswitch', 'add_flow', 'br0',
+ {'in_port': '2', 'actions': ['output:#STEP[-2][1]'], 'idle_timeout': '0', 'dl_type':'0x800',
+ 'nw_proto':'17', 'tp_dst':'0', 'priority': '33000'}],
+ ['vswitch', 'add_flow', 'br0', {'in_port': '#STEP[-4][1]', 'actions': ['output:1'],
+ 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'br0', {'in_port': '#STEP[-4][1]', 'actions': ['output:2'],
+ 'idle_timeout': '0'}],
+ ['vswitch', 'dump_flows', 'br0'],
+ ['vnf1', 'start'],
+ ]
+ },
+
+To run the test:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py pvvp_pvp_cont
+