diff options
26 files changed, 541 insertions, 695 deletions
diff --git a/3rd_party/ixia/ixnetrfc2544.tcl b/3rd_party/ixia/ixnetrfc2544.tcl index c47e8fc1..435f335f 100644 --- a/3rd_party/ixia/ixnetrfc2544.tcl +++ b/3rd_party/ixia/ixnetrfc2544.tcl @@ -1,7 +1,7 @@ #!/usr/bin/env tclsh # Copyright (c) 2014, Ixia -# Copyright (c) 2015-2017, Intel Corporation +# Copyright (c) 2015-2018, Intel Corporation, Tieto # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -2971,7 +2971,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -trackingEnabled False \ -valueType $L4ValueType \ -activeFieldChoice False \ - -startValue {0} \ + -startValue $dstPort \ -countValue $L4CountValue sg_commit set sg_field [lindex [ixNet remapIds $sg_field] 0] diff --git a/3rd_party/ixia/ixnetrfc2544_bad_l2_crc.tcl b/3rd_party/ixia/ixnetrfc2544_bad_l2_crc.tcl index 31031ecb..5c42ea50 100644 --- a/3rd_party/ixia/ixnetrfc2544_bad_l2_crc.tcl +++ b/3rd_party/ixia/ixnetrfc2544_bad_l2_crc.tcl @@ -1,7 +1,7 @@ #!/usr/bin/env tclsh # Copyright (c) 2014, Ixia -# Copyright (c) 2015-2018, Intel Corporation +# Copyright (c) 2015-2018, Intel Corporation, Tieto # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -2971,7 +2971,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -trackingEnabled False \ -valueType $L4ValueType \ -activeFieldChoice False \ - -startValue {0} \ + -startValue $dstPort \ -countValue $L4CountValue sg_commit set sg_field [lindex [ixNet remapIds $sg_field] 0] diff --git a/3rd_party/ixia/ixnetrfc2544v2.tcl b/3rd_party/ixia/ixnetrfc2544v2.tcl index b5c0fe2a..01e7b482 100755 --- a/3rd_party/ixia/ixnetrfc2544v2.tcl +++ b/3rd_party/ixia/ixnetrfc2544v2.tcl @@ -1,7 +1,7 @@ #!/usr/bin/env tclsh # Copyright (c) 2014, Ixia -# Copyright (c) 2015-2017, Intel Corporation +# Copyright (c) 2015-2018, Intel Corporation, Tieto # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1667,7 +1667,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -trackingEnabled False \ -valueType $L4ValueType \ -activeFieldChoice False \ - -startValue {0} \ + -startValue $dstPort \ -countValue $L4CountValue # diff --git a/3rd_party/ixia/ixnetrfc2544v2_random_ip_crc.tcl b/3rd_party/ixia/ixnetrfc2544v2_random_ip_crc.tcl index 7955fd23..29cb6e83 100755 --- a/3rd_party/ixia/ixnetrfc2544v2_random_ip_crc.tcl +++ b/3rd_party/ixia/ixnetrfc2544v2_random_ip_crc.tcl @@ -1,7 +1,7 @@ #!/usr/bin/env tclsh # Copyright (c) 2014, Ixia -# Copyright (c) 2015-2017, Intel Corporation +# Copyright (c) 2015-2018, Intel Corporation, Tieto # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1667,7 +1667,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -trackingEnabled False \ -valueType $L4ValueType \ -activeFieldChoice False \ - -startValue {0} \ + -startValue $dstPort \ -countValue $L4CountValue # diff --git a/3rd_party/ixia/ixnetrfc2544v2_random_udp_crc.tcl b/3rd_party/ixia/ixnetrfc2544v2_random_udp_crc.tcl index dc35f78e..7af4b9fc 100755 --- a/3rd_party/ixia/ixnetrfc2544v2_random_udp_crc.tcl +++ b/3rd_party/ixia/ixnetrfc2544v2_random_udp_crc.tcl @@ -1,7 +1,7 @@ #!/usr/bin/env tclsh # Copyright (c) 2014, Ixia -# Copyright (c) 2015-2017, Intel Corporation +# Copyright (c) 2015-2018, Intel Corporation, Tieto # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -1667,7 +1667,7 @@ proc startRfc2544Test { testSpec trafficSpec } { -trackingEnabled False \ -valueType $L4ValueType \ -activeFieldChoice False \ - -startValue {0} \ + -startValue $dstPort \ -countValue $L4CountValue # diff --git a/ci/build-vsperf.sh b/ci/build-vsperf.sh index 265a2031..a5ee8501 100755 --- a/ci/build-vsperf.sh +++ b/ci/build-vsperf.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -44,9 +44,9 @@ RESULTS_ARCHIVE="$HOME/ci_results_archive" # CI job specific configuration # VERIFY - run basic set of TCs with default settings -TESTCASES_VERIFY="vswitch_add_del_bridge vswitch_add_del_bridges vswitch_add_del_vport vswitch_add_del_vports vswitch_vports_add_del_flow" +TESTCASES_VERIFY="vswitch_add_del_bridge vswitch_add_del_bridges vswitch_add_del_vport vswitch_add_del_vports vswitch_vports_add_del_connection" TESTPARAM_VERIFY="--integration" -TESTCASES_VERIFY_VPP="vswitch_add_del_bridge vswitch_add_del_bridges vswitch_add_del_vport vswitch_add_del_vports vswitch_vports_add_del_connection_vpp" +TESTCASES_VERIFY_VPP=$TESTCASES_VERIFY TESTPARAM_VERIFY_VPP=$TESTPARAM_VERIFY # MERGE - run selected TCs with default settings TESTCASES_MERGE=$TESTCASES_VERIFY diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf index 4a68ab3f..d766df65 100755 --- a/conf/01_testcases.conf +++ b/conf/01_testcases.conf @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -92,82 +92,6 @@ # "Dependency": [Test_Case_Name |None], # -# VPP specific macros used in TC defintions -# -VPP_P2P = [ - ['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_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]', True], - ['trafficgen', 'send_traffic', {}], - ['vswitch', 'dump_connections', 'int_br0'], - ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]', True], - ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], - ['vswitch', 'del_switch', 'int_br0'], - ] -VPP_PVP = [ - ['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 - ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], - ['vnf', 'start'], - ['trafficgen', 'send_traffic', {}], - ['vnf', 'stop'], - ['vswitch', 'dump_connections', 'int_br0'], - ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], - ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'], - ['vswitch', 'del_switch', 'int_br0'], - ] -VPP_PVVP = [ - ['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 - ['vswitch', 'add_vport', 'int_br0'], # STEP 5 - ['vswitch', 'add_vport', 'int_br0'], # STEP 6 - ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]', True], - ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], - ['vnf1', 'start'], - ['vnf2', 'start'], - ['trafficgen', 'send_traffic', {}], - ['vnf2', 'stop'], - ['vnf1', 'stop'], - ['vswitch', 'dump_connections', 'int_br0'], - ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]', True], - ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]', True], - ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[3][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[5][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'], - ['vswitch', 'del_switch', 'int_br0'], - ] - -# # Generic performance TC definitions # PERFORMANCE_TESTS = [ @@ -397,9 +321,14 @@ PERFORMANCE_TESTS = [ }, }, }, + # + # Backward compatible definition of VPP TCs. + # It will be removed after CI reporting will be fixed to use + # default TCs for VPP reporting. + # { "Name": "phy2phy_tput_vpp", - "Deployment": "clean", + "Deployment": "p2p", "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -407,11 +336,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_throughput", }, }, - "TestSteps": VPP_P2P, }, { "Name": "phy2phy_cont_vpp", - "Deployment": "clean", + "Deployment": "p2p", "Description": "VPP: Phy2Phy Continuous Stream", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -420,11 +348,10 @@ PERFORMANCE_TESTS = [ "frame_rate" : 100, }, }, - "TestSteps": VPP_P2P, }, { "Name": "phy2phy_back2back_vpp", - "Deployment": "clean", + "Deployment": "p2p", "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -432,11 +359,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_back2back", }, }, - "TestSteps": VPP_P2P, }, { "Name": "pvp_tput_vpp", - "Deployment": "clean", + "Deployment": "pvp", "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -444,11 +370,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_throughput", }, }, - "TestSteps": VPP_PVP, }, { "Name": "pvp_cont_vpp", - "Deployment": "clean", + "Deployment": "pvp", "Description": "VPP: PVP Continuous Stream", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -456,11 +381,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_continuous", }, }, - "TestSteps": VPP_PVP, }, { "Name": "pvp_back2back_vpp", - "Deployment": "clean", + "Deployment": "pvp", "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -468,11 +392,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_back2back", }, }, - "TestSteps": VPP_PVP, }, { "Name": "pvvp_tput_vpp", - "Deployment": "clean", + "Deployment": "pvvp", "Description": "VPP: LTD.Throughput.RFC2544.PacketLossRatio", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -480,11 +403,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_throughput", }, }, - "TestSteps": VPP_PVVP, }, { "Name": "pvvp_cont_vpp", - "Deployment": "clean", + "Deployment": "pvvp", "Description": "VPP: PVP Continuous Stream", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -492,11 +414,10 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_continuous", }, }, - "TestSteps": VPP_PVVP, }, { "Name": "pvvp_back2back_vpp", - "Deployment": "clean", + "Deployment": "pvvp", "Description": "VPP: LTD.Throughput.RFC2544.BackToBackFrames", "vSwitch" : "VppDpdkVhost", "Parameters" : { @@ -504,6 +425,5 @@ PERFORMANCE_TESTS = [ "traffic_type" : "rfc2544_back2back", }, }, - "TestSteps": VPP_PVVP, }, ] diff --git a/conf/02_vswitch.conf b/conf/02_vswitch.conf index 61131a77..84ef71cb 100644 --- a/conf/02_vswitch.conf +++ b/conf/02_vswitch.conf @@ -210,6 +210,15 @@ OVS_VSCTL_ARGS = [] OVS_OFCTL_ARGS = ['-O', 'OpenFlow13'] # backward compatible default value OVS_APPCTL_ARGS = [] +# default flow template to be used by OVS classes +OVS_FLOW_TEMPLATE = { + 'idle_timeout': '0' +} + +# enable or disable configuration of routing tables; See vswitchperf_design.rst +# for details. +OVS_ROUTING_TABLES = False + ######################### ## VPP ######################### diff --git a/conf/03_traffic.conf b/conf/03_traffic.conf index f043b4ca..597f2ceb 100644 --- a/conf/03_traffic.conf +++ b/conf/03_traffic.conf @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -64,7 +64,6 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log' # feature. If enabled, it will implicitly insert a flow # for each stream. If multistream is disabled, then # pre-installed flows will be ignored. -# Note: It is supported only for p2p deployment scenario. # Data type: str # Supported values: # "Yes" - flows will be inserted into OVS diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf index 945b36f7..7daff217 100644 --- a/conf/integration/01_testcases.conf +++ b/conf/integration/01_testcases.conf @@ -35,7 +35,9 @@ # Common TestSteps parts ("macros") # +# # P2P macros +# STEP_VSWITCH_P2P_INIT = [ ['vswitch', 'add_switch', 'int_br0'], # STEP 0 ['vswitch', 'add_phy_port', 'int_br0'], # STEP 1 @@ -48,6 +50,18 @@ STEP_VSWITCH_P2P_FINIT = [ ['vswitch', 'del_switch', 'int_br0'], ] +STEP_VSWITCH_P2P_CONNECTIONS_INIT = STEP_VSWITCH_P2P_INIT + [ + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]'], +] + +STEP_VSWITCH_P2P_CONNECTIONS_FINIT = [ + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[1][0]'], +] + STEP_VSWITCH_P2P_FINIT + +# P2P OVS specific macros STEP_VSWITCH_P2P_FLOWS_INIT = STEP_VSWITCH_P2P_INIT + [ ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[2][1]', 'actions': ['output:#STEP[1][1]'], 'idle_timeout': '0'}], @@ -59,7 +73,9 @@ STEP_VSWITCH_P2P_FLOWS_FINIT = [ ['vswitch', 'del_flow', 'int_br0', {'in_port': '#STEP[2][1]'}], ] + STEP_VSWITCH_P2P_FINIT -# PVP and PVVP macros +# +# PVP macros +# STEP_VSWITCH_PVP_INIT = STEP_VSWITCH_P2P_INIT + [ ['vswitch', 'add_vport', 'int_br0'], # STEP 3 vm1 ports ['vswitch', 'add_vport', 'int_br0'], # STEP 4 @@ -70,6 +86,22 @@ STEP_VSWITCH_PVP_FINIT = [ ['vswitch', 'del_port', 'int_br0', '#STEP[4][0]'], ] + STEP_VSWITCH_P2P_FINIT +STEP_VSWITCH_PVP_CONNECTIONS_INIT = STEP_VSWITCH_PVP_INIT + [ + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]'], +] + +STEP_VSWITCH_PVP_CONNECTIONS_FINIT = [ + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[2][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[4][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]'], +] + STEP_VSWITCH_PVP_FINIT + +# PVP OVS specific macros STEP_VSWITCH_PVP_FLOWS_INIT = STEP_VSWITCH_PVP_INIT + [ ['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'}], @@ -85,6 +117,9 @@ STEP_VSWITCH_PVP_FLOWS_FINIT = [ ['vswitch', 'del_flow', 'int_br0', {'in_port': '#STEP[3][1]'}], ] + STEP_VSWITCH_PVP_FINIT +# +# PVVP macros +# STEP_VSWITCH_PVVP_INIT = STEP_VSWITCH_PVP_INIT + [ ['vswitch', 'add_vport', 'int_br0'], # STEP 5 vm2 ports ['vswitch', 'add_vport', 'int_br0'], # STEP 6 @@ -95,6 +130,26 @@ STEP_VSWITCH_PVVP_FINIT = [ ['vswitch', 'del_port', 'int_br0', '#STEP[6][0]'], ] + STEP_VSWITCH_PVP_FINIT +STEP_VSWITCH_PVVP_CONNECTIONS_INIT = STEP_VSWITCH_PVVP_INIT + [ + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]'], +] + +STEP_VSWITCH_PVVP_CONNECTIONS_FINIT = [ + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[3][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[4][0]', '#STEP[5][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[6][0]', '#STEP[2][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[2][0]', '#STEP[6][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[5][0]', '#STEP[4][0]'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[3][0]', '#STEP[1][0]'], +] + STEP_VSWITCH_PVVP_FINIT + +# PVVP OVS specific macros STEP_VSWITCH_PVVP_FLOWS_INIT = STEP_VSWITCH_PVVP_INIT + [ ['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[5][1]'], 'idle_timeout': '0'}], @@ -255,9 +310,49 @@ INTEGRATION_TESTS = [ ] }, { + "Name": "vswitch_add_del_connection", + "Deployment": "clean", + "Description": "vSwitch - add and delete connection", + "TestSteps": [ + ['vswitch', 'add_switch', 'int_br0'], + ['vswitch', 'add_phy_port', 'int_br0'], + ['vswitch', 'add_phy_port', 'int_br0'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] + }, + { + "Name": "vswitch_vports_add_del_connection", + "Deployment": "clean", + "Description": "vSwitch - add and delete connection", + "Description": "vSwitch - configure switch with vports, add and delete connection", + "TestSteps": [ + ['vswitch', 'add_switch', 'int_br0'], + ['vswitch', 'add_vport', 'int_br0'], + ['vswitch', 'add_vport', 'int_br0'], + ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'dump_connections', 'int_br0'], + ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] + }, + { + "Name": "vswitch_add_del_connections", + "Deployment": "clean", + "Description": "vSwitch - add and delete connections", + "TestSteps": STEP_VSWITCH_P2P_CONNECTIONS_INIT + + STEP_VSWITCH_P2P_CONNECTIONS_FINIT + }, + { "Name": "vswitch_add_del_flow", "Deployment": "clean", - "Description": "vSwitch - add and delete flow", + "Description": "OVS: vSwitch - add and delete flow", "TestSteps": [ ['vswitch', 'add_switch', 'int_br0'], ['vswitch', 'add_phy_port', 'int_br0'], @@ -272,7 +367,7 @@ INTEGRATION_TESTS = [ { "Name": "vswitch_vports_add_del_flow", "Deployment": "clean", - "Description": "vSwitch - configure switch with vports, add and delete flow", + "Description": "OVS: vSwitch - configure switch with vports, add and delete flow", "TestSteps": [ ['vswitch', 'add_switch', 'int_br0'], ['vswitch', 'add_vport', 'int_br0'], @@ -287,7 +382,7 @@ INTEGRATION_TESTS = [ { "Name": "vswitch_add_del_flows", "Deployment": "clean", - "Description": "vSwitch - add and delete flows", + "Description": "OVS: vSwitch - add and delete flows", "TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT + STEP_VSWITCH_P2P_FLOWS_FINIT }, @@ -295,31 +390,31 @@ INTEGRATION_TESTS = [ "Name": "vswitch_p2p_tput", "Deployment": "clean", "Description": "vSwitch - configure switch and execute RFC2544 throughput test", - "TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_P2P_CONNECTIONS_INIT + [ ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput', 'bidir' : 'True'}], ] + - STEP_VSWITCH_P2P_FLOWS_FINIT + STEP_VSWITCH_P2P_CONNECTIONS_FINIT }, { "Name": "vswitch_p2p_back2back", "Deployment": "clean", "Description": "vSwitch - configure switch and execute RFC2544 back2back test", - "TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_P2P_CONNECTIONS_INIT + [ ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_back2back', 'bidir' : 'True'}], ] + - STEP_VSWITCH_P2P_FLOWS_FINIT + STEP_VSWITCH_P2P_CONNECTIONS_FINIT }, { "Name": "vswitch_p2p_cont", "Deployment": "clean", "Description": "vSwitch - configure switch and execute RFC2544 continuous stream test", - "TestSteps": STEP_VSWITCH_P2P_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_P2P_CONNECTIONS_INIT + [ ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'True'}], ] + - STEP_VSWITCH_P2P_FLOWS_FINIT + STEP_VSWITCH_P2P_CONNECTIONS_FINIT }, { "Name": "vswitch_pvp", @@ -351,43 +446,43 @@ INTEGRATION_TESTS = [ "Name": "vswitch_pvp_tput", "Deployment": "clean", "Description": "vSwitch - configure switch, vnf and execute RFC2544 throughput test", - "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVP_CONNECTIONS_INIT + [ ['vnf', 'start'], ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput', 'bidir' : 'True'}], ['vnf', 'stop'], ] + - STEP_VSWITCH_PVP_FLOWS_FINIT + STEP_VSWITCH_PVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvp_back2back", "Deployment": "clean", "Description": "vSwitch - configure switch, vnf and execute RFC2544 back2back test", - "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVP_CONNECTIONS_INIT + [ ['vnf', 'start'], ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_back2back', 'bidir' : 'True'}], ['vnf', 'stop'], ] + - STEP_VSWITCH_PVP_FLOWS_FINIT + STEP_VSWITCH_PVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvp_cont", "Deployment": "clean", "Description": "vSwitch - configure switch, vnf and execute RFC2544 continuous stream test", - "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVP_CONNECTIONS_INIT + [ ['vnf', 'start'], ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'True'}], ['vnf', 'stop'], ] + - STEP_VSWITCH_PVP_FLOWS_FINIT + STEP_VSWITCH_PVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvp_all", "Deployment": "clean", "Description": "vSwitch - configure switch, vnf and execute all test types", - "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVP_CONNECTIONS_INIT + [ ['vnf', 'start'], ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput', 'bidir' : 'True'}], @@ -395,7 +490,7 @@ INTEGRATION_TESTS = [ ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'True'}], ['vnf', 'stop'], ] + - STEP_VSWITCH_PVP_FLOWS_FINIT + STEP_VSWITCH_PVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvvp", @@ -414,7 +509,7 @@ INTEGRATION_TESTS = [ "Name": "vswitch_pvvp_tput", "Deployment": "clean", "Description": "vSwitch - configure switch, two chained vnfs and execute RFC2544 throughput test", - "TestSteps": STEP_VSWITCH_PVVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVVP_CONNECTIONS_INIT + [ ['vnf1', 'start'], ['vnf2', 'start'], @@ -422,13 +517,13 @@ INTEGRATION_TESTS = [ ['vnf1', 'stop'], ['vnf2', 'stop'], ] + - STEP_VSWITCH_PVVP_FLOWS_FINIT + STEP_VSWITCH_PVVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvvp_back2back", "Deployment": "clean", "Description": "vSwitch - configure switch, two chained vnfs and execute RFC2544 back2back test", - "TestSteps": STEP_VSWITCH_PVVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVVP_CONNECTIONS_INIT + [ ['vnf1', 'start'], ['vnf2', 'start'], @@ -436,13 +531,13 @@ INTEGRATION_TESTS = [ ['vnf1', 'stop'], ['vnf2', 'stop'], ] + - STEP_VSWITCH_PVVP_FLOWS_FINIT + STEP_VSWITCH_PVVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvvp_cont", "Deployment": "clean", "Description": "vSwitch - configure switch, two chained vnfs and execute RFC2544 continuous stream test", - "TestSteps": STEP_VSWITCH_PVVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVVP_CONNECTIONS_INIT + [ ['vnf1', 'start'], ['vnf2', 'start'], @@ -450,13 +545,13 @@ INTEGRATION_TESTS = [ ['vnf1', 'stop'], ['vnf2', 'stop'], ] + - STEP_VSWITCH_PVVP_FLOWS_FINIT + STEP_VSWITCH_PVVP_CONNECTIONS_FINIT }, { "Name": "vswitch_pvvp_all", "Deployment": "clean", "Description": "vSwitch - configure switch, two chained vnfs and execute all test types", - "TestSteps": STEP_VSWITCH_PVVP_FLOWS_INIT + + "TestSteps": STEP_VSWITCH_PVVP_CONNECTIONS_INIT + [ ['vnf1', 'start'], ['vnf2', 'start'], @@ -466,7 +561,7 @@ INTEGRATION_TESTS = [ ['vnf1', 'stop'], ['vnf2', 'stop'], ] + - STEP_VSWITCH_PVVP_FLOWS_FINIT + STEP_VSWITCH_PVVP_CONNECTIONS_FINIT }, { "Name": "vswitch_p4vp_tput", @@ -682,23 +777,6 @@ INTEGRATION_TESTS = [ ['tools', 'assert', 'len(#STEP[-1][0])'], ] }, - { - "Name": "vswitch_vports_add_del_connection_vpp", - "Deployment": "clean", - "Description": "VPP: vSwitch - configure switch with vports, add and delete connection", - "vSwitch" : "VppDpdkVhost", - "TestSteps": [ - ['vswitch', 'add_switch', 'int_br0'], - ['vswitch', 'add_vport', 'int_br0'], - ['vswitch', 'add_vport', 'int_br0'], - ['vswitch', 'add_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], - ['vswitch', 'dump_connections', 'int_br0'], - ['vswitch', 'del_connection', 'int_br0', '#STEP[1][0]', '#STEP[2][0]', True], - ['vswitch', 'del_port', 'int_br0', '#STEP[1][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[2][0]'], - ['vswitch', 'del_switch', 'int_br0'], - ] - }, # # END of VPP tests used by VERIFY and MERGE jobs by OPNFV Jenkins # @@ -874,11 +952,11 @@ INTEGRATION_TESTS += [ # "VNF" : "QemuVirtioNet", # "Trafficgen": "IxNet", # "Parameters": {"GUEST_LOOPBACK" : ["linux_bridge"],}, -# "TestSteps": STEP_VSWITCH_PVP_FLOWS_INIT + +# "TestSteps": STEP_VSWITCH_PVP_CONNECTIONS_INIT + # [ # ['vnf', 'start'], # ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'True'}], # ['vnf', 'stop'], # ] + -# STEP_VSWITCH_PVP_FLOWS_FINIT +# STEP_VSWITCH_PVP_CONNECTIONS_FINIT # }, diff --git a/conf/integration/01c_trex_vm_tests.conf b/conf/integration/01c_trex_vm_tests.conf index 50982bea..1bec4efd 100644 --- a/conf/integration/01c_trex_vm_tests.conf +++ b/conf/integration/01c_trex_vm_tests.conf @@ -30,6 +30,7 @@ TREX_VM_INIT = [ ['#trex_p2', 'vswitch', 'add_vport', 'int_br0'], # configure IP access to T-Rex VM ['vswitch', 'add_switch', 'trex_br'], + ['vswitch', 'add_flow', 'trex_br', {'actions': ['NORMAL']}], # turn on MAC learning mode ['#trex_admin', 'vswitch', 'add_vport', 'trex_br'], ['#trex_spare', 'vswitch', 'add_vport', 'trex_br'], # spare to have even number of NICs ['tools', 'exec_shell', 'sudo ip addr flush dev trex_br'], diff --git a/core/component_factory.py b/core/component_factory.py index b6bd2677..2c51a060 100644 --- a/core/component_factory.py +++ b/core/component_factory.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -66,23 +66,23 @@ def create_vswitch(deployment_scenario, vswitch_class, traffic, :return: IVSwitchController for the deployment_scenario """ # pylint: disable=too-many-return-statements - deployment_scenario = deployment_scenario.lower() - if deployment_scenario.startswith("p2p"): - return VswitchControllerP2P(vswitch_class, traffic) - elif deployment_scenario.startswith("pvp"): - return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic) - elif deployment_scenario.startswith("pvvp"): - return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic) - elif deployment_scenario.startswith("pvpv"): - return VswitchControllerPXP(deployment_scenario, vswitch_class, traffic) - elif deployment_scenario.startswith("op2p"): - return VswitchControllerOP2P(vswitch_class, traffic, tunnel_operation) - elif deployment_scenario.startswith("ptunp"): - return VswitchControllerPtunP(vswitch_class, traffic) - elif deployment_scenario.startswith("clean"): - return VswitchControllerClean(vswitch_class, traffic) + deployment = deployment_scenario.lower() + if deployment.startswith("p2p"): + return VswitchControllerP2P(deployment, vswitch_class, traffic) + elif deployment.startswith("pvp"): + return VswitchControllerPXP(deployment, vswitch_class, traffic) + elif deployment.startswith("pvvp"): + return VswitchControllerPXP(deployment, vswitch_class, traffic) + elif deployment.startswith("pvpv"): + return VswitchControllerPXP(deployment, vswitch_class, traffic) + elif deployment.startswith("op2p"): + return VswitchControllerOP2P(deployment, vswitch_class, traffic, tunnel_operation) + elif deployment.startswith("ptunp"): + return VswitchControllerPtunP(deployment, vswitch_class, traffic) + elif deployment.startswith("clean"): + return VswitchControllerClean(deployment, vswitch_class, traffic) else: - raise RuntimeError("Unknown deployment scenario '{}'.".format(deployment_scenario)) + raise RuntimeError("Unknown deployment scenario '{}'.".format(deployment)) def create_vnf(deployment_scenario, vnf_class, extra_vnfs): diff --git a/core/pktfwd_controller.py b/core/pktfwd_controller.py index bdc91822..363302c3 100644 --- a/core/pktfwd_controller.py +++ b/core/pktfwd_controller.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -89,9 +89,9 @@ class PktFwdController(object): """ return self._pktfwd - def dump_vswitch_flows(self): - """ Dumps flows from vswitch + def dump_vswitch_connections(self): + """ Dumps connections from vswitch """ raise NotImplementedError( "The PktFwdController does not implement the " - "\"dump_vswitch_flows\" function.") + "\"dump_vswitch_connections\" function.") diff --git a/core/vswitch_controller.py b/core/vswitch_controller.py index 855de8b2..889f14bc 100644 --- a/core/vswitch_controller.py +++ b/core/vswitch_controller.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,33 +13,57 @@ # limitations under the License. """Interface for deployment specific vSwitch controllers """ +import logging class IVswitchController(object): - """Abstract class which defines a vSwitch controller object + """Interface class for a vSwitch controller object This interface is used to setup and control a vSwitch provider for a particular deployment scenario. """ - def __enter__(self): + def __init__(self, deployment, vswitch_class, traffic): + """Initializes up the generic prerequisites for deployment scenario. + + :deployment: the deployment scenario to configure + :vswitch_class: the vSwitch class to be used. + :traffic: dictionary with detailed traffic definition + """ + self._logger = logging.getLogger(__name__) + self._vswitch_class = vswitch_class + self._vswitch = vswitch_class() + self._deployment_scenario = deployment + self._logger.debug('Creation using %s', str(self._vswitch_class)) + self._traffic = traffic.copy() + self._bridge = None + + def setup(self): """Sets up the switch for the particular deployment scenario """ raise NotImplementedError( "The VswitchController does not implement the \"setup\" function.") - def __exit__(self, type_, value, traceback): + def stop(self): """Tears down the switch created in setup() """ raise NotImplementedError( "The VswitchController does not implement the \"stop\" function.") + def __enter__(self): + """Sets up the switch for the particular deployment scenario + """ + self.setup() + + def __exit__(self, type_, value, traceback): + """Tears down the switch created in setup() + """ + self.stop() + def get_vswitch(self): """Get the controlled vSwitch :return: The controlled IVswitch """ - raise NotImplementedError( - "The VswitchController does not implement the \"get_vswitch\" " - "function.") + return self._vswitch def get_ports_info(self): """Returns a dictionary describing all ports on the vSwitch. @@ -50,9 +74,9 @@ class IVswitchController(object): "The VswitchController does not implement the \"get_ports_info\" " "function.") - def dump_vswitch_flows(self): - """ Dumps flows from vswitch + def dump_vswitch_connections(self): + """ Dumps connections from vswitch """ raise NotImplementedError( "The VswitchController does not implement the " - "\"dump_vswitch_flows\" function.") + "\"dump_vswitch_connections\" function.") diff --git a/core/vswitch_controller_clean.py b/core/vswitch_controller_clean.py index 432406a7..7a771226 100644 --- a/core/vswitch_controller_clean.py +++ b/core/vswitch_controller_clean.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,9 +14,6 @@ """VSwitch controller for basic initialization of vswitch """ - -import logging - from core.vswitch_controller import IVswitchController class VswitchControllerClean(IVswitchController): @@ -28,18 +25,6 @@ class VswitchControllerClean(IVswitchController): _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 Clean 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 = "Clean" - self._logger.debug('Creation using %s', str(self._vswitch_class)) - self._traffic = traffic.copy() - def setup(self): """Sets up the switch for Clean. """ @@ -57,23 +42,12 @@ class VswitchControllerClean(IVswitchController): self._logger.debug('Stop using %s', 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 """ pass - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ pass diff --git a/core/vswitch_controller_op2p.py b/core/vswitch_controller_op2p.py index 3f879f9f..072a690a 100644 --- a/core/vswitch_controller_op2p.py +++ b/core/vswitch_controller_op2p.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,39 +14,19 @@ """VSwitch controller for Physical to Tunnel Endpoint to Physical deployment """ - -import logging - from core.vswitch_controller import IVswitchController from vswitches.utils import add_ports_to_flow from conf import settings as S from tools import tasks -_FLOW_TEMPLATE = { - 'idle_timeout': '0' -} - class VswitchControllerOP2P(IVswitchController): """VSwitch controller for OP2P deployment scenario. - - 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, tunnel_operation=None): - """Initializes up the prerequisites for the OP2P deployment scenario. - - :vswitch_class: the vSwitch class to be used. + def __init__(self, deployment, vswitch_class, traffic, tunnel_operation=None): + """See IVswitchController for general description """ - self._logger = logging.getLogger(__name__) - self._vswitch_class = vswitch_class - self._vswitch = vswitch_class() - self._deployment_scenario = "OP2P" - self._traffic = traffic.copy() + super().__init__(deployment, vswitch_class, traffic) self._tunnel_operation = tunnel_operation - self._logger.debug('Creation using %s', str(self._vswitch_class)) def setup(self): """ Sets up the switch for overlay P2P (tunnel encap or decap) @@ -118,10 +98,13 @@ class VswitchControllerOP2P(IVswitchController): # Test is unidirectional for now self._vswitch.del_flow(bridge) - flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy1_number, + flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy1_number, phy2_number) self._vswitch.add_flow(bridge, flow1) - + # enable MAC learning mode at external bridge + flow_ext = S.getValue('OVS_FLOW_TEMPLATE').copy() + flow_ext.update({'actions': ['NORMAL']}) + self._vswitch.add_flow(bridge_ext, flow_ext) except: self._vswitch.stop() raise @@ -178,7 +161,7 @@ class VswitchControllerOP2P(IVswitchController): bridge) # Test is unidirectional for now self._vswitch.del_flow(bridge_ext) - flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number, + flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy3_number, phy2_number) self._vswitch.add_flow(bridge_ext, flow1) @@ -251,7 +234,7 @@ class VswitchControllerOP2P(IVswitchController): # Test is unidirectional for now self._vswitch.del_flow(bridge_ext) - flow1 = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, 'LOCAL') + flow1 = add_ports_to_flow(S.getValue('OVS_FLOW_TEMPLATE'), phy2_number, 'LOCAL') self._vswitch.add_flow(bridge_ext, flow1) except: @@ -264,17 +247,6 @@ class VswitchControllerOP2P(IVswitchController): self._logger.debug('Stop using %s', 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 """ @@ -286,8 +258,8 @@ class VswitchControllerOP2P(IVswitchController): self._vswitch.get_ports( S.getValue('TUNNEL_EXTERNAL_BRIDGE')) - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._vswitch.dump_flows(S.getValue('TUNNEL_INTEGRATION_BRIDGE')) - self._vswitch.dump_flows(S.getValue('TUNNEL_EXTERNAL_BRIDGE')) + self._vswitch.dump_connections(S.getValue('TUNNEL_INTEGRATION_BRIDGE')) + self._vswitch.dump_connections(S.getValue('TUNNEL_EXTERNAL_BRIDGE')) diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py index eb1f57f0..d8f22e4c 100644 --- a/core/vswitch_controller_p2p.py +++ b/core/vswitch_controller_p2p.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,20 +14,9 @@ """VSwitch controller for Physical to Physical deployment """ - -import logging -import netaddr - from core.vswitch_controller import IVswitchController from conf import settings -_FLOW_TEMPLATE = { - 'idle_timeout': '0' -} - -_PROTO_TCP = 6 -_PROTO_UDP = 17 - class VswitchControllerP2P(IVswitchController): """VSwitch controller for P2P deployment scenario. @@ -37,17 +26,11 @@ class VswitchControllerP2P(IVswitchController): _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 P2P deployment scenario. - - :vswitch_class: the vSwitch class to be used. + def __init__(self, deployment, vswitch_class, traffic): + """See IVswitchController for general description """ - self._logger = logging.getLogger(__name__) - self._vswitch_class = vswitch_class - self._vswitch = vswitch_class() - self._deployment_scenario = "P2P" - self._logger.debug('Creation using %s', str(self._vswitch_class)) - self._traffic = traffic.copy() + super().__init__(deployment, vswitch_class, traffic) + self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME') def setup(self): """Sets up the switch for p2p. @@ -57,51 +40,14 @@ class VswitchControllerP2P(IVswitchController): try: self._vswitch.start() - bridge = settings.getValue('VSWITCH_BRIDGE_NAME') - self._vswitch.add_switch(bridge) - - (_, _) = self._vswitch.add_phy_port(bridge) - (_, _) = self._vswitch.add_phy_port(bridge) - - self._vswitch.del_flow(bridge) - - # table#0 - flows designed to force 5 & 13 tuple matches go here - flow = {'table':'0', 'priority':'1', 'actions': ['goto_table:1']} - self._vswitch.add_flow(bridge, flow) - - # table#1 - flows to route packets between ports goes here. The - # chosen port is communicated to subsequent tables by setting the - # metadata value to the egress port number + self._vswitch.add_switch(self._bridge) - # configure flows according to the TC definition - flow_template = _FLOW_TEMPLATE.copy() - if self._traffic['flow_type'] == 'IP': - flow_template.update({'dl_type':'0x0800', 'nw_src':self._traffic['l3']['srcip'], - 'nw_dst':self._traffic['l3']['dstip']}) + (port1, _) = self._vswitch.add_phy_port(self._bridge) + (port2, _) = self._vswitch.add_phy_port(self._bridge) - flow = flow_template.copy() - flow.update({'table':'1', 'priority':'1', 'in_port':'1', - 'actions': ['write_actions(output:2)', 'write_metadata:0x2', - 'goto_table:2']}) - self.process_flow_template(bridge, flow) - flow = flow_template.copy() - flow.update({'table':'1', 'priority':'1', 'in_port':'2', - 'actions': ['write_actions(output:1)', 'write_metadata:0x1', - 'goto_table:2']}) - self.process_flow_template(bridge, flow) + self._vswitch.add_connection(self._bridge, port1, port2, self._traffic) + self._vswitch.add_connection(self._bridge, port2, port1, self._traffic) - # Frame modification table. Frame modification flow rules are - # isolated in this table so that they can be turned on or off - # without affecting the routing or tuple-matching flow rules. - flow = {'table':'2', 'priority':'1', 'actions': ['goto_table:3']} - self._vswitch.add_flow(bridge, flow) - - # Egress table - # (TODO) Billy O'Mahony - the drop action here actually required in - # order to egress the packet. This is the subject of a thread on - # ovs-discuss 2015-06-30. - flow = {'table':'3', 'priority':'1', 'actions': ['drop']} - self._vswitch.add_flow(bridge, flow) except: self._vswitch.stop() raise @@ -112,65 +58,13 @@ class VswitchControllerP2P(IVswitchController): self._logger.debug('Stop using %s', 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 %s', str(self._vswitch_class)) - return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) + return self._vswitch.get_ports(self._bridge) - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._vswitch.dump_flows(settings.getValue('VSWITCH_BRIDGE_NAME')) - - def process_flow_template(self, bridge, flow_template): - """Method adds flows into the vswitch based on given flow template - and configuration of multistream feature. - """ - if ('pre_installed_flows' in self._traffic and - self._traffic['pre_installed_flows'].lower() == 'yes' and - 'multistream' in self._traffic and self._traffic['multistream'] > 0 and - 'stream_type' in self._traffic): - # multistream feature is enabled and flows should be inserted into OVS - # so generate flows based on template and multistream configuration - if self._traffic['stream_type'] == 'L2': - # iterate through destimation MAC address - dst_mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value - for i in range(self._traffic['multistream']): - tmp_mac = netaddr.EUI(dst_mac_value + i) - tmp_mac.dialect = netaddr.mac_unix_expanded - flow_template.update({'dl_dst':tmp_mac}) - # optimize flow insertion by usage of cache - self._vswitch.add_flow(bridge, flow_template, cache='on') - elif self._traffic['stream_type'] == 'L3': - # iterate through destimation IP address - dst_ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value - for i in range(self._traffic['multistream']): - tmp_ip = netaddr.IPAddress(dst_ip_value + i) - flow_template.update({'dl_type':'0x0800', 'nw_dst':tmp_ip}) - # optimize flow insertion by usage of cache - self._vswitch.add_flow(bridge, flow_template, cache='on') - elif self._traffic['stream_type'] == 'L4': - # read transport protocol from configuration and iterate through its destination port - proto = _PROTO_TCP if self._traffic['l3']['proto'].lower() == 'tcp' else _PROTO_UDP - for i in range(self._traffic['multistream']): - flow_template.update({'dl_type':'0x0800', 'nw_proto':proto, 'tp_dst':i}) - # optimize flow insertion by usage of cache - self._vswitch.add_flow(bridge, flow_template, cache='on') - else: - self._logger.error('Stream type is set to uknown value %s', self._traffic['stream_type']) - # insert cached flows into the OVS - self._vswitch.add_flow(bridge, [], cache='flush') - else: - self._vswitch.add_flow(bridge, flow_template) + self._vswitch.dump_connections(self._bridge) diff --git a/core/vswitch_controller_ptunp.py b/core/vswitch_controller_ptunp.py index 853c7d5c..b10da2a9 100644 --- a/core/vswitch_controller_ptunp.py +++ b/core/vswitch_controller_ptunp.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,8 +15,6 @@ """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 @@ -24,10 +22,6 @@ 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 @@ -40,16 +34,10 @@ class VswitchControllerPtunP(IVswitchController): _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. + def __init__(self, deployment, vswitch_class, traffic): + """See IVswitchController for general description """ - self._logger = logging.getLogger(__name__) - self._vswitch_class = vswitch_class - self._vswitch = vswitch_class() - self._deployment_scenario = "ptunp" - self._traffic = traffic.copy() + super().__init__(deployment, vswitch_class, traffic) self.bridge_phy1 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE1') self.bridge_phy2 = settings.getValue('TUNNEL_EXTERNAL_BRIDGE2') self.bridge_mod1 = settings.getValue('TUNNEL_MODIFY_BRIDGE1') @@ -59,7 +47,6 @@ class VswitchControllerPtunP(IVswitchController): 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 %s', str(self._vswitch_class)) def setup(self): """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap) @@ -156,23 +143,23 @@ class VswitchControllerPtunP(IVswitchController): 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, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy1_number, phy3_number) self._vswitch.add_flow(self.bridge_phy1, flow) - flow = add_ports_to_flow(_FLOW_TEMPLATE, phy3_number, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy3_number, phy1_number) self._vswitch.add_flow(self.bridge_phy1, flow) - flow = add_ports_to_flow(_FLOW_TEMPLATE, phy2_number, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy2_number, phy4_number) self._vswitch.add_flow(self.bridge_phy2, flow) - flow = add_ports_to_flow(_FLOW_TEMPLATE, phy4_number, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy4_number, phy2_number) self._vswitch.add_flow(self.bridge_phy2, flow) - flow = add_ports_to_flow(_FLOW_TEMPLATE, phy5_number, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy5_number, 'LOCAL') self._vswitch.add_flow(self.bridge_mod1, flow) - mod_flow_template = _FLOW_TEMPLATE.copy() + mod_flow_template = settings.getValue('OVS_FLOW_TEMPLATE').copy() mod_flow_template.update({'ip':'', 'actions': ['mod_dl_src:' + str(vxlan_rem_mac2), @@ -183,10 +170,10 @@ class VswitchControllerPtunP(IVswitchController): }) 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, + flow = add_ports_to_flow(settings.getValue('OVS_FLOW_TEMPLATE'), phy6_number, 'LOCAL') self._vswitch.add_flow(self.bridge_mod2, flow) - mod_flow_template = _FLOW_TEMPLATE.copy() + mod_flow_template = settings.getValue('OVS_FLOW_TEMPLATE').copy() mod_flow_template.update({'ip':'', 'actions': ['mod_dl_src:' + str(vxlan_rem_mac1), @@ -207,17 +194,6 @@ class VswitchControllerPtunP(IVswitchController): self._logger.debug('Stop using %s', 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 """ @@ -228,11 +204,11 @@ class VswitchControllerPtunP(IVswitchController): self._vswitch.get_ports(self.bridge_mod2) return ports - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._logger.debug('dump_flows using %s', 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) + self._logger.debug('dump_connections using %s', str(self._vswitch_class)) + self._vswitch.dump_connections(self.bridge_phy1) + self._vswitch.dump_connections(self.bridge_mod1) + self._vswitch.dump_connections(self.bridge_phy2) + self._vswitch.dump_connections(self.bridge_mod2) diff --git a/core/vswitch_controller_pxp.py b/core/vswitch_controller_pxp.py index e3c208a3..d36ecdba 100644 --- a/core/vswitch_controller_pxp.py +++ b/core/vswitch_controller_pxp.py @@ -1,4 +1,4 @@ -# Copyright 2016 Intel Corporation. +# Copyright 2016-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,34 +14,18 @@ """VSwitch controller for multi VM scenarios with serial or parallel connection """ - -import logging import netaddr from core.vswitch_controller import IVswitchController -from vswitches.utils import add_ports_to_flow from conf import settings -_FLOW_TEMPLATE = { - 'idle_timeout': '0' -} - -_PROTO_TCP = 6 -_PROTO_UDP = 17 - class VswitchControllerPXP(IVswitchController): """VSwitch controller for PXP deployment scenario. """ def __init__(self, deployment, vswitch_class, traffic): - """Initializes up the prerequisites for the PXP deployment scenario. - - :vswitch_class: the vSwitch class to be used. - :deployment: the deployment scenario to configure - :traffic: dictionary with detailed traffic definition + """See IVswitchController for general description """ - self._logger = logging.getLogger(__name__) - self._vswitch_class = vswitch_class - self._vswitch = vswitch_class() + super().__init__(deployment, vswitch_class, traffic) self._pxp_topology = 'parallel' if deployment.startswith('pvpv') else 'serial' if deployment == 'pvp': self._pxp_vm_count = 1 @@ -55,9 +39,7 @@ class VswitchControllerPXP(IVswitchController): self._deployment_scenario = deployment - self._traffic = traffic.copy() self._bidir = True if self._traffic['bidir'] == 'True' else False - self._logger.debug('Creation using %s', str(self._vswitch_class)) self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME') def setup(self): @@ -71,8 +53,8 @@ class VswitchControllerPXP(IVswitchController): self._vswitch.add_switch(self._bridge) # create physical ports - (_, phy1_number) = self._vswitch.add_phy_port(self._bridge) - (_, phy2_number) = self._vswitch.add_phy_port(self._bridge) + (phy1, _) = self._vswitch.add_phy_port(self._bridge) + (phy2, _) = self._vswitch.add_phy_port(self._bridge) # create VM ports # initialize vport array to requested number of VMs @@ -86,54 +68,42 @@ class VswitchControllerPXP(IVswitchController): self._logger.debug('Create %s vports for %s. VM with index %s', nics_nr, vmindex + 1, vmindex) for _ in range(nics_nr): - (_, vport) = self._vswitch.add_vport(self._bridge) + (vport, _) = self._vswitch.add_vport(self._bridge) vm_ports[vmindex].append(vport) - self._vswitch.del_flow(self._bridge) - - # configure flows according to the TC definition + # configure connections according to the TC definition if self._pxp_topology == 'serial': - flow = _FLOW_TEMPLATE.copy() - if self._traffic['flow_type'] == 'IP': - flow.update({'dl_type':'0x0800', - 'nw_src':self._traffic['l3']['srcip'], - 'nw_dst':self._traffic['l3']['dstip']}) + # NOTE: all traffic from VMs is sent to other ports directly + # without applying traffic options to avoid issues with MAC swapping + # and upper layer mods performed inside guests - # insert flows for phy ports first + # insert connections for phy ports first # from 1st PHY to 1st vport of 1st VM - self._add_flow(flow, - phy1_number, - vm_ports[0][0], - self._bidir) + self._vswitch.add_connection(self._bridge, phy1, vm_ports[0][0], self._traffic) + self._vswitch.add_connection(self._bridge, vm_ports[0][0], phy1) # from last vport of last VM to 2nd phy - self._add_flow(flow, - vm_ports[self._pxp_vm_count-1][-1], - phy2_number, - self._bidir) + self._vswitch.add_connection(self._bridge, vm_ports[self._pxp_vm_count-1][-1], phy2) + self._vswitch.add_connection(self._bridge, phy2, vm_ports[self._pxp_vm_count-1][-1], self._traffic) # add serial connections among VMs and VM NICs pairs if needed # in case of multiple NICs pairs per VM, the pairs are chained - # first, before flow to the next VM is created + # first, before connection to the next VM is created for vmindex in range(self._pxp_vm_count): # connect VMs NICs pairs in case of 4 and more NICs per VM connections = [(vm_ports[vmindex][2*(x+1)-1], vm_ports[vmindex][2*(x+1)]) for x in range(int(len(vm_ports[vmindex])/2)-1)] for connection in connections: - self._add_flow(flow, - connection[0], - connection[1], - self._bidir) + self._vswitch.add_connection(self._bridge, connection[0], connection[1]) + self._vswitch.add_connection(self._bridge, connection[1], connection[0]) # connect last NICs to the next VM if there is any if self._pxp_vm_count > vmindex + 1: - self._add_flow(flow, - vm_ports[vmindex][-1], - vm_ports[vmindex+1][0], - self._bidir) + self._vswitch.add_connection(self._bridge, vm_ports[vmindex][-1], vm_ports[vmindex+1][0]) + self._vswitch.add_connection(self._bridge, vm_ports[vmindex+1][0], vm_ports[vmindex][-1]) else: - proto = _PROTO_TCP if self._traffic['l3']['proto'].lower() == 'tcp' else _PROTO_UDP - dst_mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value - dst_ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value + mac_value = netaddr.EUI(self._traffic['l2']['dstmac']).value + ip_value = netaddr.IPAddress(self._traffic['l3']['dstip']).value + port_value = self._traffic['l4']['dstport'] # initialize stream index; every NIC pair of every VM uses unique stream stream = 0 for vmindex in range(self._pxp_vm_count): @@ -146,31 +116,33 @@ class VswitchControllerPXP(IVswitchController): port_pairs = [(vm_ports[vmindex][0], vm_ports[vmindex][0])] for port_pair in port_pairs: - flow_p = _FLOW_TEMPLATE.copy() - flow_v = _FLOW_TEMPLATE.copy() - - # update flow based on trafficgen settings + # override traffic options to ensure, that traffic is + # dispatched among VMs connected in parallel + options = {'multistream':1, + 'stream_type':self._traffic['stream_type'], + 'pre_installed_flows':'Yes'} + # update connection based on trafficgen settings if self._traffic['stream_type'] == 'L2': - tmp_mac = netaddr.EUI(dst_mac_value + stream) + tmp_mac = netaddr.EUI(mac_value + stream) tmp_mac.dialect = netaddr.mac_unix_expanded - flow_p.update({'dl_dst':tmp_mac}) + options.update({'l2':{'dstmac':tmp_mac}}) elif self._traffic['stream_type'] == 'L3': - tmp_ip = netaddr.IPAddress(dst_ip_value + stream) - flow_p.update({'dl_type':'0x0800', 'nw_dst':tmp_ip}) + tmp_ip = netaddr.IPAddress(ip_value + stream) + options.update({'l3':{'dstip':tmp_ip}}) elif self._traffic['stream_type'] == 'L4': - flow_p.update({'dl_type':'0x0800', 'nw_proto':proto, 'tp_dst':stream}) + options.update({'l3':{'proto':self._traffic['l3']['proto']}}) + options.update({'l4':{'dstport':(port_value + stream) % 65536}}) else: raise RuntimeError('Unknown stream_type {}'.format(self._traffic['stream_type'])) - # insert flow to dispatch traffic from physical ports + # insert connection to dispatch traffic from physical ports # to VMs based on stream type; all traffic from VMs is # sent to physical ports to avoid issues with MAC swapping # and upper layer mods performed inside guests - self._add_flow(flow_p, phy1_number, port_pair[0]) - self._add_flow(flow_v, port_pair[1], phy2_number) - if self._bidir: - self._add_flow(flow_p, phy2_number, port_pair[1]) - self._add_flow(flow_v, port_pair[0], phy1_number) + self._vswitch.add_connection(self._bridge, phy1, port_pair[0], options) + self._vswitch.add_connection(self._bridge, port_pair[1], phy2) + self._vswitch.add_connection(self._bridge, phy2, port_pair[1], options) + self._vswitch.add_connection(self._bridge, port_pair[0], phy1) # every NIC pair needs its own unique traffic stream stream += 1 @@ -185,37 +157,13 @@ class VswitchControllerPXP(IVswitchController): self._logger.debug('Stop using %s', str(self._vswitch_class)) self._vswitch.stop() - def _add_flow(self, flow, port1, port2, reverse_flow=False): - """ Helper method to insert flow into the vSwitch - """ - self._vswitch.add_flow(self._bridge, - add_ports_to_flow(flow, - port1, - port2)) - if reverse_flow: - self._vswitch.add_flow(self._bridge, - add_ports_to_flow(flow, - port2, - port1)) - - 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 %s', str(self._vswitch_class)) return self._vswitch.get_ports(self._bridge) - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._vswitch.dump_flows(self._bridge) + self._vswitch.dump_connections(self._bridge) diff --git a/docs/testing/developer/devguide/design/vswitchperf_design.rst b/docs/testing/developer/devguide/design/vswitchperf_design.rst index 7fbde886..b8a3ba19 100644 --- a/docs/testing/developer/devguide/design/vswitchperf_design.rst +++ b/docs/testing/developer/devguide/design/vswitchperf_design.rst @@ -1,6 +1,6 @@ .. 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. +.. (c) OPNFV, Intel Corporation, AT&T, Tieto and others. .. _vsperf-design: @@ -332,7 +332,6 @@ Detailed description of ``TRAFFIC`` dictionary items follows: feature. If enabled, it will implicitly insert a flow for each stream. If multistream is disabled, then pre-installed flows will be ignored. - Note: It is supported only for p2p deployment scenario. Data type: str Supported values: "Yes" - flows will be inserted into OVS @@ -777,6 +776,13 @@ As it is able to forward traffic between multiple VM NIC pairs. Note: In case of ``linux_bridge``, all NICs are connected to the same bridge inside the VM. +Note: In case that multistream feature is configured and ``pre_installed_flows`` +is set to ``Yes``, then stream specific flows will be inserted only for connections +originating at physical ports. The rest of the flows will be based on port +numbers only. The same logic applies in case that ``flow_type`` TRAFFIC option +is set to ``ip``. This configuration will avoid a testcase malfunction if frame headers +are modified inside VM (e.g. MAC swap or IP change). + VM, vSwitch, Traffic Generator Independence =========================================== @@ -912,6 +918,10 @@ Vsperf uses a standard set of routing tables in order to allow tests to easily mix and match Deployment Scenarios (PVP, P2P topology), Tuple Matching and Frame Modification requirements. +The usage of routing tables is driven by configuration parameter ``OVS_ROUTING_TABLES``. +Routing tables are disabled by default (i.e. parameter is set to ``False``) for better +comparison of results among supported vSwitches (e.g. OVS vs. VPP). + .. code-block:: console +--------------+ diff --git a/testcases/testcase.py b/testcases/testcase.py index 809e3b34..a30558ff 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -373,7 +373,7 @@ class TestCase(object): # dump vswitch flows before they are affected by VNF termination if not self._vswitch_none: - self._vswitch_ctl.dump_vswitch_flows() + self._vswitch_ctl.dump_vswitch_connections() # garbage collection for case that TestSteps modify existing deployment self.step_stop_vnfs() diff --git a/vswitches/ovs.py b/vswitches/ovs.py index be7b77df..6dbf0cf8 100644 --- a/vswitches/ovs.py +++ b/vswitches/ovs.py @@ -1,4 +1,4 @@ -# Copyright 2015-2018 Intel Corporation, Tieto and Others. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,12 +15,13 @@ """VSPERF Open vSwitch base class """ -import logging import os import re import time import datetime import random +import socket +import netaddr import pexpect from conf import settings @@ -28,6 +29,10 @@ from src.ovs import OFBridge, flow_key, flow_match from vswitches.vswitch import IVSwitch from tools import tasks from tools.module_manager import ModuleManager + +# enable caching of flows if their number exceeds given limit +_CACHE_FLOWS_LIMIT = 10 + # pylint: disable=too-many-public-methods class IVSwitchOvs(IVSwitch, tasks.Process): """Open vSwitch base class implementation @@ -41,23 +46,31 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def __init__(self): """See IVswitch for general description """ + super().__init__() self._logfile = os.path.join(settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_VSWITCHD')) self._ovsdb_pidfile_path = os.path.join(settings.getValue('TOOLS')['ovs_var_tmp'], "ovsdb-server.pid") self._vswitchd_pidfile_path = os.path.join(settings.getValue('TOOLS')['ovs_var_tmp'], "{}.pid".format(self._proc_name)) - self._logger = logging.getLogger(__name__) # sign '|' must be escaped or avoided, otherwise it is handled as 'or' by regex self._expect = r'bridge.INFO.{}'.format(self._proc_name) - self._timeout = 30 - self._bridges = {} self._vswitchd_args = ['--pidfile=' + self._vswitchd_pidfile_path, '--overwrite-pidfile', '--log-file=' + self._logfile] - self._cmd = [] self._cmd_template = ['sudo', '-E', settings.getValue('TOOLS')['ovs-vswitchd']] - self._stamp = None self._module_manager = ModuleManager() + self._flow_template = settings.getValue('OVS_FLOW_TEMPLATE').copy() + self._flow_actions = ['output:{}'] + + # if routing tables are enabled, then flows should go into table 1 + # see design document for details about Routing Tables feature + if settings.getValue('OVS_ROUTING_TABLES'): + # flows should be added into table 1 + self._flow_template.update({'table':'1', 'priority':'1'}) + # and chosen port will be propagated via metadata + self._flow_actions = ['write_actions(output:{})', + 'write_metadata:{}', + 'goto_table:2'] def start(self): """ Start ``ovsdb-server`` and ``ovs-vswitchd`` instance. @@ -85,7 +98,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): tasks.Process.start(self) self.relinquish() except (pexpect.EOF, pexpect.TIMEOUT) as exc: - logging.error("Exception during VSwitch start.") + self._logger.error("Exception during VSwitch start.") self._kill_ovsdb() raise exc @@ -107,7 +120,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): tasks.Process.start(self) self.relinquish() except (pexpect.EOF, pexpect.TIMEOUT) as exc: - logging.error("Exception during VSwitch start.") + self._logger.error("Exception during VSwitch start.") self._kill_ovsdb() raise exc self._logger.info("Vswitchd...Started.") @@ -128,31 +141,57 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def stop(self): """See IVswitch for general description """ - for switch_name in list(self._bridges): + for switch_name in list(self._switches): self.del_switch(switch_name) self._logger.info("Terminating vswitchd...") self.kill() - self._bridges = {} + self._switches = {} self._logger.info("Vswitchd...Terminated.") def add_switch(self, switch_name, params=None): """See IVswitch for general description """ + # create and configure new ovs bridge and delete all default flows bridge = OFBridge(switch_name) bridge.create(params) + bridge.del_flow({}) bridge.set_db_attribute('Open_vSwitch', '.', 'other_config:max-idle', settings.getValue('VSWITCH_FLOW_TIMEOUT')) - self._bridges[switch_name] = bridge + self._switches[switch_name] = bridge + if settings.getValue('OVS_ROUTING_TABLES'): + # table#0 - flows designed to force 5 & 13 tuple matches go here + flow = {'table':'0', 'priority':'1', 'actions': ['goto_table:1']} + bridge.add_flow(flow) + + # table#1 - flows to route packets between ports goes here. The + # chosen port is communicated to subsequent tables by setting the + # metadata value to the egress port number + # + # A placeholder - flows are added into this table by deployments + # or by TestSteps via add_connection() method + + # table#2 - frame modification table. Frame modification flow rules are + # isolated in this table so that they can be turned on or off + # without affecting the routing or tuple-matching flow rules. + flow = {'table':'2', 'priority':'1', 'actions': ['goto_table:3']} + bridge.add_flow(flow) + + # table#3 - egress table + # (NOTE) Billy O'Mahony - the drop action here actually required in + # order to egress the packet. This is the subject of a thread on + # ovs-discuss 2015-06-30. + flow = {'table':'3', 'priority':'1', 'actions': ['drop']} + bridge.add_flow(flow) def del_switch(self, switch_name): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.del_flow({}) for port in list(bridge.get_ports()): bridge.del_port(port) - self._bridges.pop(switch_name) + self._switches.pop(switch_name) bridge.destroy() def add_phy_port(self, switch_name): @@ -173,8 +212,8 @@ class IVSwitchOvs(IVSwitch, tasks.Process): if switch_name is None or remote_switch_name is None: return None - bridge = self._bridges[switch_name] - remote_bridge = self._bridges[remote_switch_name] + bridge = self._switches[switch_name] + remote_bridge = self._switches[remote_switch_name] pcount = str(self._get_port_count('type=patch')) # NOTE ::: What if interface name longer than allowed width?? local_port_name = switch_name + '-' + remote_switch_name + '-' + pcount @@ -200,7 +239,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def add_tunnel_port(self, switch_name, remote_ip, tunnel_type='vxlan', params=None): """Creates tunneling port """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] pcount = str(self._get_port_count('type=' + tunnel_type)) port_name = tunnel_type + pcount local_params = ['--', 'set', 'Interface', port_name, @@ -216,53 +255,123 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def get_ports(self, switch_name): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] ports = list(bridge.get_ports().items()) return [(name, of_port) for (name, (of_port, _)) in ports] def del_port(self, switch_name, port_name): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.del_port(port_name) def add_flow(self, switch_name, flow, cache='off'): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.add_flow(flow, cache=cache) def del_flow(self, switch_name, flow=None): """See IVswitch for general description """ flow = flow or {} - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.del_flow(flow) def dump_flows(self, switch_name): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.dump_flows() + def _prepare_flows(self, operation, switch_name, port1, port2, traffic=None): + """Prepare flows for add_connection, del_connection and validate methods + It returns a list of flows based on given parameters. + """ + flows = [] + if operation == 'add': + bridge = self._switches[switch_name] + flow = self._flow_template.copy() + actions = [action.format(bridge.get_ports()[port2][0]) for action in self._flow_actions] + flow.update({'in_port': bridge.get_ports()[port1][0], 'actions': actions}) + # check if stream specific connection(s) should be crated for multistream feature + if traffic and traffic['pre_installed_flows'].lower() == 'yes': + for stream in range(traffic['multistream']): + tmp_flow = flow.copy() + # update flow based on trafficgen settings + if traffic['stream_type'] == 'L2': + dst_mac_value = netaddr.EUI(traffic['l2']['dstmac']).value + tmp_mac = netaddr.EUI(dst_mac_value + stream) + tmp_mac.dialect = netaddr.mac_unix_expanded + tmp_flow.update({'dl_dst':tmp_mac}) + elif traffic['stream_type'] == 'L3': + dst_ip_value = netaddr.IPAddress(traffic['l3']['dstip']).value + tmp_ip = netaddr.IPAddress(dst_ip_value + stream) + tmp_flow.update({'dl_type':'0x0800', 'nw_dst':tmp_ip}) + elif traffic['stream_type'] == 'L4': + tmp_flow.update({'dl_type':'0x0800', + 'nw_proto':socket.getprotobyname(traffic['l3']['proto'].lower()), + 'tp_dst':(traffic['l4']['dstport'] + stream) % 65536}) + flows.append(tmp_flow) + elif traffic and traffic['flow_type'].lower() == 'ip': + flow.update({'dl_type':'0x0800', 'nw_src':traffic['l3']['srcip'], + 'nw_dst':traffic['l3']['dstip']}) + flows.append(flow) + else: + flows.append(flow) + elif operation == 'del' and port1: + bridge = self._switches[switch_name] + flows.append({'in_port': bridge.get_ports()[port1][0]}) + else: + flows.append({}) + + return flows + + def add_connection(self, switch_name, port1, port2, traffic=None): + """See IVswitch for general description + """ + flows = self._prepare_flows('add', switch_name, port1, port2, traffic) + + # enable flows caching for large number of flows + cache = 'on' if len(flows) > _CACHE_FLOWS_LIMIT else 'off' + + for flow in flows: + self.add_flow(switch_name, flow, cache) + + if cache == 'on': + self.add_flow(switch_name, [], cache='flush') + + def del_connection(self, switch_name, port1=None, port2=None): + """See IVswitch for general description + """ + flows = self._prepare_flows('del', switch_name, port1, port2) + + for flow in flows: + self.del_flow(switch_name, flow) + + def dump_connections(self, switch_name): + """See IVswitch for general description + """ + self.dump_flows(switch_name) + def add_route(self, switch_name, network, destination): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.add_route(network, destination) def set_tunnel_arp(self, ip_addr, mac_addr, switch_name): """See IVswitch for general description """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.set_tunnel_arp(ip_addr, mac_addr, switch_name) def _get_port_count(self, param): """Returns the number of ports having a certain parameter """ cnt = 0 - for k in self._bridges: - pparams = [c for (_, (_, c)) in list(self._bridges[k].get_ports().items())] + for k in self._switches: + pparams = [c for (_, (_, c)) in list(self._switches[k].get_ports().items())] phits = [i for i in pparams if param in i] cnt += len(phits) @@ -276,7 +385,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): :param switch_name: bridge to disable stp :return: None """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.set_stp(False) self._logger.info('Sleeping for 50 secs to allow stp to stop.') time.sleep(50) # needs time to disable @@ -287,7 +396,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): :param switch_name: bridge to enable stp :return: None """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.set_stp(True) self._logger.info('Sleeping for 50 secs to allow stp to start.') time.sleep(50) # needs time to enable @@ -298,7 +407,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): :param switch_name: bridge to disable rstp :return: None """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.set_rstp(False) self._logger.info('Sleeping for 15 secs to allow rstp to stop.') time.sleep(15) # needs time to disable @@ -309,7 +418,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): :param switch_name: bridge to enable rstp :return: None """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] bridge.set_rstp(True) self._logger.info('Sleeping for 15 secs to allow rstp to start.') time.sleep(15) # needs time to enable @@ -417,7 +526,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def validate_add_switch(self, _dummy_result, switch_name, _dummy_params=None): """Validate - Create a new logical switch with no ports """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] output = bridge.run_vsctl(['show'], check_error=True) assert not output[1] # there shouldn't be any stderr, but in case assert re.search('Bridge ["\']?%s["\']?' % switch_name, output[0]) is not None @@ -437,7 +546,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def validate_add_phy_port(self, result, switch_name): """ Validate that physical port was added to bridge. """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] output = bridge.run_vsctl(['show'], check_error=True) assert not output[1] # there shouldn't be any stderr, but in case assert re.search('Port ["\']?%s["\']?' % result[0], output[0]) is not None @@ -452,12 +561,35 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def validate_del_port(self, _dummy_result, switch_name, port_name): """ Validate that port_name was removed from bridge. """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] output = bridge.run_vsctl(['show'], check_error=True) assert not output[1] # there shouldn't be any stderr, but in case assert 'Port "%s"' % port_name not in output[0] return True + def validate_add_connection(self, result, switch_name, port1, port2, traffic=None): + """ Validate that connection was added + """ + for flow in self._prepare_flows('add', switch_name, port1, port2, traffic): + if not self.validate_add_flow(result, switch_name, flow): + return False + + return True + + def validate_del_connection(self, result, switch_name, port1, port2): + """ Validate that connection was deleted + """ + for flow in self._prepare_flows('del', switch_name, port1, port2): + if not self.validate_del_flow(result, switch_name, flow): + return False + + return True + + def validate_dump_connections(self, _dummy_result, _dummy_switch_name): + """ Validate dump connections call + """ + return True + def validate_add_flow(self, _dummy_result, switch_name, flow, _dummy_cache='off'): """ Validate insertion of the flow into the switch """ @@ -471,7 +603,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): # get dump of flows and compare them one by one flow_src = flow_key(flow) - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] output = bridge.run_ofctl(['dump-flows', switch_name], check_error=True) for flow_dump in output[0].split('\n'): if flow_match(flow_dump, flow_src): @@ -495,25 +627,25 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def validate_disable_rstp(self, _dummy_result, switch_name): """ Validate rstp disable """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] return 'rstp_enable : false' in ''.join(bridge.bridge_info()) def validate_enable_rstp(self, _dummy_result, switch_name): """ Validate rstp enable """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] return 'rstp_enable : true' in ''.join(bridge.bridge_info()) def validate_disable_stp(self, _dummy_result, switch_name): """ Validate stp disable """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] return 'stp_enable : false' in ''.join(bridge.bridge_info()) def validate_enable_stp(self, _dummy_result, switch_name): """ Validate stp enable """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] return 'stp_enable : true' in ''.join(bridge.bridge_info()) def validate_restart(self, _dummy_result): diff --git a/vswitches/ovs_dpdk_vhost.py b/vswitches/ovs_dpdk_vhost.py index 6deb0c25..8da043c6 100644 --- a/vswitches/ovs_dpdk_vhost.py +++ b/vswitches/ovs_dpdk_vhost.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ """VSPERF VSwitch implementation using DPDK and vhost ports """ -import logging import subprocess from src.ovs import OFBridge @@ -36,9 +35,7 @@ class OvsDpdkVhost(IVSwitchOvs): """ def __init__(self): - super(OvsDpdkVhost, self).__init__() - self._logger = logging.getLogger(__name__) - + super().__init__() vswitchd_args = [] # legacy DPDK configuration through --dpdk option of vswitchd @@ -104,9 +101,9 @@ class OvsDpdkVhost(IVSwitchOvs): if S.getValue('VSWITCH_AFFINITIZATION_ON') == 1: # Sets the PMD core mask to VSWITCH_PMD_CPU_MASK # for CPU core affinitization - self._bridges[switch_name].set_db_attribute('Open_vSwitch', '.', - 'other_config:pmd-cpu-mask', - S.getValue('VSWITCH_PMD_CPU_MASK')) + self._switches[switch_name].set_db_attribute('Open_vSwitch', '.', + 'other_config:pmd-cpu-mask', + S.getValue('VSWITCH_PMD_CPU_MASK')) def add_phy_port(self, switch_name): """See IVswitch for general description @@ -115,7 +112,7 @@ class OvsDpdkVhost(IVSwitchOvs): The new port is named dpdk<n> where n is an integer starting from 0. """ _nics = S.getValue('NICS') - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] dpdk_count = self._get_port_count('type=dpdk') if dpdk_count == len(_nics): raise RuntimeError("Can't add phy port! There are only {} ports defined " @@ -144,7 +141,7 @@ class OvsDpdkVhost(IVSwitchOvs): The new port is named dpdkvhost<n> where n is an integer starting from 0 """ - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'): nic_type = 'dpdkvhostuser' @@ -177,18 +174,3 @@ class OvsDpdkVhost(IVSwitchOvs): return True except subprocess.CalledProcessError: return False - - def add_connection(self, switch_name, port1, port2, bidir=False): - """See IVswitch for general description - """ - raise NotImplementedError() - - def del_connection(self, switch_name, port1, port2, bidir=False): - """See IVswitch for general description - """ - raise NotImplementedError() - - def dump_connections(self, switch_name): - """See IVswitch for general description - """ - raise NotImplementedError() diff --git a/vswitches/ovs_vanilla.py b/vswitches/ovs_vanilla.py index 83c52050..d23a0c61 100644 --- a/vswitches/ovs_vanilla.py +++ b/vswitches/ovs_vanilla.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ """VSPERF Vanilla OVS implementation """ -import logging import time from conf import settings from vswitches.ovs import IVSwitchOvs @@ -36,9 +35,8 @@ class OvsVanilla(IVSwitchOvs): _vport_id = 0 def __init__(self): - super(OvsVanilla, self).__init__() + super().__init__() self._ports = list(nic['device'] for nic in settings.getValue('NICS')) - self._logger = logging.getLogger(__name__) self._vswitchd_args += ["unix:%s" % self.get_db_sock_path()] self._vswitchd_args += settings.getValue('VSWITCHD_VANILLA_ARGS') @@ -81,7 +79,7 @@ class OvsVanilla(IVSwitchOvs): self._logger.error("Can't detect device name for NIC %s", self._current_id) raise ValueError("Invalid device name for %s" % self._current_id) - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] port_name = self._ports[self._current_id] params = [] @@ -129,21 +127,6 @@ class OvsVanilla(IVSwitchOvs): tasks.run_task(['sudo', 'ip', 'link', 'set', 'dev', tap_name, 'up'], self._logger, 'Bring up ' + tap_name, False) - bridge = self._bridges[switch_name] + bridge = self._switches[switch_name] of_port = bridge.add_port(tap_name, []) return (tap_name, of_port) - - def add_connection(self, switch_name, port1, port2, bidir=False): - """See IVswitch for general description - """ - raise NotImplementedError() - - def del_connection(self, switch_name, port1, port2, bidir=False): - """See IVswitch for general description - """ - raise NotImplementedError() - - def dump_connections(self, switch_name): - """See IVswitch for general description - """ - raise NotImplementedError() diff --git a/vswitches/vpp_dpdk_vhost.py b/vswitches/vpp_dpdk_vhost.py index 15e32f32..5d676a01 100644 --- a/vswitches/vpp_dpdk_vhost.py +++ b/vswitches/vpp_dpdk_vhost.py @@ -1,4 +1,4 @@ -# Copyright 2017 Intel Corporation. +# Copyright 2017-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ """VSPERF VPP implementation using DPDK and vhostuser vports """ -import logging import os import copy import re @@ -37,19 +36,13 @@ class VppDpdkVhost(IVSwitch, tasks.Process): def __init__(self): """See IVswitch for general description """ + super().__init__() self._logfile = os.path.join(S.getValue('LOG_DIR'), S.getValue('LOG_FILE_VPP')) - self._logger = logging.getLogger(__name__) self._expect = r'vpp#' - self._timeout = 30 - self._vswitch_args = [] - self._cmd = [] self._cmd_template = ['sudo', '-E', S.getValue('TOOLS')['vpp']] - self._stamp = None - self._logger = logging.getLogger(__name__) self._phy_ports = [] self._virt_ports = [] - self._switches = {} self._vpp_ctl = ['sudo', S.getValue('TOOLS')['vppctl']] # configure DPDK NICs @@ -151,7 +144,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): tasks.Process.start(self) self.relinquish() except (pexpect.EOF, pexpect.TIMEOUT) as exc: - logging.error("Exception during VPP start.") + self._logger.error("Exception during VPP start.") raise exc self._logger.info("VPP...Started.") @@ -269,21 +262,17 @@ class VppDpdkVhost(IVSwitch, tasks.Process): else: self._logger.warning("Port %s is not configured.", port_name) - def add_l2patch(self, port1, port2, bidir=False): + def add_l2patch(self, port1, port2): """Create l2patch connection between given ports """ self.run_vppctl(['test', 'l2patch', 'rx', port1, 'tx', port2]) - if bidir: - self.run_vppctl(['test', 'l2patch', 'rx', port2, 'tx', port1]) - def add_xconnect(self, port1, port2, bidir=False): + def add_xconnect(self, port1, port2): """Create l2patch connection between given ports """ self.run_vppctl(['set', 'interface', 'l2', 'xconnect', port1, port2]) - if bidir: - self.run_vppctl(['set', 'interface', 'l2', 'xconnect', port2, port1]) - def add_bridge(self, switch_name, port1, port2, _dummy_bidir=False): + def add_bridge(self, switch_name, port1, port2): """Add given ports to bridge ``switch_name`` """ self.run_vppctl(['set', 'interface', 'l2', 'bridge', port1, @@ -291,33 +280,33 @@ class VppDpdkVhost(IVSwitch, tasks.Process): self.run_vppctl(['set', 'interface', 'l2', 'bridge', port2, str(self._switches[switch_name])]) - def add_connection(self, switch_name, port1, port2, bidir=False): + def add_connection(self, switch_name, port1, port2, traffic=None): """See IVswitch for general description :raises: RuntimeError """ + if traffic: + self._logger.warning("VPP add_connection() does not support 'traffic' options.") + mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') if mode == 'l2patch': - self.add_l2patch(port1, port2, bidir) + self.add_l2patch(port1, port2) elif mode == 'xconnect': - self.add_xconnect(port1, port2, bidir) + self.add_xconnect(port1, port2) elif mode == 'bridge': self.add_bridge(switch_name, port1, port2) else: raise RuntimeError('VPP: Unsupported l2 connection mode detected %s' % mode) - def del_l2patch(self, port1, port2, bidir=False): + def del_l2patch(self, port1, port2): """Remove l2patch connection between given ports :param port1: port to be used in connection :param port2: port to be used in connection - :param bidir: switch between uni and bidirectional traffic """ self.run_vppctl(['test', 'l2patch', 'rx', port1, 'tx', port2, 'del']) - if bidir: - self.run_vppctl(['test', 'l2patch', 'rx', port2, 'tx', port1, 'del']) - def del_xconnect(self, port1, port2, _dummy_bidir=False): + def del_xconnect(self, port1, port2): """Remove xconnect connection between given ports """ self.run_vppctl(['set', 'interface', 'l3', port1]) @@ -329,20 +318,21 @@ class VppDpdkVhost(IVSwitch, tasks.Process): self.run_vppctl(['set', 'interface', 'l3', port1]) self.run_vppctl(['set', 'interface', 'l3', port2]) - def del_connection(self, switch_name, port1, port2, bidir=False): + def del_connection(self, switch_name, port1=None, port2=None): """See IVswitch for general description :raises: RuntimeError """ - mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') - if mode == 'l2patch': - self.del_l2patch(port1, port2, bidir) - elif mode == 'xconnect': - self.del_xconnect(port1, port2, bidir) - elif mode == 'bridge': - self.del_bridge(switch_name, port1, port2) - else: - raise RuntimeError('VPP: Unsupported l2 connection mode detected %s' % mode) + if port1 and port2: + mode = S.getValue('VSWITCH_VPP_L2_CONNECT_MODE') + if mode == 'l2patch': + self.del_l2patch(port1, port2) + elif mode == 'xconnect': + self.del_xconnect(port1, port2) + elif mode == 'bridge': + self.del_bridge(switch_name, port1, port2) + else: + raise RuntimeError('VPP: Unsupported l2 connection mode detected %s' % mode) def dump_l2patch(self): """Dump l2patch connections @@ -417,13 +407,13 @@ class VppDpdkVhost(IVSwitch, tasks.Process): # pylint: disable=no-self-use def validate_add_connection(self, _dummy_result, _dummy_switch_name, _dummy_port1, - _dummy_port2, _dummy_bidir=False): + _dummy_port2, _dummy_traffic=None): """ Validate that connection was added """ return True def validate_del_connection(self, _dummy_result, _dummy_switch_name, _dummy_port1, - _dummy_port2, _dummy_bidir=False): + _dummy_port2): """ Validate that connection was deleted """ return True @@ -442,21 +432,6 @@ class VppDpdkVhost(IVSwitch, tasks.Process): # # Non implemented methods # - def add_flow(self, switch_name, flow, cache='off'): - """See IVswitch for general description - """ - raise NotImplementedError() - - def del_flow(self, switch_name, flow=None): - """See IVswitch for general description - """ - raise NotImplementedError() - - def dump_flows(self, switch_name): - """See IVswitch for general description - """ - raise NotImplementedError() - def add_route(self, switch_name, network, destination): """See IVswitch for general description """ diff --git a/vswitches/vswitch.py b/vswitches/vswitch.py index efa3a349..a3d4e974 100644 --- a/vswitches/vswitch.py +++ b/vswitches/vswitch.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2018 Intel Corporation., Tieto # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,12 +14,23 @@ """Generic interface VSPERF uses for controlling a vSwitch """ +import logging class IVSwitch(object): """Interface class that is implemented by vSwitch-specific classes Other methods are called only between start() and stop() """ + def __init__(self): + """Initialization of vswitch class + """ + self._timeout = 30 + self._switches = {} + self._logger = logging.getLogger(__name__) + self._cmd = [] + self._vswitch_args = [] + self._stamp = None + def get_version(self): """Return version of vSwitch and DPDK (if used by vSwitch) This method should be implemented in case, that version @@ -112,58 +123,23 @@ class IVSwitch(object): """ raise NotImplementedError() - def add_flow(self, switch_name, flow, cache='off'): - """Add a flow rule to the logical switch - - :param switch_name: The switch on which to operate - :param flow: Flow description as a dictionary - :param cache: Optional. Specifies if flow should be inserted - to the switch or cached to increase performance during manipulation - with large number of flows. - Values: - 'off' - cache is off and flow is inserted directly to the switch - 'on' - cache is on and flow is inserted into the cache - 'flush' - cache content will be inserted into the switch - - Example flow dictionary: - flow = { - 'in_port': '1', - 'idle_timeout': '0', - 'actions': ['output:3'] - } - """ - raise NotImplementedError() - - def del_flow(self, switch_name, flow=None): - """Delete the flow rule from the logical switch - - :param switch_name: The switch on which to operate - :param flow: Flow description as a dictionary - - For flow dictionary description, see add_flow - For flow==None, all flows are deleted - """ - raise NotImplementedError() - - def add_connection(self, switch_name, port1, port2, bidir=False): + def add_connection(self, switch_name, port1, port2, traffic=None): """Creates connection between given ports. :param switch_name: switch on which to operate :param port1: port to be used in connection :param port2: port to be used in connection - :param bidir: switch between uni and bidirectional traffic :raises: RuntimeError """ raise NotImplementedError() - def del_connection(self, switch_name, port1, port2, bidir=False): + def del_connection(self, switch_name, port1=None, port2=None): """Remove connection between two interfaces. :param switch_name: switch on which to operate :param port1: port to be used in connection :param port2: port to be used in connection - :param bidir: switch between uni and bidirectional traffic :raises: RuntimeError """ @@ -178,13 +154,6 @@ class IVSwitch(object): """ raise NotImplementedError() - def dump_flows(self, switch_name): - """Dump flows from the logical switch - - :param switch_name: The switch on which to operate - """ - raise NotImplementedError() - def add_route(self, switch_name, network, destination): """Add a route for tunneling routing table |