Merge "bugfix: Harmonize test/trial RFC2544 terminology"
[vswitchperf.git] / tools / pkt_gen / moongen / moongen.py
index 21dec9c..86a39a7 100644 (file)
@@ -20,10 +20,11 @@ Moongen Traffic Generator Model
 """
 
 # python imports
-import logging
 from collections import OrderedDict
-import subprocess
+import logging
+import math
 import re
+import subprocess
 
 # VSPerf imports
 from conf import settings
@@ -49,6 +50,13 @@ class Moongen(ITrafficGenerator):
         self._moongen_user = settings.getValue('TRAFFICGEN_MOONGEN_USER')
         self._moongen_ports = settings.getValue('TRAFFICGEN_MOONGEN_PORTS')
 
+        if settings.getValue('TRAFFICGEN_MOONGEN_LINE_SPEED_GBPS') == '10':
+            self._moongen_line_speed = math.pow(10, 10)
+        else:
+            raise RuntimeError(
+                'MOONGEN: Invalid line speed in configuration ' + \
+                'file (today 10Gbps supported)')
+
     @property
     def traffic_defaults(self):
         """Default traffic values.
@@ -157,10 +165,17 @@ class Moongen(ITrafficGenerator):
         if one_shot:
             out_file.write("oneShot = true,\n")
 
-        # Assume 10G line rates at the moment.  Need to convert VSPERF
-        # frame_rate (percentage of line rate) to Mpps for Moongen
+        # Need to convert VSPERF frame_rate (percentage of line rate)
+        # to Mpps for Moongen
+        start_rate = str(
+            (traffic['frame_rate'] / 100) * (self._moongen_line_speed / \
+            (8 * (traffic['l2']['framesize'] + 20)) / math.pow(10, 6)))
+
+        logging.debug("startRate = " + start_rate)
+
+        out_file.write("startRate = " + \
+            start_rate + "\n")
 
-        out_file.write("startRate = " + str((traffic['frame_rate'] / 100) * 14.88) + "\n")
         out_file.write("}" + "\n")
         out_file.close()
 
@@ -317,31 +332,31 @@ class Moongen(ITrafficGenerator):
 
         results = OrderedDict()
         results[ResultsConstants.THROUGHPUT_RX_FPS] = (
-            '{:,.6f}'.format(total_throughput_rx_fps))
+            '{:.6f}'.format(total_throughput_rx_fps))
 
         results[ResultsConstants.THROUGHPUT_RX_MBPS] = (
-            '{:,.3f}'.format(total_throughput_rx_mbps))
+            '{:.3f}'.format(total_throughput_rx_mbps))
 
         results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
-            '{:,.3f}'.format(total_throughput_rx_pct))
+            '{:.3f}'.format(total_throughput_rx_pct))
 
         results[ResultsConstants.TX_RATE_FPS] = (
-            '{:,.6f}'.format(total_throughput_tx_fps))
+            '{:.6f}'.format(total_throughput_tx_fps))
 
         results[ResultsConstants.TX_RATE_MBPS] = (
-            '{:,.3f}'.format(total_throughput_tx_mbps))
+            '{:.3f}'.format(total_throughput_tx_mbps))
 
         results[ResultsConstants.TX_RATE_PERCENT] = (
-            '{:,.3f}'.format(total_throughput_tx_pct))
+            '{:.3f}'.format(total_throughput_tx_pct))
 
         results[ResultsConstants.MIN_LATENCY_NS] = (
-            '{:,.3f}'.format(total_min_latency_ns))
+            '{:.3f}'.format(total_min_latency_ns))
 
         results[ResultsConstants.MAX_LATENCY_NS] = (
-            '{:,.3f}'.format(total_max_latency_ns))
+            '{:.3f}'.format(total_max_latency_ns))
 
         results[ResultsConstants.AVG_LATENCY_NS] = (
-            '{:,.3f}'.format(total_avg_latency_ns))
+            '{:.3f}'.format(total_avg_latency_ns))
 
         return results
 
@@ -473,10 +488,21 @@ class Moongen(ITrafficGenerator):
                     'PARAMETERS section of Moongen log file')
                 frame_size = 0
 
