NFVBENCH-94 End to end traffic test triggers too early on chatty network
[nfvbench.git] / nfvbench / traffic_gen / trex.py
index 7d64f0f..cabf1cb 100644 (file)
@@ -73,26 +73,35 @@ class TRex(AbstractTrafficGenerator):
         return self.client.get_server_version()
 
     def extract_stats(self, in_stats):
+        """Extract stats from dict returned by Trex API.
+
+        :param in_stats: dict as returned by TRex api
+        """
         utils.nan_replace(in_stats)
         LOG.debug(in_stats)
 
         result = {}
+        # port_handles should have only 2 elements: [0, 1]
+        # so (1 - ph) will be the index for the far end port
         for ph in self.port_handle:
-            stats = self.__combine_stats(in_stats, ph)
+            stats = in_stats[ph]
+            far_end_stats = in_stats[1 - ph]
             result[ph] = {
                 'tx': {
-                    'total_pkts': cast_integer(stats['tx_pkts']['total']),
-                    'total_pkt_bytes': cast_integer(stats['tx_bytes']['total']),
-                    'pkt_rate': cast_integer(stats['tx_pps']['total']),
-                    'pkt_bit_rate': cast_integer(stats['tx_bps']['total'])
+                    'total_pkts': cast_integer(stats['opackets']),
+                    'total_pkt_bytes': cast_integer(stats['obytes']),
+                    'pkt_rate': cast_integer(stats['tx_pps']),
+                    'pkt_bit_rate': cast_integer(stats['tx_bps'])
                 },
                 'rx': {
-                    'total_pkts': cast_integer(stats['rx_pkts']['total']),
-                    'total_pkt_bytes': cast_integer(stats['rx_bytes']['total']),
-                    'pkt_rate': cast_integer(stats['rx_pps']['total']),
-                    'pkt_bit_rate': cast_integer(stats['rx_bps']['total']),
+                    'total_pkts': cast_integer(stats['ipackets']),
+                    'total_pkt_bytes': cast_integer(stats['ibytes']),
+                    'pkt_rate': cast_integer(stats['rx_pps']),
+                    'pkt_bit_rate': cast_integer(stats['rx_bps']),
+                    # how many pkts were dropped in RX direction
+                    # need to take the tx counter on the far end port
                     'dropped_pkts': cast_integer(
-                        stats['tx_pkts']['total'] - stats['rx_pkts']['total'])
+                        far_end_stats['opackets'] - stats['ipackets'])
                 }
             }
 
@@ -107,20 +116,6 @@ class TRex(AbstractTrafficGenerator):
         result["total_tx_rate"] = cast_integer(total_tx_pkts / self.config.duration_sec)
         return result
 
-    def __combine_stats(self, in_stats, port_handle):
-        """Traverses TRex result dictionary and combines stream stats. Used for combining latency
-        and regular streams together.
-        """
-        result = defaultdict(lambda: defaultdict(float))
-
-        for pg_id in [self.stream_ids[port_handle]] + self.latencies[port_handle]:
-            record = in_stats['flow_stats'][pg_id]
-            for stat_type, stat_type_values in record.iteritems():
-                for ph, value in stat_type_values.iteritems():
-                    result[stat_type][ph] += value
-
-        return result
-
     def __combine_latencies(self, in_stats, port_handle):
         """Traverses TRex result dictionary and combines chosen latency stats."""
         if not self.latencies[port_handle]:
@@ -216,6 +211,7 @@ class TRex(AbstractTrafficGenerator):
 
             if latency:
                 idx_lat = self.id.next()
+                pkt = self.create_pkt(stream_cfg, self.imix_avg_l2_size)
                 sl = STLStream(packet=pkt,
                                isg=isg,
                                flow_stats=STLFlowLatencyStats(pg_id=idx_lat),
@@ -255,7 +251,7 @@ class TRex(AbstractTrafficGenerator):
                 break
             except Exception as ex:
                 if it == (self.config.generic_retry_count - 1):
-                    raise ex
+                    raise
                 LOG.info("Retrying connection to TRex (%s)...", ex.message)
 
     def connect(self):
@@ -441,7 +437,7 @@ class TRex(AbstractTrafficGenerator):
         LOG.info('Cleared all existing streams.')
 
     def get_stats(self):
-        stats = self.client.get_pgid_stats()
+        stats = self.client.get_stats()
         return self.extract_stats(stats)
 
     def get_macs(self):
@@ -459,10 +455,17 @@ class TRex(AbstractTrafficGenerator):
         self.client.stop(ports=self.port_handle)
 
     def start_capture(self):
+        """Capture all packets on both ports that are unicast to us."""
         if self.capture_id:
             self.stop_capture()
+        # Need to filter out unwanted packets so we do not end up counting
+        # src MACs of frames that are not unicast to us
+        src_mac_list = self.get_macs()
+        bpf_filter = "ether dst %s or ether dst %s" % (src_mac_list[0], src_mac_list[1])
+        # ports must be set in service in order to enable capture
         self.client.set_service_mode(ports=self.port_handle)
-        self.capture_id = self.client.start_capture(rx_ports=self.port_handle)
+        self.capture_id = self.client.start_capture(rx_ports=self.port_handle,
+                                                    bpf_filter=bpf_filter)
 
     def fetch_capture_packets(self):
         if self.capture_id: