diff options
118 files changed, 9575 insertions, 1713 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 new file mode 100644 index 00000000..5c42ea50 --- /dev/null +++ b/3rd_party/ixia/ixnetrfc2544_bad_l2_crc.tcl @@ -0,0 +1,6632 @@ +#!/usr/bin/env tclsh + +# Copyright (c) 2014, Ixia +# Copyright (c) 2015-2018, Intel Corporation, Tieto +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# This file is a modified version of a script generated by Ixia +# IxNetwork. + +lappend auto_path [list $lib_path] + +################################################################### +########################## Configuration ########################## +################################################################### + +# verify that the IXIA chassis spec is given + +set reqVars [list "machine" "port" "user" "chassis" "card" "port1" "port2" "output_dir" "bidir"] +set rfc2544test "" + +foreach var $reqVars { + set var_ns [namespace which -variable "$var"] + if { [string compare $var_ns ""] == 0 } { + errorMsg "The '$var' variable is undefined. Did you set it?" + return -1 + } +} + +# machine configuration + +set ::IxNserver $machine +set ::IxNport $port +set ::biDirect $bidir + +# change to windows path format and append directory +set output_dir [string map {"/" "\\"} $output_dir] +set output_dir "$output_dir\\rfctests" +puts "Output directory is $output_dir" + +proc startRfc2544Test { testSpec trafficSpec } { + # Start RFC2544 quicktest. + + # Configure global variables. See documentation on 'global' for more + # information on why this is necessary + # https://www.tcl.tk/man/tcl8.5/tutorial/Tcl13.html + global rfc2544test + global sg_rfc2544throughput + global sg_rfc2544back2back + + # Suffix for stack names + # This variable should be incremented after setting sg_stack like: + # set sg_stack $ixNetSG_Stack(2)/stack:"protocolnamehere-$stack_number" + # incr stack_number + set stack_number 1 + + # flow spec + + set rfc2544TestType [dict get $testSpec rfc2544TestType] + + set binary [dict get $testSpec binary] + + set duration [dict get $testSpec duration] + + # check if only one tgen port is requested + if {($::port1 == $::port2)} { + set twoPorts 0 + set selfDestined True + } else { + set twoPorts 1 + set selfDestined False + } + + # RFC2544 to IXIA terminology mapping (it affects Ixia configuration inside this script): + # Test => Trial + # Trial => Iteration + if {$binary} { + set numTests [dict get $testSpec tests] + set frameRate 100 + set tolerance [dict get $testSpec lossrate] + set loadType binary + } else { + set numTests 1 + set frameRate [dict get $testSpec framerate] + set tolerance 0.0 + set loadType custom + } + + set learningFrames [dict get $testSpec learningFrames] + + set L2CountValue 1 + set L2Increment False + set L3ValueType singleValue + set L3CountValue 1 + set L4ValueType singleValue + set L4CountValue 1 + + if {$learningFrames} { + set learningFrequency oncePerTest + set fastPathEnable True + } else { + set learningFrequency never + set fastPathEnable False + } + + set multipleStreams [dict get $testSpec multipleStreams] + set streamType [dict get $testSpec streamType] + + if {($multipleStreams < 0)} { + set multipleStreams 0 + } + + if {$multipleStreams} { + if {($streamType == "L2")} { + set L2CountValue $multipleStreams + set L2Increment True + } elseif {($streamType == "L3")} { + set L3ValueType increment + set L3CountValue $multipleStreams + } else { + set L4ValueType increment + set L4CountValue $multipleStreams + } + } + + set flowControl [dict get $testSpec flowControl] + set fastConvergence True + set convergenceDuration [expr $duration/10] + + # traffic spec + + # extract nested dictionaries + set trafficSpec_l2 [dict get $trafficSpec l2] + set trafficSpec_l3 [dict get $trafficSpec l3] + set trafficSpec_l4 [dict get $trafficSpec l4] + set trafficSpec_vlan [dict get $trafficSpec vlan] + + set frameSize [dict get $trafficSpec_l2 framesize] + set srcMac [dict get $trafficSpec_l2 srcmac] + set dstMac [dict get $trafficSpec_l2 dstmac] + + set proto [dict get $trafficSpec_l3 proto] + set srcIp [dict get $trafficSpec_l3 srcip] + set dstIp [dict get $trafficSpec_l3 dstip] + + set srcPort [dict get $trafficSpec_l4 srcport] + set dstPort [dict get $trafficSpec_l4 dstport] + + set l3Enabled [dict get $trafficSpec_l3 enabled] + set l4Enabled [dict get $trafficSpec_l4 enabled] + set vlanEnabled [dict get $trafficSpec_vlan enabled] + + if {$vlanEnabled == 1 } { + # these keys won't exist if vlan wasn't enabled + set vlanId [dict get $trafficSpec_vlan id] + set vlanUserPrio [dict get $trafficSpec_vlan priority] + set vlanCfi [dict get $trafficSpec_vlan cfi] + } else { + set vlanId 0 + set vlanUserPrio 0 + set vlanCfi 0 + } + + if {$frameSize < 68 } { + if {$rfc2544TestType == "back2back"} { + puts "INFO: Packet size too small, packet size will be \ + increased to 68 for this test" + } + } + # constants + + set VERSION [package require IxTclNetwork] + + ################################################################### + ############################ Operation ############################ + ################################################################### + + puts "Connecting to IxNetwork machine..." + + ixNet connect $::IxNserver -port $::IxNport -version $VERSION + + puts "Connected to IxNetwork machine" + + puts "Configuring IxNetwork machine..." + + set ::_sg_cc 0 + proc sg_commit {} {ixNet commit} + + ixNet rollback + ixNet setSessionParameter version 6.30.701.16 + ixNet execute newConfig + set ixNetSG_Stack(0) [ixNet getRoot] + + # + # setting global options + # + set sg_top [ixNet getRoot] + ixNet setMultiAttrs $sg_top/availableHardware \ + -offChassisHwM {} \ + -isOffChassis False + ixNet setMultiAttrs $sg_top/globals/preferences \ + -connectPortsOnLoadConfig True \ + -rebootPortsOnConnect False + ixNet setMultiAttrs $sg_top/globals/interfaces \ + -arpOnLinkup True \ + -nsOnLinkup True \ + -sendSingleArpPerGateway True \ + -sendSingleNsPerGateway True + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/checksums \ + -dropRxL2FcsErrors False \ + -correctTxL2FcsErrors False \ + -alwaysCorrectWhenModifying True \ + -correctTxChecksumOverIp False \ + -correctTxIpv4Checksum False + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/rxRateLimit \ + -enabled False \ + -value 8 \ + -units {kKilobitsPerSecond} + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/drop \ + -enabled False \ + -clusterSize 1 \ + -percentRate 0 + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/reorder \ + -enabled False \ + -clusterSize 1 \ + -percentRate 0 \ + -skipCount 1 + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/duplicate \ + -enabled False \ + -clusterSize 1 \ + -percentRate 0 \ + -duplicateCount 1 + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/bitError \ + -enabled False \ + -logRate 3 \ + -skipEndOctets 0 \ + -skipStartOctets 0 + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/delay \ + -enabled False \ + -value 300 \ + -units {kMicroseconds} + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/delayVariation \ + -uniformSpread 0 \ + -enabled False \ + -units {kMicroseconds} \ + -distribution {kUniform} \ + -exponentialMeanArrival 0 \ + -gaussianStandardDeviation 0 + ixNet setMultiAttrs $sg_top/impairment/defaultProfile/customDelayVariation \ + -enabled False \ + -name {} + ixNet setMultiAttrs $sg_top/statistics \ + -additionalFcoeStat2 fcoeInvalidFrames \ + -csvLogPollIntervalMultiplier 1 \ + -pollInterval 2 \ + -guardrailEnabled True \ + -enableCsvLogging False \ + -dataStorePollingIntervalMultiplier 1 \ + -maxNumberOfStatsPerCustomGraph 16 \ + -additionalFcoeStat1 fcoeInvalidDelimiter \ + -timestampPrecision 3 \ + -enableDataCenterSharedStats False \ + -timeSynchronization syncTimeToTestStart \ + -enableAutoDataStore False + ixNet setMultiAttrs $sg_top/statistics/measurementMode \ + -measurementMode mixedMode + ixNet setMultiAttrs $sg_top/eventScheduler \ + -licenseServerLocation {127.0.0.1} + ixNet setMultiAttrs $sg_top/traffic \ + -destMacRetryCount 1 \ + -maxTrafficGenerationQueries 500 \ + -enableStaggeredTransmit False \ + -learningFrameSize $frameSize \ + -useTxRxSync True \ + -enableDestMacRetry True \ + -enableMulticastScalingFactor False \ + -destMacRetryDelay 5 \ + -largeErrorThreshhold 2 \ + -refreshLearnedInfoBeforeApply False \ + -enableMinFrameSize True \ + -macChangeOnFly False \ + -waitTime 1 \ + -enableInstantaneousStatsSupport False \ + -learningFramesCount 10 \ + -globalStreamControl continuous \ + -displayMplsCurrentLabelValue False \ + -mplsLabelLearningTimeout 30 \ + -enableStaggeredStartDelay True \ + -enableDataIntegrityCheck False \ + -enableSequenceChecking False \ + -globalStreamControlIterations 1 \ + -enableStreamOrdering False \ + -frameOrderingMode none \ + -learningFramesRate 100 + ixNet setMultiAttrs $sg_top/traffic/statistics/latency \ + -enabled True \ + -mode storeForward + ixNet setMultiAttrs $sg_top/traffic/statistics/interArrivalTimeRate \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/delayVariation \ + -enabled False \ + -statisticsMode rxDelayVariationErrorsAndRate \ + -latencyMode storeForward \ + -largeSequenceNumberErrorThreshold 2 + ixNet setMultiAttrs $sg_top/traffic/statistics/sequenceChecking \ + -enabled False \ + -sequenceMode rxThreshold + ixNet setMultiAttrs $sg_top/traffic/statistics/advancedSequenceChecking \ + -enabled False \ + -advancedSequenceThreshold 1 + ixNet setMultiAttrs $sg_top/traffic/statistics/cpdpConvergence \ + -enabled False \ + -dataPlaneJitterWindow 10485760 \ + -dataPlaneThreshold 95 \ + -enableDataPlaneEventsRateMonitor False \ + -enableControlPlaneEvents False + ixNet setMultiAttrs $sg_top/traffic/statistics/packetLossDuration \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/dataIntegrity \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/errorStats \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/prbs \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/iptv \ + -enabled False + ixNet setMultiAttrs $sg_top/traffic/statistics/l1Rates \ + -enabled False + ixNet setMultiAttrs $sg_top/quickTest/globals \ + -productLabel {Your switch/router name here} \ + -serialNumber {Your switch/router serial number here} \ + -version {Your firmware version here} \ + -comments {} \ + -titlePageComments {} \ + -maxLinesToDisplay 100 \ + -enableCheckLinkState False \ + -enableAbortIfLinkDown False \ + -enableSwitchToStats True \ + -enableCapture False \ + -enableSwitchToResult True \ + -enableGenerateReportAfterRun False \ + -enableRebootCpu False \ + -saveCaptureBeforeRun False \ + -linkDownTimeout 5 \ + -sleepTimeAfterReboot 10 \ + -useDefaultRootPath False \ + -outputRootPath $::output_dir + sg_commit + set sg_top [lindex [ixNet remapIds $sg_top] 0] + set ixNetSG_Stack(0) $sg_top + + ### + ### /vport area + ### + + # + # configuring the object that corresponds to /vport:1 + # + set sg_vport [ixNet add $ixNetSG_Stack(0) vport] + ixNet setMultiAttrs $sg_vport \ + -transmitIgnoreLinkStatus False \ + -txGapControlMode averageMode \ + -type tenGigLan \ + -connectedTo ::ixNet::OBJ-null \ + -txMode interleaved \ + -isPullOnly False \ + -rxMode captureAndMeasure \ + -name {10GE LAN - 001} + ixNet setMultiAttrs $sg_vport/l1Config \ + -currentType tenGigLan + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan \ + -ppm 0 \ + -flowControlDirectedAddress "01 80 C2 00 00 01" \ + -enablePPM False \ + -autoInstrumentation endOfFrame \ + -transmitClocking internal \ + -txIgnoreRxLinkFaults False \ + -loopback False \ + -enableLASIMonitoring False \ + -enabledFlowControl $flowControl + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan/oam \ + -tlvType {00} \ + -linkEvents False \ + -enabled False \ + -vendorSpecificInformation {00 00 00 00} \ + -macAddress "00:00:00:00:00:00" \ + -loopback False \ + -idleTimer 5 \ + -tlvValue {00} \ + -enableTlvOption False \ + -maxOAMPDUSize 64 \ + -organizationUniqueIdentifier {000000} + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan/fcoe \ + -supportDataCenterMode False \ + -priorityGroupSize priorityGroupSize-8 \ + -pfcPauseDelay 1 \ + -pfcPriorityGroups {0 1 2 3 4 5 6 7} \ + -flowControlType ieee802.1Qbb \ + -enablePFCPauseDelay False + ixNet setMultiAttrs $sg_vport/l1Config/fortyGigLan \ + -ppm 0 \ + -flowControlDirectedAddress "01 80 C2 00 00 01" \ + -enablePPM False \ + -autoInstrumentation endOfFrame \ + -transmitClocking internal \ + -txIgnoreRxLinkFaults False \ + -loopback False \ + -enableLASIMonitoring False \ + -enabledFlowControl $flowControl + ixNet setMultiAttrs $sg_vport/l1Config/fortyGigLan/fcoe \ + -supportDataCenterMode False \ + -priorityGroupSize priorityGroupSize-8 \ + -pfcPauseDelay 1 \ + -pfcPriorityGroups {0 1 2 3 4 5 6 7} \ + -flowControlType ieee802.1Qbb \ + -enablePFCPauseDelay False + ixNet setMultiAttrs $sg_vport/l1Config/OAM \ + -tlvType {00} \ + -linkEvents False \ + -enabled False \ + -vendorSpecificInformation {00 00 00 00} \ + -macAddress "00:00:00:00:00:00" \ + -loopback False \ + -idleTimer 5 \ + -tlvValue {00} \ + -enableTlvOption False \ + -maxOAMPDUSize 64 \ + -organizationUniqueIdentifier {000000} + ixNet setMultiAttrs $sg_vport/l1Config/rxFilters/filterPalette \ + -sourceAddress1Mask {00:00:00:00:00:00} \ + -destinationAddress1Mask {00:00:00:00:00:00} \ + -sourceAddress2 {00:00:00:00:00:00} \ + -pattern2OffsetType fromStartOfFrame \ + -pattern2Offset 20 \ + -pattern1Mask {00} \ + -sourceAddress2Mask {00:00:00:00:00:00} \ + -destinationAddress2 {00:00:00:00:00:00} \ + -destinationAddress1 {00:00:00:00:00:00} \ + -sourceAddress1 {00:00:00:00:00:00} \ + -pattern1 {00} \ + -destinationAddress2Mask {00:00:00:00:00:00} \ + -pattern2Mask {00} \ + -pattern1Offset 20 \ + -pattern2 {00} \ + -pattern1OffsetType fromStartOfFrame + ixNet setMultiAttrs $sg_vport/protocols/arp \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/bfd \ + -enabled False \ + -intervalValue 0 \ + -packetsPerInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/bgp \ + -autoFillUpDutIp False \ + -disableReceivedUpdateValidation False \ + -enableAdVplsPrefixLengthInBits False \ + -enableExternalActiveConnect True \ + -enableInternalActiveConnect True \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -externalRetries 0 \ + -externalRetryDelay 120 \ + -internalRetries 0 \ + -internalRetryDelay 120 \ + -mldpP2mpFecType 6 \ + -triggerVplsPwInitiation False + ixNet setMultiAttrs $sg_vport/protocols/cfm \ + -enableOptionalLmFunctionality False \ + -enableOptionalTlvValidation True \ + -enabled False \ + -receiveCcm True \ + -sendCcm True \ + -suppressErrorsOnAis True + ixNet setMultiAttrs $sg_vport/protocols/eigrp \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/elmi \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/igmp \ + -enabled False \ + -numberOfGroups 0 \ + -numberOfQueries 0 \ + -queryTimePeriod 0 \ + -sendLeaveOnStop True \ + -statsEnabled False \ + -timePeriod 0 + ixNet setMultiAttrs $sg_vport/protocols/isis \ + -allL1RbridgesMac "01:80:c2:00:00:40" \ + -emulationType isisL3Routing \ + -enabled False \ + -helloMulticastMac "01:80:c2:00:00:41" \ + -lspMgroupPdusPerInterval 0 \ + -nlpId 192 \ + -rateControlInterval 0 \ + -sendP2PHellosToUnicastMac True \ + -spbAllL1BridgesMac "09:00:2b:00:00:05" \ + -spbHelloMulticastMac "09:00:2b:00:00:05" \ + -spbNlpId 192 + ixNet setMultiAttrs $sg_vport/protocols/lacp \ + -enablePreservePartnerInfo False \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/ldp \ + -enableDiscardSelfAdvFecs False \ + -enableHelloJitter True \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -helloHoldTime 15 \ + -helloInterval 5 \ + -keepAliveHoldTime 30 \ + -keepAliveInterval 10 \ + -p2mpCapabilityParam 1288 \ + -p2mpFecType 6 \ + -targetedHelloInterval 15 \ + -targetedHoldTime 45 \ + -useTransportLabelsForMplsOam False + ixNet setMultiAttrs $sg_vport/protocols/linkOam \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/lisp \ + -burstIntervalInMs 0 \ + -enabled False \ + -ipv4MapRegisterPacketsPerBurst 0 \ + -ipv4MapRequestPacketsPerBurst 0 \ + -ipv4SmrPacketsPerBurst 0 \ + -ipv6MapRegisterPacketsPerBurst 0 \ + -ipv6MapRequestPacketsPerBurst 0 \ + -ipv6SmrPacketsPerBurst 0 + ixNet setMultiAttrs $sg_vport/protocols/mld \ + -enableDoneOnStop True \ + -enabled False \ + -mldv2Report type143 \ + -numberOfGroups 0 \ + -numberOfQueries 0 \ + -queryTimePeriod 0 \ + -timePeriod 0 + ixNet setMultiAttrs $sg_vport/protocols/mplsOam \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/mplsTp \ + -apsChannelType {00 02 } \ + -bfdCcChannelType {00 07 } \ + -delayManagementChannelType {00 05 } \ + -enableHighPerformanceMode True \ + -enabled False \ + -faultManagementChannelType {00 58 } \ + -lossMeasurementChannelType {00 04 } \ + -onDemandCvChannelType {00 09 } \ + -pwStatusChannelType {00 0B } \ + -y1731ChannelType {7F FA } + ixNet setMultiAttrs $sg_vport/protocols/ospf \ + -enableDrOrBdr False \ + -enabled False \ + -floodLinkStateUpdatesPerInterval 0 \ + -rateControlInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/ospfV3 \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/pimsm \ + -bsmFramePerInterval 0 \ + -crpFramePerInterval 0 \ + -dataMdtFramePerInterval 0 \ + -denyGrePimIpPrefix {0.0.0.0/32} \ + -enableDiscardJoinPruneProcessing False \ + -enableRateControl False \ + -enabled False \ + -helloMsgsPerInterval 0 \ + -interval 0 \ + -joinPruneMessagesPerInterval 0 \ + -registerMessagesPerInterval 0 \ + -registerStopMessagesPerInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/ping \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/rip \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/ripng \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/rsvp \ + -enableControlLspInitiationRate False \ + -enableShowTimeValue False \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -maxLspInitiationsPerSec 400 \ + -useTransportLabelsForMplsOam False + ixNet setMultiAttrs $sg_vport/protocols/stp \ + -enabled False + ixNet setMultiAttrs $sg_vport/rateControlParameters \ + -maxRequestsPerBurst 1 \ + -maxRequestsPerSec 250 \ + -minRetryInterval 10 \ + -retryCount 3 \ + -sendInBursts False \ + -sendRequestsAsFastAsPossible False + ixNet setMultiAttrs $sg_vport/capture \ + -controlCaptureTrigger {} \ + -controlCaptureFilter {} \ + -hardwareEnabled False \ + -softwareEnabled False \ + -displayFiltersDataCapture {} \ + -displayFiltersControlCapture {} \ + -controlBufferSize 30 \ + -controlBufferBehaviour bufferLiveNonCircular + ixNet setMultiAttrs $sg_vport/protocolStack/options \ + -routerSolicitationDelay 1 \ + -routerSolicitationInterval 4 \ + -routerSolicitations 3 \ + -retransTime 1000 \ + -dadTransmits 1 \ + -dadEnabled True \ + -ipv4RetransTime 3000 \ + -ipv4McastSolicit 4 + sg_commit + set sg_vport [lindex [ixNet remapIds $sg_vport] 0] + set ixNetSG_ref(2) $sg_vport + set ixNetSG_Stack(1) $sg_vport + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:1 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:1 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:2 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:2 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:3 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:3 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:4 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:4 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:5 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:5 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/l1Config/rxFilters/uds:6 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:6 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:1/protocols/static/lan:1 + # + set sg_lan [ixNet add $ixNetSG_Stack(1)/protocols/static lan] + ixNet setMultiAttrs $sg_lan \ + -atmEncapsulation ::ixNet::OBJ-null \ + -count $L2CountValue \ + -countPerVc 1 \ + -enableIncrementMac $L2Increment \ + -enableIncrementVlan False \ + -enableSiteId False \ + -enableVlan False \ + -enabled True \ + -frEncapsulation ::ixNet::OBJ-null \ + -incrementPerVcVlanMode noIncrement \ + -incrementVlanMode noIncrement \ + -mac $srcMac \ + -macRangeMode normal \ + -numberOfVcs 1 \ + -siteId 0 \ + -skipVlanIdZero True \ + -tpid {0x8100} \ + -trafficGroupId ::ixNet::OBJ-null \ + -vlanCount 1 \ + -vlanId {1} \ + -vlanPriority {0} + sg_commit + set sg_lan [lindex [ixNet remapIds $sg_lan] 0] + + if {$twoPorts} { + # + # configuring the object that corresponds to /vport:2 + # + set sg_vport [ixNet add $ixNetSG_Stack(0) vport] + ixNet setMultiAttrs $sg_vport \ + -transmitIgnoreLinkStatus False \ + -txGapControlMode averageMode \ + -type tenGigLan \ + -connectedTo ::ixNet::OBJ-null \ + -txMode interleaved \ + -isPullOnly False \ + -rxMode captureAndMeasure \ + -name {10GE LAN - 002} + ixNet setMultiAttrs $sg_vport/l1Config \ + -currentType tenGigLan + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan \ + -ppm 0 \ + -flowControlDirectedAddress "01 80 C2 00 00 01" \ + -enablePPM False \ + -autoInstrumentation endOfFrame \ + -transmitClocking internal \ + -txIgnoreRxLinkFaults False \ + -loopback False \ + -enableLASIMonitoring False \ + -enabledFlowControl $flowControl + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan/oam \ + -tlvType {00} \ + -linkEvents False \ + -enabled False \ + -vendorSpecificInformation {00 00 00 00} \ + -macAddress "00:00:00:00:00:00" \ + -loopback False \ + -idleTimer 5 \ + -tlvValue {00} \ + -enableTlvOption False \ + -maxOAMPDUSize 64 \ + -organizationUniqueIdentifier {000000} + ixNet setMultiAttrs $sg_vport/l1Config/tenGigLan/fcoe \ + -supportDataCenterMode False \ + -priorityGroupSize priorityGroupSize-8 \ + -pfcPauseDelay 1 \ + -pfcPriorityGroups {0 1 2 3 4 5 6 7} \ + -flowControlType ieee802.1Qbb \ + -enablePFCPauseDelay False + ixNet setMultiAttrs $sg_vport/l1Config/fortyGigLan \ + -ppm 0 \ + -flowControlDirectedAddress "01 80 C2 00 00 01" \ + -enablePPM False \ + -autoInstrumentation endOfFrame \ + -transmitClocking internal \ + -txIgnoreRxLinkFaults False \ + -loopback False \ + -enableLASIMonitoring False \ + -enabledFlowControl $flowControl + ixNet setMultiAttrs $sg_vport/l1Config/fortyGigLan/fcoe \ + -supportDataCenterMode False \ + -priorityGroupSize priorityGroupSize-8 \ + -pfcPauseDelay 1 \ + -pfcPriorityGroups {0 1 2 3 4 5 6 7} \ + -flowControlType ieee802.1Qbb \ + -enablePFCPauseDelay False + ixNet setMultiAttrs $sg_vport/l1Config/OAM \ + -tlvType {00} \ + -linkEvents False \ + -enabled False \ + -vendorSpecificInformation {00 00 00 00} \ + -macAddress "00:00:00:00:00:00" \ + -loopback False \ + -idleTimer 5 \ + -tlvValue {00} \ + -enableTlvOption False \ + -maxOAMPDUSize 64 \ + -organizationUniqueIdentifier {000000} + ixNet setMultiAttrs $sg_vport/l1Config/rxFilters/filterPalette \ + -sourceAddress1Mask {00:00:00:00:00:00} \ + -destinationAddress1Mask {00:00:00:00:00:00} \ + -sourceAddress2 {00:00:00:00:00:00} \ + -pattern2OffsetType fromStartOfFrame \ + -pattern2Offset 20 \ + -pattern1Mask {00} \ + -sourceAddress2Mask {00:00:00:00:00:00} \ + -destinationAddress2 {00:00:00:00:00:00} \ + -destinationAddress1 {00:00:00:00:00:00} \ + -sourceAddress1 {00:00:00:00:00:00} \ + -pattern1 {00} \ + -destinationAddress2Mask {00:00:00:00:00:00} \ + -pattern2Mask {00} \ + -pattern1Offset 20 \ + -pattern2 {00} \ + -pattern1OffsetType fromStartOfFrame + ixNet setMultiAttrs $sg_vport/protocols/arp \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/bfd \ + -enabled False \ + -intervalValue 0 \ + -packetsPerInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/bgp \ + -autoFillUpDutIp False \ + -disableReceivedUpdateValidation False \ + -enableAdVplsPrefixLengthInBits False \ + -enableExternalActiveConnect True \ + -enableInternalActiveConnect True \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -externalRetries 0 \ + -externalRetryDelay 120 \ + -internalRetries 0 \ + -internalRetryDelay 120 \ + -mldpP2mpFecType 6 \ + -triggerVplsPwInitiation False + ixNet setMultiAttrs $sg_vport/protocols/cfm \ + -enableOptionalLmFunctionality False \ + -enableOptionalTlvValidation True \ + -enabled False \ + -receiveCcm True \ + -sendCcm True \ + -suppressErrorsOnAis True + ixNet setMultiAttrs $sg_vport/protocols/eigrp \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/elmi \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/igmp \ + -enabled False \ + -numberOfGroups 0 \ + -numberOfQueries 0 \ + -queryTimePeriod 0 \ + -sendLeaveOnStop True \ + -statsEnabled False \ + -timePeriod 0 + ixNet setMultiAttrs $sg_vport/protocols/isis \ + -allL1RbridgesMac "01:80:c2:00:00:40" \ + -emulationType isisL3Routing \ + -enabled False \ + -helloMulticastMac "01:80:c2:00:00:41" \ + -lspMgroupPdusPerInterval 0 \ + -nlpId 192 \ + -rateControlInterval 0 \ + -sendP2PHellosToUnicastMac True \ + -spbAllL1BridgesMac "09:00:2b:00:00:05" \ + -spbHelloMulticastMac "09:00:2b:00:00:05" \ + -spbNlpId 192 + ixNet setMultiAttrs $sg_vport/protocols/lacp \ + -enablePreservePartnerInfo False \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/ldp \ + -enableDiscardSelfAdvFecs False \ + -enableHelloJitter True \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -helloHoldTime 15 \ + -helloInterval 5 \ + -keepAliveHoldTime 30 \ + -keepAliveInterval 10 \ + -p2mpCapabilityParam 1288 \ + -p2mpFecType 6 \ + -targetedHelloInterval 15 \ + -targetedHoldTime 45 \ + -useTransportLabelsForMplsOam False + ixNet setMultiAttrs $sg_vport/protocols/linkOam \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/lisp \ + -burstIntervalInMs 0 \ + -enabled False \ + -ipv4MapRegisterPacketsPerBurst 0 \ + -ipv4MapRequestPacketsPerBurst 0 \ + -ipv4SmrPacketsPerBurst 0 \ + -ipv6MapRegisterPacketsPerBurst 0 \ + -ipv6MapRequestPacketsPerBurst 0 \ + -ipv6SmrPacketsPerBurst 0 + ixNet setMultiAttrs $sg_vport/protocols/mld \ + -enableDoneOnStop True \ + -enabled False \ + -mldv2Report type143 \ + -numberOfGroups 0 \ + -numberOfQueries 0 \ + -queryTimePeriod 0 \ + -timePeriod 0 + ixNet setMultiAttrs $sg_vport/protocols/mplsOam \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/mplsTp \ + -apsChannelType {00 02 } \ + -bfdCcChannelType {00 07 } \ + -delayManagementChannelType {00 05 } \ + -enableHighPerformanceMode True \ + -enabled False \ + -faultManagementChannelType {00 58 } \ + -lossMeasurementChannelType {00 04 } \ + -onDemandCvChannelType {00 09 } \ + -pwStatusChannelType {00 0B } \ + -y1731ChannelType {7F FA } + ixNet setMultiAttrs $sg_vport/protocols/ospf \ + -enableDrOrBdr False \ + -enabled False \ + -floodLinkStateUpdatesPerInterval 0 \ + -rateControlInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/ospfV3 \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/pimsm \ + -bsmFramePerInterval 0 \ + -crpFramePerInterval 0 \ + -dataMdtFramePerInterval 0 \ + -denyGrePimIpPrefix {0.0.0.0/32} \ + -enableDiscardJoinPruneProcessing False \ + -enableRateControl False \ + -enabled False \ + -helloMsgsPerInterval 0 \ + -interval 0 \ + -joinPruneMessagesPerInterval 0 \ + -registerMessagesPerInterval 0 \ + -registerStopMessagesPerInterval 0 + ixNet setMultiAttrs $sg_vport/protocols/ping \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/rip \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/ripng \ + -enabled False + ixNet setMultiAttrs $sg_vport/protocols/rsvp \ + -enableControlLspInitiationRate False \ + -enableShowTimeValue False \ + -enableVpnLabelExchangeOverLsp True \ + -enabled False \ + -maxLspInitiationsPerSec 400 \ + -useTransportLabelsForMplsOam False + ixNet setMultiAttrs $sg_vport/protocols/stp \ + -enabled False + ixNet setMultiAttrs $sg_vport/rateControlParameters \ + -maxRequestsPerBurst 1 \ + -maxRequestsPerSec 250 \ + -minRetryInterval 10 \ + -retryCount 3 \ + -sendInBursts False \ + -sendRequestsAsFastAsPossible False + ixNet setMultiAttrs $sg_vport/capture \ + -controlCaptureTrigger {} \ + -controlCaptureFilter {} \ + -hardwareEnabled False \ + -softwareEnabled False \ + -displayFiltersDataCapture {} \ + -displayFiltersControlCapture {} \ + -controlBufferSize 30 \ + -controlBufferBehaviour bufferLiveNonCircular + ixNet setMultiAttrs $sg_vport/protocolStack/options \ + -routerSolicitationDelay 1 \ + -routerSolicitationInterval 4 \ + -routerSolicitations 3 \ + -retransTime 1000 \ + -dadTransmits 1 \ + -dadEnabled True \ + -ipv4RetransTime 3000 \ + -ipv4McastSolicit 4 + sg_commit + set sg_vport [lindex [ixNet remapIds $sg_vport] 0] + set ixNetSG_ref(10) $sg_vport + set ixNetSG_Stack(1) $sg_vport + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:1 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:1 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:2 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:2 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:3 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:3 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:4 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:4 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:5 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:5 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/l1Config/rxFilters/uds:6 + # + set sg_uds $ixNetSG_Stack(1)/l1Config/rxFilters/uds:6 + ixNet setMultiAttrs $sg_uds \ + -destinationAddressSelector anyAddr \ + -customFrameSizeTo 0 \ + -customFrameSizeFrom 0 \ + -error errAnyFrame \ + -patternSelector anyPattern \ + -sourceAddressSelector anyAddr \ + -isEnabled True \ + -frameSizeType any + sg_commit + set sg_uds [lindex [ixNet remapIds $sg_uds] 0] + + # + # configuring the object that corresponds to /vport:2/protocols/static/lan:1 + # + set sg_lan [ixNet add $ixNetSG_Stack(1)/protocols/static lan] + ixNet setMultiAttrs $sg_lan \ + -atmEncapsulation ::ixNet::OBJ-null \ + -count $L2CountValue \ + -countPerVc 1 \ + -enableIncrementMac $L2Increment \ + -enableIncrementVlan False \ + -enableSiteId False \ + -enableVlan False \ + -enabled True \ + -frEncapsulation ::ixNet::OBJ-null \ + -incrementPerVcVlanMode noIncrement \ + -incrementVlanMode noIncrement \ + -mac $dstMac \ + -macRangeMode normal \ + -numberOfVcs 1 \ + -siteId 0 \ + -skipVlanIdZero True \ + -tpid {0x8100} \ + -trafficGroupId ::ixNet::OBJ-null \ + -vlanCount 1 \ + -vlanId {1} \ + -vlanPriority {0} + sg_commit + set sg_lan [lindex [ixNet remapIds $sg_lan] 0] + } + + ### + ### /availableHardware area + ### + + # + # configuring the object that corresponds to /availableHardware/chassis" + # + set sg_chassis [ixNet add $ixNetSG_Stack(0)/availableHardware chassis] + ixNet setMultiAttrs $sg_chassis \ + -masterChassis {} \ + -sequenceId 1 \ + -cableLength 0 \ + -hostname $::chassis + sg_commit + set sg_chassis [lindex [ixNet remapIds $sg_chassis] 0] + set ixNetSG_Stack(1) $sg_chassis + + # + # configuring the object that corresponds to /availableHardware/chassis/card + # + set sg_card $ixNetSG_Stack(1)/card:$::card + ixNet setMultiAttrs $sg_card \ + -aggregationMode normal + sg_commit + set sg_card [lindex [ixNet remapIds $sg_card] 0] + set ixNetSG_ref(19) $sg_card + set ixNetSG_Stack(2) $sg_card + + # + # configuring the object that corresponds to /availableHardware/chassis/card/aggregation:1 + # + set sg_aggregation $ixNetSG_Stack(2)/aggregation:1 + ixNet setMultiAttrs $sg_aggregation \ + -mode normal + sg_commit + set sg_aggregation [lindex [ixNet remapIds $sg_aggregation] 0] + + # + # configuring the object that corresponds to /availableHardware/chassis/card/aggregation:2 + # + set sg_aggregation $ixNetSG_Stack(2)/aggregation:2 + ixNet setMultiAttrs $sg_aggregation \ + -mode normal + sg_commit + set sg_aggregation [lindex [ixNet remapIds $sg_aggregation] 0] + + # + # configuring the object that corresponds to /availableHardware/chassis/card/aggregation:3 + # + set sg_aggregation $ixNetSG_Stack(2)/aggregation:3 + ixNet setMultiAttrs $sg_aggregation \ + -mode normal + sg_commit + set sg_aggregation [lindex [ixNet remapIds $sg_aggregation] 0] + + # + # configuring the object that corresponds to /availableHardware/chassis/card/aggregation:4 + # + set sg_aggregation $ixNetSG_Stack(2)/aggregation:4 + ixNet setMultiAttrs $sg_aggregation \ + -mode normal + sg_commit + set sg_aggregation [lindex [ixNet remapIds $sg_aggregation] 0] + ixNet setMultiAttrs $ixNetSG_ref(2) \ + -connectedTo $ixNetSG_ref(19)/port:$::port1 + sg_commit + if {$twoPorts} { + ixNet setMultiAttrs $ixNetSG_ref(10) \ + -connectedTo $ixNetSG_ref(19)/port:$::port2 + sg_commit + } + sg_commit + + ### + ### /impairment area + ### + + # + # configuring the object that corresponds to /impairment/profile:3 + # + set sg_profile [ixNet add $ixNetSG_Stack(0)/impairment profile] + ixNet setMultiAttrs $sg_profile \ + -enabled False \ + -name {Impairment Profile 1} \ + -links {} \ + -allLinks True \ + -priority 1 + ixNet setMultiAttrs $sg_profile/checksums \ + -dropRxL2FcsErrors False \ + -correctTxL2FcsErrors False \ + -alwaysCorrectWhenModifying True \ + -correctTxChecksumOverIp False \ + -correctTxIpv4Checksum False + ixNet setMultiAttrs $sg_profile/rxRateLimit \ + -enabled False \ + -value 8 \ + -units {kKilobitsPerSecond} + ixNet setMultiAttrs $sg_profile/drop \ + -enabled True \ + -clusterSize 1 \ + -percentRate 0 + ixNet setMultiAttrs $sg_profile/reorder \ + -enabled False \ + -clusterSize 1 \ + -percentRate 0 \ + -skipCount 1 + ixNet setMultiAttrs $sg_profile/duplicate \ + -enabled False \ + -clusterSize 1 \ + -percentRate 0 \ + -duplicateCount 1 + ixNet setMultiAttrs $sg_profile/bitError \ + -enabled False \ + -logRate 3 \ + -skipEndOctets 0 \ + -skipStartOctets 0 + ixNet setMultiAttrs $sg_profile/delay \ + -enabled True \ + -value 300 \ + -units {kMicroseconds} + ixNet setMultiAttrs $sg_profile/delayVariation \ + -uniformSpread 0 \ + -enabled False \ + -units {kMicroseconds} \ + -distribution {kUniform} \ + -exponentialMeanArrival 0 \ + -gaussianStandardDeviation 0 + ixNet setMultiAttrs $sg_profile/customDelayVariation \ + -enabled False \ + -name {} + sg_commit + set sg_profile [lindex [ixNet remapIds $sg_profile] 0] + set ixNetSG_Stack(1) $sg_profile + + # + # configuring the object that corresponds to /impairment/profile:3/fixedClassifier:1 + # + set sg_fixedClassifier [ixNet add $ixNetSG_Stack(1) fixedClassifier] + sg_commit + set sg_fixedClassifier [lindex [ixNet remapIds $sg_fixedClassifier] 0] + + ### + ### /traffic area + ### + + # + # configuring the object that corresponds to /traffic/trafficItem:1 + # + set sg_trafficItem [ixNet add $ixNetSG_Stack(0)/traffic trafficItem] + ixNet setMultiAttrs $sg_trafficItem \ + -transportRsvpTePreference one \ + -trafficItemType l2L3 \ + -biDirectional $::biDirect \ + -mergeDestinations True \ + -hostsPerNetwork 1 \ + -transmitMode interleaved \ + -ordinalNo 0 \ + -trafficType {ethernetVlan} \ + -interAsLdpPreference two \ + -allowSelfDestined $selfDestined \ + -enabled True \ + -maxNumberOfVpnLabelStack 2 \ + -interAsBgpPreference one \ + -suspend False \ + -transportLdpPreference two \ + -egressEnabled False \ + -enableDynamicMplsLabelValues False \ + -routeMesh oneToOne \ + -name {Traffic Item 1} \ + -srcDestMesh oneToOne + sg_commit + set sg_trafficItem [lindex [ixNet remapIds $sg_trafficItem] 0] + set ixNetSG_ref(26) $sg_trafficItem + set ixNetSG_Stack(1) $sg_trafficItem + + # + # configuring the object that corresponds to /traffic/trafficItem:1/endpointSet:1 + # + set sg_endpointSet [ixNet add $ixNetSG_Stack(1) endpointSet] + if {$twoPorts} { + ixNet setMultiAttrs $sg_endpointSet \ + -destinations [list $ixNetSG_ref(10)/protocols] \ + -destinationFilter {} \ + -sourceFilter {} \ + -trafficGroups {} \ + -sources [list $ixNetSG_ref(2)/protocols] \ + -name {EndpointSet-1} + } else { + ixNet setMultiAttrs $sg_endpointSet \ + -destinations [list $ixNetSG_ref(2)/protocols] \ + -destinationFilter {} \ + -sourceFilter {} \ + -trafficGroups {} \ + -sources [list $ixNetSG_ref(2)/protocols] \ + -name {EndpointSet-1} + } + sg_commit + set sg_endpointSet [lindex [ixNet remapIds $sg_endpointSet] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1 + # + set sg_configElement $ixNetSG_Stack(1)/configElement:1 + ixNet setMultiAttrs $sg_configElement \ + -crc badCrc \ + -preambleCustomSize 8 \ + -enableDisparityError False \ + -preambleFrameSizeMode auto \ + -destinationMacMode manual + ixNet setMultiAttrs $sg_configElement/frameSize \ + -weightedPairs {} \ + -fixedSize 64 \ + -incrementFrom 64 \ + -randomMin 64 \ + -randomMax 1518 \ + -quadGaussian {} \ + -type fixed \ + -presetDistribution cisco \ + -incrementStep 1 \ + -incrementTo 1518 + ixNet setMultiAttrs $sg_configElement/frameRate \ + -bitRateUnitsType bitsPerSec \ + -rate 10 \ + -enforceMinimumInterPacketGap 0 \ + -type percentLineRate \ + -interPacketGapUnitsType nanoseconds + ixNet setMultiAttrs $sg_configElement/framePayload \ + -type incrementByte \ + -customRepeat True \ + -customPattern {} + ixNet setMultiAttrs $sg_configElement/frameRateDistribution \ + -streamDistribution applyRateToAll \ + -portDistribution applyRateToAll + ixNet setMultiAttrs $sg_configElement/transmissionControl \ + -frameCount 1 \ + -minGapBytes 12 \ + -interStreamGap 0 \ + -interBurstGap 0 \ + -interBurstGapUnits nanoseconds \ + -type continuous \ + -duration 1 \ + -repeatBurst 1 \ + -enableInterStreamGap False \ + -startDelayUnits bytes \ + -iterationCount 1 \ + -burstPacketCount 1 \ + -enableInterBurstGap False \ + -startDelay 0 + sg_commit + set sg_configElement [lindex [ixNet remapIds $sg_configElement] 0] + set ixNetSG_Stack(2) $sg_configElement + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ethernet-1" + # + set sg_stack $ixNetSG_Stack(2)/stack:"ethernet-$stack_number" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + incr stack_number + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"/field:"ethernet.header.destinationAddress-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.destinationAddress-1" + ixNet setMultiAttrs $sg_field \ + -singleValue $dstMac \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:01} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue $dstMac \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue $dstMac \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"/field:"ethernet.header.sourceAddress-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.sourceAddress-2" + ixNet setMultiAttrs $sg_field \ + -singleValue $srcMac \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:00} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue $srcMac \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue $srcMac \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"/field:"ethernet.header.etherType-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.etherType-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {800} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0xFFFF}} \ + -stepValue {0xFFFF} \ + -fixedBits {0xFFFF} \ + -fieldValue {800} \ + -auto True \ + -randomMask {0xFFFF} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0xFFFF} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ethernet-1"/field:"ethernet.header.pfcQueue-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.pfcQueue-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + if {$vlanEnabled == 1 } { + set sg_stack $ixNetSG_Stack(2)/stack:"vlan-$stack_number" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + incr stack_number + + set sg_field $ixNetSG_Stack(3)/field:"vlan.header.vlanTag.vlanUserPriority-1" + ixNet setMultiAttrs $sg_field \ + -singleValue $vlanUserPrio \ + -seed 1 \ + -optionalEnabled true \ + -fullMesh false \ + -valueList [list 0] \ + -stepValue 0 \ + -fixedBits 0 \ + -fieldValue $vlanUserPrio \ + -auto false \ + -randomMask 0 \ + -trackingEnabled false \ + -valueType singleValue \ + -activeFieldChoice false \ + -startValue 0 \ + -countValue 1 + + set sg_field $ixNetSG_Stack(3)/field:"vlan.header.vlanTag.cfi-2" + ixNet setMultiAttrs $sg_field \ + -singleValue $vlanCfi \ + -seed 1 \ + -optionalEnabled true \ + -fullMesh false \ + -valueList [list 0] \ + -stepValue 0 \ + -fixedBits 0 \ + -fieldValue $vlanCfi \ + -auto false \ + -randomMask 0 \ + -trackingEnabled false \ + -valueType singleValue \ + -activeFieldChoice false \ + -startValue 0 \ + -countValue 1 + + set sg_field $ixNetSG_Stack(3)/field:"vlan.header.vlanTag.vlanID-3" + ixNet setMultiAttrs $sg_field \ + -singleValue $vlanId \ + -seed 1 \ + -optionalEnabled true \ + -fullMesh false \ + -valueList [list 0] \ + -stepValue 0 \ + -fixedBits 0 \ + -fieldValue $vlanId \ + -auto false \ + -randomMask 0 \ + -trackingEnabled false \ + -valueType singleValue \ + -activeFieldChoice false \ + -startValue 0 \ + -countValue 1 + + set sg_field $ixNetSG_Stack(3)/field:"vlan.header.protocolID-4" + ixNet setMultiAttrs $sg_field \ + -singleValue ffff \ + -seed 1 \ + -optionalEnabled true \ + -fullMesh false \ + -valueList [list 0xffff] \ + -stepValue 0xffff \ + -fixedBits 0xffff \ + -fieldValue ffff \ + -auto true \ + -randomMask 0xffff \ + -trackingEnabled false \ + -valueType singleValue \ + -activeFieldChoice false \ + -startValue 0xffff \ + -countValue 1 + } + + if {$l3Enabled == 1 } { + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2" + # + set sg_stack $ixNetSG_Stack(2)/stack:"ipv4-$stack_number" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + incr stack_number + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.version-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.version-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.headerLength-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.headerLength-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {5} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.raw-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.raw-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.precedence-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.precedence-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {000 Routine} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.delay-5" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.delay-5" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.throughput-6" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.throughput-6" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.reliability-7" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.reliability-7" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.monetary-8" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.monetary-8" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.tos.unused-9" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.unused-9" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {Precedence 1} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + ixNet setMultiAttrs $sg_field \ + -singleValue {10} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{10}} \ + -stepValue {10} \ + -fixedBits {10} \ + -fieldValue {Class 1, Low drop precedence} \ + -auto False \ + -randomMask {10} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {10} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + ixNet setMultiAttrs $sg_field \ + -singleValue {46} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{46}} \ + -stepValue {46} \ + -fixedBits {46} \ + -fieldValue {46} \ + -auto False \ + -randomMask {46} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {46} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.totalLength-18" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.totalLength-18" + ixNet setMultiAttrs $sg_field \ + -singleValue {46} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{20}} \ + -stepValue {20} \ + -fixedBits {20} \ + -fieldValue {46} \ + -auto True \ + -randomMask {20} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {20} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.identification-19" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.identification-19" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.flags.reserved-20" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.reserved-20" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.flags.fragment-21" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.fragment-21" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {May fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.flags.lastFragment-22" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.lastFragment-22" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Last fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.fragmentOffset-23" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.fragmentOffset-23" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.ttl-24" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.ttl-24" + ixNet setMultiAttrs $sg_field \ + -singleValue {64} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{64}} \ + -stepValue {64} \ + -fixedBits {64} \ + -fieldValue {64} \ + -auto False \ + -randomMask {64} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {64} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.protocol-25" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.protocol-25" + ixNet setMultiAttrs $sg_field \ + -singleValue {17} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{61}} \ + -stepValue {61} \ + -fixedBits {61} \ + -fieldValue {UDP} \ + -auto True \ + -randomMask {61} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {61} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.checksum-26" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.checksum-26" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.srcIp-27" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.srcIp-27" + ixNet setMultiAttrs $sg_field \ + -singleValue $srcIp \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.0} \ + -fixedBits {0.0.0.0} \ + -fieldValue $srcIp \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0.0.0.0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.dstIp-28" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.dstIp-28" + ixNet setMultiAttrs $sg_field \ + -singleValue $dstIp \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.1} \ + -fixedBits {0.0.0.0} \ + -fieldValue $dstIp \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType $L3ValueType \ + -activeFieldChoice False \ + -startValue $dstIp \ + -countValue $L3CountValue + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.nop-29" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.nop-29" + ixNet setMultiAttrs $sg_field \ + -singleValue {1} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{1}} \ + -stepValue {1} \ + -fixedBits {1} \ + -fieldValue {1} \ + -auto False \ + -randomMask {1} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {1} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.type-30" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.type-30" + ixNet setMultiAttrs $sg_field \ + -singleValue {130} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{130}} \ + -stepValue {130} \ + -fixedBits {130} \ + -fieldValue {130} \ + -auto False \ + -randomMask {130} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {130} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.length-31" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.length-31" + ixNet setMultiAttrs $sg_field \ + -singleValue {11} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{11}} \ + -stepValue {11} \ + -fixedBits {11} \ + -fieldValue {11} \ + -auto False \ + -randomMask {11} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {11} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.security-32" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.security-32" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Unclassified} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.compartments-33" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.compartments-33" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.handling-34" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.handling-34" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.tcc-35" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.tcc-35" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + ixNet setMultiAttrs $sg_field \ + -singleValue {131} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{131}} \ + -stepValue {131} \ + -fixedBits {131} \ + -fieldValue {131} \ + -auto False \ + -randomMask {131} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {131} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.pointer-38" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.pointer-38" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routeData-39" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routeData-39" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + ixNet setMultiAttrs $sg_field \ + -singleValue {137} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{137}} \ + -stepValue {137} \ + -fixedBits {137} \ + -fieldValue {137} \ + -auto False \ + -randomMask {137} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {137} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + ixNet setMultiAttrs $sg_field \ + -singleValue {7} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{7}} \ + -stepValue {7} \ + -fixedBits {7} \ + -fieldValue {7} \ + -auto False \ + -randomMask {7} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {7} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.type-44" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.type-44" + ixNet setMultiAttrs $sg_field \ + -singleValue {136} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{136}} \ + -stepValue {136} \ + -fixedBits {136} \ + -fieldValue {136} \ + -auto False \ + -randomMask {136} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {136} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.length-45" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.length-45" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.id-46" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.id-46" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + ixNet setMultiAttrs $sg_field \ + -singleValue {68} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{68}} \ + -stepValue {68} \ + -fixedBits {68} \ + -fieldValue {68} \ + -auto False \ + -randomMask {68} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {68} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + ixNet setMultiAttrs $sg_field \ + -singleValue {12} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{12}} \ + -stepValue {12} \ + -fixedBits {12} \ + -fieldValue {12} \ + -auto False \ + -randomMask {12} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {12} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{5}} \ + -stepValue {5} \ + -fixedBits {5} \ + -fieldValue {5} \ + -auto False \ + -randomMask {5} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {5} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Timestamps only, in consecutive 32-bit words} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.last-54" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.last-54" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + ixNet setMultiAttrs $sg_field \ + -singleValue {94} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x94}} \ + -stepValue {0x94} \ + -fixedBits {0x94} \ + -fieldValue {94} \ + -auto False \ + -randomMask {0x94} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x94} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x04}} \ + -stepValue {0x04} \ + -fixedBits {0x04} \ + -fieldValue {4} \ + -auto False \ + -randomMask {0x04} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x04} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Router shall examine packet} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"ipv4-2"/field:"ipv4.header.options.pad-58" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.pad-58" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + } + + if {$l4Enabled == 1 } { + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"udp-3" + # + set sg_stack $ixNetSG_Stack(2)/stack:"udp-$stack_number" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + incr stack_number + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"udp-3"/field:"udp.header.srcPort-1" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.srcPort-1" + ixNet setMultiAttrs $sg_field \ + -singleValue $srcPort \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {63} \ + -fixedBits {63} \ + -fieldValue $srcPort \ + -auto False \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue $srcPort \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"udp-3"/field:"udp.header.dstPort-2" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.dstPort-2" + ixNet setMultiAttrs $sg_field \ + -singleValue $dstPort \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {1} \ + -fixedBits {63} \ + -fieldValue $dstPort \ + -auto False \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType $L4ValueType \ + -activeFieldChoice False \ + -startValue $dstPort \ + -countValue $L4CountValue + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"udp-3"/field:"udp.header.length-3" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.length-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {26} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {26} \ + -auto True \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"udp-3"/field:"udp.header.checksum-4" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.checksum-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + } + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"fcs-4" + # + set sg_stack $ixNetSG_Stack(2)/stack:"fcs-$stack_number" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + incr stack_number + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/stack:"fcs-4"/field:"ethernet.fcs-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.fcs-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/configElement:1/transmissionDistribution + # + set sg_transmissionDistribution $ixNetSG_Stack(2)/transmissionDistribution + ixNet setMultiAttrs $sg_transmissionDistribution \ + -distributions {} + sg_commit + set sg_transmissionDistribution [lindex [ixNet remapIds $sg_transmissionDistribution] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/transmissionDistribution + # + set sg_transmissionDistribution $ixNetSG_Stack(1)/transmissionDistribution + ixNet setMultiAttrs $sg_transmissionDistribution \ + -distributions {} + sg_commit + set sg_transmissionDistribution [lindex [ixNet remapIds $sg_transmissionDistribution] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking + # + set sg_tracking $ixNetSG_Stack(1)/tracking + ixNet setMultiAttrs $sg_tracking \ + -offset 0 \ + -oneToOneMesh False \ + -trackBy {} \ + -values {} \ + -fieldWidth thirtyTwoBits \ + -protocolOffset {Root.0} + ixNet setMultiAttrs $sg_tracking/egress \ + -offset {Outer VLAN Priority (3 bits)} \ + -enabled False \ + -customOffsetBits 0 \ + -encapsulation {Ethernet} \ + -customWidthBits 0 + ixNet setMultiAttrs $sg_tracking/latencyBin \ + -enabled False \ + -binLimits {1 1.42 2 2.82 4 5.66 8 11.32} \ + -numberOfBins 8 + sg_commit + set sg_tracking [lindex [ixNet remapIds $sg_tracking] 0] + set ixNetSG_Stack(2) $sg_tracking + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ethernet-1" + # + set sg_stack $ixNetSG_Stack(2)/egress/fieldOffset/stack:"ethernet-1" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.destinationAddress-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.destinationAddress-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {00:00:00:00:00:00} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:00} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue {00:00:00:00:00:00} \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled True \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {00:00:00:00:00:00} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.sourceAddress-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.sourceAddress-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {00:00:00:00:00:00} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:00} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue {00:00:00:00:00:00} \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {00:00:00:00:00:00} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.etherType-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.etherType-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {800} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0xFFFF}} \ + -stepValue {0xFFFF} \ + -fixedBits {0xFFFF} \ + -fieldValue {800} \ + -auto True \ + -randomMask {0xFFFF} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0xFFFF} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.pfcQueue-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.pfcQueue-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2" + # + set sg_stack $ixNetSG_Stack(2)/egress/fieldOffset/stack:"ipv4-2" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.version-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.version-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.headerLength-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.headerLength-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {5} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.raw-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.raw-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.precedence-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.precedence-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {000 Routine} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.delay-5" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.delay-5" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.throughput-6" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.throughput-6" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.reliability-7" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.reliability-7" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.monetary-8" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.monetary-8" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.unused-9" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.unused-9" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {Precedence 1} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + ixNet setMultiAttrs $sg_field \ + -singleValue {10} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{10}} \ + -stepValue {10} \ + -fixedBits {10} \ + -fieldValue {Class 1, Low drop precedence} \ + -auto False \ + -randomMask {10} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {10} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + ixNet setMultiAttrs $sg_field \ + -singleValue {46} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{46}} \ + -stepValue {46} \ + -fixedBits {46} \ + -fieldValue {46} \ + -auto False \ + -randomMask {46} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {46} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.totalLength-18" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.totalLength-18" + ixNet setMultiAttrs $sg_field \ + -singleValue {92} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{20}} \ + -stepValue {20} \ + -fixedBits {20} \ + -fieldValue {92} \ + -auto True \ + -randomMask {20} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {20} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.identification-19" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.identification-19" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.reserved-20" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.reserved-20" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.fragment-21" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.fragment-21" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {May fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.lastFragment-22" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.lastFragment-22" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Last fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.fragmentOffset-23" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.fragmentOffset-23" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.ttl-24" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.ttl-24" + ixNet setMultiAttrs $sg_field \ + -singleValue {64} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{64}} \ + -stepValue {64} \ + -fixedBits {64} \ + -fieldValue {64} \ + -auto False \ + -randomMask {64} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {64} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.protocol-25" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.protocol-25" + ixNet setMultiAttrs $sg_field \ + -singleValue {17} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{61}} \ + -stepValue {61} \ + -fixedBits {61} \ + -fieldValue {UDP} \ + -auto True \ + -randomMask {61} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {61} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.checksum-26" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.checksum-26" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.srcIp-27" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.srcIp-27" + ixNet setMultiAttrs $sg_field \ + -singleValue {0.0.0.0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.0} \ + -fixedBits {0.0.0.0} \ + -fieldValue {0.0.0.0} \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0.0.0.0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.dstIp-28" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.dstIp-28" + ixNet setMultiAttrs $sg_field \ + -singleValue {0.0.0.0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.0} \ + -fixedBits {0.0.0.0} \ + -fieldValue {0.0.0.0} \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0.0.0.0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.nop-29" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.nop-29" + ixNet setMultiAttrs $sg_field \ + -singleValue {1} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{1}} \ + -stepValue {1} \ + -fixedBits {1} \ + -fieldValue {1} \ + -auto False \ + -randomMask {1} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {1} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.type-30" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.type-30" + ixNet setMultiAttrs $sg_field \ + -singleValue {130} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{130}} \ + -stepValue {130} \ + -fixedBits {130} \ + -fieldValue {130} \ + -auto False \ + -randomMask {130} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {130} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.length-31" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.length-31" + ixNet setMultiAttrs $sg_field \ + -singleValue {11} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{11}} \ + -stepValue {11} \ + -fixedBits {11} \ + -fieldValue {11} \ + -auto False \ + -randomMask {11} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {11} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.security-32" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.security-32" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Unclassified} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.compartments-33" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.compartments-33" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.handling-34" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.handling-34" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.tcc-35" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.tcc-35" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + ixNet setMultiAttrs $sg_field \ + -singleValue {131} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{131}} \ + -stepValue {131} \ + -fixedBits {131} \ + -fieldValue {131} \ + -auto False \ + -randomMask {131} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {131} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.pointer-38" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.pointer-38" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routeData-39" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routeData-39" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + ixNet setMultiAttrs $sg_field \ + -singleValue {137} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{137}} \ + -stepValue {137} \ + -fixedBits {137} \ + -fieldValue {137} \ + -auto False \ + -randomMask {137} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {137} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + ixNet setMultiAttrs $sg_field \ + -singleValue {7} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{7}} \ + -stepValue {7} \ + -fixedBits {7} \ + -fieldValue {7} \ + -auto False \ + -randomMask {7} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {7} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.type-44" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.type-44" + ixNet setMultiAttrs $sg_field \ + -singleValue {136} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{136}} \ + -stepValue {136} \ + -fixedBits {136} \ + -fieldValue {136} \ + -auto False \ + -randomMask {136} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {136} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.length-45" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.length-45" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.id-46" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.id-46" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + ixNet setMultiAttrs $sg_field \ + -singleValue {68} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{68}} \ + -stepValue {68} \ + -fixedBits {68} \ + -fieldValue {68} \ + -auto False \ + -randomMask {68} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {68} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + ixNet setMultiAttrs $sg_field \ + -singleValue {12} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{12}} \ + -stepValue {12} \ + -fixedBits {12} \ + -fieldValue {12} \ + -auto False \ + -randomMask {12} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {12} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{5}} \ + -stepValue {5} \ + -fixedBits {5} \ + -fieldValue {5} \ + -auto False \ + -randomMask {5} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {5} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Timestamps only, in consecutive 32-bit words} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.last-54" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.last-54" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + ixNet setMultiAttrs $sg_field \ + -singleValue {94} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x94}} \ + -stepValue {0x94} \ + -fixedBits {0x94} \ + -fieldValue {94} \ + -auto False \ + -randomMask {0x94} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x94} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x04}} \ + -stepValue {0x04} \ + -fixedBits {0x04} \ + -fieldValue {4} \ + -auto False \ + -randomMask {0x04} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x04} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Router shall examine packet} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.pad-58" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.pad-58" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"udp-3" + # + set sg_stack $ixNetSG_Stack(2)/egress/fieldOffset/stack:"udp-3" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"udp-3"/field:"udp.header.srcPort-1" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.srcPort-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {63} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {63} \ + -fixedBits {63} \ + -fieldValue {Default} \ + -auto True \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {63} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"udp-3"/field:"udp.header.dstPort-2" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.dstPort-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {63} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {63} \ + -fixedBits {63} \ + -fieldValue {Default} \ + -auto True \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {63} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"udp-3"/field:"udp.header.length-3" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.length-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {72} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {72} \ + -auto True \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"udp-3"/field:"udp.header.checksum-4" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.checksum-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"fcs-4" + # + set sg_stack $ixNetSG_Stack(2)/egress/fieldOffset/stack:"fcs-4" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/tracking/egress/fieldOffset/stack:"fcs-4"/field:"ethernet.fcs-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.fcs-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1 + # + set sg_egressTracking [ixNet add $ixNetSG_Stack(1) egressTracking] + ixNet setMultiAttrs $sg_egressTracking \ + -offset {Outer VLAN Priority (3 bits)} \ + -customOffsetBits 0 \ + -encapsulation {Ethernet} \ + -customWidthBits 0 + sg_commit + set sg_egressTracking [lindex [ixNet remapIds $sg_egressTracking] 0] + set ixNetSG_Stack(2) $sg_egressTracking + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ethernet-1" + # + set sg_stack $ixNetSG_Stack(2)/fieldOffset/stack:"ethernet-1" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.destinationAddress-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.destinationAddress-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {00:00:00:00:00:00} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:00} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue {00:00:00:00:00:00} \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled True \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {00:00:00:00:00:00} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.sourceAddress-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.sourceAddress-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {00:00:00:00:00:00} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{00:00:00:00:00:00}} \ + -stepValue {00:00:00:00:00:00} \ + -fixedBits {00:00:00:00:00:00} \ + -fieldValue {00:00:00:00:00:00} \ + -auto False \ + -randomMask {00:00:00:00:00:00} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {00:00:00:00:00:00} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.etherType-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.etherType-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {800} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0xFFFF}} \ + -stepValue {0xFFFF} \ + -fixedBits {0xFFFF} \ + -fieldValue {800} \ + -auto True \ + -randomMask {0xFFFF} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0xFFFF} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ethernet-1"/field:"ethernet.header.pfcQueue-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.header.pfcQueue-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2" + # + set sg_stack $ixNetSG_Stack(2)/fieldOffset/stack:"ipv4-2" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.version-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.version-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.headerLength-2" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.headerLength-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {5} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.raw-3" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.raw-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.precedence-4" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.precedence-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {000 Routine} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.delay-5" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.delay-5" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.throughput-6" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.throughput-6" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.reliability-7" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.reliability-7" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.monetary-8" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.monetary-8" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Normal} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.tos.unused-9" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.tos.unused-9" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.defaultPHB-10" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.defaultPHB.unused-11" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.classSelectorPHB-12" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {Precedence 1} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.classSelectorPHB.unused-13" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.assuredForwardingPHB-14" + ixNet setMultiAttrs $sg_field \ + -singleValue {10} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{10}} \ + -stepValue {10} \ + -fixedBits {10} \ + -fieldValue {Class 1, Low drop precedence} \ + -auto False \ + -randomMask {10} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {10} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.assuredForwardingPHB.unused-15" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.expeditedForwardingPHB-16" + ixNet setMultiAttrs $sg_field \ + -singleValue {46} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{46}} \ + -stepValue {46} \ + -fixedBits {46} \ + -fieldValue {46} \ + -auto False \ + -randomMask {46} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {46} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.priority.ds.phb.expeditedForwardingPHB.unused-17" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.totalLength-18" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.totalLength-18" + ixNet setMultiAttrs $sg_field \ + -singleValue {92} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{20}} \ + -stepValue {20} \ + -fixedBits {20} \ + -fieldValue {92} \ + -auto True \ + -randomMask {20} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {20} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.identification-19" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.identification-19" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.reserved-20" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.reserved-20" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.fragment-21" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.fragment-21" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {May fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.flags.lastFragment-22" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.flags.lastFragment-22" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Last fragment} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.fragmentOffset-23" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.fragmentOffset-23" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.ttl-24" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.ttl-24" + ixNet setMultiAttrs $sg_field \ + -singleValue {64} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{64}} \ + -stepValue {64} \ + -fixedBits {64} \ + -fieldValue {64} \ + -auto False \ + -randomMask {64} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {64} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.protocol-25" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.protocol-25" + ixNet setMultiAttrs $sg_field \ + -singleValue {17} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{61}} \ + -stepValue {61} \ + -fixedBits {61} \ + -fieldValue {UDP} \ + -auto True \ + -randomMask {61} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {61} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.checksum-26" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.checksum-26" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.srcIp-27" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.srcIp-27" + ixNet setMultiAttrs $sg_field \ + -singleValue {0.0.0.0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.0} \ + -fixedBits {0.0.0.0} \ + -fieldValue {0.0.0.0} \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0.0.0.0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.dstIp-28" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.dstIp-28" + ixNet setMultiAttrs $sg_field \ + -singleValue {0.0.0.0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0.0.0.0}} \ + -stepValue {0.0.0.0} \ + -fixedBits {0.0.0.0} \ + -fieldValue {0.0.0.0} \ + -auto False \ + -randomMask {0.0.0.0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0.0.0.0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.nop-29" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.nop-29" + ixNet setMultiAttrs $sg_field \ + -singleValue {1} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{1}} \ + -stepValue {1} \ + -fixedBits {1} \ + -fieldValue {1} \ + -auto False \ + -randomMask {1} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice True \ + -startValue {1} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.type-30" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.type-30" + ixNet setMultiAttrs $sg_field \ + -singleValue {130} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{130}} \ + -stepValue {130} \ + -fixedBits {130} \ + -fieldValue {130} \ + -auto False \ + -randomMask {130} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {130} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.length-31" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.length-31" + ixNet setMultiAttrs $sg_field \ + -singleValue {11} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{11}} \ + -stepValue {11} \ + -fixedBits {11} \ + -fieldValue {11} \ + -auto False \ + -randomMask {11} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {11} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.security-32" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.security-32" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Unclassified} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.compartments-33" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.compartments-33" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.handling-34" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.handling-34" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.security.tcc-35" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.security.tcc-35" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.type-36" + ixNet setMultiAttrs $sg_field \ + -singleValue {131} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{131}} \ + -stepValue {131} \ + -fixedBits {131} \ + -fieldValue {131} \ + -auto False \ + -randomMask {131} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {131} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.lsrr.length-37" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.pointer-38" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.pointer-38" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routeData-39" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routeData-39" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.type-40" + ixNet setMultiAttrs $sg_field \ + -singleValue {137} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{137}} \ + -stepValue {137} \ + -fixedBits {137} \ + -fieldValue {137} \ + -auto False \ + -randomMask {137} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {137} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.ssrr.length-41" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.type-42" + ixNet setMultiAttrs $sg_field \ + -singleValue {7} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{7}} \ + -stepValue {7} \ + -fixedBits {7} \ + -fieldValue {7} \ + -auto False \ + -randomMask {7} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {7} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.recordRoute.length-43" + ixNet setMultiAttrs $sg_field \ + -singleValue {8} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {8} \ + -auto False \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.type-44" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.type-44" + ixNet setMultiAttrs $sg_field \ + -singleValue {136} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{136}} \ + -stepValue {136} \ + -fixedBits {136} \ + -fieldValue {136} \ + -auto False \ + -randomMask {136} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {136} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.length-45" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.length-45" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{4}} \ + -stepValue {4} \ + -fixedBits {4} \ + -fieldValue {4} \ + -auto False \ + -randomMask {4} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {4} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.streamId.id-46" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.streamId.id-46" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.type-47" + ixNet setMultiAttrs $sg_field \ + -singleValue {68} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{68}} \ + -stepValue {68} \ + -fixedBits {68} \ + -fieldValue {68} \ + -auto False \ + -randomMask {68} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {68} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.length-48" + ixNet setMultiAttrs $sg_field \ + -singleValue {12} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{12}} \ + -stepValue {12} \ + -fixedBits {12} \ + -fieldValue {12} \ + -auto False \ + -randomMask {12} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {12} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pointer-49" + ixNet setMultiAttrs $sg_field \ + -singleValue {5} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{5}} \ + -stepValue {5} \ + -fixedBits {5} \ + -fieldValue {5} \ + -auto False \ + -randomMask {5} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {5} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.overflow-50" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.flags-51" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Timestamps only, in consecutive 32-bit words} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.address-52" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.timestamp.pair.timestamp-53" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.last-54" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.last-54" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.type-55" + ixNet setMultiAttrs $sg_field \ + -singleValue {94} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x94}} \ + -stepValue {0x94} \ + -fixedBits {0x94} \ + -fieldValue {94} \ + -auto False \ + -randomMask {0x94} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x94} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.length-56" + ixNet setMultiAttrs $sg_field \ + -singleValue {4} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0x04}} \ + -stepValue {0x04} \ + -fixedBits {0x04} \ + -fieldValue {4} \ + -auto False \ + -randomMask {0x04} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0x04} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.nextOption.option.routerAlert.value-57" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {Router shall examine packet} \ + -auto False \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"ipv4-2"/field:"ipv4.header.options.pad-58" + # + set sg_field $ixNetSG_Stack(3)/field:"ipv4.header.options.pad-58" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled False \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"udp-3" + # + set sg_stack $ixNetSG_Stack(2)/fieldOffset/stack:"udp-3" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"udp-3"/field:"udp.header.srcPort-1" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.srcPort-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {63} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {63} \ + -fixedBits {63} \ + -fieldValue {Default} \ + -auto True \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {63} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"udp-3"/field:"udp.header.dstPort-2" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.dstPort-2" + ixNet setMultiAttrs $sg_field \ + -singleValue {63} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{63}} \ + -stepValue {63} \ + -fixedBits {63} \ + -fieldValue {Default} \ + -auto True \ + -randomMask {63} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {63} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"udp-3"/field:"udp.header.length-3" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.length-3" + ixNet setMultiAttrs $sg_field \ + -singleValue {72} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{8}} \ + -stepValue {8} \ + -fixedBits {8} \ + -fieldValue {72} \ + -auto True \ + -randomMask {8} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {8} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"udp-3"/field:"udp.header.checksum-4" + # + set sg_field $ixNetSG_Stack(3)/field:"udp.header.checksum-4" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"fcs-4" + # + set sg_stack $ixNetSG_Stack(2)/fieldOffset/stack:"fcs-4" + sg_commit + set sg_stack [lindex [ixNet remapIds $sg_stack] 0] + set ixNetSG_Stack(3) $sg_stack + + # + # configuring the object that corresponds to /traffic/trafficItem:1/egressTracking:1/fieldOffset/stack:"fcs-4"/field:"ethernet.fcs-1" + # + set sg_field $ixNetSG_Stack(3)/field:"ethernet.fcs-1" + ixNet setMultiAttrs $sg_field \ + -singleValue {0} \ + -seed {1} \ + -optionalEnabled True \ + -fullMesh False \ + -valueList {{0}} \ + -stepValue {0} \ + -fixedBits {0} \ + -fieldValue {0} \ + -auto True \ + -randomMask {0} \ + -trackingEnabled False \ + -valueType singleValue \ + -activeFieldChoice False \ + -startValue {0} \ + -countValue {1} + sg_commit + set sg_field [lindex [ixNet remapIds $sg_field] 0] + + # + # configuring the object that corresponds to /traffic/trafficItem:1/dynamicUpdate + # + set sg_dynamicUpdate $ixNetSG_Stack(1)/dynamicUpdate + ixNet setMultiAttrs $sg_dynamicUpdate \ + -enabledSessionAwareTrafficFields {} \ + -enabledDynamicUpdateFields {} + sg_commit + set sg_dynamicUpdate [lindex [ixNet remapIds $sg_dynamicUpdate] 0] + + ### + ### /quickTest area + ### + + # + # configuring the object that corresponds to /quickTest/rfc2544throughput:1 + # + if {$rfc2544TestType == "throughput"} { + set sg_rfc2544throughput [ixNet add $ixNetSG_Stack(0)/quickTest rfc2544throughput] + ixNet setMultiAttrs $sg_rfc2544throughput \ + -name {QuickTest1} \ + -mode existingMode \ + -inputParameters {{}} + ixNet setMultiAttrs $sg_rfc2544throughput/testConfig \ + -protocolItem {} \ + -enableMinFrameSize True \ + -framesize $frameSize \ + -reportTputRateUnit mbps \ + -duration $duration \ + -numtrials $numTests \ + -trafficType constantLoading \ + -burstSize 1 \ + -framesPerBurstGap 1 \ + -tolerance 0 \ + -frameLossUnit {0} \ + -staggeredStart False \ + -framesizeList $frameSize \ + -frameSizeMode custom \ + -rateSelect percentMaxRate \ + -percentMaxRate 100 \ + -resolution 0.01 \ + -forceRegenerate False \ + -reportSequenceError False \ + -ipv4rate 50 \ + -ipv6rate 50 \ + -loadRateList $frameRate \ + -fixedLoadUnit percentMaxRate \ + -loadRateValue 80 \ + -incrementLoadUnit percentMaxRate \ + -initialIncrementLoadRate 10 \ + -stepIncrementLoadRate 10 \ + -maxIncrementLoadRate 100 \ + -randomLoadUnit percentMaxRate \ + -minRandomLoadRate 10 \ + -maxRandomLoadRate 80 \ + -countRandomLoadRate 1 \ + -minFpsRate 1000 \ + -minKbpsRate 64 \ + -txDelay 2 \ + -delayAfterTransmit 2 \ + -minRandomFrameSize 64 \ + -maxRandomFrameSize 1518 \ + -countRandomFrameSize 1 \ + -minIncrementFrameSize 64 \ + -stepIncrementFrameSize 64 \ + -maxIncrementFrameSize 1518 \ + -calculateLatency True \ + -latencyType storeForward \ + -calculateJitter False \ + -enableDataIntegrity False \ + -enableBackoffIteration False \ + -enableSaturationIteration False \ + -enableStopTestOnHighLoss False \ + -enableBackoffUseAs% False \ + -backoffIteration 1 \ + -saturationIteration 1 \ + -stopTestOnHighLoss 0 \ + -loadType $loadType \ + -stepLoadUnit percentMaxRate \ + -customLoadUnit percentMaxRate \ + -comboLoadUnit percentMaxRate \ + -binaryLoadUnit percentMaxRate \ + -initialBinaryLoadRate 100 \ + -minBinaryLoadRate 1 \ + -maxBinaryLoadRate 100 \ + -binaryResolution 1 \ + -binaryBackoff 50 \ + -binaryTolerance $tolerance \ + -binaryFrameLossUnit % \ + -comboFrameLossUnit % \ + -stepFrameLossUnit % \ + -initialStepLoadRate 10 \ + -maxStepLoadRate 100 \ + -stepStepLoadRate 10 \ + -stepTolerance 0 \ + -initialComboLoadRate 10 \ + -maxComboLoadRate 100 \ + -minComboLoadRate 10 \ + -stepComboLoadRate 10 \ + -comboResolution 1 \ + -comboBackoff 50 \ + -comboTolerance 0 \ + -binarySearchType linear \ + -unchangedValueList {0} \ + -enableFastConvergence $fastConvergence \ + -fastConvergenceDuration $convergenceDuration \ + -fastConvergenceThreshold 10 \ + -framesizeFixedValue $frameSize \ + -gap 3 \ + -unchangedInitial False \ + -generateTrackingOptionAggregationFiles False \ + -enableExtraIterations False \ + -extraIterationOffsets {10, -10} \ + -usePercentOffsets False \ + -imixDistribution weight \ + -imixAdd {0} \ + -imixDelete {0} \ + -imixData {{{{64}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 40}}{{128}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 30}}{{256}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 30}}}} \ + -imixEnabled False \ + -imixTemplates none \ + -framesizeImixList $frameSize \ + -imixTrafficType {UNCHNAGED} \ + -mapType {oneToOne} \ + -supportedTrafficTypes {mac,ipv4,ipv6,ipmix} + ixNet setMultiAttrs $sg_rfc2544throughput/learnFrames \ + -learnFrequency $learningFrequency \ + -learnNumFrames 10 \ + -learnRate 100 \ + -learnWaitTime 1000 \ + -learnFrameSize $frameSize \ + -fastPathLearnFrameSize $frameSize \ + -learnWaitTimeBeforeTransmit 0 \ + -learnSendMacOnly False \ + -learnSendRouterSolicitation False \ + -fastPathEnable $fastPathEnable \ + -fastPathRate 100 \ + -fastPathNumFrames 10 + ixNet setMultiAttrs $sg_rfc2544throughput/passCriteria \ + -passCriteriaLoadRateMode average \ + -passCriteriaLoadRateValue 100 \ + -passCriteriaLoadRateScale mbps \ + -enablePassFail False \ + -enableRatePassFail False \ + -enableLatencyPassFail False \ + -enableStandardDeviationPassFail False \ + -latencyThresholdValue 10 \ + -latencyThresholdScale us \ + -latencyThresholdMode average \ + -latencyVariationThresholdValue 0 \ + -latencyVariationThresholdScale us \ + -latencyVarThresholdMode average \ + -enableSequenceErrorsPassFail False \ + -seqErrorsThresholdValue 0 \ + -seqErrorsThresholdMode average \ + -enableDataIntegrityPassFail False \ + -dataErrorThresholdValue 0 \ + -dataErrorThresholdMode average + sg_commit + set sg_rfc2544throughput [lindex [ixNet remapIds $sg_rfc2544throughput] 0] + set ixNetSG_Stack(1) $sg_rfc2544throughput + + # + # configuring the object that corresponds to /quickTest/rfc2544throughput:1/protocols + # + set sg_protocols $ixNetSG_Stack(1)/protocols + ixNet setMultiAttrs $sg_protocols \ + -protocolState default \ + -waitAfterStart 120 \ + -waitAfterStop 30 + sg_commit + set sg_protocols [lindex [ixNet remapIds $sg_protocols] 0] + + # + # configuring the object that corresponds to /quickTest/rfc2544throughput:1/trafficSelection:1 + # + set sg_trafficSelection [ixNet add $ixNetSG_Stack(1) trafficSelection] + ixNet setMultiAttrs $sg_trafficSelection \ + -id $ixNetSG_ref(26) \ + -includeMode inTest \ + -itemType trafficItem + sg_commit + set sg_trafficSelection [lindex [ixNet remapIds $sg_trafficSelection] 0] + ixNet commit + + } elseif {$rfc2544TestType == "back2back"} { + # + # configuring the object that corresponds to /quickTest/rfc2544back2back:2 + # + set sg_rfc2544back2back [ixNet add $ixNetSG_Stack(0)/quickTest rfc2544back2back] + ixNet setMultiAttrs $sg_rfc2544back2back \ + -name {B2B} \ + -mode existingMode \ + -inputParameters {{}} + ixNet setMultiAttrs $sg_rfc2544back2back/testConfig \ + -protocolItem {} \ + -framesize $frameSize \ + -reportTputRateUnit mbps \ + -rfc2544ImixDataQoS False \ + -detailedResultsEnabled True \ + -rfc2889ordering noOrdering \ + -floodedFramesEnabled False \ + -duration $duration \ + -numtrials $numTests \ + -trafficType constantLoading \ + -burstSize 1 \ + -framesPerBurstGap 1 \ + -tolerance 0 \ + -frameLossUnit {0} \ + -staggeredStart False \ + -framesizeList $frameSize \ + -frameSizeMode custom \ + -rateSelect percentMaxRate \ + -percentMaxRate 100 \ + -resolution 0.01 \ + -forceRegenerate False \ + -reportSequenceError False \ + -ipv4rate 50 \ + -ipv6rate 50 \ + -loadRateList $frameRate \ + -minFpsRate 1000 \ + -minKbpsRate 64 \ + -txDelay 2 \ + -delayAfterTransmit 2 \ + -minRandomFrameSize 64 \ + -maxRandomFrameSize 1518 \ + -countRandomFrameSize 1 \ + -minIncrementFrameSize 64 \ + -stepIncrementFrameSize 64 \ + -maxIncrementFrameSize 1518 \ + -calculateLatency False \ + -calibrateLatency False \ + -latencyType cutThrough \ + -calculateJitter False \ + -enableDataIntegrity False \ + -loadType $loadType \ + -binaryFrameLossUnit % \ + -loadUnit percentMaxRate \ + -customLoadUnit percentMaxRate \ + -randomLoadUnit percentMaxRate \ + -incrementLoadUnit percentMaxRate \ + -binaryResolution 1000 \ + -binaryBackoff 50 \ + -binaryTolerance $tolerance \ + -initialIncrementLoadRate 100 \ + -stepIncrementLoadRate 10 \ + -maxIncrementLoadRate 100 \ + -minRandomLoadRate 10 \ + -maxRandomLoadRate 80 \ + -countRandomLoadRate 1 \ + -numFrames {100000} \ + -loadRate 100 \ + -enableMinFrameSize True \ + -gap 3 \ + -generateTrackingOptionAggregationFiles False \ + -sendFullyMeshed False \ + -imixDistribution weight \ + -imixAdd {0} \ + -imixDelete {0} \ + -imixData {{{{64}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 40}}{{128}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 30}}{{256}{{TOS S:0 S:0 S:0 S:0 S:0} S:0}{1 30}}}} \ + -imixEnabled False \ + -imixTemplates none \ + -framesizeImixList $frameSize \ + -imixTrafficType {UNCHNAGED} \ + -ipRatioMode fixed \ + -ipv4RatioList {10,25,50,75,90} \ + -ipv6RatioList {90,75,50,25,10} \ + -minIncrementIpv4Ratio {10} \ + -stepIncrementIpv4Ratio {10} \ + -maxIncrementIpv4Ratio {90} \ + -minIncrementIpv6Ratio {90} \ + -stepIncrementIpv6Ratio {-10} \ + -maxIncrementIpv6Ratio {10} \ + -minRandomIpv4Ratio {10} \ + -maxRandomIpv4Ratio {90} \ + -minRandomIpv6Ratio {90} \ + -maxRandomIpv6Ratio {10} \ + -countRandomIpRatio 1 \ + -mapType {oneToOne|manyToMany|fullMesh} \ + -supportedTrafficTypes {mac,ipv4,ipv6,ipmix} + ixNet setMultiAttrs $sg_rfc2544back2back/learnFrames \ + -learnFrequency $learningFrequency \ + -learnNumFrames 10 \ + -learnRate 100 \ + -learnWaitTime 1000 \ + -learnFrameSize 64 \ + -fastPathLearnFrameSize 64 \ + -learnWaitTimeBeforeTransmit 0 \ + -learnSendMacOnly False \ + -learnSendRouterSolicitation False \ + -fastPathEnable $fastPathEnable \ + -fastPathRate 100 \ + -fastPathNumFrames 10 + ixNet setMultiAttrs $sg_rfc2544back2back/passCriteria \ + -passCriteriaLoadRateMode average \ + -passCriteriaLoadRateValue 100 \ + -passCriteriaLoadRateScale mbps \ + -enablePassFail False \ + -enableRatePassFail False \ + -enableLatencyPassFail False \ + -enableStandardDeviationPassFail False \ + -latencyThresholdValue 10 \ + -latencyThresholdScale us \ + -latencyThresholdMode average \ + -latencyVariationThresholdValue 0 \ + -latencyVariationThresholdScale us \ + -latencyVarThresholdMode average \ + -enableSequenceErrorsPassFail False \ + -seqErrorsThresholdValue 0 \ + -seqErrorsThresholdMode average \ + -enableDataIntegrityPassFail False \ + -dataErrorThresholdValue 0 \ + -dataErrorThresholdMode average \ + -enableFrameCountPassFail False \ + -passCriteriaFrameCountValue 100 \ + -passCriteriaFrameCountMode average + sg_commit + set sg_rfc2544back2back [lindex [ixNet remapIds $sg_rfc2544back2back] 0] + set ixNetSG_Stack(1) $sg_rfc2544back2back + + # + # configuring the object that corresponds to /quickTest/rfc2544back2back:2/protocols + # + set sg_protocols $ixNetSG_Stack(1)/protocols + ixNet setMultiAttrs $sg_protocols \ + -protocolState default \ + -waitAfterStart 120 \ + -waitAfterStop 30 + sg_commit + set sg_protocols [lindex [ixNet remapIds $sg_protocols] 0] + + # + # configuring the object that corresponds to /quickTest/rfc2544back2back:2/trafficSelection:1 + # + set sg_trafficSelection [ixNet add $ixNetSG_Stack(1) trafficSelection] + ixNet setMultiAttrs $sg_trafficSelection \ + -id $ixNetSG_ref(26) \ + -includeMode inTest \ + -itemType trafficItem + sg_commit + set sg_trafficSelection [lindex [ixNet remapIds $sg_trafficSelection] 0] + ixNet commit + } + # + # getting and applying the RFC2544 test + # + set root [ixNet getRoot] + set qt [ixNet getList $root quickTest] + if {$rfc2544TestType == "throughput"} { + set rfc2544test [ixNet getList $qt rfc2544throughput] + } elseif {$rfc2544TestType == "back2back"} { + set rfc2544test [ixNet getList $qt rfc2544back2back] + } + ixNet exec apply $rfc2544test + after 5000 + + # + # starting the RFC2544 Throughput test + # + puts "Starting test..." + ixNet exec start $rfc2544test +} + +proc waitForRfc2544Test { } { + # Wait for- and return results of- RFC2544 quicktest. + + global rfc2544test + + puts "Waiting for test to complete..." + set result [ixNet exec waitForTest $rfc2544test] + puts "Finished Test" + + return "$result" +} 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/3rd_party/ixia/pass_fail.tcl b/3rd_party/ixia/pass_fail.tcl index 0a5a7677..bf1fb556 100755 --- a/3rd_party/ixia/pass_fail.tcl +++ b/3rd_party/ixia/pass_fail.tcl @@ -431,7 +431,7 @@ proc sendTraffic { flowSpec trafficSpec } { if {[udp set $::chassis $::card $::port1]} { errorMsg "Error setting udp on port $::chassis.$::card.$::port1" } - errorMsg "frameSize: $frameSize, packetSize: $packetSize, srcMac: $srcMac, dstMac: $dstMac, srcPort: $srcPort, dstPort: $dstPort" + errorMsg "frameSize: $frameSize, packetSize: $packetSize, srcMac: $srcMac, dstMac: $dstMac, srcPort: $srcPort, dstPort: $dstPort, framerate: $frameRate %" if {[info exists protocolPad]} { errorMsg "protocolPad: $protocolPad, protocolPadBytes: $protocolPadBytes" } @@ -544,8 +544,8 @@ proc sendTraffic { flowSpec trafficSpec } { } else { errorMsg "Too many packets for capture." } - - set result [list $framesSent $framesRecv $bytesSent $bytesRecv $payError $seqError] + lappend result $payError + lappend result $seqError return $result } else { errorMsg "streamtype is not supported: '$streamType'" @@ -638,6 +638,9 @@ proc stopTraffic {} { logMsg "Frame Rate Sent: $sendRate" logMsg "Frame Rate Recv: $recvRate\n" + logMsg "Bytes Rate Sent: $sendRateBytes" + logMsg "Bytes Rate Recv: $recvRateBytes\n" + set result [list $framesSent $framesRecv $bytesSent $bytesRecv $sendRate $recvRate $sendRateBytes $recvRateBytes] return $result @@ -728,13 +731,6 @@ proc rfcThroughputTest { testSpec trafficSpec } { set framesDroppedRate 100 } - # check if we've already found the rate before 10 iterations, i.e. - # 'percentRate = idealValue'. This is as accurate as we can get with - # integer values. - if {[expr "$max - $min"] <= 0.5 } { - break - } - # handle 'percentRate <= idealValue' case if {$framesDroppedRate <= $lossRate} { logMsg "Frame sendRate of '$sendRate' pps succeeded ('$framesDropped' frames dropped)" @@ -754,6 +750,18 @@ proc rfcThroughputTest { testSpec trafficSpec } { set max $percentRate set percentRate [expr "$percentRate - ([expr "$max - $min"] * 0.5)"] } + + # check if we've already found the rate before 10 iterations, i.e. + # 'percentRate = idealValue'. This is as accurate as we can get with + # integer values. + if {[expr "$max - $min"] <= 0.5 } { + logMsg "End of search condition for framerate is met: $max % - $min % <= 0.5 %" + break + } + + logMsg "Waiting 2000 ms" + # wait to process delayed frames + after 2000 } set bestRate [lindex $result 4] @@ -159,7 +159,7 @@ if [ -s $FILE_LIST ] ; then fi # run pylint and extract final rating output=`$PYLINT --rcfile $PYLINT_RC $pyfile 2>/dev/null` - rating=`echo -e $output | tail -n3 | grep rated | sed -e 's/^.*rated at \([0-9.]*\).*$/\1/'` + rating=`echo -e $output | tail -n3 | grep rated | sed -e 's/^.*rated at \(-\?[0-9.]*\).*$/\1/'` # evaluate and display aquired rating if [ "x$rating" == "x" ] ; then # rating is not available for files without python statements @@ -167,7 +167,7 @@ if [ -s $FILE_LIST ] ; then elif rating_is_ok $rating ; then printf " %-70s ${GREEN}%-6s${BLACK}\n" $pyfile "OK" else - echo -e "$output" | awk '/^*+ Module|^[A-Z]\:/' + echo -e "$output" | awk '/^\*+ Module|^[A-Z]\:/' printf " %-70s ${RED}%-6s${BLACK}\n" $pyfile $rating fi done diff --git a/ci/build-vsperf.sh b/ci/build-vsperf.sh index 00a548ba..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 @@ -137,7 +137,7 @@ function print_results() { printf " %-70s %-6s\n" "result_${i}" "FAILED" EXIT=$EXIT_TC_FAILED else - RES_FILE=`ls -1 $1 | egrep "result_${i}_[0-9a-zA-Z\-]+.csv"` + RES_FILE=`ls -1 $1 | egrep "result_[0-9]+_${i}_[0-9a-zA-Z\-]+.csv"` if [ "x$RES_FILE" != "x" -a -e "${1}/${RES_FILE}" ]; then if grep ^FAILED "${1}/${RES_FILE}" &> /dev/null ; then @@ -433,15 +433,6 @@ function dependencies_check() { sudo apt-get install -y $PACKAGE fi done - # install additional python packages into python environment - for PACKAGE in "pylint" ; do - if pip show $PACKAGE &> /dev/null ; then - printf " %-70s %-6s\n" $PACKAGE "OK" - else - printf " %-70s %-6s\n" $PACKAGE "missing" - pip install $PACKAGE - fi - done echo fi } @@ -535,7 +526,7 @@ case $1 in echo "VSPERF merge job" echo "================" - execute_pylint_check + execute_vsperf_pylint_check terminate_vsperf execute_vsperf_sanity terminate_vsperf diff --git a/conf/00_common.conf b/conf/00_common.conf index 279c67b4..a846fb55 100644 --- a/conf/00_common.conf +++ b/conf/00_common.conf @@ -90,9 +90,6 @@ PATHS = {} # shell command to use when running commands through Pexpect SHELL_CMD = ['/bin/bash', '-c'] -# internal list to keep track of PIDs of jobs executed by vsperf -_EXECUTED_PIDS = [] - # ############################ # Logging configuration # ############################ @@ -101,11 +98,14 @@ _EXECUTED_PIDS = [] LOG_DIR = '/tmp' # default log for all "small" executables -LOG_FILE_DEFAULT = 'overall.log' +LOG_FILE_DEFAULT = 'vsperf-overall.log' # log file for all commands executed on host LOG_FILE_HOST_CMDS = 'host-cmds.log' +# log file prefix for infrastructure metrics +LOG_FILE_INFRA_METRICS_PFX = 'collectd_' + # ############################ # Test configuration # ############################ @@ -122,6 +122,15 @@ TEST_PARAMS = {} # delay enforced after every step to allow system to process changes TEST_STEP_DELAY = 5 +# parameter used, when running mupltiple tests, to accumulate _PARAMS_LIST +# parameters for multiple tests running in a series +CUMULATIVE_PARAMS = False + +# metric used by the performance matrix for comparision and analysis +# of tests run in a series. Must always refer to a numeric value. +# For example: 'throughput_rx_mbps', 'throughput_rx_fps', 'avg_latency_ns' +MATRIX_METRIC = 'throughput_rx_fps' + # ############################ # Modules # ############################ @@ -131,3 +140,18 @@ TEST_STEP_DELAY = 5 # Example: # EXCLUDE_MODULES = ['ovs_vanilla', 'qemu_virtio_net', 'pidstat'] EXCLUDE_MODULES = ["testcenter-rfc2544-throughput"] + +# ############################ +# Vsperf Internal Options +# ############################ +# following options should not be changed by the user + +# internal list to keep track of PIDs of jobs executed by vsperf +_EXECUTED_PIDS = [] + +# dictionary containing the test-specific parameters of all tests being run +# for the purposes of cummulative parameter assignment using performance matrix +_PARAMS_LIST = {} + +# index number of the current test, used for naming of result files +_TEST_INDEX = 0 diff --git a/conf/01_testcases.conf b/conf/01_testcases.conf index bd5ba9eb..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 = [ @@ -232,6 +156,18 @@ PERFORMANCE_TESTS = [ }, }, }, + { + "Name": "phy2phy_tput_mod_vlan_cont", + "Deployment": "p2p", + "Frame Modification": "vlan", + "Description": "Phy2Phy VLAN Continuous Stream", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + "frame_rate" : 100, + }, + }, + }, { "Name": "phy2phy_cont", "Deployment": "p2p", @@ -244,6 +180,18 @@ PERFORMANCE_TESTS = [ }, }, { + "Name": "phy2phy_burst", + "Deployment": "p2p", + "Description": "Phy2Phy single burst of 1000 frames at 100% frame rate", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "burst", + "frame_rate" : 100, + "burst_size" : 1000, + }, + }, + }, + { "Name": "pvp_cont", "Deployment": "pvp", "Description": "PVP Continuous Stream", @@ -288,6 +236,18 @@ PERFORMANCE_TESTS = [ }, }, { + "Name": "phy2phy_scalability_cont", + "Deployment": "p2p", + "Description": "Phy2Phy Scalability Continuous Stream", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + "frame_rate" : 100, + "multistream" : 8000, + }, + }, + }, + { "Name": "pvp_tput", "Deployment": "pvp", "Description": "LTD.Throughput.RFC2544.PacketLossRatio", @@ -361,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" : { @@ -371,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" : { @@ -384,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" : { @@ -396,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" : { @@ -408,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" : { @@ -420,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" : { @@ -432,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" : { @@ -444,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" : { @@ -456,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" : { @@ -468,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 6a830a05..84ef71cb 100644 --- a/conf/02_vswitch.conf +++ b/conf/02_vswitch.conf @@ -1,4 +1,4 @@ -# Copyright 2015-2016 Intel Corporation. +# Copyright 2015-2018 Intel Corporation, Tieto and others. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -172,7 +172,11 @@ OVS_OLD_STYLE_MQ = False VSWITCHD_VANILLA_ARGS = [] # Bridge name to be used by VSWTICH -VSWITCH_BRIDGE_NAME = 'br0' +VSWITCH_BRIDGE_NAME = 'vsperf-br0' + +# A tunnel type used by OP2P and PTUNP deployments +# Supported values: 'vxlan', 'gre' or 'geneve' +TUNNEL_TYPE = 'vxlan' # directory where hugepages will be mounted on system init HUGEPAGE_DIR = '/dev/hugepages' @@ -201,6 +205,20 @@ VSWITCH = "OvsDpdkVhost" VSWITCH_JUMBO_FRAMES_ENABLED = False VSWITCH_JUMBO_FRAMES_SIZE = 9000 +# default arguments of OVS ctl tools +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 67318893..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. @@ -23,8 +23,8 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log' # Detailed description of TRAFFIC dictionary items follows: # # 'traffic_type' - One of the supported traffic types. -# E.g. rfc2544_throughput, rfc2544_back2back -# or rfc2544_continuous +# E.g. rfc2544_throughput, rfc2544_back2back, +# rfc2544_continuous or burst # Data type: str # Default value: "rfc2544_throughput". # 'bidir' - Specifies if generated traffic will be full-duplex (True) @@ -36,6 +36,12 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log' # continuous stream tests. # Data type: int # Default value: 100. +# 'burst_size' - Defines a number of frames in the single burst, which is sent +# by burst traffic type. Burst size is applied for each direction, +# i.e. the total number of tx frames will be 2*burst_size in case of +# bidirectional traffic. +# Data type: int +# Default value: 100. # 'multistream' - Defines number of flows simulated by traffic generator. # Value 0 disables multistream feature # Data type: int @@ -58,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 @@ -112,7 +117,7 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log' # NOTE: It can be modified by vsperf in some scenarios. # Data type: str # Default value: "90.90.90.90". -# 'proto' - Specifies deflaut protocol type. +# 'proto' - Specifies protocol type. # Please check particular traffic generator implementation # for supported protocol types. # Data type: str @@ -171,9 +176,38 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log' # details. # Data type: str # Default value: '' +# 'scapy' - A dictionary with definition of a frame content for both traffic +# directions. The frame content is defined by a SCAPY notation. +# NOTE: It is supported only by the T-Rex traffic generator. +# Following keywords can be used to refer to the related parts of +# the TRAFFIC dictionary: +# Ether_src - refers to TRAFFIC['l2']['srcmac'] +# Ether_dst - refers to TRAFFIC['l2']['dstmac'] +# IP_proto - refers to TRAFFIC['l3']['proto'] +# IP_PROTO - refers to upper case version of TRAFFIC['l3']['proto'] +# IP_src - refers to TRAFFIC['l3']['srcip'] +# IP_dst - refers to TRAFFIC['l3']['dstip'] +# IP_PROTO_sport - refers to TRAFFIC['l4']['srcport'] +# IP_PROTO_dport - refers to TRAFFIC['l4']['dstport'] +# Dot1Q_prio - refers to TRAFFIC['vlan']['priority'] +# Dot1Q_id - refers to TRAFFIC['vlan']['cfi'] +# Dot1Q_vlan - refers to TRAFFIC['vlan']['id'] +# '0' - A string with the frame definition for the 1st direction. +# Data type: str +# Default value: 'Ether(src={Ether_src}, dst={Ether_dst})/' +# 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' +# 'IP(proto={IP_proto}, src={IP_src}, dst={IP_dst})/' +# '{IP_PROTO}(sport={IP_PROTO_sport}, dport={IP_PROTO_dport})' +# '1' - A string with the frame definition for the 2nd direction. +# Data type: str +# Default value: 'Ether(src={Ether_dst}, dst={Ether_src})/' +# 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' +# 'IP(proto={IP_proto}, src={IP_dst}, dst={IP_src})/' +# '{IP_PROTO}(sport={IP_PROTO_dport}, dport={IP_PROTO_sport})', TRAFFIC = { 'traffic_type' : 'rfc2544_throughput', 'frame_rate' : 100, + 'burst_size' : 100, 'bidir' : 'True', # will be passed as string in title format to tgen 'multistream' : 0, 'stream_type' : 'L4', @@ -210,6 +244,17 @@ TRAFFIC = { 'count': 1, 'filter': '', }, + 'scapy': { + 'enabled': False, + '0' : 'Ether(src={Ether_src}, dst={Ether_dst})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_src}, dst={IP_dst})/' + '{IP_PROTO}(sport={IP_PROTO_sport}, dport={IP_PROTO_dport})', + '1' : 'Ether(src={Ether_dst}, dst={Ether_src})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_dst}, dst={IP_src})/' + '{IP_PROTO}(sport={IP_PROTO_dport}, dport={IP_PROTO_sport})', + } } #path to traffic generators directory. @@ -487,6 +532,11 @@ TRAFFICGEN_TREX_LEARNING_MODE = True TRAFFICGEN_TREX_LEARNING_DURATION = 5 # FOR SR-IOV or multistream layer 2 tests to work with T-Rex enable Promiscuous mode TRAFFICGEN_TREX_PROMISCUOUS = False +# Enable below options to force T-rex api to attempt to use speed specified on server +# side when pushing traffic. For 40G use 40000. For 25G use 25000. +TRAFFICGEN_TREX_FORCE_PORT_SPEED = False +TRAFFICGEN_TREX_PORT_SPEED = 10000 # 10G + PATHS['trafficgen'] = { 'Trex': { 'type' : 'src', diff --git a/conf/04_vnf.conf b/conf/04_vnf.conf index 37fbe2b1..234f11b6 100644 --- a/conf/04_vnf.conf +++ b/conf/04_vnf.conf @@ -142,6 +142,8 @@ GUEST_MEMORY = ['2048'] GUEST_HUGEPAGES_NR = ['1024'] # test-pmd requires 2 VM cores +# It is also possible to configure GUEST's CPU topology, +# e.g. GUEST_SMP = ["sockets=1,cores=2"] GUEST_SMP = ['2'] # cpu features to the guest, default options provided to pass all available diff --git a/conf/07_loadgen.conf b/conf/07_loadgen.conf index e7349a5d..0b2cc1e6 100644 --- a/conf/07_loadgen.conf +++ b/conf/07_loadgen.conf @@ -15,7 +15,23 @@ LOADGEN_DIR = os.path.join(ROOT_DIR, 'tools/load_gen') ###################################################### -# LOADGEN tool: one of DummyLoadGen, Stress, StressNg +# LOADGEN tool: one of DummyLoadGen, Stress, StressNg, +# and StressorVM ###################################################### LOADGEN = "DummyLoadGen" ###################################################### + + +###################################################### +# StressorVm specific COnfiguration +###################################################### +NN_COUNT = 1 +NN_MEMORY = ['4096'] +NN_SMP = ['2'] +NN_IMAGE = ['/home/opnfv/stressng-images/stressng-high-TypeE.qemu'] +NN_SHARED_DRIVE_TYPE = ['scsi'] +NN_BOOT_DRIVE_TYPE = ['scsi'] +NN_CORE_BINDING = [('9','10')] +NN_NICS_NR = ['2'] +NN_BASE_VNC_PORT = 4 +NN_LOG_FILE = 'nnqemu.log' diff --git a/conf/10_custom.conf b/conf/10_custom.conf index 917d16b4..0e274aab 100644 --- a/conf/10_custom.conf +++ b/conf/10_custom.conf @@ -138,6 +138,10 @@ TRAFFICGEN_TREX_LEARNING_MODE = True TRAFFICGEN_TREX_LEARNING_DURATION = 5 # FOR SR-IOV or multistream layer 2 tests to work with T-Rex enable Promiscuous mode TRAFFICGEN_TREX_PROMISCUOUS = False +# Enable below options to force T-rex api to attempt to use speed specified on server +# side when pushing traffic. For 40G use 40000. For 25G use 25000. +TRAFFICGEN_TREX_FORCE_PORT_SPEED = False +TRAFFICGEN_TREX_PORT_SPEED = 10000 # 10G # TRex validation option for RFC2544 TRAFFICGEN_TREX_VERIFICATION_MODE = False TRAFFICGEN_TREX_VERIFICATION_DURATION = 60 diff --git a/conf/__init__.py b/conf/__init__.py index d5d26757..83c5475f 100644 --- a/conf/__init__.py +++ b/conf/__init__.py @@ -70,7 +70,7 @@ class Settings(object): except AttributeError: pass return param - elif isinstance(param, list) or isinstance(param, tuple): + elif isinstance(param, (list, tuple)): tmp_list = [] for item in param: tmp_list.append(self._eval_param(item)) @@ -229,7 +229,7 @@ class Settings(object): if key not in self.__dict__ and key not in _EXTRA_TEST_PARAMS: unknown_keys.append(key) - if len(unknown_keys): + if unknown_keys: raise RuntimeError('Test parameters contain unknown configuration ' 'parameter(s): {}'.format(', '.join(unknown_keys))) @@ -270,7 +270,7 @@ class Settings(object): for vmindex in range(vm_number): value = master_value_str.replace('#VMINDEX', str(vmindex)) for macro, args, param, _, step in re.findall(_PARSE_PATTERN, value): - multi = int(step) if len(step) and int(step) else 1 + multi = int(step) if step and int(step) else 1 if macro == '#EVAL': # pylint: disable=eval-used tmp_result = str(eval(param)) @@ -325,13 +325,13 @@ class Settings(object): assert result == self.getValue(attr) return True - def validate_setValue(self, dummy_result, name, value): + def validate_setValue(self, _dummy_result, name, value): """Verifies, that value was correctly set """ assert value == self.__dict__[name] return True - def validate_resetValue(self, dummy_result, attr): + def validate_resetValue(self, _dummy_result, attr): """Verifies, that value was correctly reset """ return 'TEST_PARAMS' not in self.__dict__ or \ diff --git a/conf/integration/01_testcases.conf b/conf/integration/01_testcases.conf index bb2809b8..7daff217 100644 --- a/conf/integration/01_testcases.conf +++ b/conf/integration/01_testcases.conf @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation, Tieto and others. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# The 1st value of SUPPORTED_TUNNELING_PROTO is used as the default -# tunneling protocol for OP2P tests. -SUPPORTED_TUNNELING_PROTO = ['vxlan', 'gre', 'geneve'] - # # Generic test configuration options are described at conf/01_testcases.conf # @@ -39,7 +35,9 @@ SUPPORTED_TUNNELING_PROTO = ['vxlan', 'gre', 'geneve'] # 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 @@ -52,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'}], @@ -63,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 @@ -74,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'}], @@ -89,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 @@ -99,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'}], @@ -118,192 +169,6 @@ STEP_VSWITCH_PVVP_FLOWS_FINIT = [ ['vswitch', 'del_flow', 'int_br0', {'in_port': '#STEP[3][1]'}], ] + STEP_VSWITCH_PVVP_FINIT -STEP_VSWITCH_P4VP_INIT = STEP_VSWITCH_PVVP_INIT + [ - ['vswitch', 'add_vport', 'int_br0'], # STEP 7 vm3 ports - ['vswitch', 'add_vport', 'int_br0'], # STEP 8 - ['vswitch', 'add_vport', 'int_br0'], # STEP 9 vm4 ports - ['vswitch', 'add_vport', 'int_br0'], # STEP 10 -] - -STEP_VSWITCH_P4VP_FINIT = [ - ['vswitch', 'del_port', 'int_br0', '#STEP[7][0]'], # vm3 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[8][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[9][0]'], # vm4 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[10][0]'], -] + STEP_VSWITCH_PVVP_FINIT - -STEP_VSWITCH_P4VP_FLOWS_INIT = STEP_VSWITCH_P4VP_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'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[6][1]', \ - 'actions': ['output:#STEP[7][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[8][1]', \ - 'actions': ['output:#STEP[9][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[10][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[2][1]', \ - 'actions': ['output:#STEP[10][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[9][1]', \ - 'actions': ['output:#STEP[8][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[7][1]', \ - 'actions': ['output:#STEP[6][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[5][1]', \ - 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[3][1]', \ - 'actions': ['output:#STEP[1][1]'], 'idle_timeout': '0'}], -] - -STEP_VSWITCH_P4VP_FLOWS_FINIT = [ - ['vswitch', 'dump_flows', 'int_br0'], - ['vswitch', 'del_flow', 'int_br0'], -] + STEP_VSWITCH_P4VP_FINIT - -STEP_VSWITCH_2PHY_2VM_INIT = STEP_VSWITCH_PVVP_INIT - -STEP_VSWITCH_2PHY_2VM_FINIT = STEP_VSWITCH_PVVP_FINIT - -STEP_VSWITCH_2_PARALLEL_VM_FLOWS_INIT = [ - # Setup Flows to reply ICMPv6 and similar packets, so to - # avoid flooding the internal port with their re-transmissions - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:01', \ - 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:02', \ - 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:03', \ - 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:04', \ - 'actions': ['output:#STEP[6][1]'], 'idle_timeout': '0'}], - # Forward UDP packets depending on dest port - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \ - 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \ - 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}], - # Send VM outputs to phy port #2 - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[6][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], -] - -STEP_VSWITCH_2PHY_4VM_INIT = STEP_VSWITCH_2PHY_2VM_INIT + [ - ['vswitch', 'add_vport', 'int_br0'], # STEP 7 vm3 ports - ['vswitch', 'add_vport', 'int_br0'], # STEP 8 - ['vswitch', 'add_vport', 'int_br0'], # STEP 9 vm4 ports - ['vswitch', 'add_vport', 'int_br0'], # STEP 10 -] - -STEP_VSWITCH_2PHY_4VM_FINIT = [ - ['vswitch', 'del_port', 'int_br0', '#STEP[7][0]'], # vm3 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[8][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[9][0]'], # vm4 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[10][0]'], -] + STEP_VSWITCH_2PHY_2VM_FINIT - -STEP_VSWITCH_FLOWS_FINIT = [ - ['vswitch', 'dump_flows', 'int_br0'], - ['vswitch', 'del_flow', 'int_br0'], -] - -STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT = [ - # Setup Flows to reply ICMPv6 and similar packets, so to - # avoid flooding the internal port with their re-transmissions - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:01', \ - 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:02', \ - 'actions': ['output:#STEP[4][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:03', \ - 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:04', \ - 'actions': ['output:#STEP[6][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:05', \ - 'actions': ['output:#STEP[7][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:06', \ - 'actions': ['output:#STEP[8][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:07', \ - 'actions': ['output:#STEP[9][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:08', \ - 'actions': ['output:#STEP[10][1]'], 'idle_timeout': '0'}], - # Forward UDP packets depending on dest port - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '0', \ - 'actions': ['output:#STEP[3][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '1', \ - 'actions': ['output:#STEP[5][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '2', \ - 'actions': ['output:#STEP[7][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '3', \ - 'actions': ['output:#STEP[9][1]'], 'idle_timeout': '0'}], - # Send VM outputs to phy port #2 - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[4][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[6][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[8][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[10][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], -] - -STEP_VSWITCH_2PHY_6VM_INIT = STEP_VSWITCH_2PHY_4VM_INIT + [ - ['vswitch', 'add_vport', 'int_br0'], # STEP 11 vm5 vhu8 - ['vswitch', 'add_vport', 'int_br0'], # STEP 12 vhu9 - ['vswitch', 'add_vport', 'int_br0'], # STEP 13 vm6 vhu10 - ['vswitch', 'add_vport', 'int_br0'], # STEP 14 vhu11 -] - -STEP_VSWITCH_6_PARALLEL_VM_FLOWS_INIT = STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT + [ - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:09', \ - 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:0a', \ - 'actions': ['output:#STEP[12][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:0b', \ - 'actions': ['output:#STEP[13][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', \ - {'priority': '1', 'dl_src': '00:00:00:00:00:0c', \ - 'actions': ['output:#STEP[14][1]'], 'idle_timeout': '0'}], - # Forward UDP packets depending on dest port - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '4', \ - 'actions': ['output:#STEP[11][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[1][1]', \ - 'dl_type': '0x0800', 'nw_proto': '17', 'udp_dst': '5', \ - 'actions': ['output:#STEP[13][1]'], 'idle_timeout': '0'}], - # Send VM outputs to phy port #2 - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[12][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[14][1]', \ - 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], -] - -STEP_VSWITCH_2PHY_6VM_FINIT = [ - ['vswitch', 'del_port', 'int_br0', '#STEP[11][0]'], # vm5 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[12][0]'], - ['vswitch', 'del_port', 'int_br0', '#STEP[13][0]'], # vm6 ports - ['vswitch', 'del_port', 'int_br0', '#STEP[14][0]'], -] + STEP_VSWITCH_2PHY_4VM_FINIT - # # Definition of integration tests # @@ -327,7 +192,6 @@ INTEGRATION_TESTS = [ { "Name": "overlay_p2p_tput", "Deployment": "op2p", - "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], "Tunnel Operation": "encapsulation", "Description": "Overlay Encapsulation Throughput RFC2544 Test", "Parameters": { @@ -341,7 +205,6 @@ INTEGRATION_TESTS = [ { "Name": "overlay_p2p_cont", "Deployment": "op2p", - "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], "Tunnel Operation": "encapsulation", "Description": "Overlay Encapsulation RFC2544 Continuous Stream", "Parameters": { @@ -355,7 +218,6 @@ INTEGRATION_TESTS = [ { "Name": "overlay_p2p_decap_tput", "Deployment": "op2p", - "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], "Tunnel Operation": "decapsulation", "Description": "Overlay Decapsulation Throughput RFC2544 Test", "Parameters": { @@ -369,7 +231,6 @@ INTEGRATION_TESTS = [ { "Name": "overlay_p2p_decap_cont", "Deployment": "op2p", - "Tunnel Type": SUPPORTED_TUNNELING_PROTO[0], "Tunnel Operation": "decapsulation", "Description": "Overlay Decapsulation RFC2544 Continuous Stream", "Parameters": { @@ -449,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'], @@ -466,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'], @@ -481,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 }, @@ -489,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", @@ -545,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'}], @@ -589,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", @@ -608,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'], @@ -616,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'], @@ -630,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'], @@ -644,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'], @@ -660,104 +561,48 @@ INTEGRATION_TESTS = [ ['vnf1', 'stop'], ['vnf2', 'stop'], ] + - STEP_VSWITCH_PVVP_FLOWS_FINIT - }, - { - "Name": "vswitch_p4vp", - "Description": "Just configure 4 chained vnfs", - "Deployment": "clean", - "TestSteps": STEP_VSWITCH_P4VP_FLOWS_INIT + - [ - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ] + - STEP_VSWITCH_P4VP_FLOWS_FINIT + STEP_VSWITCH_PVVP_CONNECTIONS_FINIT }, { "Name": "vswitch_p4vp_tput", - "Description": "4 chained vnfs, execute RFC2544 throughput test", - "Deployment": "clean", - "TestSteps": STEP_VSWITCH_P4VP_FLOWS_INIT + - [ - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput', \ - 'bidir' : 'True'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ] + - STEP_VSWITCH_P4VP_FLOWS_FINIT + "Description": "4 chained vnfs, execute RFC2544 throughput test, deployment pvvp4", + "Deployment": "pvvp4", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + }, }, { "Name": "vswitch_p4vp_back2back", - "Description": "4 chained vnfs, execute RFC2544 back2back test", - "Deployment": "clean", - "TestSteps": STEP_VSWITCH_P4VP_FLOWS_INIT + - [ - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_back2back', \ - 'bidir' : 'True'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ] + - STEP_VSWITCH_P4VP_FLOWS_FINIT + "Description": "4 chained vnfs, execute RFC2544 back2back test, deployment pvvp4", + "Deployment": "pvvp4", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_back2back", + }, + }, }, { "Name": "vswitch_p4vp_cont", - "Description": "4 chained vnfs, execute RFC2544 continuous stream test", - "Deployment": "clean", - "TestSteps": STEP_VSWITCH_P4VP_FLOWS_INIT + - [ - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', \ - 'bidir' : 'True'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ] + - STEP_VSWITCH_P4VP_FLOWS_FINIT + "Description": "4 chained vnfs, execute RFC2544 continuous stream test, deployment pvvp4", + "Deployment": "pvvp4", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + }, + }, }, { "Name": "vswitch_p4vp_all", - "Description": "4 chained vnfs, execute RFC2544 throughput test", - "Deployment": "clean", - "TestSteps": STEP_VSWITCH_P4VP_FLOWS_INIT + + "Description": "4 chained vnfs, execute RFC2544 throughput tests, deployment pvvp4", + "Deployment": "pvvp4", + "TestSteps": [ - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput', \ - 'bidir' : 'True'}], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_back2back', \ - 'bidir' : 'True'}], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', \ - 'bidir' : 'True'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ] + - STEP_VSWITCH_P4VP_FLOWS_FINIT + ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_throughput'}], + ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_back2back'}], + ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous'}], + ] }, { # Topology: 2 Parallel PVP connections @@ -766,25 +611,13 @@ INTEGRATION_TESTS = [ # or add "Parameters" option to the test definition: # "Parameters" : {'GUEST_LOOPBACK' : ['linux_bridge'],}, "Name": "2pvp_udp_dest_flows", - "Description": "RFC2544 Continuous TC with 2 Parallel VMs, flows on UDP Dest Port", - "Deployment": "clean", + "Description": "RFC2544 Continuous TC with 2 Parallel VMs, flows on UDP Dest Port, deployment pvpv2", + "Deployment": "pvpv2", "Parameters" : { "TRAFFIC" : { - "multistream" : 2, - "stream_type" : "L4", + "traffic_type" : "rfc2544_continuous", }, }, - "TestSteps": STEP_VSWITCH_2PHY_2VM_INIT + - STEP_VSWITCH_2_PARALLEL_VM_FLOWS_INIT + [ - # Start 2 VMs - ['vnf1', 'start'], - ['vnf2', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'False'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - # Clean up - ] + STEP_VSWITCH_FLOWS_FINIT + - STEP_VSWITCH_2PHY_2VM_FINIT }, { # Topology: 4 Parallel PVP connections @@ -793,29 +626,13 @@ INTEGRATION_TESTS = [ # or add "Parameters" option to the test definition: # "Parameters" : {'GUEST_LOOPBACK' : ['linux_bridge'],}, "Name": "4pvp_udp_dest_flows", - "Description": "RFC2544 Continuous TC with 4 Parallel VMs, flows on UDP Dest Port", - "Deployment": "clean", + "Description": "RFC2544 Continuous TC with 4 Parallel VMs, flows on UDP Dest Port, deployment pvpv4", + "Deployment": "pvpv4", "Parameters" : { "TRAFFIC" : { - "multistream" : 4, - "stream_type" : "L4", + "traffic_type" : "rfc2544_continuous", }, }, - "TestSteps": STEP_VSWITCH_2PHY_4VM_INIT + - STEP_VSWITCH_4_PARALLEL_VM_FLOWS_INIT + [ - # Start 4 VMs - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'False'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - # Clean up - ] + STEP_VSWITCH_FLOWS_FINIT + - STEP_VSWITCH_2PHY_4VM_FINIT }, { # Topology: 6 Parallel PVP connections @@ -824,32 +641,13 @@ INTEGRATION_TESTS = [ # or add "Parameters" option to the test definition: # "Parameters" : {'GUEST_LOOPBACK' : ['linux_bridge'],}, "Name": "6pvp_udp_dest_flows", - "Description": "RFC2544 Continuous TC with 6 Parallel VMs, flows on UDP Dest Port", - "Deployment": "clean", + "Description": "RFC2544 Continuous TC with 6 Parallel VMs, flows on UDP Dest Port, deployment pvpv6", + "Deployment": "pvpv6", "Parameters" : { "TRAFFIC" : { - "multistream" : 6, - "stream_type" : "L4", + "traffic_type" : "rfc2544_continuous", }, }, - "TestSteps": STEP_VSWITCH_2PHY_6VM_INIT + - STEP_VSWITCH_6_PARALLEL_VM_FLOWS_INIT + [ - # Start VMs - ['vnf1', 'start'], - ['vnf2', 'start'], - ['vnf3', 'start'], - ['vnf4', 'start'], - ['vnf5', 'start'], - ['vnf6', 'start'], - ['trafficgen', 'send_traffic', {'traffic_type' : 'rfc2544_continuous', 'bidir' : 'False'}], - ['vnf1', 'stop'], - ['vnf2', 'stop'], - ['vnf3', 'stop'], - ['vnf4', 'stop'], - ['vnf5', 'stop'], - ['vnf6', 'stop'], - ] + STEP_VSWITCH_FLOWS_FINIT + - STEP_VSWITCH_2PHY_6VM_FINIT }, { # Testcase for verification of vHost User NUMA awareness feature @@ -979,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 # @@ -1027,9 +808,9 @@ INTEGRATION_TESTS = [ }, "TestSteps": [ # replace original flows with vlan ID modification - ['!vswitch', 'add_flow', 'br0', {'in_port': '1', 'actions': ['mod_vlan_vid:4','output:3']}], - ['!vswitch', 'add_flow', 'br0', {'in_port': '2', 'actions': ['mod_vlan_vid:4','output:4']}], - ['vswitch', 'dump_flows', 'br0'], + ['!vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '1', 'actions': ['mod_vlan_vid:4','output:3']}], + ['!vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '2', 'actions': ['mod_vlan_vid:4','output:4']}], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], # verify that received frames have modified vlan ID ['VNF0', 'execute_and_wait', 'tcpdump -i eth0 -c 5 -w dump.pcap vlan 4 &'], ['trafficgen', 'send_traffic',{}], @@ -1055,14 +836,14 @@ _CAPTURE_P2P2P_SETUP = [ # create and configure two bridges to forward traffic through NIC under # the test and back to the traffic generator # 1st bridge: - ['vswitch', 'add_switch', 'br0'], + ['vswitch', 'add_switch', '$VSWITCH_BRIDGE_NAME'], ['tools', 'exec_shell', 'sudo ip addr flush dev $NICS[0]["device"]'], ['tools', 'exec_shell', 'sudo ip link set dev $NICS[0]["device"] up'], - ['tools', 'exec_shell', '$TOOLS["ovs-vsctl"] add-port br0 $NICS[0]["device"]'], + ['tools', 'exec_shell', '$TOOLS["ovs-vsctl"] add-port $VSWITCH_BRIDGE_NAME $NICS[0]["device"]'], ['tools', 'exec_shell', 'sudo $TOOLS["bind-tool"] --bind igb_uio $NICS[3]["pci"]'], - ['tools', 'exec_shell', '$TOOLS["ovs-vsctl"] add-port br0 dpdk0 -- ' + ['tools', 'exec_shell', '$TOOLS["ovs-vsctl"] add-port $VSWITCH_BRIDGE_NAME dpdk0 -- ' 'set Interface dpdk0 type=dpdk options:dpdk-devargs=$NICS[3]["pci"]'], - ['tools', 'exec_shell', '$TOOLS["ovs-ofctl"] add-flow br0 in_port=1,action=' + ['tools', 'exec_shell', '$TOOLS["ovs-ofctl"] add-flow $VSWITCH_BRIDGE_NAME in_port=1,action=' '$_CAPTURE_P2P2P_OVS_ACTION,output:2'], # 2nd bridge: ['vswitch', 'add_switch', 'br1'], @@ -1074,7 +855,7 @@ _CAPTURE_P2P2P_SETUP = [ ['tools', 'exec_shell', '$TOOLS["ovs-vsctl"] add-port br1 $NICS[1]["device"]'], ['vswitch', 'add_flow', 'br1', {'in_port': '1', 'actions': ['output:2']}], # log flow details - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], ['vswitch', 'dump_flows', 'br1'], ] INTEGRATION_TESTS += [ @@ -1108,7 +889,7 @@ INTEGRATION_TESTS += [ ['tools', 'exec_shell_background', 'tcpdump -i $NICS[2]["device"] -c 5 -w capture.pcap ' 'ether src $TRAFFIC["l2"]["srcmac"]'], ['trafficgen', 'send_traffic', {}], - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], ['vswitch', 'dump_flows', 'br1'], # there must be 5 captured frames... ['tools', 'exec_shell', 'tcpdump -r capture.pcap | wc -l', '|^(\d+)$'], @@ -1129,10 +910,11 @@ INTEGRATION_TESTS += [ "vSwitch" : "OvsDpdkVhost", # works also for Vanilla OVS "Parameters" : { "TRAFFICGEN" : "Trex", - "TRAFFICGEN_DURATION" : 5, + "TRAFFICGEN_TREX_LEARNING_MODE" : True, "TRAFFIC" : { - "traffic_type" : "rfc2544_continuous", + "traffic_type" : "burst", "frame_rate" : 100, + "burst_size" : 5, # enable capture of five RX frames 'capture': { 'enabled': True, @@ -1170,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/01a_testcases_l34_vxlan.conf b/conf/integration/01a_testcases_l34_vxlan.conf index 17c0d6ff..b42a14d1 100644 --- a/conf/integration/01a_testcases_l34_vxlan.conf +++ b/conf/integration/01a_testcases_l34_vxlan.conf @@ -1,4 +1,4 @@ -# Copyright 2017 Intel Corporation. +# Copyright 2017-2018 Intel Corporation and Tieto. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -63,7 +63,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ 'cmds.close()'], ['tools', 'exec_shell', "sudo $TOOLS['ovs-ofctl'] -O OpenFlow13 --bundle add-flows int_br0 /tmp/ovsofctl_cmds.txt"], ['trafficgen', 'send_traffic', {}], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_P2P_FINIT }, @@ -93,7 +92,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0' }], ['trafficgen', 'send_traffic', {}], ['vswitch', 'dump_flows', 'int_br0'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_P2P_FINIT }, @@ -130,7 +128,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['trafficgen', 'send_traffic', {}], ['vswitch', 'dump_flows', 'int_br0'], ['vnf', 'stop'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_PVP_FINIT }, { @@ -172,7 +169,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['vswitch', 'dump_flows', 'int_br0'], ['vnf2', 'stop'], ['vnf1', 'stop'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_PVVP_FINIT }, @@ -213,7 +209,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['tools', 'exec_shell', "sudo $TOOLS['ovs-ofctl'] -O OpenFlow13 --bundle " "add-flows int_br0 /tmp/ovsofctl_cmds.txt"], ['trafficgen', 'send_traffic', {}], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_P2P_FINIT }, @@ -249,7 +244,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ 'actions': ['output:#STEP[2][1]'], 'idle_timeout': '0'}], ['trafficgen', 'send_traffic', {}], ['vswitch', 'dump_flows', 'int_br0'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_P2P_FINIT }, @@ -293,7 +287,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['trafficgen', 'send_traffic', {}], ['vswitch', 'dump_flows', 'int_br0'], ['vnf', 'stop'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_PVP_FINIT }, @@ -344,7 +337,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['vswitch', 'dump_flows', 'int_br0'], ['vnf2', 'stop'], ['vnf1', 'stop'], - ['vswitch', 'del_flow', 'int_br0'], ] + STEP_VSWITCH_PVVP_FINIT }, @@ -888,13 +880,13 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ }, }, "TestSteps": [ - ['vswitch', 'del_flow', 'br0', {'in_port': '1'}], - ['vswitch', 'add_flow', 'br0', + ['vswitch', 'del_flow', '$TUNNEL_INTEGRATION_BRIDGE', {'in_port': '1'}], + ['vswitch', 'add_flow', '$TUNNEL_INTEGRATION_BRIDGE', {'in_port': '1', 'dl_type': '0x800', 'nw_proto': '17', 'nw_dst': '$TRAFFICGEN_PORT2_IP/8', 'actions': ['output:2'], 'idle_timeout': '0'}], - ['vswitch', 'dump_flows', 'br0'], - ['vswitch', 'dump_flows', 'br-ext'], + ['vswitch', 'dump_flows', '$TUNNEL_INTEGRATION_BRIDGE'], + ['vswitch', 'dump_flows', '$TUNNEL_EXTERNAL_BRIDGE'], ], }, { diff --git a/conf/integration/01b_dpdk_regression_tests.conf b/conf/integration/01b_dpdk_regression_tests.conf index 2e63d677..abc56c28 100644 --- a/conf/integration/01b_dpdk_regression_tests.conf +++ b/conf/integration/01b_dpdk_regression_tests.conf @@ -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. @@ -170,9 +170,6 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] show', '|Error attaching device.*$NICS[0]["pci"]'], ['tools', 'assert', 'not len(#STEP[-1])'], - # clean up - ['vswitch', 'del_port', 'int_br0', '#STEP[port2][0]'], - ['vswitch', 'del_switch', 'int_br0'], ] }, { @@ -344,14 +341,14 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ # frame loss with small packets should be detected ['tools', 'assert', '#STEP[-1][0]["frame_loss_percent"] > 10'], # delete phy ports so they can be created with flow control - ['vswitch', 'del_flow', 'br0', {}], - ['vswitch', 'del_port', 'br0', 'dpdk0'], - ['vswitch', 'del_port', 'br0', 'dpdk1'], + ['vswitch', 'del_flow', '$VSWITCH_BRIDGE_NAME', {}], + ['vswitch', 'del_port', '$VSWITCH_BRIDGE_NAME', 'dpdk0'], + ['vswitch', 'del_port', '$VSWITCH_BRIDGE_NAME', 'dpdk1'], # turn on flow control - ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=$NICS[0]["pci"] options:rx-flow-ctrl=true'], - ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] add-port br0 dpdk1 -- set Interface dpdk1 type=dpdk options:dpdk-devargs=$NICS[1]["pci"] options:rx-flow-ctrl=true'], - ['vswitch', 'add_flow', 'br0', {'in_port': '3', 'actions': ['output:4'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '4', 'actions': ['output:3'], 'idle_timeout': '0'}], + ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] add-port $VSWITCH_BRIDGE_NAME dpdk0 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=$NICS[0]["pci"] options:rx-flow-ctrl=true'], + ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] add-port $VSWITCH_BRIDGE_NAME dpdk1 -- set Interface dpdk1 type=dpdk options:dpdk-devargs=$NICS[1]["pci"] options:rx-flow-ctrl=true'], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '3', 'actions': ['output:4'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '4', 'actions': ['output:3'], 'idle_timeout': '0'}], ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] show'], ['trafficgen', 'send_traffic', {}], ['trafficgen', 'get_results'], @@ -671,15 +668,17 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ "TestSteps": [ # send traffic to verify correct PVP configuration ['trafficgen', 'send_traffic', {}], - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], # restart vswitchd, ovsdb is kept untouched, so ovs configuration # (except flows) will be restored ['vswitch', 'restart'], - ['vswitch', 'del_flow', 'br0'], - ['vswitch', 'add_flow', 'br0', {'in_port': '1', 'actions': ['output:3'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '3', 'actions': ['output:1'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '2', 'actions': ['output:4'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '4', 'actions': ['output:2'], 'idle_timeout': '0'}], + ['vswitch', 'del_flow', '$VSWITCH_BRIDGE_NAME', {}], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '1', 'actions': ['output:3'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '3', 'actions': ['output:1'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '2', 'actions': ['output:4'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '4', 'actions': ['output:2'], 'idle_timeout': '0'}], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], # send traffic to verify that OVS works correctly after restart ['trafficgen', 'send_traffic', {}], ], @@ -718,13 +717,13 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ "VSWITCH_VHOSTUSER_SERVER_MODE" : True, }, "TestSteps": [ - ['vswitch', 'add_switch', 'br0'], + ['vswitch', 'add_switch', '$VSWITCH_BRIDGE_NAME'], ['tools', 'exec_shell', 'sudo $TOOLS["ovs-vsctl"] set Open_vSwitch . ' 'other_config:vhost-sock-dir=test_dir'], # enforce vswitchd to read new configuration ['vswitch', 'restart'], ['tools', 'exec_shell', 'sudo mkdir $TOOLS["ovs_var_tmp"]/test_dir'], - ['vswitch', 'add_vport', 'br0'], + ['vswitch', 'add_vport', '$VSWITCH_BRIDGE_NAME'], ['tools', 'exec_shell', 'ls -1 $TOOLS["ovs_var_tmp"]/test_dir', '|dpdkvhostuser0'], ['tools', 'assert', 'len(#STEP[-1])'], @@ -1297,7 +1296,7 @@ _OVSDPDK_RATE_confirm_multiple_rate_limit_setup = \ # check that traffic rate is no longer limited ['trafficgen', 'get_results'], ['tools', 'assert', 'int(#STEP[-1][0]["throughput_rx_mbps"])>500'], - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], ] INTEGRATION_TESTS = INTEGRATION_TESTS + [ @@ -1603,8 +1602,8 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ "Parameters" : {}, "TestSteps": [ # Setup switch,port and logs - ['vswitch', 'add_switch', 'br0'], - ['vswitch', 'add_vport', 'br0'], + ['vswitch', 'add_switch', '$VSWITCH_BRIDGE_NAME'], + ['vswitch', 'add_vport', '$VSWITCH_BRIDGE_NAME'], ['#LOG_MARK', 'tools', 'exec_shell', 'echo $((1+`wc -l $_OVSDPDK_VSWITCH_LOG | cut -d" " -f1`))', '(\d+)'], @@ -1633,8 +1632,8 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ "Parameters" : {}, "TestSteps": [ # Setup switch,port and logs - ['vswitch', 'add_switch', 'br0'], - ['vswitch', 'add_vport', 'br0'], + ['vswitch', 'add_switch', '$VSWITCH_BRIDGE_NAME'], + ['vswitch', 'add_vport', '$VSWITCH_BRIDGE_NAME'], ['#LOG_MARK', 'tools', 'exec_shell', 'echo $((1+`wc -l $_OVSDPDK_VSWITCH_LOG | cut -d" " -f1`))', '(\d+)'], @@ -1686,4 +1685,72 @@ INTEGRATION_TESTS = INTEGRATION_TESTS + [ }, "TestSteps": _OVSDPDK_QOS_confirm_multiple_qos_setup }, + ############################################################ + # + # Custom statistics + # + ############################################################ + { + "Name": "ovsdpdk_custstat_check", + "Deployment": "clean", + "Description": "Test if custom statistics are supported.", + "vSwitch" : "OvsDpdkVhost", + "TestSteps": [ + # enable custom statistics + ['vswitch', 'add_switch', 'int_br0', [ + 'protocols=OpenFlow10,OpenFlow11,OpenFlow12,' + 'OpenFlow13,OpenFlow14,OpenFlow15']], + ['#port', 'vswitch', 'add_phy_port', 'int_br0'], + # check that custom statistics are available for given interface + ['tools', 'exec_shell', 'sudo $TOOLS["ovs-ofctl"] -O OpenFlow14 ' + 'dump-ports int_br0 #STEP[port][1]', + '|CUSTOM Statistics'], + ['tools', 'assert', 'len(#STEP[-1])'], + ['vswitch', 'del_port', 'int_br0', '#STEP[port][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] + }, + { + "Name": "ovsdpdk_custstat_rx_error", + "Deployment": "clean", + "Description": "Test bad ethernet CRC counter 'rx_crc_errors' exposed by custom statistics.", + "vSwitch" : "OvsDpdkVhost", + "Parameters" : { + "OVS_OFCTL_ARGS" : [], + "TRAFFICGEN" : "IxNet", + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + "frame_rate" : 10, + }, + "TRAFFICGEN_DURATION" : 10, + "TRAFFICGEN_IXNET_TCL_SCRIPT" : "ixnetrfc2544_bad_l2_crc.tcl", + }, + "TestSteps": [ + # enable custom statistics + ['vswitch', 'add_switch', 'int_br0', [ + 'protocols=OpenFlow10,OpenFlow11,OpenFlow12,' + 'OpenFlow13,OpenFlow14,OpenFlow15']], + ['#port1', 'vswitch', 'add_phy_port', 'int_br0'], + ['#port2', 'vswitch', 'add_phy_port', 'int_br0'], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '1', 'actions': ['output:2']}], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '2', 'actions': ['output:1']}], + ['#crc_old', 'tools', 'exec_shell', 'sudo $TOOLS["ovs-ofctl"] -O OpenFlow14 ' + 'dump-ports int_br0 #STEP[port1][1]', + '|rx_crc_errors=(\d+)'], + # frames will be dropped by NIC, so we have to suppress send_traffic validation + # to avoid test failure + ['!trafficgen', 'send_traffic', {}], + # check that custom statistics are available for given interface + ['#crc_new', 'tools', 'exec_shell', 'sudo $TOOLS["ovs-ofctl"] -O OpenFlow14 ' + 'dump-ports int_br0 #STEP[port1][1]', + '|rx_crc_errors=(\d+)'], + ['tools', 'assert', '#STEP[crc_new] > #STEP[crc_old]'], + # tear down the environment + ['vswitch', 'dump_flows', 'int_br0'], + ['vswitch', 'del_flow', 'int_br0', {}], + ['vswitch', 'del_port', 'int_br0', '#STEP[port1][0]'], + ['vswitch', 'del_port', 'int_br0', '#STEP[port2][0]'], + ['vswitch', 'del_switch', 'int_br0'], + ] + }, ] diff --git a/conf/integration/01c_trex_vm_tests.conf b/conf/integration/01c_trex_vm_tests.conf new file mode 100644 index 00000000..1bec4efd --- /dev/null +++ b/conf/integration/01c_trex_vm_tests.conf @@ -0,0 +1,182 @@ +# Copyright 2018 Intel Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Testcases in this files use T-Rex running in VM as a traffic generator. +# + +# A set of options passed to the T-Rex stateless server +_TREX_OPTIONS="--no-scapy-server --no-watchdog --nc" +_TREX_SERVER_IP="192.168.35.2" +_TREX_BRIDGE_IP="192.168.35.1" +_TREX_IP_MASK="24" + +# Macro for initialization of T-Rex VM and execution of T-Rex server +# NOTE: It is expected that T-Rex will run in the LAST VM! +TREX_VM_INIT = [ + # configure T-Rex ports, which will be used for traffic generation + ['#trex_p1', 'vswitch', 'add_vport', 'int_br0'], + ['#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'], + ['tools', 'exec_shell', 'sudo ip addr add $_TREX_BRIDGE_IP/$_TREX_IP_MASK dev trex_br'], + ['tools', 'exec_shell', 'sudo ip link set dev trex_br up'], + ['vnf_trex', 'start'], + ['vnf_trex', 'execute_and_wait', 'sudo ip addr flush dev eth2'], + ['vnf_trex', 'execute_and_wait', 'sudo ip addr add $_TREX_SERVER_IP/$_TREX_IP_MASK dev eth2'], + ['vnf_trex', 'execute_and_wait', 'sudo ip link set dev eth2 up'], + # preapre system for T-Rex execution + ['vnf_trex', 'execute_and_wait', 'sysctl vm.nr_hugepages=$GUEST_HUGEPAGES_NR[-1]'], + ['vnf_trex', 'execute_and_wait', 'mkdir -p /dev/hugepages'], + ['vnf_trex', 'execute_and_wait', 'mount -t hugetlbfs hugetlbfs /dev/hugepages'], + ['vnf_trex', 'execute_and_wait', 'grep -i huge /proc/meminfo'], + ['vnf_trex', 'execute_and_wait', 'iptables -F'], + # configure passwordless ssh access to VM with T-Rex server + ['tools', 'exec_shell', 'sshpass -p $GUEST_PASSWORD[-1] ssh-copy-id -o StrictHostKeyChecking=no $GUEST_USERNAME[-1]@$_TREX_SERVER_IP'], + # prepare T-Rex configuration + ['vnf_trex', 'execute_and_wait', 'echo \'- port_limit: 2\' > /etc/trex_cfg.yaml'], + ['vnf_trex', 'execute_and_wait', 'echo \' version: 2\' >> /etc/trex_cfg.yaml'], + ['vnf_trex', 'execute_and_wait', "echo \" interfaces: [ '$GUEST_NICS[-1][0]['pci']', '$GUEST_NICS[-1][1]['pci']' ]\" >> /etc/trex_cfg.yaml"], + # execute T-Rex stateless server and wait until it is up and running + ['vnf_trex', 'execute_and_wait', 'cd $TRAFFICGEN_TREX_BASE_DIR'], + ['#trex_pid', 'vnf_trex', 'execute_and_wait', 'nohup sudo bash -c "./t-rex-64 -i $_TREX_OPTIONS" &', '|\[1\] (\d+)$'], + ['vnf_trex', 'execute_and_wait', 'echo -ne "Starting T-Rex " ; while ! netstat -nl | grep 4501 &> /dev/null ; do echo -ne "."; sleep 1 ; done; echo', 300], +] + +# T-Rex VM teardown macro +TREX_VM_FINIT = [ + ['vnf_trex', 'execute_and_wait', 'sudo kill #STEP[trex_pid][0]'], + ['vnf_trex', 'execute_and_wait', 'sudo pkill t-rex-64'], + ['vnf_trex', 'stop'], + ['vswitch', 'del_port', 'trex_br', '#STEP[trex_admin][0]'], + ['vswitch', 'del_port', 'trex_br', '#STEP[trex_spare][0]'], + ['tools', 'exec_shell', 'sudo ip link set dev trex_br down'], + ['tools', 'exec_shell', 'sudo ip addr flush dev trex_br'], + ['vswitch', 'del_switch', 'trex_br'], +] + +# Configure T-Rex loopback test, where traffic from T-Rex is forwarded back via OVS flows +TREX_VM_TEST = [ + ['vswitch', 'add_switch', 'int_br0'], + ] + TREX_VM_INIT + [ + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[trex_p1][1]', 'actions': ['output:#STEP[trex_p2][1]'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[trex_p2][1]', 'actions': ['output:#STEP[trex_p1][1]'], 'idle_timeout': '0'}], + ['trafficgen', 'send_traffic', {}], + ['trafficgen', 'get_results'], + # cleanup + ] + TREX_VM_FINIT + +# Configure VM2VM test, where traffic from T-Rex VM is forwarded to 2nd VM with loopback app. +TREX_VM2VM_TEST = [ + ['vswitch', 'add_switch', 'int_br0'], + ['#vm_p1', 'vswitch', 'add_vport', 'int_br0'], + ['#vm_p2', 'vswitch', 'add_vport', 'int_br0'], + ['vnf', 'start'], + ] + TREX_VM_INIT + [ + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[trex_p1][1]', 'actions': ['output:#STEP[vm_p1][1]'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[vm_p1][1]', 'actions': ['output:#STEP[trex_p1][1]'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[trex_p2][1]', 'actions': ['output:#STEP[vm_p2][1]'], 'idle_timeout': '0'}], + ['vswitch', 'add_flow', 'int_br0', {'in_port': '#STEP[vm_p2][1]', 'actions': ['output:#STEP[trex_p2][1]'], 'idle_timeout': '0'}], + ['trafficgen', 'send_traffic', {}], + ['trafficgen', 'get_results'], + ['vnf', 'stop'], + ['vswitch', 'dump_flows', 'int_br0'], + # cleanup + ] + TREX_VM_FINIT + +# +# A set of tests with T-Rex VM as a traffic generator. +# +INTEGRATION_TESTS = INTEGRATION_TESTS + [ + { + "Name": "trex_vm_cont", + "Deployment": "clean", + "Description": "T-Rex VM - execute RFC2544 Continuous Stream from T-Rex VM and loop it back through Open vSwitch.", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + }, + 'GUEST_LOOPBACK' : ['clean',], + 'GUEST_NICS_NR' : [4], + 'GUEST_SMP' : ['sockets=1,cores=3'], + 'GUEST_CORE_BINDING' : [['6', '7', '8'],], + 'TRAFFICGEN' : 'Trex', + 'TRAFFICGEN_TREX_HOST_IP_ADDR' : _TREX_SERVER_IP, + 'TRAFFICGEN_TREX_BASE_DIR' : '/root/trex/scripts/', + 'TRAFFICGEN_TREX_USER' : 'root', + }, + "TestSteps": TREX_VM_TEST + }, + { + "Name": "trex_vm_tput", + "Deployment": "clean", + "Description": "T-Rex VM - execute RFC2544 Throughput from T-Rex VM and loop it back through Open vSwitch.", + "Parameters" : { + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + 'GUEST_LOOPBACK' : ['clean',], + 'GUEST_NICS_NR' : [4], + 'GUEST_SMP' : ['sockets=1,cores=3'], + 'GUEST_CORE_BINDING' : [['6', '7', '8'],], + 'TRAFFICGEN' : 'Trex', + 'TRAFFICGEN_TREX_HOST_IP_ADDR' : _TREX_SERVER_IP, + 'TRAFFICGEN_TREX_BASE_DIR' : '/root/trex/scripts/', + 'TRAFFICGEN_TREX_USER' : 'root', + }, + "TestSteps": TREX_VM_TEST + }, + { + "Name": "trex_vm2vm_cont", + "Deployment": "clean", + "Description": "T-Rex VM2VM - execute RFC2544 Continuous Stream from T-Rex VM and loop it back through 2nd VM.", + "Parameters" : { + 'GUEST_LOOPBACK' : ['testpmd', 'clean'], + 'GUEST_NICS_NR' : [2, 4], + 'GUEST_SMP' : ['sockets=1,cores=2', 'sockets=1,cores=3'], + 'GUEST_CORE_BINDING' : [['9', '10'],['6', '7', '8'],], + 'TRAFFICGEN' : 'Trex', + 'TRAFFICGEN_TREX_HOST_IP_ADDR' : _TREX_SERVER_IP, + 'TRAFFICGEN_TREX_BASE_DIR' : '/root/trex/scripts/', + 'TRAFFICGEN_TREX_USER' : 'root', + "TRAFFIC" : { + "traffic_type" : "rfc2544_continuous", + }, + }, + "TestSteps": TREX_VM2VM_TEST, + }, + { + "Name": "trex_vm2vm_tput", + "Deployment": "clean", + "Description": "T-Rex VM2VM - execute RFC2544 Throughput from T-Rex VM and loop it back through 2nd VM.", + "Parameters" : { + 'GUEST_LOOPBACK' : ['testpmd', 'clean'], + 'GUEST_NICS_NR' : [2, 4], + 'GUEST_SMP' : ['sockets=1,cores=2', 'sockets=1,cores=3'], + 'GUEST_CORE_BINDING' : [['9', '10'],['6', '7', '8'],], + 'TRAFFICGEN' : 'Trex', + 'TRAFFICGEN_TREX_HOST_IP_ADDR' : _TREX_SERVER_IP, + 'TRAFFICGEN_TREX_BASE_DIR' : '/root/trex/scripts/', + 'TRAFFICGEN_TREX_USER' : 'root', + "TRAFFIC" : { + "traffic_type" : "rfc2544_throughput", + }, + }, + "TestSteps": TREX_VM2VM_TEST, + }, +] diff --git a/conf/integration/02_vswitch.conf b/conf/integration/02_vswitch.conf index 63ffe1bc..9477a1d0 100644 --- a/conf/integration/02_vswitch.conf +++ b/conf/integration/02_vswitch.conf @@ -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. @@ -16,8 +16,8 @@ VTEP_IP1 = '192.168.0.1/24' VTEP_IP2 = '192.168.240.10' VTEP_IP2_SUBNET = '192.168.240.0/24' -TUNNEL_INTEGRATION_BRIDGE = 'br0' -TUNNEL_EXTERNAL_BRIDGE = 'br-ext' +TUNNEL_INTEGRATION_BRIDGE = 'vsperf-br0' +TUNNEL_EXTERNAL_BRIDGE = 'vsperf-br-ext' TUNNEL_EXTERNAL_BRIDGE_IP = '192.168.240.1/24' # vxlan|gre|geneve diff --git a/core/component_factory.py b/core/component_factory.py index bd9a1019..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): @@ -121,7 +121,6 @@ def create_loadgen(loadgen_class, loadgen_cfg): :param loadgen_cfg: Configuration for the loadgen :return: A new ILoadGenerator class """ - # pylint: disable=too-many-function-args return loadgen_class(loadgen_cfg) def create_pktfwd(deployment, pktfwd_class): diff --git a/core/loader/loader_servant.py b/core/loader/loader_servant.py index 8bad9ab9..6db8e0f2 100644 --- a/core/loader/loader_servant.py +++ b/core/loader/loader_servant.py @@ -120,7 +120,7 @@ class LoaderServant(object): if class_name in results: logging.info( - "Class found: " + class_name + ".") + "Class found: %s.", class_name) return results.get(class_name) return None @@ -180,7 +180,7 @@ class LoaderServant(object): mod = imp.load_module( modname, *imp.find_module(modname, [root])) except ImportError: - logging.error('Could not import file ' + filename) + logging.error('Could not import file %s', filename) raise mods.append((modname, mod)) diff --git a/core/pktfwd_controller.py b/core/pktfwd_controller.py index b38aefa5..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. @@ -35,12 +35,12 @@ class PktFwdController(object): self._pktfwd_class = pktfwd_class self._pktfwd = pktfwd_class(guest=True if deployment == "pvp" and settings.getValue('VNF') != "QemuPciPassthrough" else False) - self._logger.debug('Creation using ' + str(self._pktfwd_class)) + self._logger.debug('Creation using %s', str(self._pktfwd_class)) def setup(self): """Sets up the packet forwarder for p2p. """ - self._logger.debug('Setup using ' + str(self._pktfwd_class)) + self._logger.debug('Setup using %s', str(self._pktfwd_class)) try: self._pktfwd.start() @@ -56,7 +56,7 @@ class PktFwdController(object): def setup_for_guest(self): """Sets up the packet forwarder for pvp. """ - self._logger.debug('Setup using ' + str(self._pktfwd_class)) + self._logger.debug('Setup using %s', str(self._pktfwd_class)) try: self._pktfwd.start_for_guest() @@ -67,7 +67,7 @@ class PktFwdController(object): def stop(self): """Tears down the packet forwarder created in setup(). """ - self._logger.debug('Stop using ' + str(self._pktfwd_class)) + self._logger.debug('Stop using %s', str(self._pktfwd_class)) self._pktfwd.stop() def __enter__(self): @@ -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/traffic_controller.py b/core/traffic_controller.py index de82dddf..1f21e57d 100644 --- a/core/traffic_controller.py +++ b/core/traffic_controller.py @@ -125,7 +125,7 @@ class TrafficController(object): :param traffic: A dictionary describing the traffic to send. """ - self._logger.debug('send_traffic with ' + + self._logger.debug('send_traffic with %s', str(self._traffic_gen_class)) self.configure(traffic) @@ -144,7 +144,8 @@ class TrafficController(object): If this function requires more than one argument, all should be should be passed using the args list and appropriately handled. """ - self._logger.debug('send_traffic_async with ' + + # pylint: disable=unused-argument + self._logger.debug('send_traffic_async with %s', str(self._traffic_gen_class)) self.configure(traffic) @@ -158,7 +159,7 @@ class TrafficController(object): """ counter = 0 for item in self._results: - logging.info("Record: " + str(counter)) + logging.info("Record: %s", str(counter)) counter += 1 for(key, value) in list(item.items()): logging.info(" Key: " + str(key) + @@ -169,7 +170,7 @@ class TrafficController(object): """ return self._results - def validate_send_traffic(self, dummy_result, dummy_traffic): + def validate_send_traffic(self, _dummy_result, _dummy_traffic): """Verify that send traffic has succeeded """ if self._results: diff --git a/core/traffic_controller_rfc2544.py b/core/traffic_controller_rfc2544.py index 488dde6f..2bb30fec 100644 --- a/core/traffic_controller_rfc2544.py +++ b/core/traffic_controller_rfc2544.py @@ -62,6 +62,9 @@ class TrafficControllerRFC2544(TrafficController, IResults): elif traffic['traffic_type'] == 'rfc2544_continuous': result = self._traffic_gen_class.send_cont_traffic( traffic, duration=self._duration) + elif traffic['traffic_type'] == 'burst': + result = self._traffic_gen_class.send_burst_traffic( + traffic, duration=self._duration) elif traffic['traffic_type'] == 'rfc2544_throughput': result = self._traffic_gen_class.send_rfc2544_throughput( traffic, tests=self._tests, duration=self._duration, lossrate=self._lossrate) @@ -87,7 +90,7 @@ class TrafficControllerRFC2544(TrafficController, IResults): tests=self._tests, duration=self._duration) self._traffic_started = True - if len(function['args']) > 0: + if function['args']: function['function'](function['args']) else: function['function']() diff --git a/core/traffic_controller_rfc2889.py b/core/traffic_controller_rfc2889.py index 64ab0ba6..316202c9 100644 --- a/core/traffic_controller_rfc2889.py +++ b/core/traffic_controller_rfc2889.py @@ -84,7 +84,7 @@ class TrafficControllerRFC2889(TrafficController, IResults): trials=self._trials, duration=self._duration) self._traffic_started = True - if len(function['args']) > 0: + if function['args']: function['function'](function['args']) else: function['function']() diff --git a/core/vnf_controller.py b/core/vnf_controller.py index 78a29258..cbf59b79 100644 --- a/core/vnf_controller.py +++ b/core/vnf_controller.py @@ -93,8 +93,7 @@ class VnfController(object): def get_vnfs_number(self): """Returns a number of vnfs controlled by this controller. """ - self._logger.debug('get_vnfs_number ' + str(len(self._vnfs)) + - ' VNF[s]') + self._logger.debug('get_vnfs_number %s VNF[s]', str(len(self._vnfs))) return len(self._vnfs) def start(self): 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 61724b9b..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,22 +25,10 @@ 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 ' + str(self._vswitch_class)) - self._traffic = traffic.copy() - def setup(self): """Sets up the switch for Clean. """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) try: self._vswitch.start() @@ -54,26 +39,15 @@ class VswitchControllerClean(IVswitchController): def stop(self): """Tears down the switch created in setup(). """ - self._logger.debug('Stop using ' + str(self._vswitch_class)) + 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 85bf79bd..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,44 +14,24 @@ """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 ' + str(self._vswitch_class)) def setup(self): """ Sets up the switch for overlay P2P (tunnel encap or decap) """ - self._logger.debug('Setting up ' + str(self._tunnel_operation)) + self._logger.debug('Setting up %s', str(self._tunnel_operation)) if self._tunnel_operation == "encapsulation": self._setup_encap() else: @@ -66,7 +46,7 @@ class VswitchControllerOP2P(IVswitchController): Create 2 bridges br0 (integration bridge) and br-ext and a VXLAN port for encapsulation. """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) try: self._vswitch.start() @@ -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 @@ -129,7 +112,7 @@ class VswitchControllerOP2P(IVswitchController): def _setup_decap(self): """ Sets up the switch for overlay P2P decapsulation test """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) try: self._vswitch.start() @@ -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) @@ -189,7 +172,7 @@ class VswitchControllerOP2P(IVswitchController): def _setup_decap_vanilla(self): """ Sets up the switch for overlay P2P decapsulation test """ - self._logger.debug('Setup decap vanilla ' + str(self._vswitch_class)) + self._logger.debug('Setup decap vanilla %s', str(self._vswitch_class)) try: self._vswitch.start() @@ -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: @@ -261,20 +244,9 @@ class VswitchControllerOP2P(IVswitchController): def stop(self): """Tears down the switch created in setup(). """ - self._logger.debug('Stop using ' + str(self._vswitch_class)) + 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 0d41b145..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,71 +26,28 @@ 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 ' + 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. """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) 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 @@ -109,68 +55,16 @@ class VswitchControllerP2P(IVswitchController): def stop(self): """Tears down the switch created in setup(). """ - self._logger.debug('Stop using ' + str(self._vswitch_class)) + 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 ' + str(self._vswitch_class)) - return self._vswitch.get_ports(settings.getValue('VSWITCH_BRIDGE_NAME')) + 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(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 27d26789..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,13 +47,12 @@ 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 ' + str(self._vswitch_class)) def setup(self): """ Sets up the switch for VxLAN overlay PTUNP (tunnel encap or decap) """ self._logger.debug('Setting up phy-tun-phy tunneling scenario') - if self.tunnel_type is 'vxlan': + if self.tunnel_type == 'vxlan': self._setup_vxlan_encap_decap() else: self._logger.error("Only VxLAN is supported for now") @@ -78,7 +65,7 @@ class VswitchControllerPtunP(IVswitchController): physical ports. Two more bridges br-mod1 and br-mod2 to mangle and redirect the packets from one tunnel port to other. """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) try: self._vswitch.start() self._vswitch.add_switch(self.bridge_phy1) @@ -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), @@ -204,35 +191,24 @@ class VswitchControllerPtunP(IVswitchController): def stop(self): """Tears down the switch created in setup(). """ - self._logger.debug('Stop using ' + str(self._vswitch_class)) + 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 ' + str(self._vswitch_class)) + self._logger.debug('get_ports_info using %s', str(self._vswitch_class)) ports = self._vswitch.get_ports(self.bridge_phy1) +\ self._vswitch.get_ports(self.bridge_mod1) +\ self._vswitch.get_ports(self.bridge_phy2) +\ self._vswitch.get_ports(self.bridge_mod2) return ports - def dump_vswitch_flows(self): + def dump_vswitch_connections(self): """See IVswitchController for description """ - self._logger.debug('dump_flows using ' + str(self._vswitch_class)) - self._vswitch.dump_flows(self.bridge_phy1) - self._vswitch.dump_flows(self.bridge_mod1) - self._vswitch.dump_flows(self.bridge_phy2) - self._vswitch.dump_flows(self.bridge_mod2) + 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 d4d1e764..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,15 +39,13 @@ 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 ' + str(self._vswitch_class)) self._bridge = settings.getValue('VSWITCH_BRIDGE_NAME') def setup(self): """ Sets up the switch for PXP """ - self._logger.debug('Setup using ' + str(self._vswitch_class)) + self._logger.debug('Setup using %s', str(self._vswitch_class)) try: self._vswitch.start() @@ -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 @@ -182,40 +154,16 @@ class VswitchControllerPXP(IVswitchController): def stop(self): """Tears down the switch created in setup(). """ - self._logger.debug('Stop using ' + str(self._vswitch_class)) + 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 ' + str(self._vswitch_class)) + 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/release/release-notes/release-notes.rst b/docs/release/release-notes/release-notes.rst index 860cca77..46eb74c0 100644 --- a/docs/release/release-notes/release-notes.rst +++ b/docs/release/release-notes/release-notes.rst @@ -2,6 +2,73 @@ .. http://creativecommons.org/licenses/by/4.0 .. (c) OPNFV, Intel Corporation, AT&T and others. +OPNFV Fraser Release +==================== + +* Supported Versions - DPDK:17.08, OVS:2.8.1, VPP:17.07, QEMU:2.9.1 +* Pylint 1.8.2 code conformity +* Python virtualenv moved to python-3. +* LTD: Requirements specification for Soak/Long Duration Tests +* Performance Matrix functionality support +* Several bugfixes and minor improvements + +* Documentation + + * Configuration and installation of additional tools. + * Xena install document update. + * Installation prerequisites update + * Traffic Capture methods explained + +* Virtual-Switches + + * OVS: Configurable arguments for ovs-\*ctl + * OVS: Fix vswitch shutdown process + * VPP: Define vppctl socket name + * VPP: Multiqueue support for VPP + * OVS and VPP: Improve add_phy_port error messages + * OVS and VPP: Updated to recent version + +* Tools + + * Support for Stressor-VMs as a Loadgen + * Support for collectd as one of the collectors + * Support for LLC management with Intel RMD + +* Traffic Generators + + * All Traffic-Gens: Postponed call of connect operation. + * Ixia: Added support of LISTs in TRAFFIC + * T-Rex: Version v2.38 support added. + * T-Rex: Support for T-Rex Traffic generator in a VM. + * T-Rex: Add logic for dealing with high speed cards. + * T-Rex: Improve error handling. + * T-Rex: Added support for traffic capture. + * T-Rex: RFC2544 verification functionality included. + * T-Rex: Added learning packet option. + * T-Rex: Added packet counts for reporting + * T-Rex: Added multistream support + * T-Rex: Added promiscuous option for SRIOV tests + * T-Rex: RFC2544 Throughput bugfixing + +* Tests + + * Tests with T-Rex in VM + * Improvements of step driven Testcases + * OVS/DPDK regression tests + * Traffic Capture testcases added. + +* Installation Scripts + + * Support for SLES15 and openSuse Tumbleweed + * Fedora installation script update + * rhel_path_fix: Fix pathing issue introduce by other commit + * Updated build scripts for Centos and RHEL to python34 + +* CI + + * Update hugepages configuration + * Support disabling VPP tests, if required + OPNFV Euphrates Release ======================= diff --git a/docs/testing/developer/devguide/design/trafficgen_integration_guide.rst b/docs/testing/developer/devguide/design/trafficgen_integration_guide.rst index c88b80ed..671c7fd8 100644 --- a/docs/testing/developer/devguide/design/trafficgen_integration_guide.rst +++ b/docs/testing/developer/devguide/design/trafficgen_integration_guide.rst @@ -199,13 +199,20 @@ functions: Note: There are parameters specific to testing of tunnelling protocols, which are discussed in detail at :ref:`integration-tests` userguide. + Note: A detailed description of the ``TRAFFIC`` dictionary can be found at + :ref:`configuration-of-traffic-dictionary`. + * param **traffic_type**: One of the supported traffic types, - e.g. **rfc2544_throughput**, **rfc2544_continuous** - or **rfc2544_back2back**. - * param **frame_rate**: Defines desired percentage of frame - rate used during continuous stream tests. + e.g. **rfc2544_throughput**, **rfc2544_continuous**, + **rfc2544_back2back** or **burst**. * param **bidir**: Specifies if generated traffic will be full-duplex (true) or half-duplex (false). + * param **frame_rate**: Defines desired percentage of frame + rate used during continuous stream tests. + * param **burst_size**: Defines a number of frames in the single burst, + which is sent by burst traffic type. Burst size is applied for each + direction, i.e. the total number of tx frames will be 2*burst_size + in case of bidirectional traffic. * param **multistream**: Defines number of flows simulated by traffic generator. Value 0 disables MultiStream feature. * param **stream_type**: Stream Type defines ISO OSI network layer @@ -224,6 +231,8 @@ functions: **dstport** and l4 on/off switch **enabled**. * param **vlan**: A dictionary with vlan specific parameters, e.g. **priority**, **cfi**, **id** and vlan on/off switch **enabled**. + * param **scapy**: A dictionary with definition of the frame content for both traffic + directions. The frame content is defined by a SCAPY notation. * param **tests**: Number of times the test is executed. * param **duration**: Duration of continuous test or per iteration duration diff --git a/docs/testing/developer/devguide/design/vswitchperf_design.rst b/docs/testing/developer/devguide/design/vswitchperf_design.rst index 96ffcf62..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: @@ -291,8 +291,8 @@ Detailed description of ``TRAFFIC`` dictionary items follows: .. code-block:: console 'traffic_type' - One of the supported traffic types. - E.g. rfc2544_throughput, rfc2544_back2back - or rfc2544_continuous + E.g. rfc2544_throughput, rfc2544_back2back, + rfc2544_continuous or burst Data type: str Default value: "rfc2544_throughput". 'bidir' - Specifies if generated traffic will be full-duplex (True) @@ -304,6 +304,12 @@ Detailed description of ``TRAFFIC`` dictionary items follows: continuous stream tests. Data type: int Default value: 100. + 'burst_size' - Defines a number of frames in the single burst, which is sent + by burst traffic type. Burst size is applied for each direction, + i.e. the total number of tx frames will be 2*burst_size in case of + bidirectional traffic. + Data type: int + Default value: 100. 'multistream' - Defines number of flows simulated by traffic generator. Value 0 disables multistream feature Data type: int @@ -326,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 @@ -439,6 +444,34 @@ Detailed description of ``TRAFFIC`` dictionary items follows: details. Data type: str Default value: '' + 'scapy' - A dictionary with definition of a frame content for both traffic + directions. The frame content is defined by a SCAPY notation. + NOTE: It is supported only by the T-Rex traffic generator. + Following keywords can be used to refer to the related parts of + the TRAFFIC dictionary: + Ether_src - refers to TRAFFIC['l2']['srcmac'] + Ether_dst - refers to TRAFFIC['l2']['dstmac'] + IP_proto - refers to TRAFFIC['l3']['proto'] + IP_PROTO - refers to upper case version of TRAFFIC['l3']['proto'] + IP_src - refers to TRAFFIC['l3']['srcip'] + IP_dst - refers to TRAFFIC['l3']['dstip'] + IP_PROTO_sport - refers to TRAFFIC['l4']['srcport'] + IP_PROTO_dport - refers to TRAFFIC['l4']['dstport'] + Dot1Q_prio - refers to TRAFFIC['vlan']['priority'] + Dot1Q_id - refers to TRAFFIC['vlan']['cfi'] + Dot1Q_vlan - refers to TRAFFIC['vlan']['id'] + '0' - A string with the frame definition for the 1st direction. + Data type: str + Default value: 'Ether(src={Ether_src}, dst={Ether_dst})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_src}, dst={IP_dst})/' + '{IP_PROTO}(sport={IP_PROTO_sport}, dport={IP_PROTO_dport})' + '1' - A string with the frame definition for the 2nd direction. + Data type: str + Default value: 'Ether(src={Ether_dst}, dst={Ether_src})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_dst}, dst={IP_src})/' + '{IP_PROTO}(sport={IP_PROTO_dport}, dport={IP_PROTO_sport})', .. _configuration-of-guest-options: @@ -743,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 =========================================== @@ -786,7 +826,7 @@ ITrafficGenerator connect() disconnect() - send_burst_traffic(traffic, numpkts, time, framerate) + send_burst_traffic(traffic, time) send_cont_traffic(traffic, time, framerate) start_cont_traffic(traffic, time, framerate) @@ -878,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/docs/testing/developer/devguide/requirements/vswitchperf_ltd.rst b/docs/testing/developer/devguide/requirements/vswitchperf_ltd.rst index e1372520..c703ff40 100644 --- a/docs/testing/developer/devguide/requirements/vswitchperf_ltd.rst +++ b/docs/testing/developer/devguide/requirements/vswitchperf_ltd.rst @@ -413,7 +413,21 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoak **Title**: RFC 2889 X% packet loss Max Forwarding Rate Soak Test - **Prerequisite Test** LTD.Throughput.RFC2544.PacketLossRatio + **Prerequisite Tests**: + + LTD.Throughput.RFC2544.PacketLossRatio will determine the offered load and + frame size for which the maximum theoretical throughput of the interface + has not been achieved. As described in RFC 2544 section 24, the final + determination of the benchmark SHOULD be conducted using a full length + trial, and for this purpose the duration is 5 minutes with zero loss ratio. + + It is also essential to verify that the Traffic Generator has sufficient + stability to conduct Soak tests. Therefore, a prerequisite is to perform + this test with the DUT removed and replaced with a cross-over cable (or + other equivalent very low overhead method such as a loopback in a HW switch), + so that the traffic generator (and any other network involved) can be tested + over the Soak period. Note that this test may be challenging for software- + based traffic generators. **Priority**: @@ -422,12 +436,19 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoak The aim of this test is to understand the Max Forwarding Rate stability over an extended test duration in order to uncover any outliers. To allow for an extended test duration, the test should ideally run for 24 hours - or, if this is not possible, for at least 6 hours. For this test, each frame - size must be sent at the highest Throughput rate with X% packet loss, as - determined in the prerequisite test. The default loss percentages to be - tested are: - X = 0% - X = 10^-7% + or if this is not possible, for at least 6 hours. - Note: Other values can be tested if required by the user. + For this test, one frame size must be sent at the highest frame rate with + X% packet loss ratio, as determined in the prerequisite test (a short trial). + The loss ratio shall be measured and recorded every 5 minutes during the test + (it may be sufficient to collect lost frame counts and divide by the number + of frames sent in 5 minutes to see if a threshold has been crossed, + and accept some small inaccuracy in the threshold evaluation, not the result). + The default loss ratio is X = 0% and loss ratio > 10^-7% is the default + threshold to terminate the test early (or inform the test operator of + the failure status). + + Note: Other values of X and loss threshold can be tested if required by the user. **Expected Result**: @@ -441,13 +462,13 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoak and reporting any time intervals with packet loss. The `RFC2889 <https://www.rfc-editor.org/rfc/rfc2289.txt>`__ Forwarding Rate shall be measured in each interval. - An interval of 60s is suggested. + An interval of 300s is suggested. - CPU and memory utilization may also be collected as part of this test, to determine the vSwitch's performance footprint on the system. - The `RFC5481 <https://www.rfc-editor.org/rfc/rfc5481.txt>`__ PDV form of delay variation on the traffic flow, - using the 99th percentile. + using the 99th percentile, may also be collected. .. 3.2.2.1.7 @@ -457,7 +478,22 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoakFrameModification **Title**: RFC 2889 Max Forwarding Rate Soak Test with Frame Modification **Prerequisite Test**: + LTD.Throughput.RFC2544.PacketLossRatioFrameModification (0% Packet Loss) + will determine the offered load and + frame size for which the maximum theoretical throughput of the interface + has not been achieved. As described in RFC 2544 section 24, the final + determination of the benchmark SHOULD be conducted using a full length + trial, and for this purpose the duration is 5 minutes with zero loss ratio. + + It is also essential to verify that the Traffic Generator has sufficient + stability to conduct Soak tests. Therefore, a prerequisite is to perform + this test with the DUT removed and replaced with a cross-over cable (or + other equivalent very low overhead method such as a loopback in a HW switch), + so that the traffic generator (and any other network involved) can be tested + over the Soak period. Note that this test may be challenging for software- + based traffic generators. + **Priority**: @@ -466,9 +502,19 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoakFrameModification The aim of this test is to understand the Max Forwarding Rate stability over an extended test duration in order to uncover any outliers. To allow for an extended test duration, the test should ideally run for 24 hours or, if - this is not possible, for at least 6 hour. For this test, each frame - size must be sent at the highest Throughput rate with 0% packet loss, as - determined in the prerequisite test. + this is not possible, for at least 6 hours. + + For this test, one frame size must be sent at the highest frame rate with + X% packet loss ratio, as determined in the prerequisite test (a short trial). + The loss ratio shall be measured and recorded every 5 minutes during the test + (it may be sufficient to collect lost frame counts and divide by the number + of frames sent in 5 minutes to see if a threshold has been crossed, + and accept some small inaccuracy in the threshold evaluation, not the result). + The default loss ratio is X = 0% and loss ratio > 10^-7% is the default + threshold to terminate the test early (or inform the test operator of + the failure status). + + Note: Other values of X and loss threshold can be tested if required by the user. During this test, the DUT must perform the following operations on the traffic flow: @@ -498,13 +544,13 @@ Test ID: LTD.Throughput.RFC2889.MaxForwardingRateSoakFrameModification and reporting any time intervals with packet loss. The `RFC2889 <https://www.rfc-editor.org/rfc/rfc2289.txt>`__ Forwarding Rate shall be measured in each interval. - An interval of 60s is suggested. + An interval of 300s is suggested. - CPU and memory utilization may also be collected as part of this test, to determine the vSwitch's performance footprint on the system. - The `RFC5481 <https://www.rfc-editor.org/rfc/rfc5481.txt>`__ PDV form of delay variation on the traffic flow, using the 99th - percentile. + percentile, may also be collected. .. 3.2.2.1.8 @@ -1150,7 +1196,22 @@ Test ID: LTD.PacketDelayVariation.RFC3393.Soak **Title**: Packet Delay Variation Soak Test - **Prerequisite Tests**: LTD.Throughput.RFC2544.PacketLossRatio (0% Packet Loss) + **Prerequisite Tests**: + + LTD.Throughput.RFC2544.PacketLossRatio will determine the offered load and + frame size for which the maximum theoretical throughput of the interface + has not been achieved. As described in RFC 2544 section 24, the final + determination of the benchmark SHOULD be conducted using a full length + trial, and for this purpose the duration is 5 minutes with zero loss ratio. + + It is also essential to verify that the Traffic Generator has sufficient + stability to conduct Soak tests. Therefore, a prerequisite is to perform + this test with the DUT removed and replaced with a cross-over cable (or + other equivalent very low overhead method such as a loopback in a HW switch), + so that the traffic generator (and any other network involved) can be tested + over the Soak period. Note that this test may be challenging for software- + based traffic generators. + **Priority**: @@ -1160,9 +1221,20 @@ Test ID: LTD.PacketDelayVariation.RFC3393.Soak variation for different frame sizes over an extended test duration and to determine if there are any outliers. To allow for an extended test duration, the test should ideally run for 24 hours or, if this is not - possible, for at least 6 hour. For this test, each frame size must be - sent at the highest possible throughput with 0% packet loss, as - determined in the prerequisite test. + possible, for at least 6 hours. + + For this test, one frame size must be sent at the highest frame rate with + X% packet loss ratio, as determined in the prerequisite test (a short trial). + The loss ratio shall be measured and recorded every 5 minutes during the test + (it may be sufficient to collect lost frame counts and divide by the number + of frames sent in 5 minutes to see if a threshold has been crossed, + and accept some small inaccuracy in the threshold evaluation, not the result). + The default loss ratio is X = 0% and loss ratio > 10^-7% is the default + threshold to terminate the test early (or inform the test operator of + the failure status). + + Note: Other values of X and loss threshold can be tested if required by the user. + **Expected Result**: @@ -1173,7 +1245,7 @@ Test ID: LTD.PacketDelayVariation.RFC3393.Soak - The packet delay variation value for traffic passing through the DUT. - The `RFC5481 <https://www.rfc-editor.org/rfc/rfc5481.txt>`__ PDV form of delay variation on the traffic flow, - using the 99th percentile, for each 60s interval during the test. + using the 99th percentile, for each 300s interval during the test. - CPU and memory utilization may also be collected as part of this test, to determine the vSwitch's performance footprint on the system. diff --git a/docs/testing/user/configguide/index.rst b/docs/testing/user/configguide/index.rst index 83908a97..75a2082d 100644 --- a/docs/testing/user/configguide/index.rst +++ b/docs/testing/user/configguide/index.rst @@ -48,6 +48,7 @@ VSPERF Install and Configuration ./installation.rst ./upgrade.rst ./trafficgen.rst + ./tools.rst ================= VSPERF Test Guide diff --git a/docs/testing/user/configguide/installation.rst b/docs/testing/user/configguide/installation.rst index 7f4d640b..51588007 100644 --- a/docs/testing/user/configguide/installation.rst +++ b/docs/testing/user/configguide/installation.rst @@ -202,7 +202,7 @@ new shell session. Its activation is specific to your OS: .. code:: bash - $ scl enable python33 bash + $ scl enable rh-python34 bash $ source $HOME/vsperfenv/bin/activate * Fedora and Ubuntu diff --git a/docs/testing/user/configguide/tools.rst b/docs/testing/user/configguide/tools.rst new file mode 100644 index 00000000..907e86d2 --- /dev/null +++ b/docs/testing/user/configguide/tools.rst @@ -0,0 +1,177 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. (c) OPNFV, Intel Corporation, Spirent, AT&T and others. + +.. _additional-tools-configuration: + +============================================= +'vsperf' Additional Tools Configuration Guide +============================================= + +Overview +-------- + +VSPERF supports the following categories additional tools: + + * `Infrastructure Metrics Collectors`_ + * `Load Generators`_ + * `L3 Cache Management`_ + +Under each category, there are one or more tools supported by VSPERF. +This guide provides the details of how to install (if required) +and configure the above mentioned tools. + +.. _`Infrastructure Metrics Collectors`: + +Infrastructure Metrics Collection +--------------------------------- + +VSPERF supports following two tools for collecting and reporting the metrics: + +* pidstat +* collectd + +*pidstat* is a command in linux systems, which is used for monitoring individual +tasks currently being managed by Linux kernel. In VSPERF this command is used to +monitor *ovs-vswitchd*, *ovsdb-server* and *kvm* processes. + +*collectd* is linux application that collects, stores and transfers various system +metrics. For every category of metrics, there is a separate plugin in collectd. For +example, CPU plugin and Interface plugin provides all the cpu metrics and interface +metrics, respectively. CPU metrics may include user-time, system-time, etc., whereas +interface metrics may include received-packets, dropped-packets, etc. + +Installation +^^^^^^^^^^^^ + +No installation is required for *pidstat*, whereas, collectd has to be installed +separately. For installation of collectd, we recommend to follow the process described +in *OPNFV-Barometer* project, which can be found here `Barometer-Euphrates <http://docs.opnfv.org/en/stable-euphrates/submodules/barometer/docs/release/userguide/feature.userguide.html#building-all-barometer-upstreamed-plugins-from-scratch>`_ or the most +recent release. + +VSPERF assumes that collectd is installed and configured to send metrics over localhost. +The metrics sent should be for the following categories: CPU, Processes, Interface, +OVS, DPDK, Intel-RDT. + +Configuration +^^^^^^^^^^^^^ + +The configuration file for the collectors can be found in **conf/05_collector.conf**. +*pidstat* specific configuration includes: + +* ``PIDSTAT_MONITOR`` - processes to be monitored by pidstat +* ``PIDSTAT_OPTIONS`` - options which will be passed to pidstat command +* ``PIDSTAT_SAMPLE_INTERVAL`` - sampling interval used by pidstat to collect statistics +* ``LOG_FILE_PIDSTAT`` - prefix of pidstat's log file + +The *collectd* configuration option includes: + +* ``COLLECTD_IP`` - IP address where collectd is running +* ``COLLECTD_PORT`` - Port number over which collectd is sending the metrics +* ``COLLECTD_SECURITY_LEVEL`` - Security level for receiving metrics +* ``COLLECTD_AUTH_FILE`` - Authentication file for receiving metrics +* ``LOG_FILE_COLLECTD`` - Prefix for collectd's log file. +* ``COLLECTD_CPU_KEYS`` - Interesting metrics from CPU +* ``COLLECTD_PROCESSES_KEYS`` - Interesting metrics from processes +* ``COLLECTD_INTERFACE_KEYS`` - Interesting metrics from interface +* ``COLLECTD_OVSSTAT_KEYS`` - Interesting metrics from OVS +* ``COLLECTD_DPDKSTAT_KEYS`` - Interesting metrics from DPDK. +* ``COLLECTD_INTELRDT_KEYS`` - Interesting metrics from Intel-RDT +* ``COLLECTD_INTERFACE_XKEYS`` - Metrics to exclude from Interface +* ``COLLECTD_INTELRDT_XKEYS`` - Metrics to exclude from Intel-RDT + + +.. _`Load Generators`: + + +Load Generation +--------------- + +In VSPERF, load generation refers to creating background cpu and memory loads to +study the impact of these loads on system under test. There are two options to +create loads in VSPERF. These options are used for different use-cases. The options are: + +* stress or stress-ng +* Stressor-VMs + +*stress and stress-ng* are linux tools to stress the system in various ways. +It can stress different subsystems such as CPU and memory. *stress-ng* is the +improvised version of *stress*. StressorVMs are custom build virtual-machines +for the noisy-neighbor use-cases. + +Installation +^^^^^^^^^^^^ + +stress and stress-ng can be installed through standard linux installation process. +Information about stress-ng, including the steps for installing can be found +here: `stress-ng <https://github.com/ColinIanKing/stress-ng>`_ + +There are two options for StressorVMs - one is VMs based on stress-ng and second +is VM based on Spirent's cloudstress. VMs based on stress-ng can be found in this +`link <https://github.com/opensource-tnbt/stressng-images>`_ . Spirent's cloudstress +based VM can be downloaded from this `site <https://github.com/spirent/cloudstress>`_ + +These stressorVMs are of OSV based VMs, which are very small in size. Download +these VMs and place it in appropriate location, and this location will used in +the configuration - as mentioned below. + +Configuration +^^^^^^^^^^^^^ + +The configuration file for loadgens can be found in **conf/07_loadgen.conf**. +There are no specific configurations for stress and stress-ng commands based +load-generation. However, for StressorVMs, following configurations apply: + +* ``NN_COUNT`` - Number of stressor VMs required. +* ``NN_MEMORY`` - Comma separated memory configuration for each VM +* ``NN_SMP`` - Comma separated configuration for each VM +* ``NN_IMAGE`` - Comma separated list of Paths for each VM image +* ``NN_SHARED_DRIVE_TYPE`` - Comma separated list of shaed drive type for each VM +* ``NN_BOOT_DRIVE_TYPE`` - Comma separated list of boot drive type for each VM +* ``NN_CORE_BINDING`` - Comma separated lists of list specifying the cores associated with each VM. +* ``NN_NICS_NR`` - Comma seprated list of number of NICS for each VM +* ``NN_BASE_VNC_PORT`` - Base VNC port Index. +* ``NN_LOG_FILE`` - Name of the log file + +.. _`L3 Cache Management`: + +Last Level Cache Management +--------------------------- + +VSPERF support last-level cache management using Intel's RDT tool(s) - the +relavant ones are `Intel CAT-CMT <https://github.com/intel/intel-cmt-cat>`_ and +`Intel RMD <https://github.com/intel/rmd>`_. RMD is a linux daemon that runs on +individual hosts, and provides a REST API for control/orchestration layer to +request LLC for the VMs/Containers/Applications. RDT receives resource policy +form orchestration layer - in this case, from VSPERF - and enforce it on the host. +It achieves this enforcement via kernel interfaces such as resctrlfs and libpqos. +The resource here refer to the last-level cache. User can configure policies to +define how much of cache a CPU can get. The policy configuration is described below. + +Installation +^^^^^^^^^^^^ + +For installation of RMD tool, please install CAT-CMT first and then install RMD. +The details of installation can be found here: `Intel CAT-CMT <https://github.com/intel/intel-cmt-cat>`_ +and `Intel RMD <https://github.com/intel/rmd>`_ + +Configuration +^^^^^^^^^^^^^ + +The configuration file for cache management can be found in **conf/08_llcmanagement.conf**. + +VSPERF provides following configuration options, for user to define and enforce policies via RMD. + +* ``LLC_ALLOCATION`` - Enable or Disable LLC management. +* ``RMD_PORT`` - RMD port (port number on which API server is listening) +* ``RMD_SERVER_IP`` - IP address where RMD is running. Currently only localhost. +* ``RMD_API_VERSION`` - RMD version. Currently it is 'v1' +* ``POLICY_TYPE`` - Specify how the policy is defined - either COS or CUSTOM +* ``VSWITCH_COS`` - Class of service (CoS for Vswitch. CoS can be gold, silver-bf or bronze-shared. +* ``VNF_COS`` - Class of service for VNF +* ``PMD_COS`` - Class of service for PMD +* ``NOISEVM_COS`` - Class of service of Noisy VM. +* ``VSWITCH_CA`` - [min-cache-value, maxi-cache-value] for vswitch +* ``VNF_CA`` - [min-cache-value, max-cache-value] for VNF +* ``PMD_CA`` - [min-cache-value, max-cache-value] for PMD +* ``NOISEVM_CA`` - [min-cache-value, max-cache-value] for Noisy VM diff --git a/docs/testing/user/configguide/trafficgen.rst b/docs/testing/user/configguide/trafficgen.rst index 33824486..2636626a 100644 --- a/docs/testing/user/configguide/trafficgen.rst +++ b/docs/testing/user/configguide/trafficgen.rst @@ -39,6 +39,7 @@ and is configured as follows: TRAFFIC = { 'traffic_type' : 'rfc2544_throughput', 'frame_rate' : 100, + 'burst_size' : 100, 'bidir' : 'True', # will be passed as string in title format to tgen 'multistream' : 0, 'stream_type' : 'L4', @@ -75,8 +76,22 @@ and is configured as follows: 'count': 1, 'filter': '', }, + 'scapy': { + 'enabled': False, + '0' : 'Ether(src={Ether_src}, dst={Ether_dst})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_src}, dst={IP_dst})/' + '{IP_PROTO}(sport={IP_PROTO_sport}, dport={IP_PROTO_dport})', + '1' : 'Ether(src={Ether_dst}, dst={Ether_src})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_dst}, dst={IP_src})/' + '{IP_PROTO}(sport={IP_PROTO_dport}, dport={IP_PROTO_sport})', + } } +A detailed description of the ``TRAFFIC`` dictionary can be found at +:ref:`configuration-of-traffic-dictionary`. + The framesize parameter can be overridden from the configuration files by adding the following to your custom configuration file ``10_custom.conf``: @@ -577,7 +592,7 @@ http://www.mono-project.com/docs/getting-started/install/linux/ rpm --import "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF" yum-config-manager --add-repo http://download.mono-project.com/repo/centos/ - yum -y install mono-complete + yum -y install mono-complete-5.8.0.127-0.xamarin.3.epel7.x86_64 To prevent gpg errors on future yum installation of packages the mono-project repo should be disabled once installed. @@ -667,6 +682,14 @@ or modify the length of the learning by modifying the following settings. TRAFFICGEN_XENA_CONT_PORT_LEARNING_ENABLED = False TRAFFICGEN_XENA_CONT_PORT_LEARNING_DURATION = 3 +Multistream Modifier +~~~~~~~~~~~~~~~~~~~~ + +Xena has a modifier maximum value or 64k in size. For this reason when specifying +Multistream values of greater than 64k for Layer 2 or Layer 3 it will use two +modifiers that may be modified to a value that can be square rooted to create the +two modifiers. You will see a log notification for the new value that was calculated. + MoonGen ------- @@ -745,11 +768,14 @@ You can directly download from GitHub: git clone https://github.com/cisco-system-traffic-generator/trex-core -and use the master branch: +and use the same Trex version for both server and client API. + +**NOTE:** The Trex API version used by VSPERF is defined by variable ``TREX_TAG`` +in file ``src/package-list.mk``. .. code-block:: console - git checkout master + git checkout v2.38 or Trex latest release you can download from here: @@ -795,6 +821,13 @@ It is neccesary for proper connection between Trex server and VSPERF. Firewall must allow a connection from DUT (VSPERF) to the T-Rex server running at TCP port 4501. +**NOTE:** For high speed cards it may be advantageous to start T-Rex with more transmit queues/cores. + +.. code-block:: console + + cd trex-cores/scripts/ + ./t-rex-64 -i -c 10 + For additional information about Trex stateless mode see Trex stateless documentation: https://trex-tgn.cisco.com/trex/doc/trex_stateless.html @@ -847,6 +880,21 @@ place. This can be adjusted with the following configurations: TRAFFICGEN_TREX_LEARNING_MODE=True TRAFFICGEN_TREX_LEARNING_DURATION=5 +Latency measurements have impact on T-Rex performance. Thus vswitchperf uses a separate +latency stream for each direction with limited speed. This workaround is used for RFC2544 +**Throughput** and **Continuous** traffic types. In case of **Burst** traffic type, +the latency statistics are measured for all frames in the burst. Collection of latency +statistics is driven by configuration option ``TRAFFICGEN_TREX_LATENCY_PPS`` as follows: + + * value ``0`` - disables latency measurements + * non zero integer value - enables latency measurements; In case of Throughput + and Continuous traffic types, it specifies a speed of latency specific stream + in PPS. In case of burst traffic type, it enables latency measurements for all frames. + +.. code-block:: console + + TRAFFICGEN_TREX_LATENCY_PPS = 1000 + SR-IOV and Multistream layer 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ T-Rex by default only accepts packets on the receive side if the destination mac matches the @@ -862,6 +910,22 @@ modified. Enable Promiscuous mode when doing multistream at layer 2 testing with TRAFFICGEN_TREX_PROMISCUOUS=True +Card Bandwidth Options +~~~~~~~~~~~~~~~~~~~~~~ + +T-Rex API will attempt to retrieve the highest possible speed from the card using internal +calls to port information. If you are using two separate cards then it will take the lowest +of the two cards as the max speed. If necessary you can try to force the API to use a +specific maximum speed per port. The below configurations can be adjusted to enable this. + +.. code-block:: console + + TRAFFICGEN_TREX_FORCE_PORT_SPEED = True + TRAFFICGEN_TREX_PORT_SPEED = 40000 # 40 gig + +**Note::** Setting higher than possible speeds will result in unpredictable behavior when running +tests such as duration inaccuracy and/or complete test failure. + RFC2544 Validation ~~~~~~~~~~~~~~~~~~ @@ -881,3 +945,68 @@ The duration and maximum number of attempted verification trials can be set to c behavior of this step. If the verification step fails, it will resume the binary search with new values where the maximum output will be the last attempted frame rate minus the current set thresh hold. + +Scapy frame definition +~~~~~~~~~~~~~~~~~~~~~~ + +It is possible to use a SCAPY frame definition to generate various network protocols +by the **T-Rex** traffic generator. In case that particular network protocol layer +is disabled by the TRAFFIC dictionary (e.g. TRAFFIC['vlan']['enabled'] = False), +then disabled layer will be removed from the scapy format definition by VSPERF. + +The scapy frame definition can refer to values defined by the TRAFFIC dictionary +by following keywords. These keywords are used in next examples. + +* ``Ether_src`` - refers to ``TRAFFIC['l2']['srcmac']`` +* ``Ether_dst`` - refers to ``TRAFFIC['l2']['dstmac']`` +* ``IP_proto`` - refers to ``TRAFFIC['l3']['proto']`` +* ``IP_PROTO`` - refers to upper case version of ``TRAFFIC['l3']['proto']`` +* ``IP_src`` - refers to ``TRAFFIC['l3']['srcip']`` +* ``IP_dst`` - refers to ``TRAFFIC['l3']['dstip']`` +* ``IP_PROTO_sport`` - refers to ``TRAFFIC['l4']['srcport']`` +* ``IP_PROTO_dport`` - refers to ``TRAFFIC['l4']['dstport']`` +* ``Dot1Q_prio`` - refers to ``TRAFFIC['vlan']['priority']`` +* ``Dot1Q_id`` - refers to ``TRAFFIC['vlan']['cfi']`` +* ``Dot1Q_vlan`` - refers to ``TRAFFIC['vlan']['id']`` + +In following examples of SCAPY frame definition only relevant parts of TRAFFIC +dictionary are shown. The rest of the TRAFFIC dictionary is set to default values +as they are defined in ``conf/03_traffic.conf``. + +Please check official documentation of SCAPY project for details about SCAPY frame +definition and supported network layers at: http://www.secdev.org/projects/scapy + +#. Generate ICMP frames: + + .. code-block:: console + + 'scapy': { + 'enabled': True, + '0' : 'Ether(src={Ether_src}, dst={Ether_dst})/IP(proto="icmp", src={IP_src}, dst={IP_dst})/ICMP()', + '1' : 'Ether(src={Ether_dst}, dst={Ether_src})/IP(proto="icmp", src={IP_dst}, dst={IP_src})/ICMP()', + } + +#. Generate IPv6 ICMP Echo Request + + .. code-block:: console + + 'l3' : { + 'srcip': 'feed::01', + 'dstip': 'feed::02', + }, + 'scapy': { + 'enabled': True, + '0' : 'Ether(src={Ether_src}, dst={Ether_dst})/IPv6(src={IP_src}, dst={IP_dst})/ICMPv6EchoRequest()', + '1' : 'Ether(src={Ether_dst}, dst={Ether_src})/IPv6(src={IP_dst}, dst={IP_src})/ICMPv6EchoRequest()', + } + +#. Generate TCP frames: + + Example uses default SCAPY frame definition, which can reflect ``TRAFFIC['l3']['proto']`` settings. + + .. code-block:: console + + 'l3' : { + 'proto' : 'tcp', + }, + diff --git a/docs/testing/user/userguide/integration.rst b/docs/testing/user/userguide/integration.rst index 66808400..9d847fd8 100644 --- a/docs/testing/user/userguide/integration.rst +++ b/docs/testing/user/userguide/integration.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. .. _integration-tests: @@ -22,6 +22,12 @@ P2P (Physical to Physical scenarios). NOTE: The configuration for overlay tests provided in this guide is for unidirectional traffic only. +NOTE: The overlay tests require an IxNet traffic generator. The tunneled traffic +is configured by ``ixnetrfc2544v2.tcl`` script. This script can be used +with all supported deployment scenarios for generation of frames with VXLAN, GRE +or GENEVE protocols. In that case options "Tunnel Operation" and +"TRAFFICGEN_IXNET_TCL_SCRIPT" must be properly configured at testcase definition. + Executing Integration Tests --------------------------- @@ -63,8 +69,8 @@ the following variables in you user_settings.py file: VTEP_IP2_SUBNET = '192.168.240.0/24' # Bridge names - TUNNEL_INTEGRATION_BRIDGE = 'br0' - TUNNEL_EXTERNAL_BRIDGE = 'br-ext' + TUNNEL_INTEGRATION_BRIDGE = 'vsperf-br0' + TUNNEL_EXTERNAL_BRIDGE = 'vsperf-br-ext' # IP of br-ext TUNNEL_EXTERNAL_BRIDGE_IP = '192.168.240.1/24' diff --git a/docs/testing/user/userguide/testlist.rst b/docs/testing/user/userguide/testlist.rst index 2b0e9d7f..fe8c840a 100644 --- a/docs/testing/user/userguide/testlist.rst +++ b/docs/testing/user/userguide/testlist.rst @@ -68,14 +68,13 @@ vswitch_pvvp_tput vSwitch - configure switch, two chained v vswitch_pvvp_back2back vSwitch - configure switch, two chained vnfs and execute RFC2544 back2back test vswitch_pvvp_cont vSwitch - configure switch, two chained vnfs and execute RFC2544 continuous stream test vswitch_pvvp_all vSwitch - configure switch, two chained vnfs and execute all test types -vswitch_p4vp Just configure 4 chained vnfs -vswitch_p4vp_tput 4 chained vnfs, execute RFC2544 throughput test -vswitch_p4vp_back2back 4 chained vnfs, execute RFC2544 back2back test -vswitch_p4vp_cont 4 chained vnfs, execute RFC2544 continuous stream test -vswitch_p4vp_all 4 chained vnfs, execute RFC2544 throughput test -2pvp_udp_dest_flows RFC2544 Continuous TC with 2 Parallel VMs, flows on UDP Dest Port -4pvp_udp_dest_flows RFC2544 Continuous TC with 4 Parallel VMs, flows on UDP Dest Port -6pvp_udp_dest_flows RFC2544 Continuous TC with 6 Parallel VMs, flows on UDP Dest Port +vswitch_p4vp_tput 4 chained vnfs, execute RFC2544 throughput test, deployment pvvp4 +vswitch_p4vp_back2back 4 chained vnfs, execute RFC2544 back2back test, deployment pvvp4 +vswitch_p4vp_cont 4 chained vnfs, execute RFC2544 continuous stream test, deployment pvvp4 +vswitch_p4vp_all 4 chained vnfs, execute RFC2544 throughput tests, deployment pvvp4 +2pvp_udp_dest_flows RFC2544 Continuous TC with 2 Parallel VMs, flows on UDP Dest Port, deployment pvpv2 +4pvp_udp_dest_flows RFC2544 Continuous TC with 4 Parallel VMs, flows on UDP Dest Port, deployment pvpv4 +6pvp_udp_dest_flows RFC2544 Continuous TC with 6 Parallel VMs, flows on UDP Dest Port, deployment pvpv6 vhost_numa_awareness vSwitch DPDK - verify that PMD threads are served by the same NUMA slot as QEMU instances ixnet_pvp_tput_1nic PVP Scenario with 1 port towards IXIA vswitch_vports_add_del_connection_vpp VPP: vSwitch - configure switch with vports, add and delete connection @@ -388,3 +387,46 @@ ovsdpdk_qos_p2p In a p2p setup, ensure when a QoS egres ovsdpdk_qos_pvp In a pvp setup, ensure when a QoS egress policer is created that the traffic is limited to the specified rate. ======================================== ====================================================================================== + +Custom Statistics ++++++++++++++++++ + +A set of functional testcases for validation of Custom Statistics support by OVS. +This feature allows Custom Statistics to be accessed by VSPERF. + +These testcases require DPDK v17.11, the latest Open vSwitch(v2.9.90) +and the IxNet traffic-generator. + +======================================== ====================================================================================== +ovsdpdk_custstat_check Test if custom statistics are supported. +ovsdpdk_custstat_rx_error Test bad ethernet CRC counter 'rx_crc_errors' exposed by custom + statistics. + +======================================== ====================================================================================== + +T-Rex in VM TestCases +^^^^^^^^^^^^^^^^^^^^^ + +A set of functional testcases, which use T-Rex running in VM as a traffic generator. +These testcases require a VM image with T-Rex server installed. An example of such +image is a vloop-vnf image with T-Rex available for download at: + +http://artifacts.opnfv.org/vswitchperf/vnf/vloop-vnf-ubuntu-16.04_trex_20180209.qcow2 + +This image can be used for both T-Rex VM and loopback VM in ``vm2vm`` testcases. + +**NOTE:** The performance of T-Rex running inside the VM is lower if compared to T-Rex +execution on bare-metal. The user should perform a calibration of the VM maximum FPS +capability, to ensure this limitation is understood. + +======================================== ====================================================================================== +trex_vm_cont T-Rex VM - execute RFC2544 Continuous Stream from T-Rex VM and loop + it back through Open vSwitch. +trex_vm_tput T-Rex VM - execute RFC2544 Throughput from T-Rex VM and loop it back + through Open vSwitch. +trex_vm2vm_cont T-Rex VM2VM - execute RFC2544 Continuous Stream from T-Rex VM and + loop it back through 2nd VM. +trex_vm2vm_tput T-Rex VM2VM - execute RFC2544 Throughput from T-Rex VM and loop it back + through 2nd VM. + +======================================== ====================================================================================== diff --git a/docs/testing/user/userguide/teststeps.rst b/docs/testing/user/userguide/teststeps.rst index 08c95311..cb627bc5 100644 --- a/docs/testing/user/userguide/teststeps.rst +++ b/docs/testing/user/userguide/teststeps.rst @@ -23,6 +23,13 @@ the step number by one which is indicated in the log. (testcases.integration) - Step 0 'vswitch add_vport ['br0']' start +Test steps are defined as a list of steps within a ``TestSteps`` item of test +case definition. Each step is a list with following structure: + +.. code-block:: python + + '[' [ optional-alias ',' ] test-object ',' test-function [ ',' optional-function-params ] '],' + Step driven tests can be used for both performance and integration testing. In case of integration test, each step in the test case is validated. If a step does not pass validation the test will fail and terminate. The test will continue @@ -57,8 +64,14 @@ Step driven testcases can be used in two different ways: Test objects and their functions -------------------------------- -Every test step can call a function of one of the supported test objects. The list -of supported objects and their most common functions follows: +Every test step can call a function of one of the supported test objects. In general +any existing function of supported test object can be called by test step. In case +that step validation is required (valid for integration test steps, which are not +suppressed), then appropriate ``validate_`` method must be implemented. + +The list of supported objects and their most common functions is listed below. Please +check implementation of test objects for full list of implemented functions and their +parameters. * ``vswitch`` - provides functions for vSwitch configuration @@ -176,6 +189,8 @@ of supported objects and their most common functions follows: * ``getValue param`` - returns value of given ``param`` * ``setValue param value`` - sets value of ``param`` to given ``value`` + * ``resetValue param`` - if ``param`` was overridden by ``TEST_PARAMS`` (e.g. by "Parameters" + section of the test case definition), then it will be set to its original value. Examples: @@ -185,6 +200,8 @@ of supported objects and their most common functions follows: ['settings', 'setValue', 'GUEST_USERNAME', ['root']] + ['settings', 'resetValue', 'WHITELIST_NICS'], + It is possible and more convenient to access any VSPERF configuration option directly via ``$NAME`` notation. Option evaluation is done during runtime and vsperf will automatically translate it to the appropriate call of ``settings.getValue``. @@ -747,6 +764,8 @@ destination UDP port. ] }, +The same test can be written in a shorter form using "Deployment" : "pvpv". + To run the test: .. code-block:: console @@ -779,20 +798,20 @@ and available in both csv and rst report files. }, }, "TestSteps": [ - ['vswitch', 'add_vport', 'br0'], - ['vswitch', 'add_vport', 'br0'], + ['vswitch', 'add_vport', '$VSWITCH_BRIDGE_NAME'], + ['vswitch', 'add_vport', '$VSWITCH_BRIDGE_NAME'], # priority must be higher than default 32768, otherwise flows won't match - ['vswitch', 'add_flow', 'br0', + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '1', 'actions': ['output:#STEP[-2][1]'], 'idle_timeout': '0', 'dl_type':'0x0800', 'nw_proto':'17', 'tp_dst':'0', 'priority': '33000'}], - ['vswitch', 'add_flow', 'br0', + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '2', 'actions': ['output:#STEP[-2][1]'], 'idle_timeout': '0', 'dl_type':'0x0800', 'nw_proto':'17', 'tp_dst':'0', 'priority': '33000'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '#STEP[-4][1]', 'actions': ['output:1'], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '#STEP[-4][1]', 'actions': ['output:1'], 'idle_timeout': '0'}], - ['vswitch', 'add_flow', 'br0', {'in_port': '#STEP[-4][1]', 'actions': ['output:2'], + ['vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '#STEP[-4][1]', 'actions': ['output:2'], 'idle_timeout': '0'}], - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], ['vnf1', 'start'], ] }, diff --git a/docs/testing/user/userguide/testusage.rst b/docs/testing/user/userguide/testusage.rst index 20c30a40..c7cc1484 100644 --- a/docs/testing/user/userguide/testusage.rst +++ b/docs/testing/user/userguide/testusage.rst @@ -91,55 +91,41 @@ Using a custom settings file ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If your ``10_custom.conf`` doesn't reside in the ``./conf`` directory -of if you want to use an alternative configuration file, the file can +or if you want to use an alternative configuration file, the file can be passed to ``vsperf`` via the ``--conf-file`` argument. .. code-block:: console $ ./vsperf --conf-file <path_to_custom_conf> ... -Note that configuration passed in via the environment (``--load-env``) -or via another command line argument will override both the default and -your custom configuration files. This "priority hierarchy" can be -described like so (1 = max priority): - -1. Testcase definition section ``Parameters`` -2. Command line arguments -3. Environment variables -4. Configuration file(s) - -Further details about configuration files evaluation and special behaviour +Evaluation of configuration parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The value of configuration parameter can be specified at various places, +e.g. at the test case definition, inside configuration files, by the command +line argument, etc. Thus it is important to understand the order of configuration +parameter evaluation. This "priority hierarchy" can be described like so +(1 = max priority): + +1. Testcase definition keywords ``vSwitch``, ``Trafficgen``, ``VNF`` and ``Tunnel Type`` +2. Parameters inside testcase definition section ``Parameters`` +3. Command line arguments (e.g. ``--test-params``, ``--vswitch``, ``--trafficgen``, etc.) +4. Environment variables (see ``--load-env`` argument) +5. Custom configuration file specified via ``--conf-file`` argument +6. Standard configuration files, where higher prefix number means higher + priority. + +For example, if the same configuration parameter is defined in custom configuration +file (specified via ``--conf-file`` argument), via ``--test-params`` argument +and also inside ``Parameters`` section of the testcase definition, then parameter +value from the ``Parameters`` section will be used. + +Further details about order of configuration files evaluation and special behaviour of options with ``GUEST_`` prefix could be found at :ref:`design document <design-configuration>`. .. _overriding-parameters-documentation: -Referencing parameter values -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It is possible to use a special macro ``#PARAM()`` to refer to the value of -another configuration parameter. This reference is evaluated during -access of the parameter value (by ``settings.getValue()`` call), so it -can refer to parameters created during VSPERF runtime, e.g. NICS dictionary. -It can be used to reflect DUT HW details in the testcase definition. - -Example: - -.. code:: python - - { - ... - "Name": "testcase", - "Parameters" : { - "TRAFFIC" : { - 'l2': { - # set destination MAC to the MAC of the first - # interface from WHITELIST_NICS list - 'dstmac' : '#PARAM(NICS[0]["mac"])', - }, - }, - ... - Overriding values defined in configuration files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -155,6 +141,17 @@ Example: $ ./vsperf --test-params "TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,);" \ "GUEST_LOOPBACK=['testpmd','l2fwd']" pvvp_tput +The ``--test-params`` command line argument can also be used to override default +configuration values for multiple tests. Providing a list of parameters will apply each +element of the list to the test with the same index. If more tests are run than +parameters provided the last element of the list will repeat. + +.. code:: console + + $ ./vsperf --test-params "['TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,)'," + "'TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(64,)']" \ + pvvp_tput pvvp_tput + The second option is to override configuration items by ``Parameters`` section of the test case definition. The configuration items can be added into ``Parameters`` dictionary with their new values. These values will override values defined in @@ -186,6 +183,36 @@ parameter name is passed via ``--test-params`` CLI argument or defined in ``Para section of test case definition. It is also forbidden to redefine a value of ``TEST_PARAMS`` configuration item via CLI or ``Parameters`` section. +**NOTE:** The new definition of the dictionary parameter, specified via ``--test-params`` +or inside ``Parameters`` section, will not override original dictionary values. Instead +the original dictionary will be updated with values from the new dictionary definition. + +Referencing parameter values +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is possible to use a special macro ``#PARAM()`` to refer to the value of +another configuration parameter. This reference is evaluated during +access of the parameter value (by ``settings.getValue()`` call), so it +can refer to parameters created during VSPERF runtime, e.g. NICS dictionary. +It can be used to reflect DUT HW details in the testcase definition. + +Example: + +.. code:: python + + { + ... + "Name": "testcase", + "Parameters" : { + "TRAFFIC" : { + 'l2': { + # set destination MAC to the MAC of the first + # interface from WHITELIST_NICS list + 'dstmac' : '#PARAM(NICS[0]["mac"])', + }, + }, + ... + vloop_vnf ^^^^^^^^^ @@ -205,6 +232,12 @@ A Kernel Module that provides OSI Layer 2 Ipv4 termination or forwarding with support for Destination Network Address Translation (DNAT) for both the MAC and IP addresses. l2fwd can be found in <vswitchperf_dir>/src/l2fwd +Additional Tools Setup +^^^^^^^^^^^^^^^^^^^^^^ + +Follow the `Additional tools instructions <additional-tools-configuration>` to +install and configure additional tools such as collectors and loadgens. + Executing tests ^^^^^^^^^^^^^^^ @@ -234,6 +267,12 @@ To run a single test: Where $TESTNAME is the name of the vsperf test you would like to run. +To run a test multiple times, repeat it: + +.. code-block:: console + + $ ./vsperf $TESTNAME $TESTNAME $TESTNAME + To run a group of tests, for example all tests with a name containing 'RFC2544': @@ -256,6 +295,30 @@ Some tests allow for configurable parameters, including test duration --tests RFC2544Tput \ --test-params "TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,)" +To specify configurable parameters for multiple tests, use a list of +parameters. One element for each test. + +.. code:: console + + $ ./vsperf --conf-file user_settings.py \ + --test-params "['TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,)',"\ + "'TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(64,)']" \ + phy2phy_cont phy2phy_cont + +If the ``CUMULATIVE_PARAMS`` setting is set to True and there are different parameters +provided for each test using ``--test-params``, each test will take the parameters of +the previous test before appyling it's own. +With ``CUMULATIVE_PARAMS`` set to True the following command will be equivalent to the +previous example: + +.. code:: console + + $ ./vsperf --conf-file user_settings.py \ + --test-params "['TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,)',"\ + "'TRAFFICGEN_PKT_SIZES=(64,)']" \ + phy2phy_cont phy2phy_cont + " + For all available options, check out the help dialog: .. code-block:: console @@ -584,7 +647,7 @@ The supported dpdk guest bind drivers are: .. code-block:: console - 'uio_pci_generic' - Use uio_pci_generic driver + 'uio_pci_generic' - Use uio_pci_generic driver 'igb_uio_from_src' - Build and use the igb_uio driver from the dpdk src files 'vfio_no_iommu' - Use vfio with no iommu option. This requires custom @@ -915,6 +978,39 @@ Example of execution of VSPERF in "trafficgen" mode: $ ./vsperf -m trafficgen --trafficgen IxNet --conf-file vsperf.conf \ --test-params "TRAFFIC={'traffic_type':'rfc2544_continuous','bidir':'False','framerate':60}" +Performance Matrix +^^^^^^^^^^^^^^^^^^ + +The ``--matrix`` command line argument analyses and displays the performance of +all the tests run. Using the metric specified by ``MATRIX_METRIC`` in the conf-file, +the first test is set as the baseline and all the other tests are compared to it. +The ``MATRIX_METRIC`` must always refer to a numeric value to enable comparision. +A table, with the test ID, metric value, the change of the metric in %, testname +and the test parameters used for each test, is printed out as well as saved into the +results directory. + +Example of 2 tests being compared using Performance Matrix: + +.. code-block:: console + + $ ./vsperf --conf-file user_settings.py \ + --test-params "['TRAFFICGEN_PKT_SIZES=(64,)',"\ + "'TRAFFICGEN_PKT_SIZES=(128,)']" \ + phy2phy_cont phy2phy_cont --matrix + +Example output: + +.. code-block:: console + + +------+--------------+---------------------+----------+---------------------------------------+ + | ID | Name | throughput_rx_fps | Change | Parameters, CUMULATIVE_PARAMS = False | + +======+==============+=====================+==========+=======================================+ + | 0 | phy2phy_cont | 23749000.000 | 0 | 'TRAFFICGEN_PKT_SIZES': [64] | + +------+--------------+---------------------+----------+---------------------------------------+ + | 1 | phy2phy_cont | 16850500.000 | -29.048 | 'TRAFFICGEN_PKT_SIZES': [128] | + +------+--------------+---------------------+----------+---------------------------------------+ + + Code change verification by pylint ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/testing/user/userguide/trafficcapture.rst b/docs/testing/user/userguide/trafficcapture.rst index fa09bfed..8a224dcb 100644 --- a/docs/testing/user/userguide/trafficcapture.rst +++ b/docs/testing/user/userguide/trafficcapture.rst @@ -92,9 +92,9 @@ An example of Traffic Capture in VM test: }, TestSteps: [ # replace original flows with vlan ID modification - ['!vswitch', 'add_flow', 'br0', {'in_port': '1', 'actions': ['mod_vlan_vid:4','output:3']}], - ['!vswitch', 'add_flow', 'br0', {'in_port': '2', 'actions': ['mod_vlan_vid:4','output:4']}], - ['vswitch', 'dump_flows', 'br0'], + ['!vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '1', 'actions': ['mod_vlan_vid:4','output:3']}], + ['!vswitch', 'add_flow', '$VSWITCH_BRIDGE_NAME', {'in_port': '2', 'actions': ['mod_vlan_vid:4','output:4']}], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], # verify that received frames have modified vlan ID ['VNF0', 'execute_and_wait', 'tcpdump -i eth0 -c 5 -w dump.pcap vlan 4 &'], ['trafficgen', 'send_traffic',{}], @@ -199,7 +199,7 @@ An example of Traffic Capture for testing NICs with HW offloading test: ['tools', 'exec_shell_background', 'tcpdump -i [2][device] -c 5 -w capture.pcap ' 'ether src [l2][srcmac]'], ['trafficgen', 'send_traffic', {}], - ['vswitch', 'dump_flows', 'br0'], + ['vswitch', 'dump_flows', '$VSWITCH_BRIDGE_NAME'], ['vswitch', 'dump_flows', 'br1'], # there must be 5 captured frames... ['tools', 'exec_shell', 'tcpdump -r capture.pcap | wc -l', '|^(\d+)$'], @@ -76,7 +76,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=E1602,E1603,E1601,E1606,E1607,E1604,E1605,E1608,W0401,W1604,W1605,W1606,W1607,W1601,W1602,W1603,W1622,W1623,W1620,W1621,W1608,W1609,W1624,W1625,W1618,W1626,W1627,I0021,I0020,W0704,R0903,W1613,W1638,W1611,W1610,W1617,W1616,W1615,W1614,W1630,W1619,W1632,W1635,W1634,W1637,W1636,W1639,W1612,W1628,W1633,W1629,I0011,W1640 +disable=E1602,E1603,E1601,E1606,E1607,E1604,E1605,E1608,W0401,W1604,W1605,W1606,W1607,W1601,W1602,W1603,W1622,W1623,W1620,W1621,W1608,W1609,W1624,W1625,W1618,W1626,W1627,I0021,I0020,W0704,R0903,W1613,W1638,W1611,W1610,W1617,W1616,W1615,W1614,W1630,W1619,W1632,W1635,W1634,W1637,W1636,W1639,W1612,W1628,W1633,W1629,I0011,W1640,R1705 [REPORTS] diff --git a/requirements.txt b/requirements.txt index 3a366d70..fdcff13b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,9 +12,11 @@ xmlrunner==1.7.7 requests==2.8.1 netaddr==0.7.18 scapy-python3==0.18 +pylint==1.8.2 pyzmq==14.5.0 distro stcrestclient matplotlib numpy pycrypto +tabulate diff --git a/src/__init__.py b/src/__init__.py index 9293b4f8..c784ea3c 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -18,4 +18,3 @@ No functionality is expected for this package and its purpose is just to keep Python package structure intact without extra requirements for PYTHONPATH. """ - diff --git a/src/dpdk/dpdk.py b/src/dpdk/dpdk.py index 2f120129..c2e656ef 100644 --- a/src/dpdk/dpdk.py +++ b/src/dpdk/dpdk.py @@ -140,7 +140,7 @@ def _vhost_user_cleanup(): def _bind_nics(): """Bind NICs using the bind tool specified in the configuration. """ - if not len(_NICS_PCI): + if not _NICS_PCI: _LOGGER.info('NICs are not configured - nothing to bind') return try: @@ -171,7 +171,7 @@ def _bind_nics(): def _unbind_nics(): """Unbind NICs using the bind tool specified in the configuration. """ - if not len(_NICS_PCI): + if not _NICS_PCI: _LOGGER.info('NICs are not configured - nothing to unbind') return try: diff --git a/src/ovs/dpctl.py b/src/ovs/dpctl.py index 015fb38c..5030223e 100644 --- a/src/ovs/dpctl.py +++ b/src/ovs/dpctl.py @@ -60,5 +60,5 @@ class DPCtl(object): :return: None """ - self.logger.debug('delete datapath ' + dp_name) + self.logger.debug('delete datapath %s', dp_name) self.run_dpctl(['del-dp', dp_name]) diff --git a/src/ovs/ofctl.py b/src/ovs/ofctl.py index 64d54466..21da850a 100644 --- a/src/ovs/ofctl.py +++ b/src/ovs/ofctl.py @@ -25,10 +25,10 @@ import re import netaddr from tools import tasks -from conf import settings +from conf import settings as S -_OVS_BRIDGE_NAME = settings.getValue('VSWITCH_BRIDGE_NAME') -_OVS_CMD_TIMEOUT = settings.getValue('OVS_CMD_TIMEOUT') +_OVS_BRIDGE_NAME = S.getValue('VSWITCH_BRIDGE_NAME') +_OVS_CMD_TIMEOUT = S.getValue('OVS_CMD_TIMEOUT') _CACHE_FILE_NAME = '/tmp/vsperf_flows_cache' @@ -62,9 +62,11 @@ class OFBase(object): :return: None """ if self.timeout == -1: - cmd = ['sudo', settings.getValue('TOOLS')['ovs-vsctl'], '--no-wait'] + args + cmd = ['sudo', S.getValue('TOOLS')['ovs-vsctl'], '--no-wait'] + \ + S.getValue('OVS_VSCTL_ARGS') + args else: - cmd = ['sudo', settings.getValue('TOOLS')['ovs-vsctl'], '--timeout', str(self.timeout)] + args + cmd = ['sudo', S.getValue('TOOLS')['ovs-vsctl'], '--timeout', + str(self.timeout)] + S.getValue('OVS_VSCTL_ARGS') + args return tasks.run_task( cmd, self.logger, 'Running ovs-vsctl...', check_error) @@ -77,9 +79,9 @@ class OFBase(object): :return: None """ - cmd = ['sudo', settings.getValue('TOOLS')['ovs-appctl'], + cmd = ['sudo', S.getValue('TOOLS')['ovs-appctl'], '--timeout', - str(self.timeout)] + args + str(self.timeout)] + S.getValue('OVS_APPCTL_ARGS') + args return tasks.run_task( cmd, self.logger, 'Running ovs-appctl...', check_error) @@ -154,21 +156,6 @@ class OFBridge(OFBase): self._ports = {} self._cache_file = None - # context manager - - def __enter__(self): - """Create datapath - - :returns: self - """ - return self - - def __exit__(self, type_, value, traceback): - """Remove datapath. - """ - if not traceback: - self.destroy() - # helpers def run_ofctl(self, args, check_error=False, timeout=None): @@ -180,8 +167,8 @@ class OFBridge(OFBase): :return: None """ tmp_timeout = self.timeout if timeout is None else timeout - cmd = ['sudo', settings.getValue('TOOLS')['ovs-ofctl'], '-O', - 'OpenFlow13', '--timeout', str(tmp_timeout)] + args + cmd = ['sudo', S.getValue('TOOLS')['ovs-ofctl'], '--timeout', + str(tmp_timeout)] + S.getValue('OVS_OFCTL_ARGS') + args return tasks.run_task( cmd, self.logger, 'Running ovs-ofctl...', check_error) @@ -467,4 +454,4 @@ def flow_match(flow_dump, flow_src): for rule in flow_src_list: if rule in flow_dump_list: flow_src_ctrl.remove(rule) - return True if not len(flow_src_ctrl) else False + return True if not flow_src_ctrl else False diff --git a/src/package-list.mk b/src/package-list.mk index 7b82ee6f..d32a9ffd 100644 --- a/src/package-list.mk +++ b/src/package-list.mk @@ -29,4 +29,4 @@ QEMU_TAG ?= v2.9.1 # TREX section TREX_URL ?= https://github.com/cisco-system-traffic-generator/trex-core.git -TREX_TAG ?= 8bf9c16556843e55c232b64d9a5061bf588fad42 +TREX_TAG ?= v2.38 diff --git a/src/trex/Makefile b/src/trex/Makefile index 41eb52ab..9a0704af 100644 --- a/src/trex/Makefile +++ b/src/trex/Makefile @@ -29,6 +29,8 @@ all: force_pull force_pull: $(TAG_DONE_FLAG) $(AT)cd $(WORK_DIR) && git pull $(TREX_URL) $(TREX_TAG) @echo "git pull done" + $(AT)wget https://raw.githubusercontent.com/phaethon/scapy/v0.18/scapy/layers/all.py -O $(WORK_DIR)/scripts/external_libs/scapy-2.3.1/python3/scapy/layers/all.py + @echo "orignal SCAPY 2.3.1 layers/all.py was restored" $(WORK_DIR): $(AT)git clone $(TREX_URL) $(WORK_DIR) diff --git a/systems/centos/build_base_machine.sh b/systems/centos/build_base_machine.sh index f2efb541..95f9e211 100755 --- a/systems/centos/build_base_machine.sh +++ b/systems/centos/build_base_machine.sh @@ -46,6 +46,7 @@ automake pciutils cifs-utils sysstat +sshpass # libs libpcap-devel @@ -60,6 +61,8 @@ pixman-devel socat numactl numactl-devel +libpng-devel +freetype-devel # install gvim vim-X11 @@ -68,13 +71,13 @@ vim-X11 epel-release " | grep -v ^#) -# install SCL for python33 -sudo yum -y install centos-release-scl +# install SCL for python34 +sudo yum -y install centos-release-scl-rh -# install python33 packages and git-review tool +# install python34 packages and git-review tool yum -y install $(echo " -python33 -python33-python-tkinter +rh-python34 +rh-python34-python-tkinter git-review " | grep -v ^#) # prevent ovs vanilla from building from source due to kernel incompatibilities diff --git a/systems/centos/prepare_python_env.sh b/systems/centos/prepare_python_env.sh index 8bce53cc..108ba1f6 100755 --- a/systems/centos/prepare_python_env.sh +++ b/systems/centos/prepare_python_env.sh @@ -21,9 +21,8 @@ if [ -d "$VSPERFENV_DIR" ] ; then exit fi -scl enable python33 " -virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 +scl enable rh-python34 " +virtualenv "$VSPERFENV_DIR" --python /opt/rh/rh-python34/root/usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint " diff --git a/systems/fedora/24/build_base_machine.sh b/systems/fedora/24/build_base_machine.sh index 2aceb34f..bbde9b77 100644 --- a/systems/fedora/24/build_base_machine.sh +++ b/systems/fedora/24/build_base_machine.sh @@ -48,6 +48,7 @@ pciutils cifs-utils socat sysstat +sshpass # install python packages python3 diff --git a/systems/fedora/24/prepare_python_env.sh b/systems/fedora/24/prepare_python_env.sh index 920604c2..bc93f703 100644 --- a/systems/fedora/24/prepare_python_env.sh +++ b/systems/fedora/24/prepare_python_env.sh @@ -25,5 +25,4 @@ fi (virtualenv-3.5 "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate -pip install -r ../requirements.txt -pip install pylint) +pip install -r ../requirements.txt) diff --git a/systems/fedora/25/build_base_machine.sh b/systems/fedora/25/build_base_machine.sh index 241b79cb..df8ae620 100644 --- a/systems/fedora/25/build_base_machine.sh +++ b/systems/fedora/25/build_base_machine.sh @@ -48,6 +48,7 @@ pciutils cifs-utils socat sysstat +sshpass # install python packages python3 diff --git a/systems/fedora/25/prepare_python_env.sh b/systems/fedora/25/prepare_python_env.sh index c4613ca4..b5df11ee 100644 --- a/systems/fedora/25/prepare_python_env.sh +++ b/systems/fedora/25/prepare_python_env.sh @@ -26,5 +26,4 @@ fi (virtualenv-3.5 "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint pip install six) diff --git a/systems/fedora/26/build_base_machine.sh b/systems/fedora/26/build_base_machine.sh index b8b65965..84c0695b 100644 --- a/systems/fedora/26/build_base_machine.sh +++ b/systems/fedora/26/build_base_machine.sh @@ -48,6 +48,7 @@ pciutils cifs-utils socat sysstat +sshpass # install python packages python3 diff --git a/systems/fedora/26/prepare_python_env.sh b/systems/fedora/26/prepare_python_env.sh index 05eedfd9..4db2eaed 100644 --- a/systems/fedora/26/prepare_python_env.sh +++ b/systems/fedora/26/prepare_python_env.sh @@ -26,5 +26,4 @@ fi (virtualenv-3.6 "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint pip install six) diff --git a/systems/opensuse/42.2/build_base_machine.sh b/systems/opensuse/42.2/build_base_machine.sh index 44d6f02b..9915b634 100755 --- a/systems/opensuse/42.2/build_base_machine.sh +++ b/systems/opensuse/42.2/build_base_machine.sh @@ -49,6 +49,7 @@ socat sysstat java-1_8_0-openjdk git-review +sshpass # python python3 diff --git a/systems/opensuse/42.2/prepare_python_env.sh b/systems/opensuse/42.2/prepare_python_env.sh index ab668ca4..a563740a 100755 --- a/systems/opensuse/42.2/prepare_python_env.sh +++ b/systems/opensuse/42.2/prepare_python_env.sh @@ -24,5 +24,4 @@ fi virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint diff --git a/systems/opensuse/42.3/build_base_machine.sh b/systems/opensuse/42.3/build_base_machine.sh index cc9f24ef..2124e6cb 100755 --- a/systems/opensuse/42.3/build_base_machine.sh +++ b/systems/opensuse/42.3/build_base_machine.sh @@ -50,6 +50,7 @@ sysstat java-1_8_0-openjdk git-review mlocate +sshpass # python python3 diff --git a/systems/opensuse/42.3/prepare_python_env.sh b/systems/opensuse/42.3/prepare_python_env.sh index ab668ca4..a563740a 100755 --- a/systems/opensuse/42.3/prepare_python_env.sh +++ b/systems/opensuse/42.3/prepare_python_env.sh @@ -24,5 +24,4 @@ fi virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint diff --git a/systems/opensuse/prepare_python_env.sh b/systems/opensuse/prepare_python_env.sh index 69871670..6ac196f0 100755 --- a/systems/opensuse/prepare_python_env.sh +++ b/systems/opensuse/prepare_python_env.sh @@ -24,5 +24,4 @@ fi virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint diff --git a/systems/rhel/7.2/build_base_machine.sh b/systems/rhel/7.2/build_base_machine.sh index 9eb8bbd2..198f39d7 100755 --- a/systems/rhel/7.2/build_base_machine.sh +++ b/systems/rhel/7.2/build_base_machine.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Build a base machine for RHEL 7.2 +# Build a base machine for RHEL 7.3 # # Copyright 2016 OPNFV, Intel Corporation & Red Hat Inc. # @@ -52,6 +52,8 @@ pkglist=( wget\ numactl\ numactl-devel\ + libpng-devel\ + sshpass\ ) # python tools for proper QEMU, DPDK, and OVS make @@ -60,6 +62,9 @@ pkglist=( python-six\ ) +# install RHEL compatible epel for sshpass +yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + # Iterate installing each package. If packages fail to install, record those # packages and exit with an error message on completion. Customer may need to # add repo locations and subscription levels. @@ -78,28 +83,24 @@ if [ "${#failedinstall[*]}" -gt 0 ]; then exit 1 fi -# install SCL for python33 by adding a repo to find its location to install it -cat <<'EOT' >> /etc/yum.repos.d/python33.repo -[rhscl-python33-el7] -name=Copr repo for python33-el7 owned by rhscl -baseurl=https://copr-be.cloud.fedoraproject.org/results/rhscl/python33-el7/epel-7-$basearch/ -type=rpm-md -skip_if_unavailable=True -gpgcheck=1 -gpgkey=https://copr-be.cloud.fedoraproject.org/results/rhscl/python33-el7/pubkey.gpg -repo_gpgcheck=0 +# install SCL for python34 by adding a repo to find its location to install it +cat <<'EOT' >> /etc/yum.repos.d/python34.repo +[centos-sclo-rh] +name=CentOS-7 - SCLo rh +baseurl=http://mirror.centos.org/centos/7/sclo/$basearch/rh/ +gpgcheck=0 enabled=1 -enabled_metadata=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-SCLo EOT -# install python33 packages and git-review tool +# install python34 packages and git-review tool yum -y install $(echo " -python33 -python33-python-tkinter +rh-python34 +rh-python34-python-tkinter " | grep -v ^#) -# cleanup python 33 repo file -rm -f /etc/yum.repos.d/python33.repo +# cleanup python 34 repo file +rm -f /etc/yum.repos.d/python34.repo # Create hugepage dirs mkdir -p /dev/hugepages diff --git a/systems/rhel/7.2/prepare_python_env.sh b/systems/rhel/7.2/prepare_python_env.sh index fb5882f1..047d6961 100755 --- a/systems/rhel/7.2/prepare_python_env.sh +++ b/systems/rhel/7.2/prepare_python_env.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Prepare Python environment for vsperf execution on Red Hat 7.2 systems. +# Prepare Python environment for vsperf execution on RHEL 7.3 systems. # # Copyright 2016-2017 OPNFV, Intel Corporation, Red Hat Inc. # @@ -21,9 +21,8 @@ if [ -d "$VSPERFENV_DIR" ] ; then exit fi -scl enable python33 " -virtualenv "$VSPERFENV_DIR" --python /opt/rh/python33/root/usr/bin/python3 +scl enable rh-python34 " +virtualenv "$VSPERFENV_DIR" --python /opt/rh/rh-python34/root/usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint -"
\ No newline at end of file +" diff --git a/systems/rhel/7.3/build_base_machine.sh b/systems/rhel/7.3/build_base_machine.sh index 5a9b4b2e..ae527214 100755 --- a/systems/rhel/7.3/build_base_machine.sh +++ b/systems/rhel/7.3/build_base_machine.sh @@ -52,6 +52,8 @@ pkglist=( wget\ numactl\ numactl-devel\ + libpng-devel\ + sshpass\ ) # python tools for proper QEMU, DPDK, and OVS make @@ -60,6 +62,9 @@ pkglist=( python-six\ ) +# install RHEL compatible epel for sshpass +yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + # Iterate installing each package. If packages fail to install, record those # packages and exit with an error message on completion. Customer may need to # add repo locations and subscription levels. @@ -78,31 +83,27 @@ if [ "${#failedinstall[*]}" -gt 0 ]; then exit 1 fi -# install SCL for python33 by adding a repo to find its location to install it -cat <<'EOT' >> /etc/yum.repos.d/python33.repo -[rhscl-python33-el7] -name=Copr repo for python33-el7 owned by rhscl -baseurl=https://copr-be.cloud.fedoraproject.org/results/rhscl/python33-el7/epel-7-$basearch/ -type=rpm-md -skip_if_unavailable=True -gpgcheck=1 -gpgkey=https://copr-be.cloud.fedoraproject.org/results/rhscl/python33-el7/pubkey.gpg -repo_gpgcheck=0 +# install SCL for python34 by adding a repo to find its location to install it +cat <<'EOT' >> /etc/yum.repos.d/python34.repo +[centos-sclo-rh] +name=CentOS-7 - SCLo rh +baseurl=http://mirror.centos.org/centos/7/sclo/$basearch/rh/ +gpgcheck=0 enabled=1 -enabled_metadata=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-SCLo EOT -# install python33 packages and git-review tool +# install python34 packages and git-review tool yum -y install $(echo " -python33 -python33-python-tkinter +rh-python34 +rh-python34-python-tkinter " | grep -v ^#) -# cleanup python 33 repo file -rm -f /etc/yum.repos.d/python33.repo +# cleanup python 34 repo file +rm -f /etc/yum.repos.d/python34.repo # Create hugepage dirs mkdir -p /dev/hugepages # prevent ovs vanilla from building from source due to kernel incompatibilities -sed -i s/'SUBBUILDS = src_vanilla'/'#SUBBUILDS = src_vanilla'/ ../src/Makefile
\ No newline at end of file +sed -i s/'SUBBUILDS = src_vanilla'/'#SUBBUILDS = src_vanilla'/ ../src/Makefile diff --git a/systems/rhel/7.3/prepare_python_env.sh b/systems/rhel/7.3/prepare_python_env.sh index b573bb9f..047d6961 100755 --- a/systems/rhel/7.3/prepare_python_env.sh +++ b/systems/rhel/7.3/prepare_python_env.sh @@ -21,9 +21,8 @@ if [ -d "$VSPERFENV_DIR" ] ; then exit fi -scl enable python33 " -virtualenv "$VSPERFENV_DIR" --python /opt/rh/python33/root/usr/bin/python3 +scl enable rh-python34 " +virtualenv "$VSPERFENV_DIR" --python /opt/rh/rh-python34/root/usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint -"
\ No newline at end of file +" diff --git a/systems/sles/15/build_base_machine.sh b/systems/sles/15/build_base_machine.sh index 9c161dd7..166fe649 100755 --- a/systems/sles/15/build_base_machine.sh +++ b/systems/sles/15/build_base_machine.sh @@ -20,6 +20,7 @@ # Jose Lausuch, SUSE LINUX GmbH zypper -q -n dup +zypper ar -G http://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15/standard/ backports zypper -q -n in -y $(echo " # compiler, tools and dependencies make @@ -32,7 +33,6 @@ fuse fuse-devel glib2-devel zlib-devel -ncurses-devel kernel-default kernel-default-devel pkg-config @@ -47,7 +47,7 @@ pciutils cifs-utils socat sysstat -java-9-openjdk +java-10-openjdk mlocate # python @@ -65,14 +65,16 @@ libpixman-1-0-devel libtool libpcap-devel libnet9 -libncurses5 +libncurses6 libcurl4 libcurl-devel libxml2 libfuse2 -libopenssl1_1_0 +libopenssl1_1 libopenssl-devel libpython3_6m1_0 +libzmq5 +sshpass " | grep -v ^#) diff --git a/systems/sles/15/prepare_python_env.sh b/systems/sles/15/prepare_python_env.sh index 12ada3cc..18b0e545 100755 --- a/systems/sles/15/prepare_python_env.sh +++ b/systems/sles/15/prepare_python_env.sh @@ -24,5 +24,4 @@ fi virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate pip install -r ../requirements.txt -pip install pylint diff --git a/systems/ubuntu/14.04/build_base_machine.sh b/systems/ubuntu/14.04/build_base_machine.sh index 04f4a7e1..a0e6895c 100755 --- a/systems/ubuntu/14.04/build_base_machine.sh +++ b/systems/ubuntu/14.04/build_base_machine.sh @@ -62,6 +62,7 @@ socat libpixman-1-0 libpixman-1-dev sysstat +sshpass # Java runtime environment: Required for Ixia TclClient default-jre diff --git a/systems/ubuntu/14.04/prepare_python_env.sh b/systems/ubuntu/14.04/prepare_python_env.sh index 4c98dc42..f3d92dce 100755 --- a/systems/ubuntu/14.04/prepare_python_env.sh +++ b/systems/ubuntu/14.04/prepare_python_env.sh @@ -25,5 +25,4 @@ fi (virtualenv "$VSPERFENV_DIR" --python /usr/bin/python3 source "$VSPERFENV_DIR"/bin/activate -pip install -r ../requirements.txt -pip install pylint) +pip install -r ../requirements.txt) diff --git a/systems/ubuntu/build_base_machine.sh b/systems/ubuntu/build_base_machine.sh index 1b42a790..2f3e7b25 100755 --- a/systems/ubuntu/build_base_machine.sh +++ b/systems/ubuntu/build_base_machine.sh @@ -46,6 +46,7 @@ apt-get -y install libglib2.0 apt-get -y install libfuse-dev apt-get -y install libnuma1 apt-get -y install libnuma-dev +apt-get -y install sshpass # Some useful tools you may optionally install #apt-get -y install ctags diff --git a/testcases/integration.py b/testcases/integration.py index f87a8ee2..8cfe5af5 100644 --- a/testcases/integration.py +++ b/testcases/integration.py @@ -17,7 +17,7 @@ import logging from collections import OrderedDict -from testcases import TestCase +from testcases.testcase import TestCase class IntegrationTestCase(TestCase): """IntegrationTestCase class diff --git a/testcases/performance.py b/testcases/performance.py index a82b5d1c..1b67911e 100644 --- a/testcases/performance.py +++ b/testcases/performance.py @@ -16,7 +16,7 @@ import logging -from testcases import TestCase +from testcases.testcase import TestCase from tools.report import report class PerformanceTestCase(TestCase): diff --git a/testcases/testcase.py b/testcases/testcase.py index 5d4a6ea9..a30558ff 100644 --- a/testcases/testcase.py +++ b/testcases/testcase.py @@ -1,4 +1,4 @@ -# Copyright 2015-2017 Intel Corporation. +# Copyright 2015-2018 Intel Corporation, Tieto and others. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import subprocess from datetime import datetime as dt from conf import settings as S -from conf import get_test_param, merge_spec +from conf import merge_spec import core.component_factory as component_factory from core.loader import Loader from core.results.results_constants import ResultsConstants @@ -38,8 +38,17 @@ from tools import veth from tools.teststepstools import TestStepsTools from tools.llc_management import rmd +# Validation methods required for integration TCs will have following prefix before the name +# of original method. CHECK_PREFIX = 'validate_' +# Several parameters can be defined by both TC definition keywords and configuration parameters. +# Following mapping table is used to correctly evaluate priority of testcase configuration, where +# TC definition keywords (i.e. mapping table keys) have higher priority than appropriate TC +# parameters (i.e. mapping table values). TC parameters can be defined within "Parameters" +# section, via CLI parameters or within configuration files. +MAPPING_TC_CFG2CONF = {'vSwitch':'VSWITCH', 'VNF':'VNF', 'Trafficgen':'TRAFFICGEN', 'Tunnel Type':'TUNNEL_TYPE'} + # pylint: disable=too-many-instance-attributes class TestCase(object): """TestCase base class @@ -85,9 +94,16 @@ class TestCase(object): S.setValue('VSWITCH', cfg.get('vSwitch', S.getValue('VSWITCH'))) S.setValue('VNF', cfg.get('VNF', S.getValue('VNF'))) S.setValue('TRAFFICGEN', cfg.get('Trafficgen', S.getValue('TRAFFICGEN'))) + S.setValue('TUNNEL_TYPE', cfg.get('Tunnel Type', S.getValue('TUNNEL_TYPE'))) test_params = copy.deepcopy(S.getValue('TEST_PARAMS')) tc_test_params = cfg.get('Parameters', S.getValue('TEST_PARAMS')) test_params = merge_spec(test_params, tc_test_params) + + # ensure that parameters from TC definition have the highest priority, see MAPPING_TC_CFG2CONF + for (cfg_param, param) in MAPPING_TC_CFG2CONF.items(): + if cfg_param in cfg and param in test_params: + del test_params[param] + S.setValue('TEST_PARAMS', test_params) S.check_test_params() @@ -125,16 +141,7 @@ class TestCase(object): self.deployment = cfg['Deployment'] self._frame_mod = cfg.get('Frame Modification', None) - self._tunnel_type = None - self._tunnel_operation = None - - if self.deployment == 'op2p': - self._tunnel_operation = cfg['Tunnel Operation'] - - if 'Tunnel Type' in cfg: - self._tunnel_type = cfg['Tunnel Type'] - self._tunnel_type = get_test_param('TUNNEL_TYPE', - self._tunnel_type) + self._tunnel_operation = cfg.get('Tunnel Operation', None) # check if test requires background load and which generator it uses self._load_cfg = cfg.get('Load', None) @@ -145,16 +152,14 @@ class TestCase(object): # set traffic details, so they can be passed to vswitch and traffic ctls self._traffic = copy.deepcopy(S.getValue('TRAFFIC')) - self._traffic.update({'bidir': bidirectional, - 'tunnel_type': self._tunnel_type,}) - - self._traffic = functions.check_traffic(self._traffic) + self._traffic.update({'bidir': bidirectional}) # Packet Forwarding mode self._vswitch_none = str(S.getValue('VSWITCH')).strip().lower() == 'none' # trafficgen configuration required for tests of tunneling protocols - if self.deployment == "op2p": + if self._tunnel_operation: + self._traffic.update({'tunnel_type': S.getValue('TUNNEL_TYPE')}) self._traffic['l2'].update({'srcmac': S.getValue('TRAFFICGEN_PORT1_MAC'), 'dstmac': @@ -166,9 +171,9 @@ class TestCase(object): S.getValue('TRAFFICGEN_PORT2_IP')}) if self._tunnel_operation == "decapsulation": - self._traffic['l2'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L2') - self._traffic['l3'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L3') - self._traffic['l4'] = S.getValue(self._tunnel_type.upper() + '_FRAME_L4') + self._traffic['l2'].update(S.getValue(S.getValue('TUNNEL_TYPE').upper() + '_FRAME_L2')) + self._traffic['l3'].update(S.getValue(S.getValue('TUNNEL_TYPE').upper() + '_FRAME_L3')) + self._traffic['l4'].update(S.getValue(S.getValue('TUNNEL_TYPE').upper() + '_FRAME_L4')) self._traffic['l2']['dstmac'] = S.getValue('NICS')[1]['mac'] elif len(S.getValue('NICS')) >= 2 and \ (S.getValue('NICS')[0]['type'] == 'vf' or @@ -180,6 +185,8 @@ class TestCase(object): else: self._logger.debug("MAC addresses can not be read") + self._traffic = functions.check_traffic(self._traffic) + # count how many VNFs are involved in TestSteps if self.test: for step in self.test: @@ -257,8 +264,8 @@ class TestCase(object): loader.get_loadgen_class(), self._load_cfg) - self._output_file = os.path.join(self._results_dir, "result_" + self.name + - "_" + self.deployment + ".csv") + self._output_file = os.path.join(self._results_dir, "result_{}_{}_{}.csv".format( + str(S.getValue('_TEST_INDEX')), self.name, self.deployment)) self._step_status = {'status' : True, 'details' : ''} @@ -287,7 +294,7 @@ class TestCase(object): # cleanup any namespaces created if os.path.isdir('/tmp/namespaces'): namespace_list = os.listdir('/tmp/namespaces') - if len(namespace_list): + if namespace_list: self._logger.info('Cleaning up namespaces') for name in namespace_list: namespace.delete_namespace(name) @@ -295,7 +302,7 @@ class TestCase(object): # cleanup any veth ports created if os.path.isdir('/tmp/veth'): veth_list = os.listdir('/tmp/veth') - if len(veth_list): + if veth_list: self._logger.info('Cleaning up veth ports') for eth in veth_list: port1, port2 = eth.split('-') @@ -322,8 +329,8 @@ class TestCase(object): if len(self._tc_results) < len(results): if len(self._tc_results) > 1: raise RuntimeError('Testcase results do not match:' - 'results: {}\n' - 'trafficgen results: {}\n', + 'results: %s\n' + 'trafficgen results: %s\n' % self._tc_results, results) else: @@ -348,8 +355,8 @@ class TestCase(object): self.run_initialize() try: - with self._vswitch_ctl, self._loadgen: - with self._vnf_ctl, self._collector: + with self._vswitch_ctl: + with self._vnf_ctl, self._collector, self._loadgen: if not self._vswitch_none: self._add_flows() @@ -366,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() @@ -379,7 +386,7 @@ class TestCase(object): self._testcase_run_time = time.strftime("%H:%M:%S", time.gmtime(self._testcase_stop_time - self._testcase_start_time)) - logging.info("Testcase execution time: " + self._testcase_run_time) + logging.info("Testcase execution time: %s", self._testcase_run_time) # report test results self.run_report() @@ -409,8 +416,8 @@ class TestCase(object): item[ResultsConstants.SCAL_PRE_INSTALLED_FLOWS] = self._traffic['pre_installed_flows'] if self._vnf_ctl.get_vnfs_number(): item[ResultsConstants.GUEST_LOOPBACK] = ' '.join(S.getValue('GUEST_LOOPBACK')) - if self._tunnel_type: - item[ResultsConstants.TUNNEL_TYPE] = self._tunnel_type + if self._tunnel_operation: + item[ResultsConstants.TUNNEL_TYPE] = S.getValue('TUNNEL_TYPE') return results def _copy_fwd_tools_for_all_guests(self, vm_count): @@ -562,7 +569,7 @@ class TestCase(object): """ with open(output, 'a') as csvfile: - logging.info("Write results to file: " + output) + logging.info("Write results to file: %s", output) fieldnames = TestCase._get_unique_keys(results) writer = csv.DictWriter(csvfile, fieldnames) @@ -720,7 +727,7 @@ class TestCase(object): self._logger.debug("Skipping %s as it isn't a configuration " "parameter.", '${}'.format(macro[0])) return param - elif isinstance(param, list) or isinstance(param, tuple): + elif isinstance(param, (list, tuple)): tmp_list = [] for item in param: tmp_list.append(self.step_eval_param(item, step_result)) @@ -758,9 +765,6 @@ class TestCase(object): # initialize list with results self._step_result = [None] * len(self.test) - # We have to suppress pylint report, because test_object has to be set according - # to the test step definition - # pylint: disable=redefined-variable-type # run test step by step... for i, step in enumerate(self.test): step_ok = not self._step_check diff --git a/tools/collectors/collectd/collectd.py b/tools/collectors/collectd/collectd.py index 90df6b04..5e996d3a 100644 --- a/tools/collectors/collectd/collectd.py +++ b/tools/collectors/collectd/collectd.py @@ -20,6 +20,7 @@ Plot the values of the stored samples once the test is completed import copy import csv +import glob import logging import multiprocessing import os @@ -30,6 +31,7 @@ import matplotlib.pyplot as plt import numpy as np import tools.collectors.collectd.collectd_bucky as cb from tools.collectors.collector import collector +from tools import tasks from conf import settings # The y-lables. Keys in this dictionary are used as y-labels. @@ -47,6 +49,7 @@ def get_label(sample): for label in YLABELS: if any(r in sample for r in YLABELS[label]): return label + return None def plot_graphs(dict_of_arrays): @@ -194,6 +197,7 @@ class Receiver(multiprocessing.Process): val = self.pd_dict[sample[1]] val.append((sample[2], sample[3])) self.pd_dict[sample[1]] = val + logging.debug("COLLECTD %s", ' '.join(str(p) for p in sample)) def stop(self): """ @@ -216,13 +220,27 @@ class Collectd(collector.ICollector): """ Initialize collection of statistics """ - self._log = os.path.join(results_dir, - settings.getValue('LOG_FILE_COLLECTD') + - '_' + test_name + '.log') + self.logger = logging.getLogger(__name__) + self.resultsdir = results_dir + self.testname = test_name self.results = {} self.sample_dict = multiprocessing.Manager().dict() self.control = multiprocessing.Value('b', False) self.receiver = Receiver(self.sample_dict, self.control) + self.cleanup_metrics() + # Assumption: collected is installed at /opt/collectd + # And collected is configured to write to csv at /tmp/csv + self.pid = tasks.run_background_task( + ['sudo', '/opt/collectd/sbin/collectd'], + self.logger, 'Staring Collectd') + + def cleanup_metrics(self): + """ + Cleaup the old or archived metrics + """ + for name in glob.glob(os.path.join('/tmp/csv/', '*')): + tasks.run_task(['sudo', 'rm', '-rf', name], self.logger, + 'Cleaning up Metrics', True) def start(self): """ @@ -235,6 +253,11 @@ class Collectd(collector.ICollector): """ Stop receiving samples """ + tasks.terminate_task_subtree(self.pid, logger=self.logger) + # At times collectd fails to fully terminate. + # Killing process by name too helps. + tasks.run_task(['sudo', 'pkill', '--signal', '2', 'collectd'], + self.logger, 'Stopping Collectd', True) self.control.value = True self.receiver.stop() self.receiver.server.join(5) @@ -244,6 +267,12 @@ class Collectd(collector.ICollector): if self.receiver.is_alive(): self.receiver.terminate() self.results = copy.deepcopy(self.sample_dict) + # Backup the collectd-metrics for this test into a zipfile + filename = ('/tmp/collectd-' + settings.getValue('LOG_TIMESTAMP') + + '.tar.gz') + tasks.run_task(['sudo', 'tar', '-czvf', filename, '/tmp/csv/'], + self.logger, 'Zipping File', True) + self.cleanup_metrics() def get_results(self): """ @@ -259,7 +288,7 @@ class Collectd(collector.ICollector): plot_graphs(self.results) proc_stats = get_results_to_print(self.results) for process in proc_stats: - logging.info("Process: " + '_'.join(process.split('_')[:-1])) + logging.info("Process: %s", '_'.join(process.split('_')[:-1])) for(key, value) in proc_stats[process].items(): logging.info(" Statistic: " + str(key) + ", Value: " + str(value)) diff --git a/tools/collectors/collectd/collectd_bucky.py b/tools/collectors/collectd/collectd_bucky.py index bac24ed7..f6061c55 100644 --- a/tools/collectors/collectd/collectd_bucky.py +++ b/tools/collectors/collectd/collectd_bucky.py @@ -498,6 +498,7 @@ class CollectDCrypto(object): return self.parse_signed(part_len, data) if sec_level == 2: return self.parse_encrypted(part_len, data) + return None def parse_signed(self, part_len, data): """ @@ -574,12 +575,12 @@ class CollectDConverter(object): try: name_parts = handler(sample) if name_parts is None: - return # treat None as "ignore sample" + return None # treat None as "ignore sample" name = '.'.join(name_parts) except (AttributeError, IndexError, MemoryError, RuntimeError): LOG.exception("Exception in sample handler %s (%s):", sample["plugin"], handler) - return + return None host = sample.get("host", "") return ( host, @@ -655,7 +656,7 @@ class CollectDHandler(object): Check the value range """ if val is None: - return + return None try: vmin, vmax = self.parser.types.type_ranges[stype][vname] except KeyError: @@ -664,11 +665,11 @@ class CollectDHandler(object): if vmin is not None and val < vmin: LOG.debug("Invalid value %s (<%s) for %s", val, vmin, vname) LOG.debug("Last sample: %s", self.last_sample) - return + return None if vmax is not None and val > vmax: LOG.debug("Invalid value %s (>%s) for %s", val, vmax, vname) LOG.debug("Last sample: %s", self.last_sample) - return + return None return val def calculate(self, host, name, vtype, val, time): @@ -684,7 +685,7 @@ class CollectDHandler(object): if vtype not in handlers: LOG.error("Invalid value type %s for %s", vtype, name) LOG.info("Last sample: %s", self.last_sample) - return + return None return handlers[vtype](host, name, val, time) def _calc_counter(self, host, name, val, time): @@ -694,13 +695,13 @@ class CollectDHandler(object): key = (host, name) if key not in self.prev_samples: self.prev_samples[key] = (val, time) - return + return None pval, ptime = self.prev_samples[key] self.prev_samples[key] = (val, time) if time <= ptime: LOG.error("Invalid COUNTER update for: %s:%s", key[0], key[1]) LOG.info("Last sample: %s", self.last_sample) - return + return None if val < pval: # this is supposed to handle counter wrap around # see https://collectd.org/wiki/index.php/Data_source @@ -719,13 +720,13 @@ class CollectDHandler(object): key = (host, name) if key not in self.prev_samples: self.prev_samples[key] = (val, time) - return + return None pval, ptime = self.prev_samples[key] self.prev_samples[key] = (val, time) if time <= ptime: LOG.debug("Invalid DERIVE update for: %s:%s", key[0], key[1]) LOG.debug("Last sample: %s", self.last_sample) - return + return None return float(abs(val - pval)) / (time - ptime) def _calc_absolute(self, host, name, val, time): @@ -735,13 +736,13 @@ class CollectDHandler(object): key = (host, name) if key not in self.prev_samples: self.prev_samples[key] = (val, time) - return + return None _, ptime = self.prev_samples[key] self.prev_samples[key] = (val, time) if time <= ptime: LOG.error("Invalid ABSOLUTE update for: %s:%s", key[0], key[1]) LOG.info("Last sample: %s", self.last_sample) - return + return None return float(val) / (time - ptime) diff --git a/tools/collectors/sysmetrics/pidstat.py b/tools/collectors/sysmetrics/pidstat.py index 99341ccf..277fdb11 100644 --- a/tools/collectors/sysmetrics/pidstat.py +++ b/tools/collectors/sysmetrics/pidstat.py @@ -70,13 +70,13 @@ class Pidstat(collector.ICollector): into the file in directory with test results """ monitor = settings.getValue('PIDSTAT_MONITOR') - self._logger.info('Statistics are requested for: ' + ', '.join(monitor)) + self._logger.info('Statistics are requested for: %s', ', '.join(monitor)) pids = systeminfo.get_pids(monitor) if pids: with open(self._log, 'w') as logfile: cmd = ['sudo', 'LC_ALL=' + settings.getValue('DEFAULT_CMD_LOCALE'), 'pidstat', settings.getValue('PIDSTAT_OPTIONS'), - '-p', ','.join(pids), + '-t', '-p', ','.join(pids), str(settings.getValue('PIDSTAT_SAMPLE_INTERVAL'))] self._logger.debug('%s', ' '.join(cmd)) self._pid = subprocess.Popen(cmd, stdout=logfile, bufsize=0).pid @@ -116,16 +116,48 @@ class Pidstat(collector.ICollector): # combine stored header fields with actual values tmp_res = OrderedDict(zip(tmp_header, line[8:].split())) - # use process's name and its pid as unique key - key = tmp_res.pop('Command') + '_' + tmp_res['PID'] - # store values for given command into results dict - if key in self._results: - self._results[key].update(tmp_res) - else: - self._results[key] = tmp_res + cmd = tmp_res.pop('Command') + # remove unused fields (given by option '-t') + tmp_res.pop('UID') + tmp_res.pop('TID') + if '|_' not in cmd: # main process + # use process's name and its pid as unique key + tmp_pid = tmp_res.pop('TGID') + tmp_key = "%s_%s" % (cmd, tmp_pid) + # do not trust cpu usage of pid + # see VSPERF-569 for more details + if 'CPU' not in tmp_header: + self.update_results(tmp_key, tmp_res, False) + else: # thread + # accumulate cpu usage of all threads + if 'CPU' in tmp_header: + tmp_res.pop('TGID') + self.update_results(tmp_key, tmp_res, True) line = logfile.readline() + def update_results(self, key, result, accumulate=False): + """ + Update final results dictionary. If ``accumulate`` param is set to + ``True``, try to accumulate existing values. + """ + # store values for given command into results dict + if key not in self._results: + self._results[key] = result + elif accumulate: + for field in result: + if field not in self._results[key]: + self._results[key][field] = result[field] + else: + try: + val = float(self._results[key][field]) + float(result[field]) + self._results[key][field] = '{0:.2f}'.format(val) + except ValueError: + # cannot cast to float, let's update with the previous value + self._results[key][field] = result[field] + else: + self._results[key].update(result) + def get_results(self): """Returns collected statistics. """ @@ -135,7 +167,7 @@ class Pidstat(collector.ICollector): """Logs collected statistics. """ for process in self._results: - logging.info("Process: " + '_'.join(process.split('_')[:-1])) + logging.info("Process: %s", '_'.join(process.split('_')[:-1])) for(key, value) in self._results[process].items(): logging.info(" Statistic: " + str(key) + ", Value: " + str(value)) diff --git a/tools/functions.py b/tools/functions.py index d35f1f84..65c9978b 100644 --- a/tools/functions.py +++ b/tools/functions.py @@ -127,7 +127,7 @@ def settings_update_paths(): # expand OS wildcards in paths if needed if glob.has_magic(tmp_tool): tmp_glob = glob.glob(tmp_tool) - if len(tmp_glob) == 0: + if not tmp_glob: raise RuntimeError('Path to the {} is not valid: {}.'.format(tool, tmp_tool)) elif len(tmp_glob) > 1: raise RuntimeError('Path to the {} is ambiguous {}'.format(tool, tmp_glob)) diff --git a/tools/load_gen/stress_ng/stress_ng.py b/tools/load_gen/stress_ng/stress_ng.py index c2592dd1..41bfe990 100644 --- a/tools/load_gen/stress_ng/stress_ng.py +++ b/tools/load_gen/stress_ng/stress_ng.py @@ -30,6 +30,3 @@ class StressNg(Stress): 'name': 'stress-ng' } _logger = logging.getLogger(__name__) - - def __init__(self, stress_config): - super(StressNg, self).__init__(stress_config) diff --git a/tools/load_gen/stressorvm/__init__.py b/tools/load_gen/stressorvm/__init__.py new file mode 100644 index 00000000..6a22d81c --- /dev/null +++ b/tools/load_gen/stressorvm/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2017-2018 Spirent Communications +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Package with wrapper for Stressor-VMs +""" diff --git a/tools/load_gen/stressorvm/stressor_vm.py b/tools/load_gen/stressorvm/stressor_vm.py new file mode 100644 index 00000000..f4936743 --- /dev/null +++ b/tools/load_gen/stressorvm/stressor_vm.py @@ -0,0 +1,116 @@ +# Copyright 2017-2018 Spirent Communications. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Wrapper file to create and manage Stressor-VM as loadgen +""" + +import logging +import os +from tools import tasks +from tools.load_gen.load_gen import ILoadGenerator +from conf import settings as S + + +class QemuVM(tasks.Process): + """ + Class for controling an instance of QEMU + """ + def __init__(self, index): + self._running = False + self._logger = logging.getLogger(__name__) + self._number = index + pnumber = int(S.getValue('NN_BASE_VNC_PORT')) + self._number + cpumask = ",".join(S.getValue('NN_CORE_BINDING')[self._number]) + self._monitor = '%s/vm%dmonitor' % ('/tmp', pnumber) + self._logfile = (os.path.join(S.getValue('LOG_DIR'), + S.getValue('NN_LOG_FILE')) + + str(self._number)) + self._log_prefix = 'vnf_%d_cmd : ' % pnumber + name = 'NN%d' % index + vnc = ':%d' % pnumber + self._shared_dir = '%s/qemu%d_share' % ('/tmp', pnumber) + if not os.path.exists(self._shared_dir): + try: + os.makedirs(self._shared_dir) + except OSError as exp: + raise OSError("Failed to create shared directory %s: %s" % + self._shared_dir, exp) + + self.nics_nr = S.getValue('NN_NICS_NR')[self._number] + self.image = S.getValue('NN_IMAGE')[self._number] + self._cmd = ['sudo', '-E', 'taskset', '-c', cpumask, + S.getValue('TOOLS')['qemu-system'], + '-m', S.getValue('NN_MEMORY')[self._number], + '-smp', S.getValue('NN_SMP')[self._number], + '-cpu', 'host,migratable=off', + '-drive', 'if={},file='.format( + S.getValue('NN_BOOT_DRIVE_TYPE')[self._number]) + + self.image, '-boot', + 'c', '--enable-kvm', + '-monitor', 'unix:%s,server,nowait' % self._monitor, + '-nographic', '-vnc', str(vnc), '-name', name, + '-snapshot', '-net none', '-no-reboot', + '-drive', + 'if=%s,format=raw,file=fat:rw:%s,snapshot=off' % + (S.getValue('NN_SHARED_DRIVE_TYPE')[self._number], + self._shared_dir) + ] + + def start(self): + """ + Start QEMU instance + """ + super(QemuVM, self).start() + self._running = True + + def stop(self, sig, slp): + """ + Stops VNF instance. + """ + if self._running: + self._logger.info('Killing VNF...') + # force termination of VNF and wait to terminate; It will avoid + # sporadic reboot of host. + super(QemuVM, self).kill(signal=sig, sleep=slp) + # remove shared dir if it exists to avoid issues with file consistency + if os.path.exists(self._shared_dir): + tasks.run_task(['rm', '-f', '-r', self._shared_dir], self._logger, + 'Removing content of shared directory...', True) + self._running = False + + +# pylint: disable=super-init-not-called +class StressorVM(ILoadGenerator): + """ + Wrapper Class for Load-Generation through stressor-vm + """ + def __init__(self, _config): + self.qvm_list = [] + for vmindex in range(int(S.getValue('NN_COUNT'))): + qvm = QemuVM(vmindex) + self.qvm_list.append(qvm) + + def start(self): + """Start stressor VMs + """ + for nvm in self.qvm_list: + nvm.start() + + def kill(self, signal='-9', sleep=2): + """ + Stop Stressor VMs + """ + for nvm in self.qvm_list: + nvm.stop(signal, sleep) diff --git a/tools/module_manager.py b/tools/module_manager.py index dd1d92be..943399ba 100644 --- a/tools/module_manager.py +++ b/tools/module_manager.py @@ -160,7 +160,7 @@ class ModuleManager(object): self._logger.info('Unable to get list of dependecies for module \'%s\'.', module) # ...and try to continue, just for case that dependecies are already loaded - if len(deps): + if deps: return deps.split(',') else: return [] diff --git a/tools/namespace.py b/tools/namespace.py index 9131398f..50374b95 100644 --- a/tools/namespace.py +++ b/tools/namespace.py @@ -135,9 +135,8 @@ def reset_port_to_root(port, name): port, name), False) -# pylint: disable=unused-argument # pylint: disable=invalid-name -def validate_add_ip_to_namespace_eth(result, port, name, ip_addr, cidr): +def validate_add_ip_to_namespace_eth(_result, port, name, ip_addr, cidr): """ Validation function for integration testcases """ @@ -147,7 +146,7 @@ def validate_add_ip_to_namespace_eth(result, port, name, ip_addr, cidr): _LOGGER, 'Validating ip address in namespace...', False)) -def validate_assign_port_to_namespace(result, port, name, port_up=False): +def validate_assign_port_to_namespace(_result, port, name, _port_up=False): """ Validation function for integration testcases """ @@ -157,14 +156,14 @@ def validate_assign_port_to_namespace(result, port, name, port_up=False): _LOGGER, 'Validating port in namespace...')) -def validate_create_namespace(result, name): +def validate_create_namespace(_result, name): """ Validation function for integration testcases """ return name in get_system_namespace_list() -def validate_delete_namespace(result, name): +def validate_delete_namespace(_result, name): """ Validation function for integration testcases """ diff --git a/tools/networkcard.py b/tools/networkcard.py index 2cd296fb..758010d2 100644 --- a/tools/networkcard.py +++ b/tools/networkcard.py @@ -191,7 +191,7 @@ def get_mac(pci_handle): """ mac_path = glob.glob(os.path.join(_PCI_DIR, _PCI_NET, '*', 'address').format(pci_handle)) # kernel driver is loaded and MAC can be read - if len(mac_path) and os.path.isfile(mac_path[0]): + if mac_path and os.path.isfile(mac_path[0]): with open(mac_path[0], 'r') as _file: return _file.readline().rstrip('\n') diff --git a/tools/pkt_gen/dummy/dummy.py b/tools/pkt_gen/dummy/dummy.py index 3dc5448e..ef4b37d9 100755 --- a/tools/pkt_gen/dummy/dummy.py +++ b/tools/pkt_gen/dummy/dummy.py @@ -25,6 +25,7 @@ own. import json +from collections import OrderedDict from conf import settings from conf import merge_spec from tools.pkt_gen import trafficgen @@ -108,41 +109,41 @@ class Dummy(trafficgen.ITrafficGenerator): """ pass - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """ Send a burst of traffic. """ traffic_ = self.traffic_defaults.copy() - result = {} + result = OrderedDict() if traffic: traffic_ = merge_spec(traffic_, traffic) results = get_user_traffic( 'burst', - '%dpkts, %dmS' % (numpkts, duration), + '%dpkts, %dmS' % (traffic['burst_size'], duration), traffic_, ('frames rx', 'payload errors', 'sequence errors')) # builds results by using user-supplied values where possible # and guessing remainder using available info - result[ResultsConstants.TX_FRAMES] = numpkts + result[ResultsConstants.TX_FRAMES] = traffic['burst_size'] result[ResultsConstants.RX_FRAMES] = results[0] result[ResultsConstants.TX_BYTES] = traffic_['l2']['framesize'] \ - * numpkts + * traffic['burst_size'] result[ResultsConstants.RX_BYTES] = traffic_['l2']['framesize'] \ * results[0] result[ResultsConstants.PAYLOAD_ERR] = results[1] result[ResultsConstants.SEQ_ERR] = results[2] - return results + return result def send_cont_traffic(self, traffic=None, duration=30): """ Send a continuous flow of traffic. """ traffic_ = self.traffic_defaults.copy() - result = {} + result = OrderedDict() if traffic: traffic_ = merge_spec(traffic_, traffic) @@ -179,7 +180,7 @@ class Dummy(trafficgen.ITrafficGenerator): Send traffic per RFC2544 throughput test specifications. """ traffic_ = self.traffic_defaults.copy() - result = {} + result = OrderedDict() if traffic: traffic_ = merge_spec(traffic_, traffic) @@ -216,7 +217,7 @@ class Dummy(trafficgen.ITrafficGenerator): Send traffic per RFC2544 back2back test specifications. """ traffic_ = self.traffic_defaults.copy() - result = {} + result = OrderedDict() if traffic: traffic_ = merge_spec(traffic_, traffic) @@ -273,4 +274,5 @@ if __name__ == '__main__': print(dev.send_cont_traffic(traffic=TRAFFIC)) print(dev.send_rfc2544_throughput(traffic=TRAFFIC)) print(dev.send_rfc2544_back2back(traffic=TRAFFIC)) + # pylint: disable=no-member print(dev.send_rfc(traffic=TRAFFIC)) diff --git a/tools/pkt_gen/ixia/ixia.py b/tools/pkt_gen/ixia/ixia.py index d4ca56f2..31f51246 100755 --- a/tools/pkt_gen/ixia/ixia.py +++ b/tools/pkt_gen/ixia/ixia.py @@ -157,8 +157,8 @@ class Ixia(trafficgen.ITrafficGenerator): return NotImplementedError( 'Ixia start back2back traffic not implemented') - def send_rfc2544_back2back(self, traffic=None, duration=60, - lossrate=0.0, tests=1): + def send_rfc2544_back2back(self, traffic=None, tests=1, duration=60, + lossrate=0.0): return NotImplementedError( 'Ixia send back2back traffic not implemented') @@ -242,11 +242,11 @@ class Ixia(trafficgen.ITrafficGenerator): return result - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """See ITrafficGenerator for description """ flow = { - 'numpkts': numpkts, + 'numpkts': traffic['burst_size'], 'duration': duration, 'type': 'stopStream', 'framerate': traffic['frame_rate'], @@ -254,9 +254,9 @@ class Ixia(trafficgen.ITrafficGenerator): result = self._send_traffic(flow, traffic) - assert len(result) == 6 # fail-fast if underlying Tcl code changes + assert len(result) == 10 # fail-fast if underlying Tcl code changes - #NOTE - implement Burst results setting via TrafficgenResults. + return Ixia._create_result(result) def send_cont_traffic(self, traffic=None, duration=30): """See ITrafficGenerator for description @@ -317,20 +317,25 @@ class Ixia(trafficgen.ITrafficGenerator): :returns: dictionary strings representing results from traffic generator. """ - assert len(result) == 8 # fail-fast if underlying Tcl code changes + assert len(result) == 8 or len(result) == 10 # fail-fast if underlying Tcl code changes + + # content of result common for all tests + # [framesSent, framesRecv, bytesSent, bytesRecv, sendRate, recvRate, sendRateBytes, recvRateBytes] + # burst test has additional two values at the end: payError, seqError if float(result[0]) == 0: loss_rate = 100 else: - loss_rate = (float(result[0]) - float(result[1])) / float(result[0]) * 100 + loss_rate = round((float(result[0]) - float(result[1])) / float(result[0]) * 100, 5) result_dict = OrderedDict() - # drop the first 4 elements as we don't use/need them. In - # addition, IxExplorer does not support latency or % line rate + # IxExplorer does not support latency or % line rate # metrics so we have to return dummy values for these metrics - result_dict[ResultsConstants.THROUGHPUT_RX_FPS] = result[4] - result_dict[ResultsConstants.TX_RATE_FPS] = result[5] - result_dict[ResultsConstants.THROUGHPUT_RX_MBPS] = str(round(int(result[6]) / 1000000, 3)) - result_dict[ResultsConstants.TX_RATE_MBPS] = str(round(int(result[7]) / 1000000, 3)) + result_dict[ResultsConstants.TX_FRAMES] = result[0] + result_dict[ResultsConstants.RX_FRAMES] = result[1] + result_dict[ResultsConstants.TX_RATE_FPS] = result[4] + result_dict[ResultsConstants.THROUGHPUT_RX_FPS] = result[5] + result_dict[ResultsConstants.TX_RATE_MBPS] = str(round(int(result[6]) * 8 / 1e6, 3)) + result_dict[ResultsConstants.THROUGHPUT_RX_MBPS] = str(round(int(result[7]) * 8 / 1e6, 3)) result_dict[ResultsConstants.FRAME_LOSS_PERCENT] = loss_rate result_dict[ResultsConstants.TX_RATE_PERCENT] = \ ResultsConstants.UNKNOWN_VALUE diff --git a/tools/pkt_gen/ixnet/ixnet.py b/tools/pkt_gen/ixnet/ixnet.py index d1ba9096..87fb2c65 100755 --- a/tools/pkt_gen/ixnet/ixnet.py +++ b/tools/pkt_gen/ixnet/ixnet.py @@ -370,7 +370,7 @@ class IxNet(trafficgen.ITrafficGenerator): next(reader) for row in reader: #Replace null entries added by Ixia with 0s. - row = [entry if len(entry) > 0 else '0' for entry in row] + row = [entry if entry else '0' for entry in row] # tx_fps and tx_mps cannot be reliably calculated # as the DUT may be modifying the frame size @@ -528,7 +528,7 @@ class IxNet(trafficgen.ITrafficGenerator): return parse_ixnet_rfc_results(parse_result_string(output[0])) - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): return NotImplementedError('IxNet does not implement send_burst_traffic') if __name__ == '__main__': diff --git a/tools/pkt_gen/moongen/moongen.py b/tools/pkt_gen/moongen/moongen.py index 570720e8..b7d55c4d 100644 --- a/tools/pkt_gen/moongen/moongen.py +++ b/tools/pkt_gen/moongen/moongen.py @@ -64,46 +64,46 @@ class Moongen(ITrafficGenerator): :param one_shot: No RFC 2544 binary search, just packet flow at traffic specifics """ - logging.debug("traffic['frame_rate'] = " + \ + logging.debug("traffic['frame_rate'] = %s", \ str(traffic['frame_rate'])) - logging.debug("traffic['multistream'] = " + \ + logging.debug("traffic['multistream'] = %s", \ str(traffic['multistream'])) - logging.debug("traffic['stream_type'] = " + \ + logging.debug("traffic['stream_type'] = %s", \ str(traffic['stream_type'])) - logging.debug("traffic['l2']['srcmac'] = " + \ + logging.debug("traffic['l2']['srcmac'] = %s", \ str(traffic['l2']['srcmac'])) - logging.debug("traffic['l2']['dstmac'] = " + \ + logging.debug("traffic['l2']['dstmac'] = %s", \ str(traffic['l2']['dstmac'])) - logging.debug("traffic['l3']['proto'] = " + \ + logging.debug("traffic['l3']['proto'] = %s", \ str(traffic['l3']['proto'])) - logging.debug("traffic['l3']['srcip'] = " + \ + logging.debug("traffic['l3']['srcip'] = %s", \ str(traffic['l3']['srcip'])) - logging.debug("traffic['l3']['dstip'] = " + \ + logging.debug("traffic['l3']['dstip'] = %s", \ str(traffic['l3']['dstip'])) - logging.debug("traffic['l4']['srcport'] = " + \ + logging.debug("traffic['l4']['srcport'] = %s", \ str(traffic['l4']['srcport'])) - logging.debug("traffic['l4']['dstport'] = " + \ + logging.debug("traffic['l4']['dstport'] = %s", \ str(traffic['l4']['dstport'])) - logging.debug("traffic['vlan']['enabled'] = " + \ + logging.debug("traffic['vlan']['enabled'] = %s", \ str(traffic['vlan']['enabled'])) - logging.debug("traffic['vlan']['id'] = " + \ + logging.debug("traffic['vlan']['id'] = %s", \ str(traffic['vlan']['id'])) - logging.debug("traffic['vlan']['priority'] = " + \ + logging.debug("traffic['vlan']['priority'] = %s", \ str(traffic['vlan']['priority'])) - logging.debug("traffic['vlan']['cfi'] = " + \ + logging.debug("traffic['vlan']['cfi'] = %s", \ str(traffic['vlan']['cfi'])) logging.debug(traffic['l2']['framesize']) @@ -160,9 +160,9 @@ class Moongen(ITrafficGenerator): (traffic['frame_rate'] / 100) * (self._moongen_line_speed / \ (8 * (traffic['l2']['framesize'] + 20)) / math.pow(10, 6))) - logging.debug("startRate = " + start_rate) + logging.debug("startRate = %s", start_rate) - out_file.write("startRate = " + \ + out_file.write("startRate = %s" % \ start_rate + "\n") out_file.write("}" + "\n") @@ -240,14 +240,13 @@ class Moongen(ITrafficGenerator): """ self._logger.info("MOONGEN: In moongen disconnect method") - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """Send a burst of traffic. - Send a ``numpkts`` packets of traffic, using ``traffic`` + Send a ``traffic['burst_traffic']`` packets of traffic, using ``traffic`` configuration, with a timeout of ``time``. :param traffic: Detailed "traffic" spec, i.e. IP address, VLAN tags - :param numpkts: Number of packets to send :param duration: Time to wait to receive packets :returns: dictionary of strings with following data: @@ -508,8 +507,8 @@ class Moongen(ITrafficGenerator): return moongen_results - def send_rfc2544_throughput(self, traffic=None, duration=20, - lossrate=0.0, tests=1): + def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20, + lossrate=0.0): # # Send traffic per RFC2544 throughput test specifications. # @@ -631,8 +630,8 @@ class Moongen(ITrafficGenerator): """ self._logger.info('In moongen wait_rfc2544_throughput') - def send_rfc2544_back2back(self, traffic=None, duration=60, - lossrate=0.0, tests=1): + def send_rfc2544_back2back(self, traffic=None, tests=1, duration=60, + lossrate=0.0): """Send traffic per RFC2544 back2back test specifications. Send packets at a fixed rate, using ``traffic`` diff --git a/tools/pkt_gen/testcenter/testcenter.py b/tools/pkt_gen/testcenter/testcenter.py index 9980ae7c..487566bf 100644 --- a/tools/pkt_gen/testcenter/testcenter.py +++ b/tools/pkt_gen/testcenter/testcenter.py @@ -182,7 +182,7 @@ class TestCenter(trafficgen.ITrafficGenerator): """ pass - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """ Do nothing. """ @@ -246,8 +246,7 @@ class TestCenter(trafficgen.ITrafficGenerator): row["ForwardingRate(fps)"]) return result - # pylint: disable=unused-argument - def send_rfc2889_forwarding(self, traffic=None, tests=1, duration=20): + def send_rfc2889_forwarding(self, traffic=None, tests=1, _duration=20): """ Send traffic per RFC2889 Forwarding test specifications. """ @@ -257,7 +256,7 @@ class TestCenter(trafficgen.ITrafficGenerator): framesize = traffic['l2']['framesize'] args = get_rfc2889_common_settings(framesize, tests, traffic['traffic_type']) - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.debug("Arguments used to call test: %s", args) @@ -273,7 +272,7 @@ class TestCenter(trafficgen.ITrafficGenerator): return self.get_rfc2889_forwarding_results(filec) - def send_rfc2889_caching(self, traffic=None, tests=1, duration=20): + def send_rfc2889_caching(self, traffic=None, tests=1, _duration=20): """ Send as per RFC2889 Addr-Caching test specifications. """ @@ -286,7 +285,7 @@ class TestCenter(trafficgen.ITrafficGenerator): custom_args = get_rfc2889_custom_settings() args = common_args + custom_args - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.debug("Arguments used to call test: %s", args) @@ -302,7 +301,7 @@ class TestCenter(trafficgen.ITrafficGenerator): return self.get_rfc2889_addr_caching_results(filec) - def send_rfc2889_learning(self, traffic=None, tests=1, duration=20): + def send_rfc2889_learning(self, traffic=None, tests=1, _duration=20): """ Send traffic per RFC2889 Addr-Learning test specifications. """ @@ -315,7 +314,7 @@ class TestCenter(trafficgen.ITrafficGenerator): custom_args = get_rfc2889_custom_settings() args = common_args + custom_args - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.debug("Arguments used to call test: %s", args) @@ -387,7 +386,7 @@ class TestCenter(trafficgen.ITrafficGenerator): custom, 1) args = rfc2544_common_args + stc_common_args + rfc2544_custom_args - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.debug("Arguments used to call test: %s", args) @@ -420,7 +419,7 @@ class TestCenter(trafficgen.ITrafficGenerator): tests) args = rfc2544_common_args + stc_common_args + rfc2544_custom_args - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.debug("Arguments used to call test: %s", args) @@ -453,7 +452,7 @@ class TestCenter(trafficgen.ITrafficGenerator): tests) args = rfc2544_common_args + stc_common_args + rfc2544_custom_args - if settings.getValue("TRAFFICGEN_STC_VERBOSE") is "True": + if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True": args.append("--verbose") verbose = True self._logger.info("Arguments used to call test: %s", args) @@ -498,4 +497,5 @@ if __name__ == '__main__': } with TestCenter() as dev: print(dev.send_rfc2544_throughput(traffic=TRAFFIC)) + # pylint: disable=no-member print(dev.send_rfc2544_backtoback(traffic=TRAFFIC)) diff --git a/tools/pkt_gen/trafficgen/trafficgen.py b/tools/pkt_gen/trafficgen/trafficgen.py index 262df71d..a6f7edcc 100755 --- a/tools/pkt_gen/trafficgen/trafficgen.py +++ b/tools/pkt_gen/trafficgen/trafficgen.py @@ -81,15 +81,14 @@ class ITrafficGenerator(object): """ raise NotImplementedError('Please call an implementation.') - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """Send a burst of traffic. - Send a ``numpkts`` packets of traffic, using ``traffic`` + Send a ``traffic['burst_size']`` packets of traffic, using ``traffic`` configuration, for ``duration`` seconds. Attributes: :param traffic: Detailed "traffic" spec, see design docs for details - :param numpkts: Number of packets to send :param duration: Time to wait to receive packets :returns: dictionary of strings with following data: diff --git a/tools/pkt_gen/trex/trex.py b/tools/pkt_gen/trex/trex.py index cfe54b78..94b793d6 100644 --- a/tools/pkt_gen/trex/trex.py +++ b/tools/pkt_gen/trex/trex.py @@ -15,12 +15,14 @@ """ Trex Traffic Generator Model """ + # pylint: disable=undefined-variable import logging import subprocess import sys import time import os +import re from collections import OrderedDict # pylint: disable=unused-import import netaddr @@ -33,6 +35,7 @@ try: # pylint: disable=wrong-import-position, import-error sys.path.append(settings.getValue('PATHS')['trafficgen']['Trex']['src']['path']) from trex_stl_lib.api import * + from trex_stl_lib import trex_stl_exceptions except ImportError: # VSPERF performs detection of T-Rex api during testcase initialization. So if # T-Rex is requsted and API is not available it will fail before this code @@ -68,6 +71,21 @@ _EMPTY_STATS = { 'tx_pps': 0.0, 'tx_util': 0.0,}} +# Default frame definition, which can be overridden by TRAFFIC['scapy']. +# The content of the frame and its network layers are driven by TRAFFIC +# dictionary, i.e. 'l2', 'l3, 'l4' and 'vlan' parts. +_SCAPY_FRAME = { + '0' : 'Ether(src={Ether_src}, dst={Ether_dst})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_src}, dst={IP_dst})/' + '{IP_PROTO}(sport={IP_PROTO_sport}, dport={IP_PROTO_dport})', + '1' : 'Ether(src={Ether_dst}, dst={Ether_src})/' + 'Dot1Q(prio={Dot1Q_prio}, id={Dot1Q_id}, vlan={Dot1Q_vlan})/' + 'IP(proto={IP_proto}, src={IP_dst}, dst={IP_src})/' + '{IP_PROTO}(sport={IP_PROTO_dport}, dport={IP_PROTO_sport})', +} + + class Trex(ITrafficGenerator): """Trex Traffic generator wrapper.""" _logger = logging.getLogger(__name__) @@ -84,6 +102,20 @@ class Trex(ITrafficGenerator): self._trex_user = settings.getValue('TRAFFICGEN_TREX_USER') self._stlclient = None self._verification_params = None + self._show_packet_data = False + + def show_packet_info(self, packet_a, packet_b): + """ + Log packet layers to screen + :param packet_a: Scapy.layers packet + :param packet_b: Scapy.layers packet + :return: None + """ + # we only want to show packet data once per test + if self._show_packet_data: + self._show_packet_data = False + self._logger.info(packet_a.show()) + self._logger.info(packet_b.show()) def connect(self): '''Connect to Trex traffic generator @@ -149,35 +181,77 @@ class Trex(ITrafficGenerator): self._logger.info("T-Rex: In trex disconnect method") self._stlclient.disconnect(stop_traffic=True, release_ports=True) - @staticmethod - def create_packets(traffic, ports_info): + def create_packets(self, traffic, ports_info): """Create base packet according to traffic specification. If traffic haven't specified srcmac and dstmac fields - packet will be create with mac address of trex server. + packet will be created with mac address of trex server. """ - mac_add = [li['hw_mac'] for li in ports_info] - - if traffic and traffic['l2']['framesize'] > 0: - if traffic['l2']['dstmac'] == '00:00:00:00:00:00' and \ - traffic['l2']['srcmac'] == '00:00:00:00:00:00': - base_pkt_a = Ether(src=mac_add[0], dst=mac_add[1])/ \ - IP(proto=traffic['l3']['proto'], src=traffic['l3']['srcip'], - dst=traffic['l3']['dstip'])/ \ - UDP(dport=traffic['l4']['dstport'], sport=traffic['l4']['srcport']) - base_pkt_b = Ether(src=mac_add[1], dst=mac_add[0])/ \ - IP(proto=traffic['l3']['proto'], src=traffic['l3']['dstip'], - dst=traffic['l3']['srcip'])/ \ - UDP(dport=traffic['l4']['srcport'], sport=traffic['l4']['dstport']) - else: - base_pkt_a = Ether(src=traffic['l2']['srcmac'], dst=traffic['l2']['dstmac'])/ \ - IP(proto=traffic['l3']['proto'], src=traffic['l3']['dstip'], - dst=traffic['l3']['srcip'])/ \ - UDP(dport=traffic['l4']['dstport'], sport=traffic['l4']['srcport']) + if not traffic or traffic['l2']['framesize'] <= 0: + return (None, None) + + if traffic['l2']['dstmac'] == '00:00:00:00:00:00' and \ + traffic['l2']['srcmac'] == '00:00:00:00:00:00': + + mac_add = [li['hw_mac'] for li in ports_info] + src_mac = mac_add[0] + dst_mac = mac_add[1] + else: + src_mac = traffic['l2']['srcmac'] + dst_mac = traffic['l2']['dstmac'] - base_pkt_b = Ether(src=traffic['l2']['dstmac'], dst=traffic['l2']['srcmac'])/ \ - IP(proto=traffic['l3']['proto'], src=traffic['l3']['dstip'], - dst=traffic['l3']['srcip'])/ \ - UDP(dport=traffic['l4']['srcport'], sport=traffic['l4']['dstport']) + if traffic['scapy']['enabled']: + base_pkt_a = traffic['scapy']['0'] + base_pkt_b = traffic['scapy']['1'] + else: + base_pkt_a = _SCAPY_FRAME['0'] + base_pkt_b = _SCAPY_FRAME['1'] + + # check and remove network layers disabled by TRAFFIC dictionary + # Note: In general, it is possible to remove layers from scapy object by + # e.g. del base_pkt_a['IP']. However it doesn't work for all layers + # (e.g. Dot1Q). Thus it is safer to modify string with scapy frame definition + # directly, before it is converted to the real scapy object. + if not traffic['vlan']['enabled']: + self._logger.info('VLAN headers are disabled by TRAFFIC') + base_pkt_a = re.sub(r'(^|\/)Dot1Q?\([^\)]*\)', '', base_pkt_a) + base_pkt_b = re.sub(r'(^|\/)Dot1Q?\([^\)]*\)', '', base_pkt_b) + if not traffic['l3']['enabled']: + self._logger.info('IP headers are disabled by TRAFFIC') + base_pkt_a = re.sub(r'(^|\/)IP(v6)?\([^\)]*\)', '', base_pkt_a) + base_pkt_b = re.sub(r'(^|\/)IP(v6)?\([^\)]*\)', '', base_pkt_b) + if not traffic['l4']['enabled']: + self._logger.info('%s headers are disabled by TRAFFIC', + traffic['l3']['proto'].upper()) + base_pkt_a = re.sub(r'(^|\/)(UDP|TCP|SCTP|{{IP_PROTO}}|{})\([^\)]*\)'.format( + traffic['l3']['proto'].upper()), '', base_pkt_a) + base_pkt_b = re.sub(r'(^|\/)(UDP|TCP|SCTP|{{IP_PROTO}}|{})\([^\)]*\)'.format( + traffic['l3']['proto'].upper()), '', base_pkt_b) + + # pylint: disable=eval-used + base_pkt_a = eval(base_pkt_a.format( + Ether_src=repr(src_mac), + Ether_dst=repr(dst_mac), + Dot1Q_prio=traffic['vlan']['priority'], + Dot1Q_id=traffic['vlan']['cfi'], + Dot1Q_vlan=traffic['vlan']['id'], + IP_proto=repr(traffic['l3']['proto']), + IP_PROTO=traffic['l3']['proto'].upper(), + IP_src=repr(traffic['l3']['srcip']), + IP_dst=repr(traffic['l3']['dstip']), + IP_PROTO_sport=traffic['l4']['srcport'], + IP_PROTO_dport=traffic['l4']['dstport'])) + base_pkt_b = eval(base_pkt_b.format( + Ether_src=repr(src_mac), + Ether_dst=repr(dst_mac), + Dot1Q_prio=traffic['vlan']['priority'], + Dot1Q_id=traffic['vlan']['cfi'], + Dot1Q_vlan=traffic['vlan']['id'], + IP_proto=repr(traffic['l3']['proto']), + IP_PROTO=traffic['l3']['proto'].upper(), + IP_src=repr(traffic['l3']['srcip']), + IP_dst=repr(traffic['l3']['dstip']), + IP_PROTO_sport=traffic['l4']['srcport'], + IP_PROTO_dport=traffic['l4']['dstport'])) return (base_pkt_a, base_pkt_b) @@ -232,22 +306,48 @@ class Trex(ITrafficGenerator): pkt_a = STLPktBuilder(pkt=base_pkt_a / payload_a) pkt_b = STLPktBuilder(pkt=base_pkt_b / payload_b) - stream_1 = STLStream(packet=pkt_a, - name='stream_1', - mode=STLTXCont(percentage=traffic['frame_rate'])) - stream_2 = STLStream(packet=pkt_b, - name='stream_2', - mode=STLTXCont(percentage=traffic['frame_rate'])) lat_pps = settings.getValue('TRAFFICGEN_TREX_LATENCY_PPS') - if lat_pps > 0: - stream_1_lat = STLStream(packet=pkt_a, + if traffic['traffic_type'] == 'burst': + if lat_pps > 0: + # latency statistics are requested; in case of frame burst we can enable + # statistics for all frames + stream_1 = STLStream(packet=pkt_a, flow_stats=STLFlowLatencyStats(pg_id=0), - name='stream_1_lat', - mode=STLTXCont(pps=lat_pps)) - stream_2_lat = STLStream(packet=pkt_b, + name='stream_1', + mode=STLTXSingleBurst(percentage=traffic['frame_rate'], + total_pkts=traffic['burst_size'])) + stream_2 = STLStream(packet=pkt_b, flow_stats=STLFlowLatencyStats(pg_id=1), - name='stream_2_lat', - mode=STLTXCont(pps=lat_pps)) + name='stream_2', + mode=STLTXSingleBurst(percentage=traffic['frame_rate'], + total_pkts=traffic['burst_size'])) + else: + stream_1 = STLStream(packet=pkt_a, + name='stream_1', + mode=STLTXSingleBurst(percentage=traffic['frame_rate'], + total_pkts=traffic['burst_size'])) + stream_2 = STLStream(packet=pkt_b, + name='stream_2', + mode=STLTXSingleBurst(percentage=traffic['frame_rate'], + total_pkts=traffic['burst_size'])) + else: + stream_1 = STLStream(packet=pkt_a, + name='stream_1', + mode=STLTXCont(percentage=traffic['frame_rate'])) + stream_2 = STLStream(packet=pkt_b, + name='stream_2', + mode=STLTXCont(percentage=traffic['frame_rate'])) + # workaround for latency statistics, which can't be enabled for streams + # with high framerate due to the huge performance impact + if lat_pps > 0: + stream_1_lat = STLStream(packet=pkt_a, + flow_stats=STLFlowLatencyStats(pg_id=0), + name='stream_1_lat', + mode=STLTXCont(pps=lat_pps)) + stream_2_lat = STLStream(packet=pkt_b, + flow_stats=STLFlowLatencyStats(pg_id=1), + name='stream_2_lat', + mode=STLTXCont(pps=lat_pps)) return (stream_1, stream_2, stream_1_lat, stream_2_lat) @@ -262,11 +362,29 @@ class Trex(ITrafficGenerator): self._stlclient.set_service_mode(ports=my_ports, enabled=False) ports_info = self._stlclient.get_port_info(my_ports) + + # get max support speed + max_speed = 0 + if settings.getValue('TRAFFICGEN_TREX_FORCE_PORT_SPEED'): + max_speed = settings.getValue('TRAFFICGEN_TREX_PORT_SPEED') + elif ports_info[0]['supp_speeds']: + max_speed_1 = max(ports_info[0]['supp_speeds']) + max_speed_2 = max(ports_info[1]['supp_speeds']) + else: + # if max supported speed not in port info or set manually, just assume 10G + max_speed = 10000 + if not max_speed: + # since we can only control both ports at once take the lower of the two + max_speed = min(max_speed_1, max_speed_2) + gbps_speed = (max_speed / 1000) * (float(traffic['frame_rate']) / 100.0) + self._logger.debug('Starting traffic at %s Gbps speed', gbps_speed) + # for SR-IOV if settings.getValue('TRAFFICGEN_TREX_PROMISCUOUS'): self._stlclient.set_port_attr(my_ports, promiscuous=True) - packet_1, packet_2 = Trex.create_packets(traffic, ports_info) + packet_1, packet_2 = self.create_packets(traffic, ports_info) + self.show_packet_info(packet_1, packet_2) stream_1, stream_2, stream_1_lat, stream_2_lat = Trex.create_streams(packet_1, packet_2, traffic) self._stlclient.add_streams(stream_1, ports=[0]) self._stlclient.add_streams(stream_2, ports=[1]) @@ -289,7 +407,13 @@ class Trex(ITrafficGenerator): pcap_id[pcap_dir] = self._stlclient.start_capture(**capture) self._stlclient.clear_stats() - self._stlclient.start(ports=my_ports, force=True, duration=duration) + # if the user did not start up T-Rex server with more than default cores, use default mask. + # Otherwise use mask to take advantage of multiple cores. + try: + self._stlclient.start(ports=my_ports, force=True, duration=duration, mult="{}gbps".format(gbps_speed), + core_mask=self._stlclient.CORE_MASK_PIN) + except STLError: + self._stlclient.start(ports=my_ports, force=True, duration=duration, mult="{}gbps".format(gbps_speed)) self._stlclient.wait_on_traffic(ports=my_ports) stats = self._stlclient.get_stats(sync_now=True) @@ -342,20 +466,29 @@ class Trex(ITrafficGenerator): result[ResultsConstants.FRAME_LOSS_PERCENT] = 100 if settings.getValue('TRAFFICGEN_TREX_LATENCY_PPS') > 0 and stats['latency']: - result[ResultsConstants.MIN_LATENCY_NS] = ( - '{:.3f}'.format( - (float(min(stats["latency"][0]["latency"]["total_min"], - stats["latency"][1]["latency"]["total_min"]))))) - - result[ResultsConstants.MAX_LATENCY_NS] = ( - '{:.3f}'.format( - (float(max(stats["latency"][0]["latency"]["total_max"], - stats["latency"][1]["latency"]["total_max"]))))) - - result[ResultsConstants.AVG_LATENCY_NS] = ( - '{:.3f}'.format( - float((stats["latency"][0]["latency"]["average"]+ - stats["latency"][1]["latency"]["average"])/2))) + try: + result[ResultsConstants.MIN_LATENCY_NS] = ( + '{:.3f}'.format( + (float(min(stats["latency"][0]["latency"]["total_min"], + stats["latency"][1]["latency"]["total_min"]))))) + except TypeError: + result[ResultsConstants.MIN_LATENCY_NS] = 'Unknown' + + try: + result[ResultsConstants.MAX_LATENCY_NS] = ( + '{:.3f}'.format( + (float(max(stats["latency"][0]["latency"]["total_max"], + stats["latency"][1]["latency"]["total_max"]))))) + except TypeError: + result[ResultsConstants.MAX_LATENCY_NS] = 'Unknown' + + try: + result[ResultsConstants.AVG_LATENCY_NS] = ( + '{:.3f}'.format( + float((stats["latency"][0]["latency"]["average"]+ + stats["latency"][1]["latency"]["average"])/2))) + except TypeError: + result[ResultsConstants.AVG_LATENCY_NS] = 'Unknown' else: result[ResultsConstants.MIN_LATENCY_NS] = 'Unknown' @@ -414,9 +547,11 @@ class Trex(ITrafficGenerator): if test_lossrate <= lossrate: # save the last passing trial for verification self._verification_params = copy.deepcopy(new_params) - self._logger.debug("Iteration: %s, frame rate: %s, throughput_rx_fps: %s, frame_loss_percent: %s", - iteration, "{:.3f}".format(new_params['frame_rate']), stats['total']['rx_pps'], - "{:.3f}".format(test_lossrate)) + packets_lost = stats['total']['opackets'] - stats['total']['ipackets'] + self._logger.debug("Iteration: %s, frame rate: %s, throughput_rx_fps: %s," + + " frames lost %s, frame_loss_percent: %s", iteration, + "{:.3f}".format(new_params['frame_rate']), stats['total']['rx_pps'], + packets_lost, "{:.3f}".format(test_lossrate)) if test_lossrate == 0.0 and new_params['frame_rate'] == traffic['frame_rate']: return copy.deepcopy(stats) elif test_lossrate > lossrate: @@ -439,6 +574,8 @@ class Trex(ITrafficGenerator): self._logger.info("In Trex send_cont_traffic method") self._params.clear() + self._show_packet_data = True + self._params['traffic'] = self.traffic_defaults.copy() if traffic: self._params['traffic'] = merge_spec( @@ -467,6 +604,7 @@ class Trex(ITrafficGenerator): """ self._logger.info("In Trex send_rfc2544_throughput method") self._params.clear() + self._show_packet_data = True self._params['traffic'] = self.traffic_defaults.copy() if traffic: self._params['traffic'] = merge_spec( @@ -523,9 +661,25 @@ class Trex(ITrafficGenerator): raise NotImplementedError( 'Trex wait rfc2544 throughput not implemented') - def send_burst_traffic(self, traffic=None, numpkts=100, duration=5): - raise NotImplementedError( - 'Trex send burst traffic not implemented') + def send_burst_traffic(self, traffic=None, duration=20): + """See ITrafficGenerator for description + """ + self._logger.info("In Trex send_burst_traffic method") + self._params.clear() + + self._params['traffic'] = self.traffic_defaults.copy() + if traffic: + self._params['traffic'] = merge_spec( + self._params['traffic'], traffic) + + if settings.getValue('TRAFFICGEN_TREX_LEARNING_MODE'): + self.learning_packets(traffic) + self._logger.info("T-Rex sending traffic") + stats = self.generate_traffic(traffic, duration) + + time.sleep(3) # allow packets to complete before reading stats + + return self.calculate_results(stats) def send_rfc2544_back2back(self, traffic=None, tests=1, duration=30, lossrate=0.0): diff --git a/tools/pkt_gen/xena/XenaDriver.py b/tools/pkt_gen/xena/XenaDriver.py index 6e39e47a..ac9cef1c 100644 --- a/tools/pkt_gen/xena/XenaDriver.py +++ b/tools/pkt_gen/xena/XenaDriver.py @@ -30,6 +30,7 @@ through socket commands and returning different statistics. """ import locale import logging +import math import socket import struct import sys @@ -86,6 +87,26 @@ CMD_VERSION = 'c_versionno ?' _LOCALE = locale.getlocale()[1] _LOGGER = logging.getLogger(__name__) +class ModSet(object): + """ + Mod set attribute tracker + """ + def __init__(self, **kwargs): + """ Constructor + All mods default to False + :param kwargs: Any class attribute can be set here. + """ + self.mod_src_mac = False + self.mod_dst_mac = False + self.mod_src_ip = False + self.mod_dst_ip = False + self.mod_src_port = False + self.mod_dst_port = False + + for (key, value) in kwargs.items(): + if hasattr(self, key): + setattr(self, key, value) + class SimpleSocket(object): """ @@ -170,8 +191,7 @@ class KeepAliveThread(threading.Thread): self.finished = threading.Event() self.setDaemon(True) _LOGGER.debug( - 'Xena Socket keep alive thread initiated, interval ' + - '{} seconds'.format(self.interval)) + 'Xena Socket keep alive thread initiated, interval %s seconds', self.interval) def stop(self): """ Thread stop. See python thread docs for more info @@ -640,57 +660,98 @@ class XenaStream(object): """ return self._stream_id - def enable_multistream(self, flows, layer): + def enable_multistream(self, flows, mod_class): """ - Basic implementation of multi stream. Enable multi stream by setting - modifiers on the stream - :param flows: Numbers of flows or end range - :param layer: layer to enable multi stream as str. Acceptable values - are L2, L3, or L4 + Implementation of multi stream. Enable multi stream by setting + modifiers on the stream. If no mods are selected, src_ip mod will be used. + :param flows: Numbers of flows, Values greater than 65535 will square rooted + to the closest value. Xena mods are limited to 4 bytes. + :param mod_class: ModSet object :return: True if success False otherwise """ if not self._header_protocol: raise RuntimeError( "Please set a protocol header before calling this method.") - - # byte offsets for setting the modifier - offsets = { - 'L2': [0, 6], - 'L3': [32, 36] if 'VLAN' in self._header_protocol else [28, 32], - 'L4': [38, 40] if 'VLAN' in self._header_protocol else [34, 36] - } - - responses = list() - if layer in offsets.keys() and flows > 0: - command = make_port_command( - CMD_STREAM_MODIFIER_COUNT + ' [{}]'.format(self._stream_id) + - ' 2', self._xena_port) - responses.append(self._manager.driver.ask_verify(command)) - command = make_port_command( - CMD_STREAM_MODIFIER + ' [{},0] {} 0xFFFF0000 INC 1'.format( - self._stream_id, offsets[layer][0]), self._xena_port) - responses.append(self._manager.driver.ask_verify(command)) - command = make_port_command( - CMD_STREAM_MODIFIER_RANGE + ' [{},0] 0 1 {}'.format( - self._stream_id, flows), self._xena_port) - responses.append(self._manager.driver.ask_verify(command)) - command = make_port_command( - CMD_STREAM_MODIFIER + ' [{},1] {} 0xFFFF0000 INC 1'.format( - self._stream_id, offsets[layer][1]), self._xena_port) - responses.append(self._manager.driver.ask_verify(command)) - command = make_port_command( - CMD_STREAM_MODIFIER_RANGE + ' [{},1] 0 1 {}'.format( - self._stream_id, flows), self._xena_port) - responses.append(self._manager.driver.ask_verify(command)) - return all(responses) # return True if they all worked - elif flows < 1: - _LOGGER.warning( - 'No flows specified in enable multistream. Bypassing...') - return False + # maximum value for a Xena modifier is 65535 (unsigned int). If flows + # is greater than 65535 we have to do two mods getting as close as we + # can with square rooting the flow count. + if flows > 4294836225: + _LOGGER.debug('Flow mods exceeds highest value, changing to 4294836225') + flows = 4294836225 + if flows <= 65535: + mod1 = flows + mod2 = 0 else: - raise NotImplementedError( - "Non-implemented stream layer in method enable multistream ", - "layer=", layer) + mod1, mod2 = int(math.sqrt(flows)), int(math.sqrt(flows)) + _LOGGER.debug('Flow count modified to %s', mod1*mod2) + offset_list = list() + if not any([mod_class.mod_src_mac, mod_class.mod_dst_mac, mod_class.mod_src_ip, + mod_class.mod_dst_ip, mod_class.mod_src_port, mod_class.mod_dst_port]): + # no mods were selected, default to src ip only + mod_class.mod_src_ip = True + if mod_class.mod_src_mac: + offset_list.append(3) + if mod_class.mod_dst_mac: + offset_list.append(9) + if mod_class.mod_src_ip: + offset_list.append(32 if 'VLAN' in self._header_protocol else 28) + if mod_class.mod_dst_ip: + offset_list.append(36 if 'VLAN' in self._header_protocol else 32) + if mod_class.mod_src_port: + offset_list.append(38 if 'VLAN' in self._header_protocol else 34) + if mod_class.mod_dst_port: + offset_list.append(40 if 'VLAN' in self._header_protocol else 36) + # calculate how many mods we have to do + countertotal = len(offset_list) + if mod2: + # to handle flows greater than 65535 we will need more mods for + # layer 2 and 3 + for mod in [mod_class.mod_src_mac, mod_class.mod_dst_mac, + mod_class.mod_src_ip, mod_class.mod_dst_ip]: + if mod: + countertotal += 1 + command = make_port_command( + CMD_STREAM_MODIFIER_COUNT + ' [{}]'.format(self._stream_id) + + ' {}'.format(countertotal), self._xena_port) + responses = list() + responses.append(self._manager.driver.ask_verify(command)) + modcounter = 0 + for offset in offset_list: + if (mod_class.mod_dst_port or mod_class.mod_src_port) and \ + (offset >= 38 if 'VLAN' in self._header_protocol else 34): + # only do a 1 mod for udp ports at max 65535 + newmod1 = 65535 if flows >= 65535 else flows + command = make_port_command( + CMD_STREAM_MODIFIER + ' [{},{}] {} 0xFFFF0000 INC 1'.format( + self._stream_id, modcounter, offset), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + command = make_port_command( + CMD_STREAM_MODIFIER_RANGE + ' [{},{}] 0 1 {}'.format( + self._stream_id, modcounter, newmod1 - 1), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + else: + command = make_port_command( + CMD_STREAM_MODIFIER + ' [{},{}] {} 0xFFFF0000 INC 1'.format( + self._stream_id, modcounter, offset), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + command = make_port_command( + CMD_STREAM_MODIFIER_RANGE + ' [{},{}] 0 1 {}'.format( + self._stream_id, modcounter, mod1 - 1), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + # if we have a second modifier set the modifier to mod2 and to + # incremement once every full rotation of mod 1 + if mod2: + modcounter += 1 + command = make_port_command( + CMD_STREAM_MODIFIER + ' [{},{}] {} 0xFFFF0000 INC {}'.format( + self._stream_id, modcounter, offset-2, mod1), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + command = make_port_command( + CMD_STREAM_MODIFIER_RANGE + ' [{},{}] 0 1 {}'.format( + self._stream_id, modcounter, mod2), self._xena_port) + responses.append(self._manager.driver.ask_verify(command)) + modcounter += 1 + return all(responses) # return True if they all worked def get_stream_data(self): """ @@ -904,7 +965,7 @@ class XenaRXStats(object): statdict[entry_id] = self._pack_stats(param, 3) elif param[1] == 'PR_TPLDS': tid_list = self._pack_tplds_stats(param, 2) - if len(tid_list): + if tid_list: statdict['pr_tplds'] = tid_list elif param[1] == 'PR_TPLDTRAFFIC': if 'pr_tpldstraffic' in statdict: diff --git a/tools/pkt_gen/xena/json/xena_json.py b/tools/pkt_gen/xena/json/xena_json.py index b1eed720..e56b4125 100644 --- a/tools/pkt_gen/xena/json/xena_json.py +++ b/tools/pkt_gen/xena/json/xena_json.py @@ -26,10 +26,9 @@ Xena JSON module from collections import OrderedDict import locale import logging +import math import os -import scapy.layers.inet as inet - from tools.pkt_gen.xena.json import json_utilities _LOGGER = logging.getLogger(__name__) @@ -73,30 +72,87 @@ class XenaJSON(object): 3: ('Dest IP Addr', 'Src IP Addr'), 4: ('Dest Port', 'Src Port') } - segments = [ - { - "Offset": 0, - "Mask": "//8=", # mask of 255/255 - "Action": "INC", - "StartValue": 0, - "StopValue": stop_value, - "StepValue": 1, - "RepeatCount": 1, - "SegmentId": seg_uuid, - "FieldName": field_name[int(layer)][0] - }, - { - "Offset": 0, - "Mask": "//8=", # mask of 255/255 - "Action": "INC", - "StartValue": 0, - "StopValue": stop_value, - "StepValue": 1, - "RepeatCount": 1, - "SegmentId": seg_uuid, - "FieldName": field_name[int(layer)][1] - } - ] + + if stop_value > 4294836225: + _LOGGER.debug('Flow mods exceeds highest value, changing to 4294836225') + stop_value = 4294836225 + + if stop_value <= 65535 or layer == 4: + segments = [ + { + "Offset": 0 if layer == 4 else 2, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": 1, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][0] + }, + { + "Offset": 0 if layer == 4 else 2, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": 1, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][1] + } + ] + else: + stop_value = int(math.sqrt(stop_value)) + _LOGGER.debug('Flow count modified to %s', stop_value * stop_value) + segments = [ + { + "Offset": 0 if layer == 3 else 1, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": stop_value, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][0] + }, + { + "Offset": 2 if layer == 3 else 3, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": 1, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][0] + }, + { + "Offset": 0 if layer == 3 else 1, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": stop_value, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][1] + }, + { + "Offset": 2 if layer == 3 else 3, + "Mask": "//8=", # mask of 255/255 + "Action": "INC", + "StartValue": 0, + "StopValue": stop_value - 1, + "StepValue": 1, + "RepeatCount": 1, + "SegmentId": seg_uuid, + "FieldName": field_name[int(layer)][1] + } + ] + + self.json_data['StreamProfileHandler']['EntityList'][entity][ 'StreamConfig']['HwModifiers'] = (segments) @@ -279,6 +335,10 @@ class XenaJSON(object): :param kwargs: Extra params per scapy usage. :return: None """ + # import can't be performed at module level, because it conflicts with import + # of customized scapy version by T-Rex + import scapy.layers.inet as inet + self.packet_data['layer2'] = [ inet.Ether(dst=dst_mac, src=src_mac, **kwargs), inet.Ether(dst=src_mac, src=dst_mac, **kwargs)] @@ -293,6 +353,10 @@ class XenaJSON(object): :param kwargs: Extra params per scapy usage :return: None """ + # import can't be performed at module level, because it conflicts with import + # of customized scapy version by T-Rex + import scapy.layers.inet as inet + self.packet_data['layer3'] = [ inet.IP(src=src_ip, dst=dst_ip, proto=protocol.lower(), **kwargs), inet.IP(src=dst_ip, dst=src_ip, proto=protocol.lower(), **kwargs)] @@ -305,6 +369,10 @@ class XenaJSON(object): :param kwargs: Extra params per scapy usage :return: None """ + # import can't be performed at module level, because it conflicts with import + # of customized scapy version by T-Rex + import scapy.layers.inet as inet + self.packet_data['layer4'] = [ inet.UDP(sport=source_port, dport=destination_port, **kwargs), inet.UDP(sport=source_port, dport=destination_port, **kwargs)] @@ -316,6 +384,10 @@ class XenaJSON(object): :param kwargs: Extra params per scapy usage :return: None """ + # import can't be performed at module level, because it conflicts with import + # of customized scapy version by T-Rex + import scapy.layers.inet as inet + self.packet_data['vlan'] = [ inet.Dot1Q(vlan=vlan_id, **kwargs), inet.Dot1Q(vlan=vlan_id, **kwargs)] diff --git a/tools/pkt_gen/xena/xena.py b/tools/pkt_gen/xena/xena.py index 19b44f0b..3adc8294 100755 --- a/tools/pkt_gen/xena/xena.py +++ b/tools/pkt_gen/xena/xena.py @@ -32,8 +32,6 @@ import xml.etree.ElementTree as ET from collections import OrderedDict from time import sleep -import scapy.layers.inet as inet - from conf import merge_spec from conf import settings from core.results.results_constants import ResultsConstants @@ -41,6 +39,7 @@ from tools.pkt_gen.trafficgen.trafficgen import ITrafficGenerator from tools.pkt_gen.xena.XenaDriver import ( aggregate_stats, line_percentage, + ModSet, XenaSocketDriver, XenaManager, ) @@ -149,6 +148,10 @@ class Xena(ITrafficGenerator): :param reverse: Swap source and destination info when building header :return: packet header in hex """ + # import can't be performed at module level, because it conflicts with import + # of customized scapy version by T-Rex + import scapy.layers.inet as inet + srcmac = self._params['traffic']['l2'][ 'srcmac'] if not reverse else self._params['traffic']['l2'][ 'dstmac'] @@ -274,10 +277,6 @@ class Xena(ITrafficGenerator): enable the pairs topology :return: None """ - # set duplex mode, this code is valid, pylint complaining with a - # warning that many have complained about online. - # pylint: disable=redefined-variable-type - try: if self._params['traffic']['bidir'] == "True": j_file = XenaJSONMesh() @@ -285,6 +284,9 @@ class Xena(ITrafficGenerator): j_file = XenaJSONBlocks() elif bonding_test: j_file = XenaJSONPairs() + else: # just default to mesh config + self._logger.error('Invalid traffic type defaulting to Mesh config') + j_file = XenaJSONMesh() j_file.set_chassis_info( settings.getValue('TRAFFICGEN_XENA_IP'), @@ -348,7 +350,7 @@ class Xena(ITrafficGenerator): id=self._params['traffic']['vlan']['cfi'], prio=self._params['traffic']['vlan']['priority']) j_file.add_header_segments( - flows=self._params['traffic']['multistream'], + flows=self._params['traffic']['multistream'] - 1, multistream_layer=self._params['traffic']['stream_type']) j_file.write_config(os.path.join( @@ -456,9 +458,17 @@ class Xena(ITrafficGenerator): port.micro_tpld_enable() if self._params['traffic']['multistream']: + if self._params['traffic']['stream_type'] == 'L2': + modobj = ModSet(mod_src_mac=True, mod_dst_mac=True) + elif self._params['traffic']['stream_type'] == 'L3': + modobj = ModSet(mod_src_ip=True, mod_dst_ip=True) + elif self._params['traffic']['stream_type'] == 'L4': + modobj = ModSet(mod_src_port=True, mod_dst_port=True) + else: + self._logger.error('Invalid segment for multistream. Using L2..') + modobj = ModSet(mod_src_mac=True, mod_dst_mac=True) stream.enable_multistream( - flows=self._params['traffic']['multistream'], - layer=self._params['traffic']['stream_type']) + flows=self._params['traffic']['multistream'], mod_class=modobj) s1_p0 = self.xmanager.ports[0].add_stream() setup_stream(s1_p0, self.xmanager.ports[0], 0) @@ -568,7 +578,7 @@ class Xena(ITrafficGenerator): self._xsocket.disconnect() self._xsocket = None - def send_burst_traffic(self, traffic=None, numpkts=100, duration=20): + def send_burst_traffic(self, traffic=None, duration=20): """Send a burst of traffic. See ITrafficGenerator for description @@ -579,7 +589,7 @@ class Xena(ITrafficGenerator): if traffic: self._params['traffic'] = merge_spec(self._params['traffic'], traffic) - self._start_traffic_api(numpkts) + self._start_traffic_api(traffic['burst_size']) return self._stop_api_traffic() def send_cont_traffic(self, traffic=None, duration=20): diff --git a/tools/report/report.py b/tools/report/report.py index b3f15c1b..5d05e7ad 100644 --- a/tools/report/report.py +++ b/tools/report/report.py @@ -137,7 +137,6 @@ def generate(testcase): 'tests': tests, } i = 0 - # pylint: disable=no-member for output_file in output_files: template = template_env.get_template(_TEMPLATE_FILES[i]) output_text = template.render(template_vars) diff --git a/tools/report/report_foot.rst b/tools/report/report_foot.rst index 5045e186..a49e3452 100644 --- a/tools/report/report_foot.rst +++ b/tools/report/report_foot.rst @@ -5,6 +5,7 @@ Rationale for decisions ======================= + The tests conducted do not have pass/fail/conditional-pass criteria. The test is simply conducted and the results are reported. @@ -12,6 +13,7 @@ is simply conducted and the results are reported. Conclusions and recommendations =============================== + The test results are stable. The vsperf CI jobs that were used to obtain the results can be found at https://wiki.opnfv.org/wiki/vsperf_results. @@ -20,11 +22,13 @@ General Glossary -------- + - NFV - Network Function Virtualization - Mbps - 1,000,000bps Document change procedures and history -------------------------------------- + =============================================== ================= ============= Document ID Author Date Modified =============================================== ================= ============= diff --git a/tools/report/report_rst.jinja b/tools/report/report_rst.jinja index eda0c01e..6b51807a 100644 --- a/tools/report/report_rst.jinja +++ b/tools/report/report_rst.jinja @@ -90,7 +90,9 @@ Testing Activities/Events ~~~~~~~~~~~~~~~~~~~~~~~~~ pidstat is used to collect the process statistics, as such some values such as %CPU and %USER maybe > 100% as the values are summed across multiple cores. For -more info on pidstat please see: http://linux.die.net/man/1/pidstat. +more info on pidstat please see: http://linux.die.net/man/1/pidstat. Please +note that vsperf recalculates the CPU consumption of a process by aggregating +the CPU usage of each thread. Known issues: Some reported metrics have the value "unkown". These values are marked unknown as they are not values retrieved from the external tester diff --git a/tools/systeminfo.py b/tools/systeminfo.py index f34bcce6..6020d0e2 100644 --- a/tools/systeminfo.py +++ b/tools/systeminfo.py @@ -191,7 +191,7 @@ def get_bin_version(binary, regex): return None versions = re.findall(regex, output) - if len(versions): + if versions: return versions[0] else: return None @@ -297,7 +297,7 @@ def get_version(app_name): if not '16' in release: tmp_ver[2] += line.rstrip('\n').split(' ')[2] - if len(tmp_ver[0]): + if tmp_ver[0]: app_version = '.'.join(tmp_ver) app_git_tag = get_git_tag(S.getValue('TOOLS')['dpdk_src']) elif app_name.lower().startswith('qemu'): diff --git a/tools/teststepstools.py b/tools/teststepstools.py index 33db8f79..db2d53e6 100644 --- a/tools/teststepstools.py +++ b/tools/teststepstools.py @@ -43,7 +43,7 @@ class TestStepsTools(object): return True @staticmethod - def validate_Assert(result, dummy_condition): + def validate_Assert(result, _dummy_condition): """ Validate evaluation of given `condition' """ return result @@ -56,7 +56,7 @@ class TestStepsTools(object): return eval(expression) @staticmethod - def validate_Eval(result, dummy_expression): + def validate_Eval(result, _dummy_expression): """ Validate result of python `expression' evaluation """ return result is not None @@ -76,7 +76,7 @@ class TestStepsTools(object): return True @staticmethod - def validate_Exec_Python(result, dummy_code): + def validate_Exec_Python(result, _dummy_code): """ Validate result of python `code' execution """ return result @@ -99,7 +99,7 @@ class TestStepsTools(object): return output @staticmethod - def validate_Exec_Shell(result, dummy_command, dummy_regex=None): + def validate_Exec_Shell(result, _dummy_command, _dummy_regex=None): """ validate result of shell `command' execution """ return result is not None @@ -115,7 +115,7 @@ class TestStepsTools(object): return None @staticmethod - def validate_Exec_Shell_Background(result, dummy_command, dummy_regex=None): + def validate_Exec_Shell_Background(result, _dummy_command, _dummy_regex=None): """ validate result of shell `command' execution on the background """ return result is not None diff --git a/tools/veth.py b/tools/veth.py index 6418d11a..6d7c9962 100644 --- a/tools/veth.py +++ b/tools/veth.py @@ -84,8 +84,7 @@ def del_veth_port(port, peer_port): port, peer_port), False) -# pylint: disable=unused-argument -def validate_add_veth_port(result, port, peer_port): +def validate_add_veth_port(_result, port, peer_port): """ Validation function for integration testcases """ @@ -93,7 +92,7 @@ def validate_add_veth_port(result, port, peer_port): return all([port in devs, peer_port in devs]) -def validate_bring_up_eth_port(result, eth_port, namespace=None): +def validate_bring_up_eth_port(_result, eth_port, namespace=None): """ Validation function for integration testcases """ @@ -110,7 +109,7 @@ def validate_bring_up_eth_port(result, eth_port, namespace=None): return True -def validate_del_veth_port(result, port, peer_port): +def validate_del_veth_port(_result, port, peer_port): """ Validation function for integration testcases """ diff --git a/vnfs/__init__.py b/vnfs/__init__.py index 34cacf4f..1743faf8 100644 --- a/vnfs/__init__.py +++ b/vnfs/__init__.py @@ -17,4 +17,3 @@ This package contains an interface the VSPERF core uses for controlling VNFs and VNF-specific implementation modules of this interface. """ - diff --git a/vnfs/qemu/__init__.py b/vnfs/qemu/__init__.py index 82f32eb9..6ed326dd 100644 --- a/vnfs/qemu/__init__.py +++ b/vnfs/qemu/__init__.py @@ -17,4 +17,3 @@ This package contains an implementation of the interface the VSPERF core uses for controlling VNFs using QEMU and DPDK's testpmd application. """ - diff --git a/vnfs/qemu/qemu.py b/vnfs/qemu/qemu.py index 8e3d44de..7ba58c05 100644 --- a/vnfs/qemu/qemu.py +++ b/vnfs/qemu/qemu.py @@ -222,7 +222,13 @@ class IVnfQemu(IVnf): stdin=proc.stdout) proc.wait() - for cpu in range(0, int(S.getValue('GUEST_SMP')[self._number])): + # calculate the number of CPUs in SMP topology specified by GUEST_SMP + # e.g. "sockets=2,cores=3", "4", etc. + cpu_nr = 1 + for i in re.findall(r'\d', S.getValue('GUEST_SMP')[self._number]): + cpu_nr = cpu_nr * int(i) + # pin each GUEST's core to host core based on configured BINDING + for cpu in range(0, cpu_nr): match = None guest_thread_binding = S.getValue('GUEST_THREAD_BINDING')[self._number] if guest_thread_binding is None: @@ -280,7 +286,7 @@ class IVnfQemu(IVnf): elif self._guest_loopback == 'linux_bridge': self._configure_linux_bridge() elif self._guest_loopback != 'clean': - raise RuntimeError('Unsupported guest loopback method "%s" was specified.', + raise RuntimeError('Unsupported guest loopback method "%s" was specified.' % self._guest_loopback) def wait(self, prompt=None, timeout=30): diff --git a/vnfs/vnf/__init__.py b/vnfs/vnf/__init__.py index b7c43217..6a7a1547 100644 --- a/vnfs/vnf/__init__.py +++ b/vnfs/vnf/__init__.py @@ -15,4 +15,4 @@ """VNF interface and helpers. """ -from vnfs import * +import vnfs diff --git a/vnfs/vnf/vnf.py b/vnfs/vnf/vnf.py index 5ac2ada3..3ad1dcda 100644 --- a/vnfs/vnf/vnf.py +++ b/vnfs/vnf/vnf.py @@ -138,7 +138,7 @@ class IVnf(tasks.Process): self.execute(cmd) return self.wait(prompt=prompt, timeout=timeout) - def validate_start(self, dummyresult): + def validate_start(self, _dummyresult): """ Validate call of VNF start() """ if self._child and self._child.isalive(): @@ -152,7 +152,7 @@ class IVnf(tasks.Process): return not self.validate_start(result) @staticmethod - def validate_execute_and_wait(result, dummy_cmd, dummy_timeout=30, dummy_prompt=''): + def validate_execute_and_wait(result, _dummy_cmd, _dummy_timeout=30, _dummy_prompt=''): """ Validate command execution within VNF """ return len(result) > 0 @@ -23,6 +23,7 @@ import sys import argparse import re import time +import csv import datetime import shutil import unittest @@ -32,6 +33,8 @@ import glob import subprocess import ast import xmlrunner +from tabulate import tabulate +from conf import merge_spec from conf import settings import core.component_factory as component_factory from core.loader import Loader @@ -42,7 +45,6 @@ from tools import networkcard from tools import functions from tools.pkt_gen import trafficgen from tools.opnfvdashboard import opnfvdashboard - sys.dont_write_bytecode = True VERBOSITY_LEVELS = { @@ -61,40 +63,67 @@ _TEMPLATE_RST = {'head' : os.path.join(_CURR_DIR, 'tools/report/report_head.rst 'tmp' : os.path.join(_CURR_DIR, 'tools/report/report_tmp_caption.rst') } +_TEMPLATE_MATRIX = "Performance Matrix\n------------------\n\n"\ + "The following performance matrix was generated with the results of all the\n"\ + "currently run tests. The metric used for comparison is {}.\n\n{}\n\n" _LOGGER = logging.getLogger() +def parse_param_string(values): + """ + Parse and split a single '--test-params' argument. + + This expects either 'x=y', 'x=y,z' or 'x' (implicit true) + values. For multiple overrides use a ; separated list for + e.g. --test-params 'x=z; y=(a,b)' + """ + results = {} + + if values == '': + return {} + + for param, _, value in re.findall('([^;=]+)(=([^;]+))?', values): + param = param.strip() + value = value.strip() + if param: + if value: + # values are passed inside string from CLI, so we must retype them accordingly + try: + results[param] = ast.literal_eval(value) + except ValueError: + # for backward compatibility, we have to accept strings without quotes + _LOGGER.warning("Adding missing quotes around string value: %s = %s", + param, str(value)) + results[param] = str(value) + else: + results[param] = True + return results + + def parse_arguments(): """ Parse command line arguments. """ class _SplitTestParamsAction(argparse.Action): """ - Parse and split the '--test-params' argument. + Parse and split '--test-params' arguments. - This expects either 'x=y', 'x=y,z' or 'x' (implicit true) - values. For multiple overrides use a ; separated list for + This expects either a single list of ; separated overrides + as 'x=y', 'x=y,z' or 'x' (implicit true) values. e.g. --test-params 'x=z; y=(a,b)' + Or a list of these ; separated lists with overrides for + multiple tests. + e.g. --test-params "['x=z; y=(a,b)','x=z']" """ def __call__(self, parser, namespace, values, option_string=None): - results = {} - - for param, _, value in re.findall('([^;=]+)(=([^;]+))?', values): - param = param.strip() - value = value.strip() - if len(param): - if len(value): - # values are passed inside string from CLI, so we must retype them accordingly - try: - results[param] = ast.literal_eval(value) - except ValueError: - # for backward compatibility, we have to accept strings without quotes - _LOGGER.warning("Adding missing quotes around string value: %s = %s", - param, str(value)) - results[param] = str(value) - else: - results[param] = True - + if values[0] == '[': + input_list = ast.literal_eval(values) + parameter_list = [] + for test_params in input_list: + parameter_list.append(parse_param_string(test_params)) + else: + parameter_list = parse_param_string(values) + results = {'_PARAMS_LIST':parameter_list} setattr(namespace, self.dest, results) class _ValidateFileAction(argparse.Action): @@ -126,7 +155,7 @@ def parse_arguments(): def list_logging_levels(): """Give a summary of all available logging levels. - :return: List of verbosity level names in decreasing order of + :return: List of verbosity level names in decreasing order of verbosity """ return sorted(VERBOSITY_LEVELS.keys(), @@ -189,9 +218,14 @@ def parse_arguments(): help='settings file') group.add_argument('--test-params', action=_SplitTestParamsAction, help='csv list of test parameters: key=val; e.g. ' - 'TRAFFICGEN_PKT_SIZES=(64,128);TRAFICGEN_DURATION=30; ' - 'GUEST_LOOPBACK=["l2fwd"] ...') + 'TRAFFICGEN_PKT_SIZES=(64,128);TRAFFICGEN_DURATION=30; ' + 'GUEST_LOOPBACK=["l2fwd"] ...' + ' or a list of csv lists of test parameters: key=val; e.g. ' + '[\'TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(128,)\',' + '\'TRAFFICGEN_DURATION=10;TRAFFICGEN_PKT_SIZES=(64,)\']') group.add_argument('--opnfvpod', help='name of POD in opnfv') + group.add_argument('--matrix', help='enable performance matrix analysis', + action='store_true', default=False) args = vars(parser.parse_args()) @@ -201,13 +235,22 @@ def parse_arguments(): def configure_logging(level): """Configure logging. """ + date = datetime.datetime.fromtimestamp(time.time()) + timestamp = date.strftime('%Y-%m-%d_%H-%M-%S') + settings.setValue('LOG_TIMEMSTAMP', timestamp) + name, ext = os.path.splitext(settings.getValue('LOG_FILE_DEFAULT')) + rename_default = "{name}_{uid}{ex}".format(name=name, uid=timestamp, ex=ext) log_file_default = os.path.join( - settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_DEFAULT')) + settings.getValue('LOG_DIR'), rename_default) log_file_host_cmds = os.path.join( settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_HOST_CMDS')) log_file_traffic_gen = os.path.join( settings.getValue('LOG_DIR'), settings.getValue('LOG_FILE_TRAFFIC_GEN')) + metrics_file = (settings.getValue('LOG_FILE_INFRA_METRICS_PFX') + + timestamp + '.log') + log_file_infra_metrics = os.path.join(settings.getValue('LOG_DIR'), + metrics_file) _LOGGER.setLevel(logging.DEBUG) @@ -219,6 +262,8 @@ def configure_logging(level): file_logger = logging.FileHandler(filename=log_file_default) file_logger.setLevel(logging.DEBUG) + file_logger.setFormatter(logging.Formatter( + '%(asctime)s : %(message)s')) _LOGGER.addHandler(file_logger) class CommandFilter(logging.Filter): @@ -231,6 +276,11 @@ def configure_logging(level): def filter(self, record): return record.getMessage().startswith(trafficgen.CMD_PREFIX) + class CollectdMetricsFilter(logging.Filter): + """Filter out strings beginning with 'COLLECTD' :'""" + def filter(self, record): + return record.getMessage().startswith('COLLECTD') + cmd_logger = logging.FileHandler(filename=log_file_host_cmds) cmd_logger.setLevel(logging.DEBUG) cmd_logger.addFilter(CommandFilter()) @@ -241,6 +291,12 @@ def configure_logging(level): gen_logger.addFilter(TrafficGenCommandFilter()) _LOGGER.addHandler(gen_logger) + if settings.getValue('COLLECTOR') == 'Collectd': + met_logger = logging.FileHandler(filename=log_file_infra_metrics) + met_logger.setLevel(logging.DEBUG) + met_logger.addFilter(CollectdMetricsFilter()) + _LOGGER.addHandler(met_logger) + def apply_filter(tests, tc_filter): """Allow a subset of tests to be conveniently selected @@ -292,7 +348,7 @@ def get_vswitch_names(rst_files): """ Function will return a list of vSwitches detected in given ``rst_files``. """ vswitch_names = set() - if len(rst_files): + if rst_files: try: output = subprocess.check_output(['grep', '-h', '^* vSwitch'] + rst_files).decode().splitlines() for line in output: @@ -300,7 +356,7 @@ def get_vswitch_names(rst_files): if match: vswitch_names.add(match.group(1)) - if len(vswitch_names): + if vswitch_names: return list(vswitch_names) except subprocess.CalledProcessError: @@ -331,7 +387,7 @@ def generate_final_report(): # check if there are any results in rst format rst_results = glob.glob(os.path.join(path, 'result*rst')) pkt_processors = get_vswitch_names(rst_results) - if len(rst_results): + if rst_results: try: test_report = os.path.join(path, '{}_{}'.format('_'.join(pkt_processors), _TEMPLATE_RST['final'])) # create report caption directly - it is not worth to execute jinja machinery @@ -359,6 +415,69 @@ def generate_final_report(): _LOGGER.error('Generatrion of overall test report has failed.') +def generate_performance_matrix(selected_tests, results_path): + """ + Loads the results of all the currently run tests, compares them + based on the MATRIX_METRIC, outputs and saves the generated table. + :selected_tests: list of currently run test + :results_path: directory path to the results of current tests + """ + _LOGGER.info('Performance Matrix:') + test_list = [] + + for test in selected_tests: + test_name = test.get('Name', '<Name not set>') + test_deployment = test.get('Deployment', '<Deployment not set>') + test_list.append({'test_name':test_name, 'test_deployment':test_deployment, 'csv_data':False}) + + test_params = {} + output = [] + all_params = settings.getValue('_PARAMS_LIST') + for i in range(len(selected_tests)): + test = test_list[i] + if isinstance(all_params, list): + list_index = i + if i >= len(all_params): + list_index = len(all_params) - 1 + if settings.getValue('CUMULATIVE_PARAMS') and (i > 0): + test_params.update(all_params[list_index]) + else: + test_params = all_params[list_index] + else: + test_params = all_params + settings.setValue('TEST_PARAMS', test_params) + test['test_params'] = copy.deepcopy(test_params) + try: + with open("{}/result_{}_{}_{}.csv".format(results_path, str(i), + test['test_name'], test['test_deployment'])) as csvfile: + reader = list(csv.DictReader(csvfile)) + test['csv_data'] = reader[0] + # pylint: disable=broad-except + except (Exception) as ex: + _LOGGER.error("Result file not found: %s", ex) + + metric = settings.getValue('MATRIX_METRIC') + change = {} + output_header = ("ID", "Name", metric, "Change [%]", "Parameters, "\ + "CUMULATIVE_PARAMS = {}".format(settings.getValue('CUMULATIVE_PARAMS'))) + if not test_list[0]['csv_data'] or float(test_list[0]['csv_data'][metric]) == 0: + _LOGGER.error("Incorrect format of test results") + return + for i, test in enumerate(test_list): + if test['csv_data']: + change[i] = float(test['csv_data'][metric])/\ + (float(test_list[0]['csv_data'][metric]) / 100) - 100 + output.append([i, test['test_name'], float(test['csv_data'][metric]), + change[i], str(test['test_params'])[1:-1]]) + else: + change[i] = 0 + output.append([i, test['test_name'], "Test Failed", 0, test['test_params']]) + print(tabulate(output, headers=output_header, tablefmt="grid", floatfmt="0.3f")) + with open(results_path + '/result_performance_matrix.rst', 'w+') as output_file: + output_file.write(_TEMPLATE_MATRIX.format(metric, tabulate(output, headers=output_header, + tablefmt="rst", floatfmt="0.3f"))) + _LOGGER.info('Performance matrix written to: "%s/result_performance_matrix.rst"', results_path) + def enable_sriov(nic_list): """ Enable SRIOV for given enhanced PCI IDs @@ -376,7 +495,7 @@ def enable_sriov(nic_list): sriov_nic.update({tmp_nic[0] : int(tmp_nic[1][2:])}) # sriov is required for some NICs - if len(sriov_nic): + if sriov_nic: for nic in sriov_nic: # check if SRIOV is supported and enough virt interfaces are available if not networkcard.is_sriov_supported(nic) \ @@ -483,9 +602,6 @@ def list_testcases(args): print(' {:40} {}'.format('', description[i])) - - - def vsperf_finalize(): """ Clean up before exit """ @@ -495,7 +611,7 @@ def vsperf_finalize(): if os.path.exists(results_path): files_list = os.listdir(results_path) if files_list == []: - _LOGGER.info("Removing empty result directory: " + results_path) + _LOGGER.info("Removing empty result directory: %s", results_path) shutil.rmtree(results_path) except AttributeError: # skip it if parameter doesn't exist @@ -663,16 +779,15 @@ def main(): # create results directory if not os.path.exists(results_path): - _LOGGER.info("Creating result directory: " + results_path) + _LOGGER.info("Creating result directory: %s", results_path) os.makedirs(results_path) - + # pylint: disable=too-many-nested-blocks if settings.getValue('mode') == 'trafficgen': # execute only traffic generator _LOGGER.debug("Executing traffic generator:") loader = Loader() # set traffic details, so they can be passed to traffic ctl traffic = copy.deepcopy(settings.getValue('TRAFFIC')) - traffic = functions.check_traffic(traffic) traffic_ctl = component_factory.create_traffic( @@ -696,7 +811,11 @@ def main(): if args['exact_test_name']: exact_names = args['exact_test_name'] # positional args => exact matches only - selected_tests = [test for test in testcases if test['Name'] in exact_names] + selected_tests = [] + for test_name in exact_names: + for test in testcases: + if test['Name'] == test_name: + selected_tests.append(test) elif args['tests']: # --tests => apply filter to select requested tests selected_tests = apply_filter(testcases, args['tests']) @@ -704,37 +823,57 @@ def main(): # Default - run all tests selected_tests = testcases - if not len(selected_tests): + if not selected_tests: _LOGGER.error("No tests matched --tests option or positional args. Done.") vsperf_finalize() sys.exit(1) - # run tests - # Add pylint exception: Redefinition of test type from - # testcases.integration.IntegrationTestCase to testcases.performance.PerformanceTestCase - # pylint: disable=redefined-variable-type suite = unittest.TestSuite() settings_snapshot = copy.deepcopy(settings.__dict__) - for cfg in selected_tests: + + for i, cfg in enumerate(selected_tests): + settings.setValue('_TEST_INDEX', i) test_name = cfg.get('Name', '<Name not set>') try: + test_params = settings.getValue('_PARAMS_LIST') + if isinstance(test_params, list): + list_index = i + if i >= len(test_params): + list_index = len(test_params) - 1 + test_params = test_params[list_index] + if settings.getValue('CUMULATIVE_PARAMS'): + test_params = merge_spec(settings.getValue('TEST_PARAMS'), test_params) + settings.setValue('TEST_PARAMS', test_params) + if args['integration']: test = IntegrationTestCase(cfg) else: test = PerformanceTestCase(cfg) + test.run() suite.addTest(MockTestCase('', True, test.name)) + # pylint: disable=broad-except except (Exception) as ex: _LOGGER.exception("Failed to run test: %s", test_name) suite.addTest(MockTestCase(str(ex), False, test_name)) _LOGGER.info("Continuing with next test...") finally: - settings.restore_from_dict(settings_snapshot) + if not settings.getValue('CUMULATIVE_PARAMS'): + settings.restore_from_dict(settings_snapshot) + + settings.restore_from_dict(settings_snapshot) + + + # Generate and printout Performance Matrix + if args['matrix']: + generate_performance_matrix(selected_tests, results_path) # generate final rst report with results of all executed TCs generate_final_report() + + if settings.getValue('XUNIT'): xmlrunner.XMLTestRunner( output=settings.getValue('XUNIT_DIR'), outsuffix="", diff --git a/vswitches/__init__.py b/vswitches/__init__.py index a34475be..20a715e0 100644 --- a/vswitches/__init__.py +++ b/vswitches/__init__.py @@ -17,4 +17,3 @@ This package contains an interface the VSPERF core uses for controlling vSwitches and vSwitch-specific implementation modules of this interface. """ - diff --git a/vswitches/ovs.py b/vswitches/ovs.py index 76cabb0d..6dbf0cf8 100644 --- a/vswitches/ovs.py +++ b/vswitches/ovs.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,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,26 +141,57 @@ class IVSwitchOvs(IVSwitch, tasks.Process): def stop(self): """See IVswitch for general description """ + 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] - self._bridges.pop(switch_name) + bridge = self._switches[switch_name] + bridge.del_flow({}) + for port in list(bridge.get_ports()): + bridge.del_port(port) + self._switches.pop(switch_name) bridge.destroy() def add_phy_port(self, switch_name): @@ -166,10 +210,10 @@ class IVSwitchOvs(IVSwitch, tasks.Process): """ if switch_name is None or remote_switch_name is None: - return + 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 @@ -195,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, @@ -211,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) @@ -271,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 @@ -282,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 @@ -293,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 @@ -304,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 @@ -382,7 +496,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): with open(self._ovsdb_pidfile_path, "r") as pidfile: ovsdb_pid = pidfile.read().strip() - self._logger.info("Killing ovsdb with pid: " + ovsdb_pid) + self._logger.info("Killing ovsdb with pid: %s", ovsdb_pid) if ovsdb_pid: tasks.terminate_task(ovsdb_pid, logger=self._logger) @@ -409,10 +523,10 @@ class IVSwitchOvs(IVSwitch, tasks.Process): # # validate methods required for integration testcases # - def validate_add_switch(self, dummy_result, switch_name, dummy_params=None): + 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 @@ -420,7 +534,7 @@ class IVSwitchOvs(IVSwitch, tasks.Process): # Method could be a function # pylint: disable=no-self-use - def validate_del_switch(self, dummy_result, switch_name): + def validate_del_switch(self, _dummy_result, switch_name): """Validate removal of switch """ bridge = OFBridge('tmp') @@ -432,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 @@ -444,16 +558,39 @@ class IVSwitchOvs(IVSwitch, tasks.Process): """ return self.validate_add_phy_port(result, switch_name) - def validate_del_port(self, dummy_result, switch_name, port_name): + 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_flow(self, dummy_result, switch_name, flow, dummy_cache='off'): + 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 """ @@ -466,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): @@ -474,44 +611,44 @@ class IVSwitchOvs(IVSwitch, tasks.Process): return True return False - def validate_del_flow(self, dummy_result, switch_name, flow=None): + def validate_del_flow(self, _dummy_result, switch_name, flow=None): """ Validate removal of the flow """ if not flow: # what else we can do? return True - return not self.validate_add_flow(dummy_result, switch_name, flow) + return not self.validate_add_flow(_dummy_result, switch_name, flow) - def validate_dump_flows(self, dummy_result, dummy_switch_name): + def validate_dump_flows(self, _dummy_result, _dummy_switch_name): """ Validate call of flow dump """ return True - def validate_disable_rstp(self, dummy_result, switch_name): + 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): + 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): + 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): + 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): + def validate_restart(self, _dummy_result): """ Validate restart """ return True 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 58d6bf51..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.") @@ -205,6 +198,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): def add_switch(self, switch_name, dummy_params=None): """See IVswitch for general description """ + # pylint: disable=unused-argument if switch_name in self._switches: self._logger.warning("switch %s already exists...", switch_name) else: @@ -221,6 +215,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): """See IVswitch for general description :raises: RuntimeError """ + # pylint: disable=unused-argument # get list of physical interfaces with PCI addresses vpp_nics = self._get_nic_info(key='Pci') # check if there are any NICs left @@ -239,6 +234,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): def add_vport(self, dummy_switch_name): """See IVswitch for general description """ + # pylint: disable=unused-argument socket_name = S.getValue('TOOLS')['ovs_var_tmp'] + 'dpdkvhostuser' + str(len(self._virt_ports)) if S.getValue('VSWITCH_VHOSTUSER_SERVER_MODE'): mode = ['server'] @@ -266,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, @@ -288,56 +280,59 @@ 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) + 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, dummy_port1, dummy_port2, dummy_bidir=False): + def del_xconnect(self, port1, port2): """Remove xconnect connection between given ports """ - self._logger.warning('VPP: Removal of l2 xconnect is not implemented.') + self.run_vppctl(['set', 'interface', 'l3', port1]) + self.run_vppctl(['set', 'interface', 'l3', port2]) - def del_bridge(self, dummy_switch_name, dummy_port1, dummy_port2): + def del_bridge(self, _dummy_switch_name, port1, port2): """Remove given ports from the bridge """ - self._logger.warning('VPP: Removal of interfaces from bridge is not implemented.') + 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 @@ -347,7 +342,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): def dump_xconnect(self): """Dump l2 xconnect connections """ - self._logger.warning("VPP: Dump of l2 xconnections is not supported.") + self.run_vppctl(['show', 'mode'] + self._phy_ports + self._virt_ports) def dump_bridge(self, switch_name): """Show bridge details @@ -369,7 +364,7 @@ class VppDpdkVhost(IVSwitch, tasks.Process): elif mode == 'bridge': self.dump_bridge(switch_name) else: - raise RuntimeError('VPP: Unsupported l2 connection mode detected %s', mode) + raise RuntimeError('VPP: Unsupported l2 connection mode detected %s' % mode) def run_vppctl(self, args, check_error=False): """Run ``vppctl`` with supplied arguments. @@ -385,50 +380,50 @@ class VppDpdkVhost(IVSwitch, tasks.Process): # # Validate methods # - def validate_add_switch(self, dummy_result, switch_name, dummy_params=None): + def validate_add_switch(self, _dummy_result, switch_name, _dummy_params=None): """Validate - Create a new logical switch with no ports """ return switch_name in self._switches - def validate_del_switch(self, dummy_result, switch_name): + def validate_del_switch(self, _dummy_result, switch_name): """Validate removal of switch """ - return not self.validate_add_switch(dummy_result, switch_name) + return not self.validate_add_switch(_dummy_result, switch_name) - def validate_add_phy_port(self, result, dummy_switch_name): + def validate_add_phy_port(self, result, _dummy_switch_name): """ Validate that physical port was added to bridge. """ return result[0] in self._phy_ports - def validate_add_vport(self, result, dummy_switch_name): + def validate_add_vport(self, result, _dummy_switch_name): """ Validate that virtual port was added to bridge. """ return result[0] in self._virt_ports - def validate_del_port(self, dummy_result, dummy_switch_name, port_name): + def validate_del_port(self, _dummy_result, _dummy_switch_name, port_name): """ Validate that port_name was removed from bridge. """ return not (port_name in self._phy_ports or port_name in self._virt_ports) # pylint: disable=no-self-use - def validate_add_connection(self, dummy_result, dummy_switch_name, dummy_port1, - dummy_port2, dummy_bidir=False): + def validate_add_connection(self, _dummy_result, _dummy_switch_name, _dummy_port1, + _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): + def validate_del_connection(self, _dummy_result, _dummy_switch_name, _dummy_port1, + _dummy_port2): """ Validate that connection was deleted """ return True - def validate_dump_connections(self, dummy_result, dummy_switch_name): + def validate_dump_connections(self, _dummy_result, _dummy_switch_name): """ Validate dump connections call """ return True - def validate_run_vppctl(self, result, dummy_args, dummy_check_error=False): + def validate_run_vppctl(self, result, _dummy_args, _dummy_check_error=False): """validate execution of ``vppctl`` with supplied arguments. """ # there shouldn't be any stderr @@ -437,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 |