1 # Copyright 2016 Spirent Communications.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 Code to integrate Spirent TestCenter with the vsperf test framework.
18 Provides a model for Spirent TestCenter as a test tool for implementing
19 various performance tests of a virtual switch.
27 from conf import settings
28 from core.results.results_constants import ResultsConstants
29 from tools.pkt_gen import trafficgen
32 def get_stc_common_settings():
34 Return the common Settings
35 These settings would apply to almost all the tests.
37 args = ["--lab_server_addr",
38 settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"),
39 "--license_server_addr",
40 settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"),
41 "--east_chassis_addr",
42 settings.getValue("TRAFFICGEN_STC_EAST_CHASSIS_ADDR"),
44 settings.getValue("TRAFFICGEN_STC_EAST_SLOT_NUM"),
46 settings.getValue("TRAFFICGEN_STC_EAST_PORT_NUM"),
47 "--west_chassis_addr",
48 settings.getValue("TRAFFICGEN_STC_WEST_CHASSIS_ADDR"),
50 settings.getValue("TRAFFICGEN_STC_WEST_SLOT_NUM"),
52 settings.getValue("TRAFFICGEN_STC_WEST_PORT_NUM"),
53 "--test_session_name",
54 settings.getValue("TRAFFICGEN_STC_TEST_SESSION_NAME"),
56 settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
57 "--csv_results_file_prefix",
58 settings.getValue("TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX")]
62 def get_rfc2544_common_settings():
64 Retrun Generic RFC 2544 settings.
65 These settings apply to all the 2544 tests
67 args = [settings.getValue("TRAFFICGEN_STC_PYTHON2_PATH"),
69 settings.getValue("TRAFFICGEN_STC_TESTCENTER_PATH"),
71 "TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME")),
73 settings.getValue("TRAFFICGEN_STC_RFC2544_METRIC"),
75 settings.getValue("TRAFFICGEN_STC_SEARCH_MODE"),
77 settings.getValue("TRAFFICGEN_STC_LEARNING_MODE"),
78 "--rate_lower_limit_pct",
79 settings.getValue("TRAFFICGEN_STC_RATE_LOWER_LIMIT_PCT"),
80 "--rate_upper_limit_pct",
81 settings.getValue("TRAFFICGEN_STC_RATE_UPPER_LIMIT_PCT"),
83 settings.getValue("TRAFFICGEN_STC_RATE_INITIAL_PCT"),
85 settings.getValue("TRAFFICGEN_STC_RATE_STEP_PCT"),
87 settings.getValue("TRAFFICGEN_STC_RESOLUTION_PCT"),
88 "--acceptable_frame_loss_pct",
89 settings.getValue("TRAFFICGEN_STC_ACCEPTABLE_FRAME_LOSS_PCT"),
91 settings.getValue("TRAFFICGEN_STC_EAST_INTF_ADDR"),
92 "--east_intf_gateway_addr",
93 settings.getValue("TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR"),
95 settings.getValue("TRAFFICGEN_STC_WEST_INTF_ADDR"),
96 "--west_intf_gateway_addr",
97 settings.getValue("TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR"),
98 "--trial_duration_sec",
99 settings.getValue("TRAFFICGEN_STC_TRIAL_DURATION_SEC"),
101 settings.getValue("TRAFFICGEN_STC_TRAFFIC_PATTERN"),
102 "--vsperf_results_dir",
103 settings.getValue("RESULTS_PATH")]
107 def get_rfc2544_custom_settings(framesize, custom_tr, tests):
109 Return RFC2544 Custom Settings
111 args = ["--frame_size_list",
120 def get_rfc2889_common_settings(framesize, tests, metric):
122 Return RFC2889 common Settings
124 new_metric = metric.replace('rfc2889_', '')
125 args = [settings.getValue("TRAFFICGEN_STC_PYTHON2_PATH"),
127 settings.getValue("TRAFFICGEN_STC_TESTCENTER_PATH"),
129 "TRAFFICGEN_STC_RFC2889_TEST_FILE_NAME")),
131 settings.getValue("TRAFFICGEN_STC_LAB_SERVER_ADDR"),
132 "--license_server_addr",
133 settings.getValue("TRAFFICGEN_STC_LICENSE_SERVER_ADDR"),
135 settings.getValue("TRAFFICGEN_STC_RFC2889_LOCATIONS"),
136 "--test_session_name",
137 settings.getValue("TRAFFICGEN_STC_TEST_SESSION_NAME"),
139 settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
140 "--csv_results_file_prefix",
141 settings.getValue("TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX"),
152 def get_rfc2889_custom_settings():
154 Return RFC2889 Custom Settings
156 args = ["--min_learning_rate",
157 settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_LR"),
158 "--max_learning_rate",
159 settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_LR"),
161 settings.getValue("TRAFFICGEN_STC_RFC2889_MIN_ADDRS"),
163 settings.getValue("TRAFFICGEN_STC_RFC2889_MAX_ADDRS"),
164 "--ac_learning_rate",
165 settings.getValue("TRAFFICGEN_STC_RFC2889_AC_LR")]
169 class TestCenter(trafficgen.ITrafficGenerator):
173 _logger = logging.getLogger(__name__)
174 _liveresults_file = settings.getValue("TRAFFICGEN_STC_LIVERESULTS_FILE")
182 def disconnect(self):
188 def send_burst_traffic(self, traffic=None, duration=20):
194 def get_rfc2889_addr_learning_results(self, filename):
196 Reads the CSV file and return the results
199 with open(filename, "r") as csvfile:
200 csvreader = csv.DictReader(csvfile)
201 for row in csvreader:
202 self._logger.info("Row: %s", row)
203 learn_rate = float(row["OptimalLearningRate"])
204 result[ResultsConstants.OPTIMAL_LEARNING_RATE_FPS] = learn_rate
207 def get_rfc2889_addr_caching_results(self, filename):
209 Reads the CSV file and return the results
212 with open(filename, "r") as csvfile:
213 csvreader = csv.DictReader(csvfile)
214 for row in csvreader:
215 self._logger.info("Row: %s", row)
216 caching_cap = float(row["RxFrameCount"])
217 learn_per = (100.0 - (float(row["PercentFrameLoss(%)"])))
218 result[ResultsConstants.CACHING_CAPACITY_ADDRS] = caching_cap
219 result[ResultsConstants.ADDR_LEARNED_PERCENT] = learn_per
222 def get_rfc2889_forwarding_results(self, filename):
224 Reads the CSV file and return the results
227 with open(filename, "r") as csvfile:
228 csvreader = csv.DictReader(csvfile)
229 for row in csvreader:
230 self._logger.info("Row: %s", row)
231 duration = int((float(row["TxSignatureFrameCount"])) /
232 (float(row["OfferedLoad(fps)"])))
233 tx_fps = (float(row["OfferedLoad(fps)"]))
234 rx_fps = float((float(row["RxFrameCount"])) /
236 tx_mbps = ((tx_fps * float(row["FrameSize"])) /
238 rx_mbps = ((rx_fps * float(row["FrameSize"])) /
240 result[ResultsConstants.TX_RATE_FPS] = tx_fps
241 result[ResultsConstants.THROUGHPUT_RX_FPS] = rx_fps
242 result[ResultsConstants.TX_RATE_MBPS] = tx_mbps
243 result[ResultsConstants.THROUGHPUT_RX_MBPS] = rx_mbps
244 result[ResultsConstants.TX_RATE_PERCENT] = float(
245 row["OfferedLoad(%)"])
246 result[ResultsConstants.FRAME_LOSS_PERCENT] = float(
247 row["PercentFrameLoss(%)"])
248 result[ResultsConstants.FORWARDING_RATE_FPS] = float(
249 row["ForwardingRate(fps)"])
252 def send_rfc2889_forwarding(self, traffic=None, tests=1, _duration=20):
254 Send traffic per RFC2889 Forwarding test specifications.
256 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
257 if traffic and 'l2' in traffic:
258 if 'framesize' in traffic['l2']:
259 framesize = traffic['l2']['framesize']
260 args = get_rfc2889_common_settings(framesize, tests,
261 traffic['traffic_type'])
262 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
263 args.append("--verbose")
265 self._logger.debug("Arguments used to call test: %s", args)
266 subprocess.check_call(args)
268 filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
270 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
274 self._logger.info("file: %s", filec)
276 return self.get_rfc2889_forwarding_results(filec)
278 def send_rfc2889_caching(self, traffic=None, tests=1, _duration=20):
280 Send as per RFC2889 Addr-Caching test specifications.
282 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
283 if traffic and 'l2' in traffic:
284 if 'framesize' in traffic['l2']:
285 framesize = traffic['l2']['framesize']
286 common_args = get_rfc2889_common_settings(framesize, tests,
287 traffic['traffic_type'])
288 custom_args = get_rfc2889_custom_settings()
289 args = common_args + custom_args
291 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
292 args.append("--verbose")
294 self._logger.debug("Arguments used to call test: %s", args)
295 subprocess.check_call(args)
297 filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
299 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
303 self._logger.info("file: %s", filec)
305 return self.get_rfc2889_addr_caching_results(filec)
307 def send_rfc2889_learning(self, traffic=None, tests=1, _duration=20):
309 Send traffic per RFC2889 Addr-Learning test specifications.
311 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
312 if traffic and 'l2' in traffic:
313 if 'framesize' in traffic['l2']:
314 framesize = traffic['l2']['framesize']
315 common_args = get_rfc2889_common_settings(framesize, tests,
316 traffic['traffic_type'])
317 custom_args = get_rfc2889_custom_settings()
318 args = common_args + custom_args
320 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
321 args.append("--verbose")
323 self._logger.debug("Arguments used to call test: %s", args)
324 subprocess.check_call(args)
326 filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
328 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
332 self._logger.info("file: %s", filec)
334 return self.get_rfc2889_addr_learning_results(filec)
336 def get_rfc2544_results(self, filename, genome=None):
338 Reads the CSV file and return the results
341 if not os.path.exists(filename):
343 with open(filename, "r") as csvfile:
344 csvreader = csv.DictReader(csvfile)
345 for row in csvreader:
346 self._logger.info("Row: %s", row)
347 tx_fps = ((float(row["TxFrameCount"])) /
348 (float(row["Duration(sec)"])))
349 rx_fps = ((float(row["RxFrameCount"])) /
350 (float(row["Duration(sec)"])))
351 tx_mbps = ((float(row["TxFrameCount"]) *
352 float(row["ConfiguredFrameSize"])) /
353 (float(row["Duration(sec)"]) * 1000000.0))
354 rx_mbps = ((float(row["RxFrameCount"]) *
355 float(row["ConfiguredFrameSize"])) /
356 (float(row["Duration(sec)"]) * 1000000.0))
357 result[ResultsConstants.TX_RATE_FPS] = tx_fps
358 result[ResultsConstants.THROUGHPUT_RX_FPS] = rx_fps
359 result[ResultsConstants.TX_RATE_MBPS] = tx_mbps
360 result[ResultsConstants.THROUGHPUT_RX_MBPS] = rx_mbps
361 result[ResultsConstants.TX_RATE_PERCENT] = float(
362 row["OfferedLoad(%)"])
363 result[ResultsConstants.THROUGHPUT_RX_PERCENT] = float(
364 row["Throughput(%)"])
365 result[ResultsConstants.MIN_LATENCY_NS] = float(
366 row["MinimumLatency(us)"]) * 1000
367 result[ResultsConstants.MAX_LATENCY_NS] = float(
368 row["MaximumLatency(us)"]) * 1000
369 result[ResultsConstants.AVG_LATENCY_NS] = float(
370 row["AverageLatency(us)"]) * 1000
371 result[ResultsConstants.FRAME_LOSS_PERCENT] = float(
374 result[ResultsConstants.IMIX_GENOME] = genome
375 result[ResultsConstants.IMIX_AVG_FRAMESIZE] = float(
379 def send_cont_traffic(self, traffic=None, duration=30):
381 Send Custom - Continuous Test traffic
382 Reuse RFC2544 throughput test specifications along with
383 'custom' configuration
387 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
388 if traffic and 'l2' in traffic:
389 if 'framesize' in traffic['l2']:
390 framesize = traffic['l2']['framesize']
392 stc_common_args = get_stc_common_settings()
393 rfc2544_common_args = get_rfc2544_common_settings()
394 rfc2544_custom_args = get_rfc2544_custom_settings(framesize,
396 args = rfc2544_common_args + stc_common_args + rfc2544_custom_args
398 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
399 args.append("--verbose")
401 self._logger.debug("Arguments used to call test: %s", args)
402 subprocess.check_call(args)
404 filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
406 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
410 self._logger.info("file: %s", filec)
412 return self.get_rfc2544_results(filec)
414 def send_rfc2544_throughput(self, traffic=None, tests=1, duration=20,
417 Send traffic per RFC2544 throughput test specifications.
420 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
421 if traffic and 'l2' in traffic:
422 if 'framesize' in traffic['l2']:
423 framesize = traffic['l2']['framesize']
425 stc_common_args = get_stc_common_settings()
426 rfc2544_common_args = get_rfc2544_common_settings()
427 rfc2544_custom_args = get_rfc2544_custom_settings(framesize, '',
429 args = rfc2544_common_args + stc_common_args + rfc2544_custom_args
431 if traffic and 'latency_histogram' in traffic:
432 if traffic['latency_histogram']['enabled']:
433 if traffic['latency_histogram']['type'] == 'Default':
434 args.append("--latency_histogram")
437 if traffic and 'imix' in traffic:
438 if traffic['imix']['enabled']:
439 if traffic['imix']['type'] == 'genome':
440 genome = traffic['imix']['genome']
441 args.append('--imix')
444 if settings.getValue("TRAFFICGEN_STC_LIVE_RESULTS") == "True":
445 args.append('--live_results')
446 args.append('--logfile')
447 args.append(self._liveresults_file)
449 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
450 args.append("--verbose")
452 self._logger.debug("Arguments used to call test: %s", args)
453 subprocess.check_call(args)
455 filec = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
457 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
461 self._logger.info("file: %s", filec)
463 return self.get_rfc2544_results(filec, genome)
465 def send_rfc2544_back2back(self, traffic=None, tests=1, duration=20,
468 Send traffic per RFC2544 BacktoBack test specifications.
471 framesize = settings.getValue("TRAFFICGEN_STC_FRAME_SIZE")
472 if traffic and 'l2' in traffic:
473 if 'framesize' in traffic['l2']:
474 framesize = traffic['l2']['framesize']
476 stc_common_args = get_stc_common_settings()
477 rfc2544_common_args = get_rfc2544_common_settings()
478 rfc2544_custom_args = get_rfc2544_custom_settings(framesize, '',
480 args = rfc2544_common_args + stc_common_args + rfc2544_custom_args
482 if settings.getValue("TRAFFICGEN_STC_VERBOSE") == "True":
483 args.append("--verbose")
485 self._logger.info("Arguments used to call test: %s", args)
486 subprocess.check_call(args)
488 filecs = os.path.join(settings.getValue("TRAFFICGEN_STC_RESULTS_DIR"),
490 "TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX") +
493 self._logger.debug("file: %s", filecs)
495 return self.get_rfc2544_results(filecs)
497 def start_cont_traffic(self, traffic=None, duration=30):
498 raise NotImplementedError('TestCenter start_cont_traffic not implement.')
500 def stop_cont_traffic(self):
501 raise NotImplementedError('TestCenter stop_cont_traffic not implement.')
503 def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20,
505 raise NotImplementedError('TestCenter start_rfc2544_back2back not implement.')
507 def wait_rfc2544_back2back(self):
508 raise NotImplementedError('TestCenter wait_rfc2544_back2back not implement.')
510 def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20,
512 raise NotImplementedError('TestCenter start_rfc2544_throughput not implement.')
514 def wait_rfc2544_throughput(self):
515 raise NotImplementedError('TestCenter wait_rfc2544_throughput not implement.')
517 if __name__ == '__main__':
522 'dstip': '90.90.90.90',
525 with TestCenter() as dev:
526 print(dev.send_rfc2544_throughput(traffic=TRAFFIC))
527 # pylint: disable=no-member
528 print(dev.send_rfc2544_backtoback(traffic=TRAFFIC))