NFVBENCH-163: Add gratuitous ARP in case of L3 router mode
[nfvbench.git] / nfvbench / traffic_client.py
index 6972509..c349289 100755 (executable)
@@ -16,6 +16,7 @@
 import socket
 import struct
 import time
+import sys
 
 from attrdict import AttrDict
 import bitmath
@@ -1068,6 +1069,9 @@ class TrafficClient(object):
                    'theoretical_tx_rate_bps': stats['theoretical_tx_rate_bps'],
                    'theoretical_tx_rate_pps': stats['theoretical_tx_rate_pps']}
 
+        if self.config.periodic_gratuitous_arp:
+            retDict['garp_total_tx_rate'] = stats['garp_total_tx_rate']
+
         tx_keys = ['total_pkts', 'total_pkt_bytes', 'pkt_rate', 'pkt_bit_rate']
         rx_keys = tx_keys + ['dropped_pkts']
 
@@ -1112,20 +1116,25 @@ class TrafficClient(object):
             for key in ['pkt_bit_rate', 'pkt_rate']:
                 for dirc in ['tx', 'rx']:
                     retDict['overall'][dirc][key] /= 2.0
-                retDict['overall']['hdrh'] = stats.get('hdrh', None)
-                if retDict['overall']['hdrh']:
-                    decoded_histogram = HdrHistogram.decode(retDict['overall']['hdrh'])
-                    # override min max and avg from hdrh
-                    retDict['overall']['rx']['min_delay_usec'] = decoded_histogram.get_min_value()
-                    retDict['overall']['rx']['max_delay_usec'] = decoded_histogram.get_max_value()
-                    retDict['overall']['rx']['avg_delay_usec'] = decoded_histogram.get_mean_value()
-                    retDict['overall']['rx']['lat_percentile'] = {}
-                    for percentile in self.config.lat_percentiles:
-                        retDict['overall']['rx']['lat_percentile'][percentile] = \
-                            decoded_histogram.get_value_at_percentile(percentile)
         else:
             retDict['overall'] = retDict[ports[0]]
         retDict['overall']['drop_rate_percent'] = self.__get_dropped_rate(retDict['overall'])
+
+        if 'overall_hdrh' in stats:
+            retDict['overall']['hdrh'] = stats.get('overall_hdrh', None)
+            decoded_histogram = HdrHistogram.decode(retDict['overall']['hdrh'])
+            retDict['overall']['rx']['lat_percentile'] = {}
+            # override min max and avg from hdrh (only if histogram is valid)
+            if decoded_histogram.get_total_count() != 0:
+                retDict['overall']['rx']['min_delay_usec'] = decoded_histogram.get_min_value()
+                retDict['overall']['rx']['max_delay_usec'] = decoded_histogram.get_max_value()
+                retDict['overall']['rx']['avg_delay_usec'] = decoded_histogram.get_mean_value()
+                for percentile in self.config.lat_percentiles:
+                    retDict['overall']['rx']['lat_percentile'][percentile] = \
+                        decoded_histogram.get_value_at_percentile(percentile)
+            else:
+                for percentile in self.config.lat_percentiles:
+                    retDict['overall']['rx']['lat_percentile'][percentile] = 'n/a'
         return retDict
 
     def __convert_rates(self, rate):
@@ -1154,19 +1163,21 @@ class TrafficClient(object):
             }
 
             if key == 'overall':
-                stats[key]['hdrh'] = interface.get('hdrh', None)
-                if stats[key]['hdrh']:
+                if 'hdrh' in interface:
+                    stats[key]['hdrh'] = interface.get('hdrh', None)
                     decoded_histogram = HdrHistogram.decode(stats[key]['hdrh'])
-                    # override min max and avg from hdrh
-                    stats[key]['min_delay_usec'] = decoded_histogram.get_min_value()
-                    stats[key]['max_delay_usec'] = decoded_histogram.get_max_value()
-                    stats[key]['avg_delay_usec'] = decoded_histogram.get_mean_value()
                     stats[key]['lat_percentile'] = {}
-                    for percentile in self.config.lat_percentiles:
-                        stats[key]['lat_percentile'][percentile] = decoded_histogram.\
-                            get_value_at_percentile(percentile)
-
-
+                    # override min max and avg from hdrh (only if histogram is valid)
+                    if decoded_histogram.get_total_count() != 0:
+                        stats[key]['min_delay_usec'] = decoded_histogram.get_min_value()
+                        stats[key]['max_delay_usec'] = decoded_histogram.get_max_value()
+                        stats[key]['avg_delay_usec'] = decoded_histogram.get_mean_value()
+                        for percentile in self.config.lat_percentiles:
+                            stats[key]['lat_percentile'][percentile] = decoded_histogram.\
+                                get_value_at_percentile(percentile)
+                    else:
+                        for percentile in self.config.lat_percentiles:
+                            stats[key]['lat_percentile'][percentile] = 'n/a'
         return stats
 
     def __targets_found(self, rate, targets, results):
@@ -1295,6 +1306,9 @@ class TrafficClient(object):
         delta_tx = cur_tx - self.prev_tx
         delta_rx = cur_rx - self.prev_rx
         drops = delta_tx - delta_rx
+        if delta_tx == 0:
+            LOG.info("\x1b[1mConfiguration issue!\x1b[0m (no transmission)")
+            sys.exit(0)
         drop_rate_pct = 100 * (delta_tx - delta_rx)/delta_tx
         self.prev_tx = cur_tx
         self.prev_rx = cur_rx
@@ -1356,12 +1370,25 @@ class TrafficClient(object):
         for idx, key in enumerate(["direction-forward", "direction-reverse"]):
             tx_rate = results["stats"][str(idx)]["tx"]["total_pkts"] / self.config.duration_sec
             rx_rate = results["stats"][str(1 - idx)]["rx"]["total_pkts"] / self.config.duration_sec
+
+            orig_rate = self.run_config['rates'][idx]
+            if self.config.periodic_gratuitous_arp:
+                orig_rate['rate_pps'] = float(
+                    orig_rate['rate_pps']) - self.config.gratuitous_arp_pps
+
             r[key] = {
-                "orig": self.__convert_rates(self.run_config['rates'][idx]),
+                "orig": self.__convert_rates(orig_rate),
                 "tx": self.__convert_rates({'rate_pps': tx_rate}),
                 "rx": self.__convert_rates({'rate_pps': rx_rate})
             }
 
+        if self.config.periodic_gratuitous_arp:
+            r['garp-direction-total'] = {
+                "orig": self.__convert_rates({'rate_pps': self.config.gratuitous_arp_pps * 2}),
+                "tx": self.__convert_rates({'rate_pps': results["stats"]["garp_total_tx_rate"]}),
+                "rx": self.__convert_rates({'rate_pps': 0})
+            }
+
         total = {}
         for direction in ['orig', 'tx', 'rx']:
             total[direction] = {}
@@ -1369,6 +1396,7 @@ class TrafficClient(object):
                 total[direction][unit] = sum([float(x[direction][unit]) for x in list(r.values())])
 
         r['direction-total'] = total
+
         return r
 
     def insert_interface_stats(self, pps_list):