aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/02_vswitch.conf4
-rw-r--r--conf/04_vnf.conf50
-rw-r--r--conf/integration/01_testcases.conf235
-rw-r--r--conf/integration/02_vswitch.conf12
-rw-r--r--core/component_factory.py3
-rw-r--r--core/vswitch_controller_ptunp.py238
-rwxr-xr-xdocs/userguide/integration.rst49
-rw-r--r--vswitches/ovs.py32
8 files changed, 604 insertions, 19 deletions
diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf
index 3d72d348..228ff057 100644
--- a/conf/02_vswitch.conf
+++ b/conf/02_vswitch.conf
@@ -62,6 +62,10 @@ VHOST_DEV_FILE = 'ovs-vhost-net'
# location of vhost-user sockets
VHOST_USER_SOCKS = ['/tmp/dpdkvhostuser0', '/tmp/dpdkvhostuser1',
'/tmp/dpdkvhostuser2', '/tmp/dpdkvhostuser3',
+ '/tmp/dpdkvhostuser4', '/tmp/dpdkvhostuser5',
+ '/tmp/dpdkvhostuser6', '/tmp/dpdkvhostuser7',
+ '/tmp/dpdkvhostuser8', '/tmp/dpdkvhostuser9',
+ '/tmp/dpdkvhostuser10', '/tmp/dpdkvhostuser11',
'/tmp/myport0', '/tmp/helloworld123', '/tmp/abcstuff0']
# ############################
diff --git a/conf/04_vnf.conf b/conf/04_vnf.conf
index ff110d93..ec242662 100644
--- a/conf/04_vnf.conf
+++ b/conf/04_vnf.conf
@@ -25,15 +25,17 @@ VNF = 'QemuDpdkVhostUser'
# directory which is shared to QEMU guests. Useful for exchanging files
# between host and guest, VNF specific share will be created
# For 2 VNFs you may use ['/tmp/qemu0_share', '/tmp/qemu1_share']
-GUEST_SHARE_DIR = ['/tmp/qemu0_share', '/tmp/qemu1_share']
+GUEST_SHARE_DIR = ['/tmp/qemu0_share', '/tmp/qemu1_share', \
+ '/tmp/qemu2_share', '/tmp/qemu3_share', \
+ '/tmp/qemu4_share', '/tmp/qemu5_share']
# location of guest disk image
# For 2 VNFs you may use ['guest1.img', 'guest2.img']
-GUEST_IMAGE = ['', '']
+GUEST_IMAGE = ['', '', '', '', '', '']
# guarding timer for VM start up
# For 2 VNFs you may use [180, 180]
-GUEST_TIMEOUT = [180, 180]
+GUEST_TIMEOUT = [180, 180, 180, 180, 180, 180]
# packet forwarding mode supported by testpmd; Please see DPDK documentation
# for comprehensive list of modes supported by your version.
@@ -50,7 +52,9 @@ GUEST_TESTPMD_FWD_MODE = 'csum'
# This configuration option can be overridden by CLI SCALAR option
# guest_loopback, e.g. --test-params "guest_loopback=l2fwd"
# For 2 VNFs you may use ['testpmd', 'l2fwd']
-GUEST_LOOPBACK = ['testpmd', 'testpmd']
+GUEST_LOOPBACK = ['testpmd', 'testpmd', \
+ 'testpmd', 'testpmd', \
+ 'testpmd', 'testpmd']
# username for guest image
GUEST_USERNAME = 'root'
@@ -81,25 +85,33 @@ LOG_FILE_GUEST_CMDS = 'guest-cmds.log'
QEMU_BIN = os.path.join(QEMU_DIR, 'x86_64-softmmu/qemu-system-x86_64')
# For 2 VNFs you may use ['eth0', 'eth2']
-GUEST_NIC1_NAME = ['eth0', 'eth0']
-GUEST_NIC2_NAME = ['eth1', 'eth1']
+GUEST_NIC1_NAME = ['eth0', 'eth0', 'eth0', 'eth0', 'eth0', 'eth0']
+GUEST_NIC2_NAME = ['eth1', 'eth1', 'eth1', 'eth1', 'eth1', 'eth1']
# For 2 VNFs you may use ['00:00:00:00:00:01', '00:00:00:00:00:03']
-GUEST_NET1_MAC = ['00:00:00:00:00:01', '00:00:00:00:00:03']
-GUEST_NET2_MAC = ['00:00:00:00:00:02', '00:00:00:00:00:04']
+GUEST_NET1_MAC = ['00:00:00:00:00:01', '00:00:00:00:00:03', \
+ '00:00:00:00:00:05', '00:00:00:00:00:07', \
+ '00:00:00:00:00:09', '00:00:00:00:00:0b']
+GUEST_NET2_MAC = ['00:00:00:00:00:02', '00:00:00:00:00:04', \
+ '00:00:00:00:00:06', '00:00:00:00:00:08', \
+ '00:00:00:00:00:0a', '00:00:00:00:00:0c']
# For 2 VNFs you may use ['00:04.0', '00:04.0']
-GUEST_NET1_PCI_ADDRESS = ['00:04.0', '00:04.0']
-GUEST_NET2_PCI_ADDRESS = ['00:05.0', '00:05.0']
+GUEST_NET1_PCI_ADDRESS = ['00:04.0', '00:04.0', \
+ '00:04.0', '00:04.0', \
+ '00:04.0', '00:04.0']
+GUEST_NET2_PCI_ADDRESS = ['00:05.0', '00:05.0', \
+ '00:05.0', '00:05.0', \
+ '00:05.0', '00:05.0']
-GUEST_MEMORY = ['4096', '4096']
+GUEST_MEMORY = ['4096', '4096', '2048', '2048', '2048', '2048']
# test-pmd requires 2 VM cores
-GUEST_SMP = ['2', '2']
+GUEST_SMP = ['2', '2', '2', '2', '2', '2']
# Host cores to use to affinitize the SMP cores of a QEMU instance
# For 2 VNFs you may use [(4,5), (6, 7)]
-GUEST_CORE_BINDING = [(6, 7), (9, 10)]
+GUEST_CORE_BINDING = [(6, 7), (9, 10), (11, 12), (13, 14), (15, 16), (17, 18)]
# Queues per NIC inside guest for multi-queue configuration, requires switch
# multi-queue to be enabled. Set to 0 for disabled.
@@ -137,9 +149,15 @@ VANILLA_TGEN_PORT1_MAC = 'AA:BB:CC:DD:EE:FF'
VANILLA_TGEN_PORT2_IP = '1.1.2.10'
VANILLA_TGEN_PORT2_MAC = 'AA:BB:CC:DD:EE:F0'
-VANILLA_BRIDGE_IP = ['1.1.1.5/16', '1.1.1.6/16']
+VANILLA_BRIDGE_IP = ['1.1.1.5/16', '1.1.1.6/16', \
+ '1.1.1.7/16', '1.1.1.8/16', \
+ '1.1.1.9/16', '1.1.1.10/16']
-VANILLA_NIC1_IP_CIDR = ['192.168.1.2/24', '192.168.1.4/24']
-VANILLA_NIC2_IP_CIDR = ['192.168.1.3/24', '192.168.1.5/24']
+VANILLA_NIC1_IP_CIDR = ['192.168.1.2/24', '192.168.1.4/24', \
+ '192.168.1.6/24', '192.168.1.8/24', \
+ '192.168.1.10/24', '192.168.1.12/24']
+VANILLA_NIC2_IP_CIDR = ['192.168.1.3/24', '192.168.1.5/24', \
+ '192.168.1.7/24', '192.168.1.9/24', \
+ '192.168.1.11/24', '192.168.1.13/24']
VNF_AFFINITIZATION_ON = True
diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf
index e050e358..a67702f8 100644
--- a/conf/integration/01_testcases.conf
+++ b/conf/integration/01_testcases.conf
@@ -72,7 +72,7 @@ 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 3 vm1 ports
['vswitch', 'add_vport', 'int_br0'], # STEP 4
]
@@ -100,12 +100,12 @@ STEP_VSWITCH_PVP_FLOWS_FINIT = [
] + STEP_VSWITCH_PVP_FINIT
STEP_VSWITCH_PVVP_INIT = STEP_VSWITCH_PVP_INIT + [
- ['vswitch', 'add_vport', 'int_br0'], # STEP 5
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 5 vm2 ports
['vswitch', 'add_vport', 'int_br0'], # STEP 6
]
STEP_VSWITCH_PVVP_FINIT = [
- ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'], # vm2 ports
['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'],
] + STEP_VSWITCH_PVP_FINIT
@@ -128,11 +128,166 @@ STEP_VSWITCH_PVVP_FLOWS_FINIT = [
['vswitch', 'del_flow', 'int_br0', {'in_port': '#STEP[3][1]'}],
] + STEP_VSWITCH_PVVP_FINIT
+STEP_VSWITCH_2PHY_2VM_INIT = STEP_VSWITCH_PVVP_INIT
+
+STEP_VSWITCH_2PHY_2VM_FINIT = STEP_VSWITCH_PVVP_FINIT
+
+STEP_VSWITCH_2_PARALLEL_VM_FLOWS_INIT = [
+ # Setup Flows to reply ICMPv6 and similar packets, so to
+ # avoid flooding the 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 outputs 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'}],
+]
+
+STEP_VSWITCH_2PHY_4VM_INIT = STEP_VSWITCH_2PHY_2VM_INIT + [
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 7 vm3 ports
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 8
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 9 vm4 ports
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 10
+]
+
+STEP_VSWITCH_2PHY_4VM_FINIT = [
+ ['vswitch', 'del_port', 'int_br0', '#STEP[7][0]'], # vm3 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[8][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[9][0]'], # vm4 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[10][0]'],
+] + STEP_VSWITCH_2PHY_2VM_FINIT
+
+STEP_VSWITCH_FLOWS_FINIT = [
+ ['vswitch', 'dump_flows', 'int_br0'],
+ ['vswitch', 'del_flow', 'int_br0'],
+]
+
+STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT = [
+ # Setup Flows to reply ICMPv6 and similar packets, so to
+ # avoid flooding the 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'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:05', \
+ 'actions': ['output:#STEP[7][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:06', \
+ 'actions': ['output:#STEP[8][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:07', \
+ 'actions': ['output:#STEP[9][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:08', \
+ 'actions': ['output:#STEP[10][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'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '2', \
+ 'actions': ['output:#STEP[7][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[9][1]'], 'idle_timeout': '0'}],
+ # Send VM outputs 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'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[8][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[10][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+]
+
+STEP_VSWITCH_2PHY_6VM_INIT = STEP_VSWITCH_2PHY_4VM_INIT + [
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 11 vm5 vhu8
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 12 vhu9
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 13 vm6 vhu10
+ ['vswitch', 'add_vport', 'int_br0'], # STEP 14 vhu11
+]
+
+STEP_VSWITCH_6_PARALLEL_VM_FLOWS_INIT = STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT + [
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:09', \
+ 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:0a', \
+ 'actions': ['output:#STEP[12][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:0b', \
+ 'actions': ['output:#STEP[13][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', \
+ {'priority': '1', 'dl_src': '00:00:00:00:00:0c', \
+ 'actions': ['output:#STEP[14][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': '4', \
+ 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \
+ 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '5', \
+ 'actions': ['output:#STEP[13][1]'], 'idle_timeout': '0'}],
+ # Send VM outputs to phy port #2
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[12][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[14][1]', \
+ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}],
+]
+
+STEP_VSWITCH_2PHY_6VM_FINIT = [
+ ['vswitch', 'del_port', 'int_br0', '#STEP[11][0]'], # vm5 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[12][0]'],
+ ['vswitch', 'del_port', 'int_br0', '#STEP[13][0]'], # vm6 ports
+ ['vswitch', 'del_port', 'int_br0', '#STEP[14][0]'],
+] + STEP_VSWITCH_2PHY_4VM_FINIT
+
#
# Definition of integration tests
#
INTEGRATION_TESTS = [
{
+ "Name": "overlay_p2p_mod_tput",
+ "Traffic Type": "rfc2544",
+ "Deployment": "ptunp",
+ "biDirectional": 'True',
+ "Tunnel Type": "vxlan",
+ "Description": ("Tunneling Throughput RFC2544 Test."
+ "The encap and decap are performed inside the "
+ "virtual switch itself in each direction to avoid "
+ "the need of ingress overlay traffic."),
+ },
+ {
"Name": "overlay_p2p_tput",
"Traffic Type": "rfc2544",
"Deployment": "op2p",
@@ -420,6 +575,80 @@ INTEGRATION_TESTS = [
] +
STEP_VSWITCH_PVVP_FLOWS_FINIT
},
+ {
+ # Topology: 2 Parallel PVP connections
+ # To run a Linux bridge as a loopback in the Guest use:
+ # --test-params "guest_loopback=linux_bridge" --integration 2pvp_udp_dest_flows
+ "Name": "2pvp_udp_dest_flows",
+ "Description": "Continuous TC with 2 Parallel VMs, flows on UDP Dest Port",
+ "Deployment": "clean",
+ "Stream Type": "L4",
+ "MultiStream": 2,
+ "TestSteps": STEP_VSWITCH_2PHY_2VM_INIT +
+ STEP_VSWITCH_2_PARALLEL_VM_FLOWS_INIT + [
+ # Start 2 VMs
+ ['vnf1', 'start'],
+ ['vnf2', 'start'],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'False'}],
+ ['vnf1', 'stop'],
+ ['vnf2', 'stop'],
+ # Clean up
+ ] + STEP_VSWITCH_FLOWS_FINIT +
+ STEP_VSWITCH_2PHY_2VM_FINIT
+ },
+ {
+ # Topology: 4 Parallel PVP connections
+ # To run a Linux bridge as a loopback in the Guest use:
+ # --test-params "guest_loopback=linux_bridge" --integration 4pvp_udp_dest_flows
+ "Name": "4pvp_udp_dest_flows",
+ "Description": "Continuous TC with 4 Parallel VMs, flows on UDP Dest Port",
+ "Deployment": "clean",
+ "Stream Type": "L4",
+ "MultiStream": 4,
+ "TestSteps": STEP_VSWITCH_2PHY_4VM_INIT +
+ STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT + [
+ # Start 4 VMs
+ ['vnf1', 'start'],
+ ['vnf2', 'start'],
+ ['vnf3', 'start'],
+ ['vnf4', 'start'],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'False'}],
+ ['vnf1', 'stop'],
+ ['vnf2', 'stop'],
+ ['vnf3', 'stop'],
+ ['vnf4', 'stop'],
+ # Clean up
+ ] + STEP_VSWITCH_FLOWS_FINIT +
+ STEP_VSWITCH_2PHY_4VM_FINIT
+ },
+ {
+ # Topology: 6 Parallel PVP connections
+ # To run a Linux bridge as a loopback in the Guest use:
+ # --test-params "guest_loopback=linux_bridge" --integration 6pvp_udp_dest_flows
+ "Name": "6pvp_udp_dest_flows",
+ "Description": "Continuous TC with 6 Parallel VMs, flows on UDP Dest Port",
+ "Deployment": "clean",
+ "Stream Type": "L4",
+ "MultiStream": 6,
+ "TestSteps": STEP_VSWITCH_2PHY_6VM_INIT +
+ STEP_VSWITCH_6_PARALLEL_VM_FLOWS_INIT + [
+ # Start VMs
+ ['vnf1', 'start'],
+ ['vnf2', 'start'],
+ ['vnf3', 'start'],
+ ['vnf4', 'start'],
+ ['vnf5', 'start'],
+ ['vnf6', 'start'],
+ ['trafficgen', 'send_traffic', {'traffic_type' : 'continuous', 'bidir' : 'False'}],
+ ['vnf1', 'stop'],
+ ['vnf2', 'stop'],
+ ['vnf3', 'stop'],
+ ['vnf4', 'stop'],
+ ['vnf5', 'stop'],
+ ['vnf6', 'stop'],
+ ] + STEP_VSWITCH_FLOWS_FINIT +
+ STEP_VSWITCH_2PHY_6VM_FINIT
+ },
]
# Example of TC definition with exact vSwitch, VNF and TRAFFICGEN values.
diff --git a/conf/integration/02_vswitch.conf b/conf/integration/02_vswitch.conf
index 6bdf79d3..68eaf73e 100644
--- a/conf/integration/02_vswitch.conf
+++ b/conf/integration/02_vswitch.conf
@@ -28,3 +28,15 @@ TUNNEL_TYPE = 'vxlan'
DUT_NIC1_MAC = ''
# Used for OVS DPDK Decap
DUT_NIC2_MAC = ''
+
+#Tunnel bridge configuration for P-TUN-P(VxLAN) deployment scenario
+# to test VxLAN performance without any overlay ingress traffic by doing the
+# encap decap inside the virtual switch itself.
+TUNNEL_EXTERNAL_BRIDGE1 = 'br-phy1'
+TUNNEL_EXTERNAL_BRIDGE2 = 'br-phy2'
+TUNNEL_MODIFY_BRIDGE1 = 'br-mod1'
+TUNNEL_MODIFY_BRIDGE2 = 'br-mod2'
+TUNNEL_MODIFY_BRIDGE_MAC1 = '00:00:10:00:00:01'
+TUNNEL_MODIFY_BRIDGE_MAC2 = '00:00:20:00:00:01'
+TUNNEL_MODIFY_BRIDGE_IP1 = '10.0.0.1/24'
+TUNNEL_MODIFY_BRIDGE_IP2 = '20.0.0.1/24'
diff --git a/core/component_factory.py b/core/component_factory.py
index a91872e2..258b7232 100644
--- a/core/component_factory.py
+++ b/core/component_factory.py
@@ -21,6 +21,7 @@ from core.vswitch_controller_p2p import VswitchControllerP2P
from core.vswitch_controller_pvp import VswitchControllerPVP
from core.vswitch_controller_pvvp import VswitchControllerPVVP
from core.vswitch_controller_op2p import VswitchControllerOP2P
+from core.vswitch_controller_ptunp import VswitchControllerPtunP
from core.vnf_controller import VnfController
from core.pktfwd_controller import PktFwdController
from tools.load_gen.stress.stress import Stress
@@ -73,6 +74,8 @@ def create_vswitch(deployment_scenario, vswitch_class, traffic,
return VswitchControllerPVVP(vswitch_class, traffic)
elif deployment_scenario.find("op2p") >= 0:
return VswitchControllerOP2P(vswitch_class, traffic, tunnel_operation)
+ elif deployment_scenario.find("ptunp") >= 0:
+ return VswitchControllerPtunP(vswitch_class, traffic)
elif deployment_scenario.find("clean") >= 0:
return VswitchControllerClean(vswitch_class, traffic)
diff --git a/core/vswitch_controller_ptunp.py b/core/vswitch_controller_ptunp.py
new file mode 100644
index 00000000..27d26789
--- /dev/null
+++ b/core/vswitch_controller_ptunp.py
@@ -0,0 +1,238 @@
+# Copyright 2015-2016 Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""VSwitch controller for Physical to VxLAN Tunnel Endpoint to Physical
+ deployment with mod operation.
+"""
+
+import logging
+from netaddr import EUI, IPNetwork, mac_unix
+
+from core.vswitch_controller import IVswitchController
+from vswitches.utils import add_ports_to_flow
+from conf import settings
+from tools import tasks
+
+_FLOW_TEMPLATE = {
+ 'idle_timeout': '0'
+}
+
+class VswitchControllerPtunP(IVswitchController):
+ """VSwitch controller for VxLAN ptunp deployment scenario.
+ The deployment scenario is to test VxLAN tunneling feature without using an
+ overlay ingress traffic. The VxLAN encap and decap performed in the virtual
+ switch in each direction.
+
+ Attributes:
+ _vswitch_class: The vSwitch class to be used.
+ _vswitch: The vSwitch object controlled by this controller
+ _deployment_scenario: A string describing the scenario to set-up in the
+ constructor.
+ """
+ def __init__(self, vswitch_class, traffic):
+ """Initializes up the prerequisites for the ptunp deployment scenario.
+
+ :vswitch_class: the vSwitch class to be used.
+ """
+ self._logger = logging.getLogger(__name__)
+ self._vswitch_class = vswitch_class
+ self._vswitch = vswitch_class()
+ self._deployment_scenario = "ptunp"
+ self._traffic = traffic.copy()
+ self.bridge_phy1 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE1')
+ self.bridge_phy2 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE2')
+ self.bridge_mod1 = settings.getValue('TUNNEL_MODIFY_BRIDGE1')
+ self.bridge_mod2 = settings.getValue('TUNNEL_MODIFY_BRIDGE2')
+ self.br_mod_mac1 = settings.getValue('TUNNEL_MODIFY_BRIDGE_MAC1')
+ self.br_mod_mac2 = settings.getValue('TUNNEL_MODIFY_BRIDGE_MAC2')
+ self.br_mod_ip1 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP1')
+ self.br_mod_ip2 = settings.getValue('TUNNEL_MODIFY_BRIDGE_IP2')
+ self.tunnel_type = settings.getValue('TUNNEL_TYPE')
+ self._logger.debug('Creation using ' + str(self._vswitch_class))
+
+ def setup(self):
+ """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap)
+ """
+ self._logger.debug('Setting up phy-tun-phy tunneling scenario')
+ if self.tunnel_type is 'vxlan':
+ self._setup_vxlan_encap_decap()
+ else:
+ self._logger.error("Only VxLAN is supported for now")
+ raise NotImplementedError
+
+ def _setup_vxlan_encap_decap(self):
+ """ Sets up switches for VxLAN overlay P-TUN-P test.
+
+ Create 2 bridges br-phy1 and br-phy2 (The bridge to connect
+ physical ports. Two more bridges br-mod1 and br-mod2 to mangle
+ and redirect the packets from one tunnel port to other.
+ """
+ self._logger.debug('Setup using ' + str(self._vswitch_class))
+ try:
+ self._vswitch.start()
+ self._vswitch.add_switch(self.bridge_phy1)
+ self._vswitch.add_switch(self.bridge_phy2)
+ self._vswitch.add_switch(self.bridge_mod1,
+ params=["other_config:hwaddr=" +
+ self.br_mod_mac1
+ ])
+ self._vswitch.add_switch(self.bridge_mod2,
+ params=["other_config:hwaddr=" +
+ self.br_mod_mac2
+ ])
+
+ tasks.run_task(['sudo', 'iptables', '-F'],
+ self._logger, 'Clean ip tables',
+ False)
+ tasks.run_task(['sudo', 'ip', 'addr', 'add',
+ self.br_mod_ip1, 'dev', self.bridge_mod1],
+ self._logger, 'Assign ' +
+ self.br_mod_ip1 + ' to ' + self.bridge_mod1,
+ False)
+ tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod1, 'up'],
+ self._logger, 'Bring up ' + self.bridge_mod1, False)
+
+ tasks.run_task(['sudo', 'ip', 'addr', 'add',
+ self.br_mod_ip2, 'dev', self.bridge_mod2],
+ self._logger, 'Assign ' +
+ self.br_mod_ip2 + ' to ' + self.bridge_mod2,
+ False)
+ tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_mod2, 'up'],
+ self._logger, 'Bring up ' + self.bridge_mod2, False)
+
+ tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_phy1, 'up'],
+ self._logger, 'Bring up ' + self.bridge_phy1, False)
+ tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', self.bridge_phy2, 'up'],
+ self._logger, 'Bring up ' + self.bridge_phy2, False)
+ self._vswitch.add_route(self.bridge_phy1, self.br_mod_ip1, self.bridge_mod1)
+ self._vswitch.add_route(self.bridge_phy2, self.br_mod_ip2, self.bridge_mod2)
+
+ # Create tunnel ip and mac from the bridge ips
+ vxlan_local_ip1 = str(IPNetwork(self.br_mod_ip1).ip)
+ vxlan_local_ip2 = str(IPNetwork(self.br_mod_ip2).ip)
+ vxlan_rem_ip1 = str(IPNetwork(self.br_mod_ip1).ip + 1)
+ vxlan_rem_ip2 = str(IPNetwork(self.br_mod_ip2).ip + 1)
+ vxlan_rem_mac1 = EUI(int(EUI(self.br_mod_mac1)) + 1)
+ vxlan_rem_mac1.dialect = mac_unix
+ vxlan_rem_mac2 = EUI(int(EUI(self.br_mod_mac2)) + 1)
+ vxlan_rem_mac2.dialect = mac_unix
+ self._vswitch.set_tunnel_arp(vxlan_local_ip1, self.br_mod_mac1,
+ self.bridge_phy1)
+ self._vswitch.set_tunnel_arp(vxlan_local_ip2, self.br_mod_mac2,
+ self.bridge_phy2)
+ self._vswitch.set_tunnel_arp(vxlan_rem_ip1, str(vxlan_rem_mac1),
+ self.bridge_mod1)
+ self._vswitch.set_tunnel_arp(vxlan_rem_ip2, str(vxlan_rem_mac2),
+ self.bridge_mod2)
+
+ # Lets add the ports to bridges
+ (_, phy1_number) = self._vswitch.add_phy_port(self.bridge_phy1)
+ (_, phy2_number) = self._vswitch.add_phy_port(self.bridge_phy2)
+ vxlan_vni = 'options:key=' + settings.getValue('VXLAN_VNI')
+ (_, phy3_number) = self._vswitch.add_tunnel_port(self.bridge_phy1,
+ vxlan_rem_ip1,
+ "vxlan",
+ params=[vxlan_vni])
+ (_, phy4_number) = self._vswitch.add_tunnel_port(self.bridge_phy2,
+ vxlan_rem_ip2,
+ "vxlan",
+ params=[vxlan_vni])
+ [(_, phy5_number), (_, phy6_number)] = \
+ self._vswitch.add_veth_pair_port(self.bridge_mod1, self.bridge_mod2)
+
+ # Set up flows for the switches
+ self._vswitch.del_flow(self.bridge_phy1)
+ self._vswitch.del_flow(self.bridge_phy2)
+ self._vswitch.del_flow(self.bridge_mod1)
+ self._vswitch.del_flow(self.bridge_mod2)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number,
+ phy3_number)
+ self._vswitch.add_flow(self.bridge_phy1, flow)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number,
+ phy1_number)
+ self._vswitch.add_flow(self.bridge_phy1, flow)
+
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number,
+ phy4_number)
+ self._vswitch.add_flow(self.bridge_phy2, flow)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy4_number,
+ phy2_number)
+ self._vswitch.add_flow(self.bridge_phy2, flow)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy5_number,
+ 'LOCAL')
+ self._vswitch.add_flow(self.bridge_mod1, flow)
+ mod_flow_template = _FLOW_TEMPLATE.copy()
+ mod_flow_template.update({'ip':'',
+ 'actions':
+ ['mod_dl_src:' + str(vxlan_rem_mac2),
+ 'mod_dl_dst:' + self.br_mod_mac2,
+ 'mod_nw_src:' + vxlan_rem_ip2,
+ 'mod_nw_dst:' + vxlan_local_ip2
+ ]
+ })
+ flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy5_number)
+ self._vswitch.add_flow(self.bridge_mod1, flow)
+ flow = add_ports_to_flow(_FLOW_TEMPLATE, phy6_number,
+ 'LOCAL')
+ self._vswitch.add_flow(self.bridge_mod2, flow)
+ mod_flow_template = _FLOW_TEMPLATE.copy()
+ mod_flow_template.update({'ip':'',
+ 'actions':
+ ['mod_dl_src:' + str(vxlan_rem_mac1),
+ 'mod_dl_dst:' + self.br_mod_mac1,
+ 'mod_nw_src:' + vxlan_rem_ip1,
+ 'mod_nw_dst:' + vxlan_local_ip1]
+ })
+ flow = add_ports_to_flow(mod_flow_template, 'LOCAL', phy6_number)
+ self._vswitch.add_flow(self.bridge_mod2, flow)
+
+ except:
+ self._vswitch.stop()
+ raise
+
+ def stop(self):
+ """Tears down the switch created in setup().
+ """
+ self._logger.debug('Stop using ' + str(self._vswitch_class))
+ self._vswitch.stop()
+
+ def __enter__(self):
+ self.setup()
+
+ def __exit__(self, type_, value, traceback):
+ self.stop()
+
+ def get_vswitch(self):
+ """See IVswitchController for description
+ """
+ return self._vswitch
+
+ def get_ports_info(self):
+ """See IVswitchController for description
+ """
+ self._logger.debug('get_ports_info using ' + str(self._vswitch_class))
+ ports = self._vswitch.get_ports(self.bridge_phy1) +\
+ self._vswitch.get_ports(self.bridge_mod1) +\
+ self._vswitch.get_ports(self.bridge_phy2) +\
+ self._vswitch.get_ports(self.bridge_mod2)
+ return ports
+
+ def dump_vswitch_flows(self):
+ """See IVswitchController for description
+ """
+ self._logger.debug('dump_flows using ' + str(self._vswitch_class))
+ self._vswitch.dump_flows(self.bridge_phy1)
+ self._vswitch.dump_flows(self.bridge_mod1)
+ self._vswitch.dump_flows(self.bridge_phy2)
+ self._vswitch.dump_flows(self.bridge_mod2)
diff --git a/docs/userguide/integration.rst b/docs/userguide/integration.rst
index c7886536..51c2f241 100755
--- a/docs/userguide/integration.rst
+++ b/docs/userguide/integration.rst
@@ -831,3 +831,52 @@ To run GENEVE decapsulation tests:
./vsperf --conf-file user_settings.py --integration
--test-params 'tunnel_type=geneve' overlay_p2p_decap_cont
+
+Executing Tunnel encapsulation+decapsulation tests
+--------------------------------------------------
+
+The OVS DPDK encapsulation_decapsulation tests requires IPs, MAC addresses,
+bridge names and WHITELIST_NICS for DPDK.
+
+The test cases can test the tunneling encap and decap without using any ingress
+overlay traffic as compared to above test cases. To achieve this the OVS is
+configured to perform encap and decap in a series on the same traffic stream as
+given below.
+
+TRAFFIC-IN --> [ENCAP] --> [MOD-PKT] --> [DECAP] --> TRAFFIC-OUT
+
+
+Default values are already provided. To customize for your environment, override
+the following variables in you user_settings.py file:
+
+ .. code-block:: python
+
+ # Variables defined in conf/integration/02_vswitch.conf
+
+ # Bridge names
+ TUNNEL_EXTERNAL_BRIDGE1 = 'br-phy1'
+ TUNNEL_EXTERNAL_BRIDGE2 = 'br-phy2'
+ TUNNEL_MODIFY_BRIDGE1 = 'br-mod1'
+ TUNNEL_MODIFY_BRIDGE2 = 'br-mod2'
+
+ # IP of br-mod1
+ TUNNEL_MODIFY_BRIDGE_IP1 = '10.0.0.1/24'
+
+ # Mac of br-mod1
+ TUNNEL_MODIFY_BRIDGE_MAC1 = '00:00:10:00:00:01'
+
+ # IP of br-mod2
+ TUNNEL_MODIFY_BRIDGE_IP2 = '20.0.0.1/24'
+
+ #Mac of br-mod2
+ TUNNEL_MODIFY_BRIDGE_MAC2 = '00:00:20:00:00:01'
+
+ # vxlan|gre|geneve, Only VXLAN is supported for now.
+ TUNNEL_TYPE = 'vxlan'
+
+To run VXLAN encapsulation+decapsulation tests:
+
+ .. code-block:: console
+
+ ./vsperf --conf-file user_settings.py --integration
+ overlay_p2p_mod_tput
diff --git a/vswitches/ovs.py b/vswitches/ovs.py
index 243619b6..d2814b6a 100644
--- a/vswitches/ovs.py
+++ b/vswitches/ovs.py
@@ -122,6 +122,38 @@ class IVSwitchOvs(IVSwitch, tasks.Process):
"""
raise NotImplementedError
+ def add_veth_pair_port(self, switch_name=None, remote_switch_name=None,
+ local_opts=None, remote_opts=None):
+ """Creates veth-pair port between 'switch_name' and 'remote_switch_name'
+
+ """
+ if switch_name is None or remote_switch_name is None:
+ return
+
+ bridge = self._bridges[switch_name]
+ remote_bridge = self._bridges[remote_switch_name]
+ pcount = str(self._get_port_count('type=patch'))
+ # TODO ::: What if interface name longer than allowed width??
+ local_port_name = switch_name + '-' + remote_switch_name + '-' + pcount
+ remote_port_name = remote_switch_name + '-' + switch_name + '-' + pcount
+ local_params = ['--', 'set', 'Interface', local_port_name,
+ 'type=patch',
+ 'options:peer=' + remote_port_name]
+ remote_params = ['--', 'set', 'Interface', remote_port_name,
+ 'type=patch',
+ 'options:peer=' + local_port_name]
+
+ if local_opts is not None:
+ local_params = local_params + local_opts
+
+ if remote_opts is not None:
+ remote_params = remote_params + remote_opts
+
+ local_of_port = bridge.add_port(local_port_name, local_params)
+ remote_of_port = remote_bridge.add_port(remote_port_name, remote_params)
+ return [(local_port_name, local_of_port),
+ (remote_port_name, remote_of_port)]
+
def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan', params=None):
"""Creates tunneling port
"""