-        if results_match and parameters_match:
+            # Each packet stream in the MoonGen report is prefaced with the
+            # words '[REPORT]Device'.  Count the instances of this string to
+            # get the total aggregrate throughput.  For example:
+            #
+            # - If num_traffic_streams = 1, there is a single
+            #                               unidirectional stream
+            #
+            # - If num_traffic_streams = 2, there is a bidirectional
+            #                               traffic stream
+            num_traffic_streams = mytext.count('[REPORT]Device')
+
+        if results_match and parameters_match and num_traffic_streams:
             # Assume for now 10G link speed
-            max_theoretical_mfps = (
-                (10000000000 / 8) / (frame_size + 20))
+            max_theoretical_fps = (
+                num_traffic_streams * (10000000000 / 8) / (frame_size + 20))
 
             moongen_results[ResultsConstants.THROUGHPUT_RX_FPS] = (
                 float(results_match.group(6)) * 1000000)
@@ -485,8 +511,7 @@ class Moongen(ITrafficGenerator):
                 (float(results_match.group(6)) * frame_size + 20) * 8)
 
             moongen_results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
-                float(results_match.group(6)) * \
-                      1000000 / max_theoretical_mfps * 100)
+                (100 * float(results_match.group(6)) * 1000000) / max_theoretical_fps)
 
             moongen_results[ResultsConstants.TX_RATE_FPS] = (
                 float(results_match.group(5)) * 1000000)
@@ -495,8 +520,7 @@ class Moongen(ITrafficGenerator):
                 float(results_match.group(5)) * (frame_size + 20) * 8)
 
             moongen_results[ResultsConstants.TX_RATE_PERCENT] = (
-                float(results_match.group(5)) *
-                1000000 / max_theoretical_mfps * 100)
+                (100 * float(results_match.group(5)) * 1000000) / max_theoretical_fps)
 
             moongen_results[ResultsConstants.B2B_TX_COUNT] = (
                 float(results_match.group(1)))
@@ -513,7 +537,7 @@ class Moongen(ITrafficGenerator):
         return moongen_results
 
     def send_rfc2544_throughput(self, traffic=None, duration=20,
-                                lossrate=0.0, trials=1):
+                                lossrate=0.0, tests=1):
         #
         # Send traffic per RFC2544 throughput test specifications.
         #
@@ -522,7 +546,7 @@ class Moongen(ITrafficGenerator):
         # detected is found.
         #
         # :param traffic: Detailed "traffic" spec, see design docs for details
-        # :param trials: Number of trials to execute
+        # :param tests: Number of tests to execute
         # :param duration: Per iteration duration
         # :param lossrate: Acceptable lossrate percentage
         # :returns: dictionary of strings with following data:
@@ -558,7 +582,7 @@ class Moongen(ITrafficGenerator):
         total_max_latency_ns = 0
         total_avg_latency_ns = 0
 
-        for test_run in range(1, trials+1):
+        for test_run in range(1, tests+1):
             collected_results = (
                 Moongen.run_moongen_and_collect_results(self, test_run=test_run))
 
@@ -587,35 +611,35 @@ class Moongen(ITrafficGenerator):
 
         results = OrderedDict()
         results[ResultsConstants.THROUGHPUT_RX_FPS] = (
-            '{:,.6f}'.format(total_throughput_rx_fps / trials))
+            '{:.6f}'.format(total_throughput_rx_fps / tests))
 
         results[ResultsConstants.THROUGHPUT_RX_MBPS] = (
-            '{:,.3f}'.format(total_throughput_rx_mbps / trials))
+            '{:.3f}'.format(total_throughput_rx_mbps / tests))
 
         results[ResultsConstants.THROUGHPUT_RX_PERCENT] = (
-            '{:,.3f}'.format(total_throughput_rx_pct / trials))
+            '{:.3f}'.format(total_throughput_rx_pct / tests))
 
         results[ResultsConstants.TX_RATE_FPS] = (
-            '{:,.6f}'.format(total_throughput_tx_fps / trials))
+            '{:.6f}'.format(total_throughput_tx_fps / tests))
 
         results[ResultsConstants.TX_RATE_MBPS] = (
-            '{:,.3f}'.format(total_throughput_tx_mbps / trials))
+            '{:.3f}'.format(total_throughput_tx_mbps / tests))
 
         results[ResultsConstants.TX_RATE_PERCENT] = (
-            '{:,.3f}'.format(total_throughput_tx_pct / trials))
+            '{:.3f}'.format(total_throughput_tx_pct / tests))
 
         results[ResultsConstants.MIN_LATENCY_NS] = (
-            '{:,.3f}'.format(total_min_latency_ns / trials))
+            '{:.3f}'.format(total_min_latency_ns / tests))
 
         results[ResultsConstants.MAX_LATENCY_NS] = (
-            '{:,.3f}'.format(total_max_latency_ns / trials))
+            '{:.3f}'.format(total_max_latency_ns / tests))
 
         results[ResultsConstants.AVG_LATENCY_NS] = (
-            '{:,.3f}'.format(total_avg_latency_ns / trials))
+            '{:.3f}'.format(total_avg_latency_ns / tests))
 
         return results
 
