NFVBENCH-192: Complete/fix hdrh related processings to consider all cases
[nfvbench.git] / nfvbench / traffic_gen / traffic_base.py
index 3bff7da..30aec6e 100644 (file)
@@ -17,6 +17,8 @@ import sys
 
 from nfvbench.log import LOG
 from . import traffic_utils
+from hdrh.histogram import HdrHistogram
+from functools import reduce
 
 
 class Latency(object):
@@ -32,11 +34,23 @@ class Latency(object):
         self.avg_usec = 0
         self.hdrh = None
         if latency_list:
+            hdrh_list = []
             for lat in latency_list:
                 if lat.available():
                     self.min_usec = min(self.min_usec, lat.min_usec)
                     self.max_usec = max(self.max_usec, lat.max_usec)
                     self.avg_usec += lat.avg_usec
+                if lat.hdrh_available():
+                    hdrh_list.append(HdrHistogram.decode(lat.hdrh))
+
+            # aggregate histograms if any
+            if hdrh_list:
+                def add_hdrh(x, y):
+                    x.add(y)
+                    return x
+                decoded_hdrh = reduce(add_hdrh, hdrh_list)
+                self.hdrh = HdrHistogram.encode(decoded_hdrh).decode('utf-8')
+
             # round to nearest usec
             self.avg_usec = int(round(float(self.avg_usec) / len(latency_list)))
 
@@ -44,6 +58,9 @@ class Latency(object):
         """Return True if latency information is available."""
         return self.min_usec != sys.maxsize
 
+    def hdrh_available(self):
+        """Return True if latency histogram information is available."""
+        return self.hdrh is not None
 
 class TrafficGeneratorException(Exception):
     """Exception for traffic generator."""
@@ -82,7 +99,7 @@ class AbstractTrafficGenerator(object):
         LOG.info('Modified traffic stream for port %s, new rate=%s.', port, self.rates[port_index])
 
     @abc.abstractmethod
-    def get_stats(self):
+    def get_stats(self, ifstats):
         # Must be implemented by sub classes
         return None
 
@@ -126,3 +143,25 @@ class AbstractTrafficGenerator(object):
 
         return: a list of speed in Gbps indexed by the port#
         """
+
+    def get_theoretical_rates(self, avg_packet_size):
+
+        result = {}
+
+        # actual interface speed? (may be a virtual override)
+        intf_speed = self.config.intf_speed_used
+
+        if hasattr(self.config, 'user_info') and self.config.user_info is not None:
+            if "extra_encapsulation_bytes" in self.config.user_info:
+                frame_size_full_encapsulation = avg_packet_size + self.config.user_info[
+                    "extra_encapsulation_bytes"]
+                result['theoretical_tx_rate_pps'] = traffic_utils.bps_to_pps(
+                    intf_speed, frame_size_full_encapsulation) * 2
+                result['theoretical_tx_rate_bps'] = traffic_utils.pps_to_bps(
+                    result['theoretical_tx_rate_pps'], avg_packet_size)
+        else:
+            result['theoretical_tx_rate_pps'] = traffic_utils.bps_to_pps(intf_speed,
+                                                                         avg_packet_size) * 2
+            result['theoretical_tx_rate_bps'] = traffic_utils.pps_to_bps(
+                result['theoretical_tx_rate_pps'], avg_packet_size)
+        return result