Update to py38
[nfvbench.git] / nfvbench / packet_stats.py
index 4b9eac5..d3ec78a 100644 (file)
@@ -21,7 +21,8 @@ PacketPathStatsManager manages all packet path stats for all chains.
 
 import copy
 
 
 import copy
 
-from traffic_gen.traffic_base import Latency
+from hdrh.histogram import HdrHistogram
+from .traffic_gen.traffic_base import Latency
 
 class InterfaceStats(object):
     """A class to hold the RX and TX counters for a virtual or physical interface.
 
 class InterfaceStats(object):
     """A class to hold the RX and TX counters for a virtual or physical interface.
@@ -141,7 +142,7 @@ class PacketPathStats(object):
     chain.
     """
 
     chain.
     """
 
-    def __init__(self, if_stats, aggregate=False):
+    def __init__(self, config, if_stats, aggregate=False):
         """Create a packet path stats intance with the list of associated if stats.
 
         if_stats: a list of interface stats that compose this packet path stats
         """Create a packet path stats intance with the list of associated if stats.
 
         if_stats: a list of interface stats that compose this packet path stats
@@ -150,6 +151,7 @@ class PacketPathStats(object):
         Aggregate packet path stats are the only one that should show counters for shared
         interface stats
         """
         Aggregate packet path stats are the only one that should show counters for shared
         interface stats
         """
+        self.config = config
         self.if_stats = if_stats
         # latency for packets sent from port 0 and 1
         self.latencies = [Latency(), Latency()]
         self.if_stats = if_stats
         # latency for packets sent from port 0 and 1
         self.latencies = [Latency(), Latency()]
@@ -170,7 +172,7 @@ class PacketPathStats(object):
                 ifstats.add_if_stats(pps.if_stats[index])
 
     @staticmethod
                 ifstats.add_if_stats(pps.if_stats[index])
 
     @staticmethod
-    def get_agg_packet_path_stats(pps_list):
+    def get_agg_packet_path_stats(config, pps_list):
         """Get the aggregated packet path stats from a list of packet path stats.
 
         Interface counters are added, latency stats are updated.
         """Get the aggregated packet path stats from a list of packet path stats.
 
         Interface counters are added, latency stats are updated.
@@ -179,7 +181,7 @@ class PacketPathStats(object):
         for pps in pps_list:
             if agg_pps is None:
                 # Get a clone of the first in the list
         for pps in pps_list:
             if agg_pps is None:
                 # Get a clone of the first in the list
-                agg_pps = PacketPathStats(pps.get_cloned_if_stats(), aggregate=True)
+                agg_pps = PacketPathStats(config, pps.get_cloned_if_stats(), aggregate=True)
             else:
                 agg_pps.add_packet_path_stats(pps)
         # aggregate all latencies
             else:
                 agg_pps.add_packet_path_stats(pps)
         # aggregate all latencies
@@ -237,6 +239,21 @@ class PacketPathStats(object):
             results = {'lat_min_usec': latency.min_usec,
                        'lat_max_usec': latency.max_usec,
                        'lat_avg_usec': latency.avg_usec}
             results = {'lat_min_usec': latency.min_usec,
                        'lat_max_usec': latency.max_usec,
                        'lat_avg_usec': latency.avg_usec}
+            if latency.hdrh_available():
+                results['hdrh'] = latency.hdrh
+                decoded_histogram = HdrHistogram.decode(latency.hdrh)
+                results['lat_percentile'] = {}
+                # override min max and avg from hdrh (only if histogram is valid)
+                if decoded_histogram.get_total_count() != 0:
+                    results['lat_min_usec'] = decoded_histogram.get_min_value()
+                    results['lat_max_usec'] = decoded_histogram.get_max_value()
+                    results['lat_avg_usec'] = decoded_histogram.get_mean_value()
+                    for percentile in self.config.lat_percentiles:
+                        results['lat_percentile'][percentile] = decoded_histogram.\
+                            get_value_at_percentile(percentile)
+                else:
+                    for percentile in self.config.lat_percentiles:
+                        results['lat_percentile'][percentile] = 'n/a'
         else:
             results = {}
         results['packets'] = counters
         else:
             results = {}
         results['packets'] = counters
@@ -249,12 +266,13 @@ class PacketPathStatsManager(object):
     Each run will generate packet path stats for 1 or more chains.
     """
 
     Each run will generate packet path stats for 1 or more chains.
     """
 
-    def __init__(self, pps_list):
+    def __init__(self, config, pps_list):
         """Create a packet path stats intance with the list of associated if stats.
 
         pps_list: a list of packet path stats indexed by the chain id.
         All packet path stats must have the same length.
         """
         """Create a packet path stats intance with the list of associated if stats.
 
         pps_list: a list of packet path stats indexed by the chain id.
         All packet path stats must have the same length.
         """
+        self.config = config
         self.pps_list = pps_list
 
     def insert_pps_list(self, chain_index, if_stats):
         self.pps_list = pps_list
 
     def insert_pps_list(self, chain_index, if_stats):
@@ -286,11 +304,11 @@ class PacketPathStatsManager(object):
         chains = {}
         # insert the aggregated row if applicable
         if len(self.pps_list) > 1:
         chains = {}
         # insert the aggregated row if applicable
         if len(self.pps_list) > 1:
-            agg_pps = PacketPathStats.get_agg_packet_path_stats(self.pps_list)
+            agg_pps = PacketPathStats.get_agg_packet_path_stats(self.config, self.pps_list)
             chains['total'] = agg_pps.get_stats(reverse)
 
         for index, pps in enumerate(self.pps_list):
             chains['total'] = agg_pps.get_stats(reverse)
 
         for index, pps in enumerate(self.pps_list):
-            chains[index] = pps.get_stats(reverse)
+            chains[str(index)] = pps.get_stats(reverse)
         return {'interfaces': self._get_if_agg_name(reverse),
                 'chains': chains}
 
         return {'interfaces': self._get_if_agg_name(reverse),
                 'chains': chains}
 
@@ -305,11 +323,11 @@ class PacketPathStatsManager(object):
             'Forward': {
                 'interfaces': ['Port0', 'vhost0', 'Port1'],
                 'chains': {
             'Forward': {
                 'interfaces': ['Port0', 'vhost0', 'Port1'],
                 'chains': {
-                    0: {'packets': [2000054, 1999996, 1999996],
+                    '0': {'packets': [2000054, 1999996, 1999996],
                         'min_usec': 10,
                         'max_usec': 187,
                         'avg_usec': 45},
                         'min_usec': 10,
                         'max_usec': 187,
                         'avg_usec': 45},
-                    1: {...},
+                    '1': {...},
                     'total': {...}
                 }
             },
                     'total': {...}
                 }
             },