-    def start_rfc2544_throughput(self, traffic=None, trials=3, duration=20,
+    def start_rfc2544_throughput(self, traffic=None, tests=1, duration=20,
                                  lossrate=0.0):
         """Non-blocking version of 'send_rfc2544_throughput'.
 
@@ -631,14 +655,14 @@ class Moongen(ITrafficGenerator):
         self._logger.info('In moongen wait_rfc2544_throughput')
 
     def send_rfc2544_back2back(self, traffic=None, duration=60,
-                               lossrate=0.0, trials=1):
+                               lossrate=0.0, tests=1):
         """Send traffic per RFC2544 back2back test specifications.
 
         Send packets at a fixed rate, using ``traffic``
         configuration, for duration seconds.
 
         :param traffic: Detailed "traffic" spec, see design docs for details
-        :param trials: Number of trials to execute
+        :param tests: Number of tests to execute
         :param duration: Per iteration duration
         :param lossrate: Acceptable loss percentage
 
@@ -672,7 +696,7 @@ class Moongen(ITrafficGenerator):
         results[ResultsConstants.SCAL_STREAM_TYPE] = 0
         results[ResultsConstants.SCAL_PRE_INSTALLED_FLOWS] = 0
 
-        for test_run in range(1, trials+1):
+        for test_run in range(1, tests+1):
             collected_results = (
                 Moongen.run_moongen_and_collect_results(self, test_run=test_run))
 
@@ -702,28 +726,28 @@ class Moongen(ITrafficGenerator):
 
         # Calculate average results
         results[ResultsConstants.B2B_RX_FPS] = (
-            results[ResultsConstants.B2B_RX_FPS] / trials)
+            results[ResultsConstants.B2B_RX_FPS] / tests)
 
         results[ResultsConstants.B2B_RX_PERCENT] = (
-            results[ResultsConstants.B2B_RX_PERCENT] / trials)
+            results[ResultsConstants.B2B_RX_PERCENT] / tests)
 
         results[ResultsConstants.B2B_TX_FPS] = (
-            results[ResultsConstants.B2B_TX_FPS] / trials)
+            results[ResultsConstants.B2B_TX_FPS] / tests)
 
         results[ResultsConstants.B2B_TX_PERCENT] = (
-            results[ResultsConstants.B2B_TX_PERCENT] / trials)
+            results[ResultsConstants.B2B_TX_PERCENT] / tests)
 
         results[ResultsConstants.B2B_TX_COUNT] = (
-            results[ResultsConstants.B2B_TX_COUNT] / trials)
+            results[ResultsConstants.B2B_TX_COUNT] / tests)
 
         results[ResultsConstants.B2B_FRAMES] = (
-            results[ResultsConstants.B2B_FRAMES] / trials)
+            results[ResultsConstants.B2B_FRAMES] / tests)
 
         results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] = (
-            results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] / trials)
+            results[ResultsConstants.B2B_FRAME_LOSS_FRAMES] / tests)
 
         results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] = (
-            results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] / trials)
+            results[ResultsConstants.B2B_FRAME_LOSS_PERCENT] / tests)
 
         results[ResultsConstants.SCAL_STREAM_COUNT] = 0
         results[ResultsConstants.SCAL_STREAM_TYPE] = 0
@@ -731,7 +755,7 @@ class Moongen(ITrafficGenerator):
 
         return results
 
-    def start_rfc2544_back2back(self, traffic=None, trials=1, duration=20,
+    def start_rfc2544_back2back(self, traffic=None, tests=1, duration=20,
                                 lossrate=0.0):
         #
         # Non-blocking version of 'send_rfc2544_back2back'.