summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuc Provoost <luc.provoost@intel.com>2020-07-15 13:51:02 +0200
committerXavier Simonart <xavier.simonart@intel.com>2020-08-03 07:28:50 +0000
commit7c31f36447aa16122ff4b6d1706f7f134d61c1f5 (patch)
treecc74bd9f56d96caf4ce70ab560e625f276f253c0
parent0973d6613091c8ac51215ed48bfd7cef116d02d8 (diff)
Improved IRQ measurements and pushing results
The IRQ test has been reworked to increase the accuracy of the IRQ measurements. Results can now also be pushed to a Prometheus push gateway or to OPNFV's Xtesting. In order to do so, a new file format.yaml has been introduced. Please use this file now to specify the details of the PushGateway or the Xtesting server. Added new test: increment_till_fail.test Change-Id: I111aae3e099bc03e3d2ddd1014a0301bac356e0b Signed-off-by: Luc Provoost <luc.provoost@intel.com>
-rwxr-xr-xVNFs/DPPD-PROX/helper-scripts/rapid/createrapid.py6
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/format.yaml64
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/increment_till_fail.test68
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_corestatstest.py27
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_flowsizetest.py52
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_impairtest.py31
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_irqtest.py78
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_parser.py47
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_portstatstest.py25
-rw-r--r--VNFs/DPPD-PROX/helper-scripts/rapid/rapid_test.py87
-rwxr-xr-xVNFs/DPPD-PROX/helper-scripts/rapid/runrapid.py14
-rwxr-xr-xVNFs/DPPD-PROX/helper-scripts/rapid/stackdeployment.py8
12 files changed, 373 insertions, 134 deletions
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/createrapid.py b/VNFs/DPPD-PROX/helper-scripts/rapid/createrapid.py
index 4644a02..8d627e5 100755
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/createrapid.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/createrapid.py
@@ -32,8 +32,6 @@ class RapidStackManager(object):
options = config.options(section)
for option in options:
rapid_stack_params[option] = config.get(section, option)
- if 'push_gateway' not in rapid_stack_params.keys():
- rapid_stack_params['push_gateway'] = None
return (rapid_stack_params)
@staticmethod
@@ -44,10 +42,9 @@ class RapidStackManager(object):
heat_param = rapid_stack_params['heat_param']
keypair_name = rapid_stack_params['keypair_name']
user = rapid_stack_params['user']
- push_gateway = rapid_stack_params['push_gateway']
deployment = StackDeployment(cloud_name)
deployment.deploy(stack_name, keypair_name, heat_template, heat_param)
- deployment.generate_env_file(user, push_gateway)
+ deployment.generate_env_file(user)
def main():
rapid_stack_params = {}
@@ -60,7 +57,6 @@ def main():
#heat_param = 'params_rapid.yaml'
#keypair_name = 'prox_key'
#user = 'centos'
- #push_gateway = None
RapidStackManager.deploy_stack(rapid_stack_params)
if __name__ == "__main__":
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/format.yaml b/VNFs/DPPD-PROX/helper-scripts/rapid/format.yaml
new file mode 100644
index 0000000..a6e5b0c
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/format.yaml
@@ -0,0 +1,64 @@
+;Format: PushGateway
+;Format: Xtesting
+;URL:
+ part1: http://192.168.36.61:9091/metrics/job/
+ part2: test
+ part3: /instance/
+ part4: environment_file
+;rapid_flowsizetest:
+ Flows: Flows
+ Size: Size
+ RequestedSpeed: RequestedSpeed
+ CoreGenerated: CoreGenerated
+ SentByNIC: SentByNIC
+ FwdBySUT: FwdBySUT
+ RevByCore: RevByCore
+ AvgLatency: AvgLatency
+ PCTLatency: PCTLatency
+ MaxLatency: MaxLatency
+ PacketsSent: PacketsSent
+ PacketsReceived: PacketsReceived
+ PacketsLost: PacketsLost
+rapid_flowsizetest:
+ project_name: "vsperf"
+ scenario: "vsperf"
+ start_date: start_date
+ stop_date: stop_date
+ case_name: test
+ pod_name: "intel-pod10"
+ installer: "Fuel"
+ version: "1.0"
+ build_tag: "none"
+ criteria: "PASS"
+ details:
+ Flows: Flows
+ Size: Size
+ Speed (Mpps):
+ RequestedSpeed: RequestedSpeed
+ CoreGenerated: CoreGenerated
+ SentByNIC: SentByNIC
+ FwdBySUT: FwdBySUT
+ RevByCore: RevByCore
+ Latency (usec):
+ AvgLatency: AvgLatency
+ PCTLatency: PCTLatency
+ MaxLatency: MaxLatency
+ Absolute Packet Count:
+ PacketsSent: PacketsSent
+ PacketsReceived: PacketsReceived
+ PacketsLost: PacketsLost
+rapid_irqtest:
+ Core: Core
+ LessThan1us : B1
+ LessThan5us : B5
+ LessThan10us : B10
+ LessThan50us : B50
+ LessThan100us : B100
+ LessThan500us : B500
+ LessThan1ms : B1000
+ LessThan5ms : B5000
+ LessThan10ms : B10000
+ LessThan50ms : B50000
+ LessThan100ms : B100000
+ LessThan500ms : B500000
+ MoreThan500ms : BM500000
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/increment_till_fail.test b/VNFs/DPPD-PROX/helper-scripts/rapid/increment_till_fail.test
new file mode 100644
index 0000000..29e36bf
--- /dev/null
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/increment_till_fail.test
@@ -0,0 +1,68 @@
+##
+## Copyright (c) 2020 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.
+##
+
+[TestParameters]
+name = IncrementTillFailTesting
+number_of_tests = 2
+total_number_of_test_machines = 2
+lat_percentile = 99
+
+[TestM1]
+name = Generator
+config_file = gen.cfg
+dest_vm = 2
+gencores = [1]
+latcores = [3]
+#bucket_size_exp = 12
+
+[TestM2]
+name = Swap
+config_file = swap.cfg
+cores = [1]
+#prox_socket = true
+#prox_launch_exit = true
+
+[test1]
+test=warmuptest
+flowsize=512
+imix=[64]
+warmupspeed=1
+warmuptime=2
+
+[test2]
+test=increment_till_fail
+# Following parameter defines the success criterium for the test.
+# When this test uses multiple combinations of packet size and flows,
+# all combinations must be meeting the same threshold
+# The threshold is expressed in Mpps
+pass_threshold=0.1
+# Each element in the imix list will result in a separate test. Each element
+# is on its turn a list of packet sizes which will be used during one test
+# execution. If you only want to test 1 size, define a list with only one
+# element.
+imixs=[[64],[64,250,800,800]]
+# the number of flows in the list need to be powers of 2, max 2^30
+# If not a power of 2, we will use the lowest power of 2 that is larger than
+# the requested number of flows. e.g. 9 will result in 16 flows
+flows=[64,500000]
+# Setting one of the following thresholds to infinity (inf)
+# results in the criterion not being evaluated to rate the test as succesful
+drop_rate_threshold = 0.1
+lat_avg_threshold = 50
+lat_perc_threshold = 80
+lat_max_threshold = inf
+step = 0.5
+startspeed = 1
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_corestatstest.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_corestatstest.py
index dddd29c..6b9fdcf 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_corestatstest.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_corestatstest.py
@@ -27,14 +27,12 @@ class CoreStatsTest(RapidTest):
"""
Class to manage the corestatstesting
"""
- def __init__(self, test_param, runtime, pushgateway, environment_file, machines):
- super().__init__(test_param, runtime, pushgateway, environment_file)
+ def __init__(self, test_param, runtime, testname, environment_file,
+ machines):
+ super().__init__(test_param, runtime, testname, environment_file)
self.machines = machines
def run(self):
- # fieldnames = ['PROXID','Time','Received','Sent','NonDPReceived','NonDPSent','Delta','NonDPDelta','Dropped']
- # writer = csv.DictWriter(data_csv_file, fieldnames=fieldnames)
- # writer.writeheader()
RapidLog.info("+------------------------------------------------------------------------------------------------------------------+")
RapidLog.info("| Measuring core statistics on 1 or more PROX instances |")
RapidLog.info("+-----------+-----------+------------+------------+------------+------------+------------+------------+------------+")
@@ -73,15 +71,16 @@ class CoreStatsTest(RapidTest):
old_tsc[i] = new_tsc[i]
tot_drop[i] = tot_drop[i] + tx - rx
RapidLog.info('|{:>10.0f}'.format(i)+ ' |{:>10.0f}'.format(duration)+' | ' + '{:>10.0f}'.format(rx) + ' | ' +'{:>10.0f}'.format(tx) + ' | '+'{:>10.0f}'.format(non_dp_rx)+' | '+'{:>10.0f}'.format(non_dp_tx)+' | ' + '{:>10.0f}'.format(tx-rx) + ' | '+ '{:>10.0f}'.format(non_dp_tx-non_dp_rx) + ' | '+'{:>10.0f}'.format(tot_drop[i]) +' |')
- # writer.writerow({'PROXID':i,'Time':duration,'Received':rx,'Sent':tx,'NonDPReceived':non_dp_rx,'NonDPSent':non_dp_tx,'Delta':tx-rx,'NonDPDelta':non_dp_tx-non_dp_rx,'Dropped':tot_drop[i]})
- if self.test['pushgateway']:
- URL = self.test['pushgateway'] + self.test['test']+ '/instance/' + self.test['environment_file'] + str(i)
- DATA = 'PROXID {}\nTime {}\n Received {}\nSent {}\nNonDPReceived {}\nNonDPSent {}\nDelta {}\nNonDPDelta {}\nDropped {}\n'.format(i,duration,rx,tx,non_dp_rx,non_dp_tx,tx-rx,non_dp_tx-non_dp_rx,tot_drop[i])
- HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'text/xml'}
- response = requests.post(url=URL, data=DATA,headers=HEADERS)
- if (response.status_code != 202) and (response.status_code != 200):
- RapidLog.info('Cannot send metrics to {}'.format(URL))
- RapidLog.info(DATA)
+ variables = {'test': self.test['test'],
+ 'environment_file': self.test['environment_file'],
+ 'PROXID': i,
+ 'StepSize': duration,
+ 'Received': rx,
+ 'Sent': tx,
+ 'NonDPReceived': non_dp_rx,
+ 'NonDPSent': non_dp_tx,
+ 'Dropped': tot_drop[i]}
+ self.post_data('rapid_corestatstest', variables)
if machines_to_go == 0:
duration = duration - 1
machines_to_go = len (self.machines)
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_flowsizetest.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_flowsizetest.py
index da53742..c90630e 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_flowsizetest.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_flowsizetest.py
@@ -16,10 +16,8 @@
## See the License for the specific language governing permissions and
## limitations under the License.
##
-
import sys
import time
-import requests
from math import ceil
from statistics import mean
from past.utils import old_div
@@ -32,9 +30,9 @@ class FlowSizeTest(RapidTest):
"""
Class to manage the flowsizetesting
"""
- def __init__(self, test_param, lat_percentile, runtime, pushgateway,
+ def __init__(self, test_param, lat_percentile, runtime, testname,
environment_file, gen_machine, sut_machine, background_machines):
- super().__init__(test_param, runtime, pushgateway, environment_file)
+ super().__init__(test_param, runtime, testname, environment_file)
self.gen_machine = gen_machine
self.sut_machine = sut_machine
self.background_machines = background_machines
@@ -62,6 +60,8 @@ class FlowSizeTest(RapidTest):
def new_speed(self, speed,size,success):
if self.test['test'] == 'fixed_rate':
return (self.test['startspeed'])
+ elif self.test['test'] == 'increment_till_fail':
+ return (speed + self.test['step'])
elif 'TST009' in self.test.keys():
if success:
self.test['TST009_L'] = self.test['TST009_m'] + 1
@@ -79,6 +79,8 @@ class FlowSizeTest(RapidTest):
def get_start_speed_and_init(self, size):
if self.test['test'] == 'fixed_rate':
return (self.test['startspeed'])
+ elif self.test['test'] == 'increment_till_fail':
+ return (self.test['startspeed'])
elif 'TST009' in self.test.keys():
self.test['TST009_L'] = 0
self.test['TST009_R'] = self.test['TST009_n'] - 1
@@ -128,6 +130,7 @@ class FlowSizeTest(RapidTest):
self.set_background_flows(self.background_machines, flow_number)
endspeed = None
speed = self.get_start_speed_and_init(size)
+ self.record_start_time()
while True:
attempts += 1
endwarning = False
@@ -167,7 +170,7 @@ class FlowSizeTest(RapidTest):
if lat_warning or retry_warning:
endwarning = '| | {:177.177} |'.format(retry_warning + lat_warning)
success = True
- TestPassed = False # fixed rate testing cannot be True, it is just reported numbers every second
+ TestPassed = False # fixed rate testing cannot be True, it is just reporting numbers every second
speed_prefix = lat_avg_prefix = lat_perc_prefix = lat_max_prefix = abs_drop_rate_prefix = drop_rate_prefix = bcolors.ENDC
# The following if statement is testing if we pass the success criteria of a certain drop rate, average latency and maximum latency below the threshold
# The drop rate success can be achieved in 2 ways: either the drop rate is below a treshold, either we want that no packet has been lost during the test
@@ -230,8 +233,12 @@ class FlowSizeTest(RapidTest):
success = False
RapidLog.debug(self.report_result(-attempts,size,speed,pps_req_tx,pps_tx,pps_sut_tx,pps_rx,lat_avg,lat_perc,lat_perc_max,lat_max,abs_tx,abs_rx,abs_dropped,actual_duration,speed_prefix,lat_avg_prefix,lat_perc_prefix,lat_max_prefix,abs_drop_rate_prefix,drop_rate_prefix)+ success_message + retry_warning + lat_warning)
speed = self.new_speed(speed, size, success)
- if self.resolution_achieved():
+ if self.test['test'] == 'increment_till_fail':
+ if not success:
+ break
+ elif self.resolution_achieved():
break
+ self.record_stop_time()
if endspeed is not None:
if TestPassed and (endpps_rx < self.test['pass_threshold']):
TestPassed = False
@@ -240,20 +247,27 @@ class FlowSizeTest(RapidTest):
if endwarning:
RapidLog.info (endwarning)
RapidLog.info("+--------+------------------+-------------+-------------+-------------+------------------------+----------+----------+----------+-----------+-----------+-----------+-----------+-------+----+")
- # writer.writerow({'Flows':flow_number,'PacketSize':(size+4),'RequestedPPS':self.get_pps(endspeed,size),'GeneratedPPS':endpps_req_tx,'SentPPS':endpps_tx,'ForwardedPPS':endpps_sut_tx,'ReceivedPPS':endpps_rx,'AvgLatencyUSEC':endlat_avg,'MaxLatencyUSEC':endlat_max,'Sent':endabs_tx,'Received':endabs_rx,'Lost':endabs_dropped,'LostTotal':endabs_dropped})
- if self.test['pushgateway']:
- URL = self.test['pushgateway'] + self.test['test']+ '/instance/' + self.test['environment_file']
- if endabs_dropped == None:
- ead = 0
- else:
- ead = endabs_dropped
- DATA = 'Flows {}\nPacketSize {}\nRequestedPPS {}\nGeneratedPPS {}\nSentPPS {}\nForwardedPPS {}\nReceivedPPS {}\nAvgLatencyUSEC {}\nMaxLatencyUSEC {}\nSent {}\nReceived {}\nLost {}\nLostTotal {}\n'.format(flow_number,size+4,self.get_pps(endspeed,size),endpps_req_tx,endpps_tx,endpps_sut_tx,endpps_rx,endlat_avg,endlat_max,endabs_tx,endabs_rx,ead,ead)
- HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'text/xml'}
- response = requests.post(url=URL, data=DATA,headers=HEADERS)
- if (response.status_code != 202) and (response.status_code != 200):
- RapidLog.info('Cannot send metrics to {}'.format(URL))
- RapidLog.info(DATA)
+ if self.test['test'] != 'fixed_rate':
+ variables = {'test': self.test['testname'],
+ 'environment_file': self.test['environment_file'],
+ 'start_date': self.start,
+ 'stop_date': self.stop,
+ 'Flows': flow_number,
+ 'Size': size,
+ 'RequestedSpeed': RapidTest.get_pps(speed,size),
+ 'CoreGenerated': endpps_req_tx,
+ 'SentByNIC': endpps_tx,
+ 'FwdBySUT': endpps_sut_tx,
+ 'RevByCore': endpps_rx,
+ 'AvgLatency': endlat_avg,
+ 'PCTLatency': endlat_perc,
+ 'MaxLatency': endlat_max,
+ 'PacketsSent': endabs_tx,
+ 'PacketsReceived': endabs_rx,
+ 'PacketsLost': abs_dropped}
+ self.post_data('rapid_flowsizetest', variables)
else:
RapidLog.info('|{:>7}'.format(str(flow_number))+" | Speed 0 or close to 0")
self.gen_machine.stop_latency_cores()
return (TestPassed)
+
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_impairtest.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_impairtest.py
index 8206729..0f92555 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_impairtest.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_impairtest.py
@@ -28,17 +28,14 @@ class ImpairTest(RapidTest):
"""
Class to manage the impair testing
"""
- def __init__(self, test_param, lat_percentile, runtime, pushgateway,
+ def __init__(self, test_param, lat_percentile, runtime, testname,
environment_file, gen_machine, sut_machine):
- super().__init__(test_param, runtime, pushgateway, environment_file)
+ super().__init__(test_param, runtime, testname, environment_file)
self.gen_machine = gen_machine
self.sut_machine = sut_machine
self.test['lat_percentile'] = lat_percentile
def run(self):
- # fieldnames = ['Flows','PacketSize','RequestedPPS','GeneratedPPS','SentPPS','ForwardedPPS','ReceivedPPS','AvgLatencyUSEC','MaxLatencyUSEC','Dropped','DropRate']
- # writer = csv.DictWriter(data_csv_file, fieldnames=fieldnames)
- # writer.writeheader()
imix = self.test['imix']
size = mean (imix)
flow_number = self.test['flowsize']
@@ -68,14 +65,20 @@ class ImpairTest(RapidTest):
else:
lat_warning = ''
RapidLog.info(self.report_result(attempts,size,speed,pps_req_tx,pps_tx,pps_sut_tx,pps_rx,lat_avg,lat_perc,lat_perc_max,lat_max,abs_tx,abs_rx,abs_dropped,actual_duration))
-# writer.writerow({'Flows':flow_number,'PacketSize':(size+4),'RequestedPPS':self.get_pps(speed,size),'GeneratedPPS':pps_req_tx,'SentPPS':pps_tx,'ForwardedPPS':pps_sut_tx_str,'ReceivedPPS':pps_rx,'AvgLatencyUSEC':lat_avg,'MaxLatencyUSEC':lat_max,'Dropped':abs_dropped,'DropRate':drop_rate})
- if self.test['pushgateway']:
- URL = self.test['pushgateway'] + self.test['test'] + '/instance/' + self.test['environment_file']
- DATA = 'Flows {}\nPacketSize {}\nRequestedPPS {}\nGeneratedPPS {}\nSentPPS {}\nForwardedPPS {}\nReceivedPPS {}\nAvgLatencyUSEC {}\nMaxLatencyUSEC {}\nDropped {}\nDropRate {}\n'.format(flow_number,size+4,self.get_pps(speed,size),pps_req_tx,pps_tx,pps_sut_tx,pps_rx,lat_avg,lat_max,abs_dropped,drop_rate)
- HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'text/xml'}
- response = requests.post(url=URL, data=DATA,headers=HEADERS)
- if (response.status_code != 202) and (response.status_code != 200):
- RapidLog.info('Cannot send metrics to {}'.format(URL))
- RapidLog.info(DATA)
+ variables = {'test': self.test['test'],
+ 'environment_file': self.test['environment_file'],
+ 'Flows': flow_number,
+ 'Size': size,
+ 'RequestedSpeed': RapidTest.get_pps(speed,size),
+ 'CoreGenerated': pps_req_tx,
+ 'SentByNIC': pps_tx,
+ 'FwdBySUT': pps_sut_tx,
+ 'RevByCore': pps_rx,
+ 'AvgLatency': lat_avg,
+ 'PCTLatency': lat_perc,
+ 'MaxLatency': lat_max,
+ 'PacketsLost': abs_dropped,
+ 'DropRate': drop_rate}
+ self.post_data('rapid_impairtest', variables)
self.gen_machine.stop_latency_cores()
return (True)
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_irqtest.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_irqtest.py
index feabe65..3b3ef94 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_irqtest.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_irqtest.py
@@ -28,9 +28,9 @@ class IrqTest(RapidTest):
"""
Class to manage the irq testing
"""
- def __init__(self, test_param, runtime, pushgateway, environment_file,
+ def __init__(self, test_param, runtime, testname, environment_file,
machines):
- super().__init__(test_param, runtime, pushgateway, environment_file)
+ super().__init__(test_param, runtime, testname, environment_file)
self.machines = machines
def run(self):
@@ -45,41 +45,53 @@ class IrqTest(RapidTest):
for machine in self.machines:
buckets=machine.socket.show_irq_buckets(1)
print('Measurement ongoing ... ',end='\r')
- machine.stop()
- old_irq = [[0 for x in range(len(buckets)+1)] for y in range(len(machine.get_cores())+1)]
- irq = [[0 for x in range(len(buckets)+1)] for y in range(len(machine.get_cores())+1)]
- irq[0][0] = 'bucket us'
- for j,bucket in enumerate(buckets,start=1):
- irq[0][j] = '<'+ bucket
- irq[0][-1] = '>'+ buckets [-2]
- machine.start()
- time.sleep(2)
- for j,bucket in enumerate(buckets,start=1):
- for i,irqcore in enumerate(machine.get_cores(),start=1):
- old_irq[i][j] = machine.socket.irq_stats(irqcore,j-1)
+ machine.start() # PROX cores will be started within 0 to 1 seconds
+ # That is why we sleep a bit over 1 second to make sure all cores
+ # are started
+ time.sleep(1.2)
+ old_irq = [[0 for x in range(len(buckets))] for y in range(len(machine.get_cores()))]
+ irq = [[0 for x in range(len(buckets))] for y in range(len(machine.get_cores()))]
+ column_names = []
+ for bucket in buckets:
+ column_names.append('<{}'.format(bucket))
+ column_names[-1] = '>{}'.format(buckets[-2])
+ for j,bucket in enumerate(buckets):
+ for i,irqcore in enumerate(machine.get_cores()):
+ old_irq[i][j] = machine.socket.irq_stats(irqcore,j)
+ # Measurements in the loop above, are updated by PROX every second
+ # This means that taking the same measurement 0.5 second later
+ # might results in the same data or data from the next 1s window
time.sleep(float(self.test['runtime']))
- machine.stop()
- for i,irqcore in enumerate(machine.get_cores(),start=1):
- irq[i][0]='core %s'%irqcore
- for j,bucket in enumerate(buckets,start=1):
- diff = machine.socket.irq_stats(irqcore,j-1) - old_irq[i][j]
+ row_names = []
+ for i,irqcore in enumerate(machine.get_cores()):
+ row_names.append(irqcore)
+ for j,bucket in enumerate(buckets):
+ diff = machine.socket.irq_stats(irqcore,j) - old_irq[i][j]
if diff == 0:
irq[i][j] = '0'
else:
irq[i][j] = str(round(old_div(diff,float(self.test['runtime'])), 2))
+ # Measurements in the loop above, are updated by PROX every second
+ # This means that taking the same measurement 0.5 second later
+ # might results in the same data or data from the next 1s window
+ # Conclusion: we don't know the exact window size.
+ # Real measurement windows might be wrong by 1 second
+ # This could be fixed in this script by checking this data every
+ # 0.5 seconds Not implemented since we can also run this test for
+ # a longer time and decrease the error. The absolute number of
+ # interrupts is not so important.
+ machine.stop()
RapidLog.info('Results for PROX instance %s'%machine.name)
- for row in irq:
- RapidLog.info(''.join(['{:>12}'.format(item) for item in row]))
- if self.test['pushgateway']:
- URL = self.test['pushgateway'] + self.test['test']+ '/instance/' + self.test['environment_file']
- HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'text/xml'}
- #DATA = 'Machine {}\n'.format(machine.name)
- for i,irqcore in enumerate(machine.get_cores(),start=1):
- DATA = '{}\n'.format(irq[i][0])
- for j,bucket in enumerate(buckets,start=1):
- DATA = DATA + 'B{} {}\n'.format(irq[0][j].replace(">","M").replace("<","").replace(" ",""),irq[i][j])
- response = requests.post(url=URL, data=DATA,headers=HEADERS)
- if (response.status_code != 202) and (response.status_code != 200):
- RapidLog.info('Cannot send metrics to {}'.format(URL))
- RapidLog.info(DATA)
+ RapidLog.info('{:>12}'.format('bucket us') + ''.join(['{:>12}'.format(item) for item in column_names]))
+ for j, row in enumerate(irq):
+ RapidLog.info('Core {:>7}'.format(row_names[j]) + ''.join(['{:>12}'.format(item) for item in row]))
+ variables = {}
+ variables['test'] = self.test['test']
+ variables['environment_file'] = self.test['environment_file']
+ variables['Machine'] = machine.name
+ for i,irqcore in enumerate(machine.get_cores()):
+ variables['Core'] = '{}'.format(row_names[i])
+ for j,bucket in enumerate(buckets):
+ variables['B{}'.format(column_names[j].replace(">","M").replace("<","").replace(" ",""))] = irq[i][j]
+ self.post_data('rapid_irqtest', variables)
return (True)
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_parser.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_parser.py
index df71811..bdf2703 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_parser.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_parser.py
@@ -33,26 +33,25 @@ class RapidConfigParser(object):
def parse_config(test_params):
testconfig = configparser.RawConfigParser()
testconfig.read(test_params['test_file'])
- test_params['required_number_of_test_machines'] = int(testconfig.get('TestParameters', 'total_number_of_test_machines'))
- test_params['number_of_tests'] = int(testconfig.get('TestParameters', 'number_of_tests'))
+ test_params['required_number_of_test_machines'] = int(testconfig.get(
+ 'TestParameters', 'total_number_of_test_machines'))
+ test_params['number_of_tests'] = int(testconfig.get('TestParameters',
+ 'number_of_tests'))
test_params['TestName'] = testconfig.get('TestParameters', 'name')
if testconfig.has_option('TestParameters', 'lat_percentile'):
- test_params['lat_percentile'] = old_div(float(testconfig.get('TestParameters', 'lat_percentile')),100.0)
+ test_params['lat_percentile'] = old_div(float(
+ testconfig.get('TestParameters', 'lat_percentile')),100.0)
else:
test_params['lat_percentile'] = 0.99
- RapidLog.info('Latency percentile at {:.0f}%'.format(test_params['lat_percentile']*100))
+ RapidLog.info('Latency percentile at {:.0f}%'.format(
+ test_params['lat_percentile']*100))
config = configparser.RawConfigParser()
config.read(test_params['environment_file'])
test_params['vim_type'] = config.get('Varia', 'vim')
test_params['key'] = config.get('ssh', 'key')
test_params['user'] = config.get('ssh', 'user')
- test_params['total_number_of_machines'] = int(config.get('rapid', 'total_number_of_machines'))
- #if config.has_option('TestParameters', 'pushgateway'):
- if config.has_option('Varia', 'pushgateway'):
- test_params['pushgateway'] = config.get('Varia', 'pushgateway')
- RapidLog.info('Measurements will be pushed to %s'%test_params['pushgateway'])
- else:
- test_params['pushgateway'] = None
+ test_params['total_number_of_machines'] = int(config.get('rapid',
+ 'total_number_of_machines'))
tests = []
test = {}
for test_index in range(1, test_params['number_of_tests']+1):
@@ -61,11 +60,16 @@ class RapidConfigParser(object):
options = testconfig.options(section)
for option in options:
if option in ['imix','imixs','flows']:
- test[option] = ast.literal_eval(testconfig.get(section, option))
+ test[option] = ast.literal_eval(testconfig.get(section,
+ option))
# test[option] = [int(i) for i in test[option]]
- elif option in ['maxframespersecondallingress','stepsize','flowsize']:
+ elif option in ['maxframespersecondallingress','stepsize',
+ 'flowsize']:
test[option] = int(testconfig.get(section, option))
- elif option in ['startspeed','drop_rate_threshold','lat_avg_threshold','lat_perc_threshold','lat_max_threshold','accuracy','maxr','maxz','pass_threshold']:
+ elif option in ['startspeed', 'step', 'drop_rate_threshold',
+ 'lat_avg_threshold','lat_perc_threshold',
+ 'lat_max_threshold','accuracy','maxr','maxz',
+ 'pass_threshold']:
test[option] = float(testconfig.get(section, option))
else:
test[option] = testconfig.get(section, option)
@@ -75,7 +79,8 @@ class RapidConfigParser(object):
if 'drop_rate_threshold' not in test.keys():
test['drop_rate_threshold'] = 0
test_params['tests'] = tests
- if test_params['required_number_of_test_machines'] > test_params['total_number_of_machines']:
+ if test_params['required_number_of_test_machines'] > test_params[
+ 'total_number_of_machines']:
RapidLog.exception("Not enough VMs for this test: %d needed and only %d available" % (required_number_of_test_machines,total_number_of_machines))
raise Exception("Not enough VMs for this test: %d needed and only %d available" % (required_number_of_test_machines,total_number_of_machines))
machine_map = configparser.RawConfigParser()
@@ -84,14 +89,19 @@ class RapidConfigParser(object):
machine = {}
for test_machine in range(1, test_params['required_number_of_test_machines']+1):
machine.clear()
- if not(testconfig.has_option('TestM%d'%test_machine, 'prox_socket') and not testconfig.getboolean('TestM%d'%test_machine, 'prox_socket')):
+ if not(testconfig.has_option('TestM%d'%test_machine, 'prox_socket')
+ and not testconfig.getboolean('TestM%d'%test_machine,
+ 'prox_socket')):
section = 'TestM%d'%test_machine
options = testconfig.options(section)
for option in options:
if option in ['prox_socket','prox_launch_exit','monitor']:
machine[option] = testconfig.getboolean(section, option)
elif option in ['cores', 'gencores','latcores']:
- machine[option] = ast.literal_eval(testconfig.get(section, option))
+ machine[option] = ast.literal_eval(testconfig.get(
+ section, option))
+ elif option in ['bucket_size_exp']:
+ machine[option] = int(testconfig.get(section, option))
else:
machine[option] = testconfig.get(section, option)
for key in ['prox_socket','prox_launch_exit']:
@@ -99,7 +109,8 @@ class RapidConfigParser(object):
machine[key] = True
if 'monitor' not in machine.keys():
machine['monitor'] = True
- index = int(machine_map.get('TestM%d'%test_machine, 'machine_index'))
+ index = int(machine_map.get('TestM%d'%test_machine,
+ 'machine_index'))
section = 'M%d'%index
options = config.options(section)
for option in options:
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_portstatstest.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_portstatstest.py
index 6991e87..90bf5b2 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_portstatstest.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_portstatstest.py
@@ -27,15 +27,12 @@ class PortStatsTest(RapidTest):
"""
Class to manage the portstatstesting
"""
- def __init__(self, test_param, runtime, pushgateway, environment_file,
+ def __init__(self, test_param, runtime, testname, environment_file,
machines):
- super().__init__(test_param, runtime, pushgateway, environment_file)
+ super().__init__(test_param, runtime, testname, environment_file)
self.machines = machines
def run(self):
- # fieldnames = ['PROXID','Time','Received','Sent','NoMbufs','iErrMiss']
- # writer = csv.DictWriter(data_csv_file, fieldnames=fieldnames)
- # writer.writeheader()
RapidLog.info("+---------------------------------------------------------------------------+")
RapidLog.info("| Measuring port statistics on 1 or more PROX instances |")
RapidLog.info("+-----------+-----------+------------+------------+------------+------------+")
@@ -69,15 +66,15 @@ class PortStatsTest(RapidTest):
old_errors[i] = new_errors[i]
old_tsc[i] = new_tsc[i]
RapidLog.info('|{:>10.0f}'.format(i)+ ' |{:>10.0f}'.format(duration)+' | ' + '{:>10.0f}'.format(rx) + ' | ' +'{:>10.0f}'.format(tx) + ' | '+'{:>10.0f}'.format(no_mbufs)+' | '+'{:>10.0f}'.format(errors)+' |')
- # writer.writerow({'PROXID':i,'Time':duration,'Received':rx,'Sent':tx,'NoMbufs':no_mbufs,'iErrMiss':errors})
- if self.test['pushgateway']:
- URL = self.test['pushgateway'] + self.test['test'] + '/instance/' + self.test['environment_file'] + str(i)
- DATA = 'PROXID {}\nTime {}\n Received {}\nSent {}\nNoMbufs {}\niErrMiss {}\n'.format(i,duration,rx,tx,no_mbufs,errors)
- HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'text/xml'}
- response = requests.post(url=URL, data=DATA,headers=HEADERS)
- if (response.status_code != 202) and (response.status_code != 200):
- RapidLog.info('Cannot send metrics to {}'.format(URL))
- RapidLog.info(DATA)
+ variables = {'test': self.test['test'],
+ 'environment_file': self.test['environment_file'],
+ 'PROXID': i,
+ 'StepSize': duration,
+ 'Received': rx,
+ 'Sent': tx,
+ 'NoMbufs': no_mbufs,
+ 'iErrMiss': errors}
+ self.post_data('rapid_corestatstest', variables)
if machines_to_go == 0:
duration = duration - 1
machines_to_go = len (self.machines)
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_test.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_test.py
index 0b0b204..3be07c2 100644
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_test.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_test.py
@@ -17,25 +17,31 @@
## limitations under the License.
##
+import yaml
+import requests
import time
+import copy
from past.utils import old_div
from rapid_log import RapidLog
from rapid_log import bcolors
inf = float("inf")
+from datetime import datetime as dt
class RapidTest(object):
"""
Class to manage the testing
"""
- def __init__(self, test_param, runtime, pushgateway, environment_file ):
+ def __init__(self, test_param, runtime, testname, environment_file ):
self.test = test_param
self.test['runtime'] = runtime
- self.test['pushgateway'] = pushgateway
+ self.test['testname'] = testname
self.test['environment_file'] = environment_file
if 'maxr' not in self.test.keys():
self.test['maxr'] = 1
if 'maxz' not in self.test.keys():
self.test['maxz'] = inf
+ with open('format.yaml') as f:
+ self.data_format = yaml.load(f, Loader=yaml.FullLoader)
@staticmethod
def get_percentageof10Gbps(pps_speed,size):
@@ -91,6 +97,48 @@ class RapidTest(object):
machine.stop()
@staticmethod
+ def parse_data_format_dict(data_format, variables):
+ for k, v in data_format.items():
+ if type(v) is dict:
+ RapidTest.parse_data_format_dict(v, variables)
+ else:
+ if v in variables.keys():
+ data_format[k] = variables[v]
+
+ def record_start_time(self):
+ self.start = dt.now().strftime('%Y-%m-%d %H:%M:%S')
+
+ def record_stop_time(self):
+ self.stop = dt.now().strftime('%Y-%m-%d %H:%M:%S')
+
+ def post_data(self, test, variables):
+ var = copy.deepcopy(self.data_format)
+ self.parse_data_format_dict(var, variables)
+ if 'URL' not in var.keys():
+ return
+ if test not in var.keys():
+ return
+ URL=''
+ for value in var['URL'].values():
+ URL = URL + value
+ HEADERS = {'X-Requested-With': 'Python requests', 'Content-type': 'application/rapid'}
+ if 'Format' in var.keys():
+ if var['Format'] == 'PushGateway':
+ data = "\n".join("{} {}".format(k, v) for k, v in var[test].items()) + "\n"
+ response = requests.post(url=URL, data=data,headers=HEADERS)
+ elif var['Format'] == 'Xtesting':
+ data = var[test]
+ response = requests.post(url=URL, json=data)
+ else:
+ return
+ else:
+ return
+ if (response.status_code != 202) and (response.status_code != 200):
+ RapidLog.info('Cannot send metrics to {}'.format(URL))
+ RapidLog.info(data)
+
+
+ @staticmethod
def report_result(flow_number, size, speed, pps_req_tx, pps_tx, pps_sut_tx,
pps_rx, lat_avg, lat_perc, lat_perc_max, lat_max, tx, rx, tot_drop,
elapsed_time,speed_prefix='', lat_avg_prefix='', lat_perc_prefix='',
@@ -114,7 +162,8 @@ class RapidTest(object):
if pps_rx is None:
pps_rx_str = '{0: >25}'.format('NA |')
else:
- pps_rx_str = bcolors.OKBLUE + '{:>4.1f} Gb/s |{:7.3f} Mpps {}|'.format(RapidTest.get_speed(pps_rx,size),pps_rx,bcolors.ENDC)
+ pps_rx_str = bcolors.OKBLUE + '{:>4.1f} Gb/s |{:7.3f} Mpps {}|'.format(
+ RapidTest.get_speed(pps_rx,size),pps_rx,bcolors.ENDC)
if tot_drop is None:
tot_drop_str = ' | NA | '
else:
@@ -122,14 +171,25 @@ class RapidTest(object):
if lat_perc is None:
lat_perc_str = ' |{:^10.10}|'.format('NA')
elif lat_perc_max == True:
- lat_perc_str = '|>{}{:>5.0f} us{} |'.format(lat_perc_prefix,float(lat_perc), bcolors.ENDC)
+ lat_perc_str = '|>{}{:>5.0f} us{} |'.format(lat_perc_prefix,
+ float(lat_perc), bcolors.ENDC)
else:
- lat_perc_str = '| {}{:>5.0f} us{} |'.format(lat_perc_prefix,float(lat_perc), bcolors.ENDC)
+ lat_perc_str = '| {}{:>5.0f} us{} |'.format(lat_perc_prefix,
+ float(lat_perc), bcolors.ENDC)
if elapsed_time is None:
elapsed_time_str = ' NA |'
else:
elapsed_time_str = '{:>3.0f} |'.format(elapsed_time)
- return(flow_number_str + '{:>5.1f}'.format(speed) + '% '+speed_prefix +'{:>6.3f}'.format(RapidTest.get_pps(speed,size)) + ' Mpps|'+ pps_req_tx_str + pps_tx_str + bcolors.ENDC + pps_sut_tx_str + pps_rx_str +lat_avg_prefix+ ' {:>6.0f}'.format(lat_avg)+' us'+lat_perc_str+lat_max_prefix+'{:>6.0f}'.format(lat_max)+' us | ' + '{:>9.0f}'.format(tx) + ' | {:>9.0f}'.format(rx) + ' | '+ abs_drop_rate_prefix+ '{:>9.0f}'.format(tx-rx) + tot_drop_str +drop_rate_prefix+ '{:>5.2f}'.format(old_div(float(tx-rx),tx)) +bcolors.ENDC+' |' + elapsed_time_str)
+ return(flow_number_str + '{:>5.1f}'.format(speed) + '% ' + speed_prefix
+ + '{:>6.3f}'.format(RapidTest.get_pps(speed,size)) + ' Mpps|' +
+ pps_req_tx_str + pps_tx_str + bcolors.ENDC + pps_sut_tx_str +
+ pps_rx_str + lat_avg_prefix + ' {:>6.0f}'.format(lat_avg) +
+ ' us' + lat_perc_str +lat_max_prefix+'{:>6.0f}'.format(lat_max)
+ + ' us | ' + '{:>9.0f}'.format(tx) + ' | {:>9.0f}'.format(rx) +
+ ' | '+ abs_drop_rate_prefix+ '{:>9.0f}'.format(tx-rx) +
+ tot_drop_str +drop_rate_prefix +
+ '{:>5.2f}'.format(old_div(float(tx-rx),tx)) + bcolors.ENDC +
+ ' |' + elapsed_time_str)
def run_iteration(self, requested_duration, flow_number, size, speed):
BUCKET_SIZE_EXP = self.gen_machine.bucket_size_exp
@@ -252,6 +312,21 @@ class RapidTest(object):
lat_avg_sample, sample_percentile, percentile_max,
lat_max_sample, delta_dp_tx, delta_dp_rx,
tot_dp_drop, single_core_measurement_duration))
+ variables = {
+ 'Flows': flow_number,
+ 'Size': size,
+ 'RequestedSpeed': self.get_pps(speed,size),
+ 'CoreGenerated': pps_req_tx,
+ 'SentByNIC': pps_tx,
+ 'FwdBySUT': pps_sut_tx,
+ 'RevByCore': pps_rx,
+ 'AvgLatency': lat_avg_sample,
+ 'PCTLatency': sample_percentile,
+ 'MaxLatency': lat_max_sample,
+ 'PacketsSent': delta_dp_tx,
+ 'PacketsReceived': delta_dp_rx,
+ 'PacketsLost': tot_dp_drop}
+ self.post_data('rapid_flowsizetest', variables)
#Stop generating
self.gen_machine.stop_gen_cores()
r += 1
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/runrapid.py b/VNFs/DPPD-PROX/helper-scripts/rapid/runrapid.py
index db4e969..d3885bf 100755
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/runrapid.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/runrapid.py
@@ -86,27 +86,29 @@ class RapidTestManager(object):
for test_param in test_params['tests']:
RapidLog.info(test_param['test'])
if test_param['test'] in ['flowsizetest', 'TST009test',
- 'fixed_rate']:
+ 'fixed_rate', 'increment_till_fail']:
test = FlowSizeTest(test_param, test_params['lat_percentile'],
- test_params['runtime'], test_params['pushgateway'],
+ test_params['runtime'],
+ test_params['TestName'],
test_params['environment_file'], gen_machine,
sut_machine, background_machines)
elif test_param['test'] in ['corestats']:
test = CoreStatsTest(test_param, test_params['runtime'],
- test_params['pushgateway'],
+ test_params['TestName'],
test_params['environment_file'], machines)
elif test_param['test'] in ['portstats']:
test = PortStatsTest(test_param, test_params['runtime'],
- test_params['pushgateway'],
+ test_params['TestName'],
test_params['environment_file'], machines)
elif test_param['test'] in ['impairtest']:
test = ImpairTest(test_param, test_params['lat_percentile'],
- test_params['runtime'], test_params['pushgateway'],
+ test_params['runtime'],
+ test_params['TestName'],
test_params['environment_file'], gen_machine,
sut_machine)
elif test_param['test'] in ['irqtest']:
test = IrqTest(test_param, test_params['runtime'],
- test_params['pushgateway'],
+ test_params['TestName'],
test_params['environment_file'], machines)
elif test_param['test'] in ['warmuptest']:
test = WarmupTest(test_param, gen_machine)
diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/stackdeployment.py b/VNFs/DPPD-PROX/helper-scripts/rapid/stackdeployment.py
index 525cff1..2e9c6cc 100755
--- a/VNFs/DPPD-PROX/helper-scripts/rapid/stackdeployment.py
+++ b/VNFs/DPPD-PROX/helper-scripts/rapid/stackdeployment.py
@@ -75,7 +75,7 @@ class StackDeployment(object):
for name in server_group_output:
self.names.append(name)
- def print_paramDict(self, user, push_gateway):
+ def print_paramDict(self, user):
if not(len(self.dp_ips) == len(self.dp_macs) == len(self.mngmt_ips)):
sys.exit()
_ENV_FILE_DIR = os.path.dirname(os.path.realpath(__file__))
@@ -106,8 +106,6 @@ class StackDeployment(object):
env_file.write('[Varia]\n')
env_file.write('vim = OpenStack\n')
env_file.write('stack = {}\n'.format(self.stack.stack_name))
- if push_gateway:
- env_file.write('pushgateway = {}\n'.format(push_gateway))
def create_stack(self, stack_name, stack_file_path, param_file):
files, template = template_utils.process_template_path(stack_file_path)
@@ -158,6 +156,6 @@ class StackDeployment(object):
self.create_key()
self.stack = self.create_stack(stack_name, heat_template, heat_param)
- def generate_env_file(self, user = 'centos', push_gateway = None):
+ def generate_env_file(self, user = 'centos'):
self.generate_paramDict()
- self.print_paramDict(user, push_gateway)
+ self.print_paramDict(user)