Esempio n. 1
0
 def set_udp_packet_size(self, imix_frame_sizes):
     # We should check the gen.cfg to make sure we only send UDP packets
     # If only 1 packet size, still using the 'old' way of setting the
     # packet sizes in PROX. Otherwise, using the 'new' way which
     # automatically sets IP and UDP sizes. We should switch to the new way
     # eventually for all cases.
     if len(imix_frame_sizes) == 1:
         # Frame size = PROX pkt size + 4 bytes CRC
         # The set_size function takes the PROX packet size as a parameter
         self.socket.set_size(self.machine_params['gencores'], 0,
                              imix_frame_sizes[0] - 4)
         # Writing length in the ip header
         self.socket.set_value(
             self.machine_params['gencores'], 0, self.ip_length_offset,
             imix_frame_sizes[0] - self.frame_size_minus_ip_size, 2)
         # Writing length in the udp header
         self.socket.set_value(
             self.machine_params['gencores'], 0, self.udp_length_offset,
             imix_frame_sizes[0] -
             self.frame_size_minus_udp_header_and_content, 2)
     else:
         if self.ipv6:
             RapidLog.critical('IMIX not supported for IPV6')
         prox_sizes = [frame_size - 4 for frame_size in imix_frame_sizes]
         self.socket.set_imix(self.machine_params['gencores'], 0,
                              prox_sizes)
Esempio n. 2
0
 def lat_stats(self, cores, tasks=[0]):
     result = {}
     result['lat_min'] = 999999999
     result['lat_max'] = result['lat_avg'] = 0
     result['buckets'] = [0] * 128
     result['mis_ordered'] = 0
     result['extent'] = 0
     result['duplicate'] = 0
     number_tasks_returning_stats = 0
     self._send('lat all stats %s %s' %
                (','.join(map(str, cores)), ','.join(map(str, tasks))))
     for core in cores:
         for task in tasks:
             stats = self._recv().split(',')
         if 'is not measuring' in stats[0]:
             continue
         if stats[0].startswith('error'):
             RapidLog.critical("lat stats error: unexpected reply from PROX\
                     (potential incompatibility between scripts and PROX)")
             raise Exception("lat stats error")
         number_tasks_returning_stats += 1
         result['lat_min'] = min(int(stats[0]), result['lat_min'])
         result['lat_max'] = max(int(stats[1]), result['lat_max'])
         result['lat_avg'] += int(stats[2])
         #min_since begin = int(stats[3])
         #max_since_begin = int(stats[4])
         result['lat_tsc'] = int(
             stats[5])  # Taking the last tsc as the timestamp since
         # PROX will return the same tsc for each
         # core/task combination
         result['lat_hz'] = int(stats[6])
         #coreid = int(stats[7])
         #taskid = int(stats[8])
         result['mis_ordered'] += int(stats[9])
         result['extent'] += int(stats[10])
         result['duplicate'] += int(stats[11])
         stats = self._recv().split(':')
         if stats[0].startswith('error'):
             RapidLog.critical("lat stats error: unexpected lat bucket \
                     reply (potential incompatibility between scripts \
                     and PROX)")
             raise Exception("lat bucket reply error")
         result['buckets'][0] = int(stats[1])
         for i in range(1, 128):
             stats = self._recv().split(':')
             result['buckets'][i] = int(stats[1])
     result['lat_avg'] = old_div(result['lat_avg'],
                                 number_tasks_returning_stats)
     self._send('stats latency(0).used')
     used = float(self._recv())
     self._send('stats latency(0).total')
     total = float(self._recv())
     result['lat_used'] = old_div(used, total)
     return (result)
Esempio n. 3
0
 def lat_stats(self, cores, tasks=[0]):
     min_lat = 999999999
     max_lat = avg_lat = 0
     number_tasks_returning_stats = 0
     buckets = [0] * 128
     self._send('lat all stats %s %s' %
                (','.join(map(str, cores)), ','.join(map(str, tasks))))
     for core in cores:
         for task in tasks:
             stats = self._recv().split(',')
         if 'is not measuring' in stats[0]:
             continue
         if stats[0].startswith('error'):
             RapidLog.critical("lat stats error: unexpected reply from PROX\
                     (potential incompatibility between scripts and PROX)")
             raise Exception("lat stats error")
         number_tasks_returning_stats += 1
         min_lat = min(int(stats[0]), min_lat)
         max_lat = max(int(stats[1]), max_lat)
         avg_lat += int(stats[2])
         #min_since begin = int(stats[3])
         #max_since_begin = int(stats[4])
         tsc = int(stats[5])  # Taking the last tsc as the timestamp since
         # PROX will return the same tsc for each
         # core/task combination
         hz = int(stats[6])
         #coreid = int(stats[7])
         #taskid = int(stats[8])
         stats = self._recv().split(':')
         if stats[0].startswith('error'):
             RapidLog.critical("lat stats error: unexpected lat bucket \
                     reply (potential incompatibility between scripts \
                     and PROX)")
             raise Exception("lat bucket reply error")
         buckets[0] = int(stats[1])
         for i in range(1, 128):
             stats = self._recv().split(':')
             buckets[i] = int(stats[1])
     avg_lat = old_div(avg_lat, number_tasks_returning_stats)
     self._send('stats latency(0).used')
     used = float(self._recv())
     self._send('stats latency(0).total')
     total = float(self._recv())
     return (min_lat, max_lat, avg_lat, (old_div(used,
                                                 total)), tsc, hz, buckets)
Esempio n. 4
0
 def multi_port_stats(self, ports=[0]):
     rx = tx = port_id = tsc = no_mbufs = errors = 0
     self._send('multi port stats %s' % (','.join(map(str, ports))))
     result = self._recv().split(';')
     if result[0].startswith('error'):
         RapidLog.critical("multi port stats error: unexpected invalid \
                 syntax (potential incompatibility between scripts and \
                 PROX)")
         raise Exception("multi port stats error")
     for statistics in result:
         stats = statistics.split(',')
         port_id = int(stats[0])
         rx += int(stats[1])
         tx += int(stats[2])
         no_mbufs += int(stats[3])
         errors += int(stats[4])
         tsc = int(stats[5])
     return rx, tx, no_mbufs, errors, tsc
Esempio n. 5
0
 def create_key(self):
     if os.path.exists(self.key_name):
         public_key_file = "{}.pub".format(self.key_name)
         if not os.path.exists(public_key_file):
             RapidLog.critical('Keypair {}.pub does not exist'.format(
                 self.key_name))
         with open(public_key_file, mode='rb') as public_file:
             public_key = public_file.read()
     else:
         public_key = None
     keypair = self.nova_client.keypairs.create(name=self.key_name,
                                                public_key=public_key)
     # Create a file for writing that can only be read and written by owner
     if not os.path.exists(self.key_name):
         fp = os.open(self.key_name, os.O_WRONLY | os.O_CREAT, 0o600)
         with os.fdopen(fp, 'w') as f:
             f.write(keypair.private_key)
     RapidLog.info('Keypair {} created'.format(self.key_name))
Esempio n. 6
0
 def core_stats(self, cores, tasks=[0]):
     rx = tx = drop = tsc = hz = rx_non_dp = tx_non_dp = tx_fail = 0
     self._send('dp core stats %s %s' %
                (','.join(map(str, cores)), ','.join(map(str, tasks))))
     for core in cores:
         for task in tasks:
             stats = self._recv().split(',')
             if stats[0].startswith('error'):
                 if stats[0].startswith('error: invalid syntax'):
                     RapidLog.critical("dp core stats error: unexpected \
                             invalid syntax (potential incompatibility \
                             between scripts and PROX)")
                     raise Exception("dp core stats error")
                 continue
             rx += int(stats[0])
             tx += int(stats[1])
             rx_non_dp += int(stats[2])
             tx_non_dp += int(stats[3])
             drop += int(stats[4])
             tx_fail += int(stats[5])
             tsc = int(stats[6])
             hz = int(stats[7])
     return rx, rx_non_dp, tx, tx_non_dp, drop, tx_fail, tsc, hz
Esempio n. 7
0
    def run_iteration(self, requested_duration, flow_number, size, speed):
        BUCKET_SIZE_EXP = self.gen_machine.bucket_size_exp
        LAT_PERCENTILE = self.test['lat_percentile']
        r = 0
        sleep_time = 2
        while (r < self.test['maxr']):
            time.sleep(sleep_time)
            # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight
            t1_rx, t1_non_dp_rx, t1_tx, t1_non_dp_tx, t1_drop, t1_tx_fail, t1_tsc, abs_tsc_hz = self.gen_machine.core_stats(
            )
            t1_dp_rx = t1_rx - t1_non_dp_rx
            t1_dp_tx = t1_tx - t1_non_dp_tx
            self.gen_machine.set_generator_speed(0)
            self.gen_machine.start_gen_cores()
            if self.background_machines:
                self.set_background_speed(self.background_machines, 0)
                self.start_background_traffic(self.background_machines)
            if 'ramp_step' in self.test.keys():
                ramp_speed = self.test['ramp_step']
            else:
                ramp_speed = speed
            while ramp_speed < speed:
                self.gen_machine.set_generator_speed(ramp_speed)
                if self.background_machines:
                    self.set_background_speed(self.background_machines,
                                              ramp_speed)
                time.sleep(2)
                ramp_speed = ramp_speed + self.test['ramp_step']
            self.gen_machine.set_generator_speed(speed)
            if self.background_machines:
                self.set_background_speed(self.background_machines, speed)
            time.sleep(
                2
            )  ## Needs to be 2 seconds since this 1 sec is the time that PROX uses to refresh the stats. Note that this can be changed in PROX!! Don't do it.
            start_bg_gen_stats = []
            for bg_gen_machine in self.background_machines:
                bg_rx, bg_non_dp_rx, bg_tx, bg_non_dp_tx, _, _, bg_tsc, _ = bg_gen_machine.core_stats(
                )
                bg_gen_stat = {
                    "bg_dp_rx": bg_rx - bg_non_dp_rx,
                    "bg_dp_tx": bg_tx - bg_non_dp_tx,
                    "bg_tsc": bg_tsc
                }
                start_bg_gen_stats.append(dict(bg_gen_stat))
            if self.sut_machine != None:
                t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
                )
            t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc, tsc_hz = self.gen_machine.core_stats(
            )
            tx = t2_tx - t1_tx
            dp_tx = tx - (t2_non_dp_tx - t1_non_dp_tx)
            dp_rx = t2_rx - t1_rx - (t2_non_dp_rx - t1_non_dp_rx)
            tot_dp_drop = dp_tx - dp_rx
            if tx == 0:
                RapidLog.critical(
                    "TX = 0. Test interrupted since no packet has been sent.")
            if dp_tx == 0:
                RapidLog.critical(
                    "Only non-dataplane packets (e.g. ARP) sent. Test interrupted since no packet has been sent."
                )
            # Ask PROX to calibrate the bucket size once we have a PROX function to do this.
            # Measure latency statistics per second
            lat_min, lat_max, lat_avg, used_avg, t2_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
            )
            lat_samples = sum(buckets)
            sample_count = 0
            for sample_percentile, bucket in enumerate(buckets, start=1):
                sample_count += bucket
                if sample_count > (lat_samples * LAT_PERCENTILE):
                    break
            percentile_max = (sample_percentile == len(buckets))
            sample_percentile = sample_percentile * float(
                2**BUCKET_SIZE_EXP) / (old_div(float(lat_hz), float(10**6)))
            if self.test['test'] == 'fixed_rate':
                RapidLog.info(
                    self.report_result(flow_number, size, speed, None, None,
                                       None, None, lat_avg, sample_percentile,
                                       percentile_max, lat_max, dp_tx, dp_rx,
                                       None, None))
            tot_rx = tot_non_dp_rx = tot_tx = tot_non_dp_tx = tot_drop = 0
            lat_avg = used_avg = 0
            buckets_total = buckets
            tot_lat_samples = sum(buckets)
            tot_lat_measurement_duration = float(0)
            tot_core_measurement_duration = float(0)
            tot_sut_core_measurement_duration = float(0)
            tot_sut_rx = tot_sut_non_dp_rx = tot_sut_tx = tot_sut_non_dp_tx = tot_sut_drop = tot_sut_tx_fail = tot_sut_tsc = 0
            lat_avail = core_avail = sut_avail = False
            while (tot_core_measurement_duration - float(requested_duration) <=
                   0.1) or (tot_lat_measurement_duration -
                            float(requested_duration) <= 0.1):
                time.sleep(0.5)
                lat_min_sample, lat_max_sample, lat_avg_sample, used_sample, t3_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
                )
                # Get statistics after some execution time
                if t3_lat_tsc != t2_lat_tsc:
                    single_lat_measurement_duration = (
                        t3_lat_tsc - t2_lat_tsc
                    ) * 1.0 / lat_hz  # time difference between the 2 measurements, expressed in seconds.
                    # A second has passed in between to lat_stats requests. Hence we need to process the results
                    tot_lat_measurement_duration = tot_lat_measurement_duration + single_lat_measurement_duration
                    if lat_min > lat_min_sample:
                        lat_min = lat_min_sample
                    if lat_max < lat_max_sample:
                        lat_max = lat_max_sample
                    lat_avg = lat_avg + lat_avg_sample * single_lat_measurement_duration  # Sometimes, There is more than 1 second between 2 lat_stats. Hence we will take the latest measurement
                    used_avg = used_avg + used_sample * single_lat_measurement_duration  # and give it more weigth.
                    lat_samples = sum(buckets)
                    tot_lat_samples += lat_samples
                    sample_count = 0
                    for sample_percentile, bucket in enumerate(buckets,
                                                               start=1):
                        sample_count += bucket
                        if sample_count > lat_samples * LAT_PERCENTILE:
                            break
                    percentile_max = (sample_percentile == len(buckets))
                    bucket_size = float(2**BUCKET_SIZE_EXP) / (old_div(
                        float(lat_hz), float(10**6)))
                    sample_percentile = sample_percentile * bucket_size
                    buckets_total = [
                        buckets_total[i] + buckets[i]
                        for i in range(len(buckets_total))
                    ]
                    t2_lat_tsc = t3_lat_tsc
                    lat_avail = True
                t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc, tsc_hz = self.gen_machine.core_stats(
                )
                if t3_tsc != t2_tsc:
                    single_core_measurement_duration = (
                        t3_tsc - t2_tsc
                    ) * 1.0 / tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                    tot_core_measurement_duration = tot_core_measurement_duration + single_core_measurement_duration
                    delta_rx = t3_rx - t2_rx
                    tot_rx += delta_rx
                    delta_non_dp_rx = t3_non_dp_rx - t2_non_dp_rx
                    tot_non_dp_rx += delta_non_dp_rx
                    delta_tx = t3_tx - t2_tx
                    tot_tx += delta_tx
                    delta_non_dp_tx = t3_non_dp_tx - t2_non_dp_tx
                    tot_non_dp_tx += delta_non_dp_tx
                    delta_dp_tx = delta_tx - delta_non_dp_tx
                    delta_dp_rx = delta_rx - delta_non_dp_rx
                    delta_dp_drop = delta_dp_tx - delta_dp_rx
                    tot_dp_drop += delta_dp_drop
                    delta_drop = t3_drop - t2_drop
                    tot_drop += delta_drop
                    t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc = t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc
                    core_avail = True
                if self.sut_machine != None:
                    t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
                    )
                    if t3_sut_tsc != t2_sut_tsc:
                        single_sut_core_measurement_duration = (
                            t3_sut_tsc - t2_sut_tsc
                        ) * 1.0 / tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                        tot_sut_core_measurement_duration = tot_sut_core_measurement_duration + single_sut_core_measurement_duration
                        tot_sut_rx += t3_sut_rx - t2_sut_rx
                        tot_sut_non_dp_rx += t3_sut_non_dp_rx - t2_sut_non_dp_rx
                        delta_sut_tx = t3_sut_tx - t2_sut_tx
                        tot_sut_tx += delta_sut_tx
                        delta_sut_non_dp_tx = t3_sut_non_dp_tx - t2_sut_non_dp_tx
                        tot_sut_non_dp_tx += delta_sut_non_dp_tx
                        t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc = t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc
                        sut_avail = True
                if self.test['test'] == 'fixed_rate':
                    if lat_avail == core_avail == True:
                        lat_avail = core_avail = False
                        pps_req_tx = (
                            delta_tx + delta_drop - delta_rx
                        ) / single_core_measurement_duration / 1000000
                        pps_tx = delta_tx / single_core_measurement_duration / 1000000
                        if self.sut_machine != None and sut_avail:
                            pps_sut_tx = delta_sut_tx / single_sut_core_measurement_duration / 1000000
                            sut_avail = False
                        else:
                            pps_sut_tx = None
                        pps_rx = delta_rx / single_core_measurement_duration / 1000000
                        RapidLog.info(
                            self.report_result(
                                flow_number, size, speed, pps_req_tx, pps_tx,
                                pps_sut_tx, pps_rx, lat_avg_sample,
                                sample_percentile, percentile_max,
                                lat_max_sample, delta_dp_tx, delta_dp_rx,
                                tot_dp_drop, single_core_measurement_duration))
                        variables = {
                            'Flows': flow_number,
                            'Size': size,
                            'RequestedSpeed': self.get_pps(speed, size),
                            'CoreGenerated': pps_req_tx,
                            'SentByNIC': pps_tx,
                            'FwdBySUT': pps_sut_tx,
                            'RevByCore': pps_rx,
                            'AvgLatency': lat_avg_sample,
                            'PCTLatency': sample_percentile,
                            'MaxLatency': lat_max_sample,
                            'PacketsSent': delta_dp_tx,
                            'PacketsReceived': delta_dp_rx,
                            'PacketsLost': tot_dp_drop,
                            'bucket_size': bucket_size,
                            'buckets': buckets
                        }

                        self.post_data('rapid_flowsizetest', variables)
            end_bg_gen_stats = []
            for bg_gen_machine in self.background_machines:
                bg_rx, bg_non_dp_rx, bg_tx, bg_non_dp_tx, _, _, bg_tsc, bg_hz = bg_gen_machine.core_stats(
                )
                bg_gen_stat = {
                    "bg_dp_rx": bg_rx - bg_non_dp_rx,
                    "bg_dp_tx": bg_tx - bg_non_dp_tx,
                    "bg_tsc": bg_tsc,
                    "bg_hz": bg_hz
                }
                end_bg_gen_stats.append(dict(bg_gen_stat))
            i = 0
            bg_rates = []
            while i < len(end_bg_gen_stats):
                bg_rates.append(0.000001 *
                                (end_bg_gen_stats[i]['bg_dp_rx'] -
                                 start_bg_gen_stats[i]['bg_dp_rx']) /
                                ((end_bg_gen_stats[i]['bg_tsc'] -
                                  start_bg_gen_stats[i]['bg_tsc']) * 1.0 /
                                 end_bg_gen_stats[i]['bg_hz']))
                i += 1
            if len(bg_rates):
                avg_bg_rate = sum(bg_rates) / len(bg_rates)
                RapidLog.debug(
                    'Average Background traffic rate: {:>7.3f} Mpps'.format(
                        avg_bg_rate))
            else:
                avg_bg_rate = None
            #Stop generating
            self.gen_machine.stop_gen_cores()
            r += 1
            lat_avg = old_div(lat_avg, float(tot_lat_measurement_duration))
            used_avg = old_div(used_avg, float(tot_lat_measurement_duration))
            t4_tsc = t2_tsc
            while t4_tsc == t2_tsc:
                t4_rx, t4_non_dp_rx, t4_tx, t4_non_dp_tx, t4_drop, t4_tx_fail, t4_tsc, abs_tsc_hz = self.gen_machine.core_stats(
                )
            if self.test['test'] == 'fixed_rate':
                t4_lat_tsc = t2_lat_tsc
                while t4_lat_tsc == t2_lat_tsc:
                    lat_min_sample, lat_max_sample, lat_avg_sample, used_sample, t4_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
                    )
                sample_count = 0
                lat_samples = sum(buckets)
                for percentile, bucket in enumerate(buckets, start=1):
                    sample_count += bucket
                    if sample_count > lat_samples * LAT_PERCENTILE:
                        break
                percentile_max = (percentile == len(buckets))
                percentile = percentile * bucket_size
                lat_max = lat_max_sample
                lat_avg = lat_avg_sample
                delta_rx = t4_rx - t2_rx
                delta_non_dp_rx = t4_non_dp_rx - t2_non_dp_rx
                delta_tx = t4_tx - t2_tx
                delta_non_dp_tx = t4_non_dp_tx - t2_non_dp_tx
                delta_dp_tx = delta_tx - delta_non_dp_tx
                delta_dp_rx = delta_rx - delta_non_dp_rx
                dp_tx = delta_dp_tx
                dp_rx = delta_dp_rx
                tot_dp_drop += delta_dp_tx - delta_dp_rx
                pps_req_tx = None
                pps_tx = None
                pps_sut_tx = None
                pps_rx = None
                drop_rate = 100.0 * (dp_tx - dp_rx) / dp_tx
                tot_core_measurement_duration = None
                break  ## Not really needed since the while loop will stop when evaluating the value of r
            else:
                sample_count = 0
                buckets = buckets_total
                for percentile, bucket in enumerate(buckets_total, start=1):
                    sample_count += bucket
                    if sample_count > tot_lat_samples * LAT_PERCENTILE:
                        break
                percentile_max = (percentile == len(buckets_total))
                percentile = percentile * bucket_size
                pps_req_tx = (
                    tot_tx + tot_drop - tot_rx
                ) / tot_core_measurement_duration / 1000000.0  # tot_drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
                pps_tx = tot_tx / tot_core_measurement_duration / 1000000.0  # tot_tx is all generated packets actually accepted by the interface
                pps_rx = tot_rx / tot_core_measurement_duration / 1000000.0  # tot_rx is all packets received by the nop task = all packets received in the gen VM
                if self.sut_machine != None and sut_avail:
                    pps_sut_tx = tot_sut_tx / tot_sut_core_measurement_duration / 1000000.0
                else:
                    pps_sut_tx = None
                dp_tx = (t4_tx - t1_tx) - (t4_non_dp_tx - t1_non_dp_tx)
                dp_rx = (t4_rx - t1_rx) - (t4_non_dp_rx - t1_non_dp_rx)
                tot_dp_drop = dp_tx - dp_rx
                drop_rate = 100.0 * tot_dp_drop / dp_tx
                if ((drop_rate < self.test['drop_rate_threshold']) or
                    (tot_dp_drop == self.test['drop_rate_threshold'] == 0)
                        or (tot_dp_drop > self.test['maxz'])):
                    break
        return (pps_req_tx, pps_tx, pps_sut_tx, pps_rx, lat_avg, percentile,
                percentile_max, lat_max, dp_tx, dp_rx, tot_dp_drop,
                (t4_tx_fail - t1_tx_fail), drop_rate, lat_min, used_avg, r,
                tot_core_measurement_duration, avg_bg_rate, bucket_size,
                buckets)
Esempio n. 8
0
    def run_iteration(self, requested_duration, flow_number, size, speed):
        BUCKET_SIZE_EXP = self.gen_machine.bucket_size_exp
        sleep_time = self.test['sleep_time']
        LAT_PERCENTILE = self.test['lat_percentile']
        iteration_data = {}
        time_loop_data = {}
        iteration_data['r'] = 0

        while (iteration_data['r'] < self.test['maxr']):
            self.gen_machine.start_latency_cores()
            time.sleep(sleep_time)
            # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight
            t1_rx, t1_non_dp_rx, t1_tx, t1_non_dp_tx, t1_drop, t1_tx_fail, t1_tsc, abs_tsc_hz = self.gen_machine.core_stats(
            )
            t1_dp_rx = t1_rx - t1_non_dp_rx
            t1_dp_tx = t1_tx - t1_non_dp_tx
            self.gen_machine.set_generator_speed(0)
            self.gen_machine.start_gen_cores()
            self.set_background_speed(self.background_machines, 0)
            self.start_background_traffic(self.background_machines)
            if 'ramp_step' in self.test.keys():
                ramp_speed = self.test['ramp_step']
            else:
                ramp_speed = speed
            while ramp_speed < speed:
                self.gen_machine.set_generator_speed(ramp_speed)
                self.set_background_speed(self.background_machines, ramp_speed)
                time.sleep(2)
                ramp_speed = ramp_speed + self.test['ramp_step']
            self.gen_machine.set_generator_speed(speed)
            self.set_background_speed(self.background_machines, speed)
            iteration_data['speed'] = speed
            time_loop_data['speed'] = speed
            time.sleep(
                2
            )  ## Needs to be 2 seconds since this 1 sec is the time that PROX uses to refresh the stats. Note that this can be changed in PROX!! Don't do it.
            start_bg_gen_stats = []
            for bg_gen_machine in self.background_machines:
                bg_rx, bg_non_dp_rx, bg_tx, bg_non_dp_tx, _, _, bg_tsc, _ = bg_gen_machine.core_stats(
                )
                bg_gen_stat = {
                    "bg_dp_rx": bg_rx - bg_non_dp_rx,
                    "bg_dp_tx": bg_tx - bg_non_dp_tx,
                    "bg_tsc": bg_tsc
                }
                start_bg_gen_stats.append(dict(bg_gen_stat))
            if self.sut_machine != None:
                t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
                )
            t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc, tsc_hz = self.gen_machine.core_stats(
            )
            tx = t2_tx - t1_tx
            iteration_data['abs_tx'] = tx - (t2_non_dp_tx - t1_non_dp_tx)
            iteration_data['abs_rx'] = t2_rx - t1_rx - (t2_non_dp_rx -
                                                        t1_non_dp_rx)
            iteration_data['abs_dropped'] = iteration_data[
                'abs_tx'] - iteration_data['abs_rx']
            if tx == 0:
                RapidLog.critical(
                    "TX = 0. Test interrupted since no packet has been sent.")
            if iteration_data['abs_tx'] == 0:
                RapidLog.critical(
                    "Only non-dataplane packets (e.g. ARP) sent. Test interrupted since no packet has been sent."
                )
            # Ask PROX to calibrate the bucket size once we have a PROX function to do this.
            # Measure latency statistics per second
            iteration_data.update(self.gen_machine.lat_stats())
            t2_lat_tsc = iteration_data['lat_tsc']
            sample_count = 0
            for sample_percentile, bucket in enumerate(
                    iteration_data['buckets'], start=1):
                sample_count += bucket
                if sample_count > sum(
                        iteration_data['buckets']) * LAT_PERCENTILE:
                    break
            iteration_data['lat_perc_max'] = (sample_percentile == len(
                iteration_data['buckets']))
            iteration_data['bucket_size'] = float(2**BUCKET_SIZE_EXP) / (
                old_div(float(iteration_data['lat_hz']), float(10**6)))
            time_loop_data['bucket_size'] = iteration_data['bucket_size']
            iteration_data[
                'lat_perc'] = sample_percentile * iteration_data['bucket_size']
            if self.test['test'] == 'fixed_rate':
                iteration_data['pps_req_tx'] = None
                iteration_data['pps_tx'] = None
                iteration_data['pps_sut_tx'] = None
                iteration_data['pps_rx'] = None
                iteration_data['lat_perc'] = None
                iteration_data['actual_duration'] = None
                iteration_prefix = {
                    'speed': '',
                    'lat_avg': '',
                    'lat_perc': '',
                    'lat_max': '',
                    'abs_drop_rate': '',
                    'drop_rate': ''
                }
                RapidLog.info(
                    self.report_result(flow_number, size, iteration_data,
                                       iteration_prefix))
            tot_rx = tot_non_dp_rx = tot_tx = tot_non_dp_tx = tot_drop = 0
            iteration_data['lat_avg'] = iteration_data['lat_used'] = 0
            tot_lat_measurement_duration = float(0)
            iteration_data['actual_duration'] = float(0)
            tot_sut_core_measurement_duration = float(0)
            tot_sut_rx = tot_sut_non_dp_rx = tot_sut_tx = tot_sut_non_dp_tx = tot_sut_drop = tot_sut_tx_fail = tot_sut_tsc = 0
            lat_avail = core_avail = sut_avail = False
            while (iteration_data['actual_duration'] -
                   float(requested_duration) <= 0.1) or (
                       tot_lat_measurement_duration - float(requested_duration)
                       <= 0.1):
                time.sleep(0.5)
                time_loop_data.update(self.gen_machine.lat_stats())
                # Get statistics after some execution time
                if time_loop_data['lat_tsc'] != t2_lat_tsc:
                    single_lat_measurement_duration = (
                        time_loop_data['lat_tsc'] - t2_lat_tsc
                    ) * 1.0 / time_loop_data[
                        'lat_hz']  # time difference between the 2 measurements, expressed in seconds.
                    # A second has passed in between to lat_stats requests. Hence we need to process the results
                    tot_lat_measurement_duration = tot_lat_measurement_duration + single_lat_measurement_duration
                    if iteration_data['lat_min'] > time_loop_data['lat_min']:
                        iteration_data['lat_min'] = time_loop_data['lat_min']
                    if iteration_data['lat_max'] < time_loop_data['lat_max']:
                        iteration_data['lat_max'] = time_loop_data['lat_max']
                    iteration_data['lat_avg'] = iteration_data[
                        'lat_avg'] + time_loop_data[
                            'lat_avg'] * single_lat_measurement_duration  # Sometimes, There is more than 1 second between 2 lat_stats. Hence we will take the latest measurement
                    iteration_data['lat_used'] = iteration_data[
                        'lat_used'] + time_loop_data[
                            'lat_used'] * single_lat_measurement_duration  # and give it more weigth.
                    sample_count = 0
                    for sample_percentile, bucket in enumerate(
                            time_loop_data['buckets'], start=1):
                        sample_count += bucket
                        if sample_count > sum(
                                time_loop_data['buckets']) * LAT_PERCENTILE:
                            break
                    time_loop_data['lat_perc_max'] = (sample_percentile == len(
                        time_loop_data['buckets']))
                    time_loop_data[
                        'lat_perc'] = sample_percentile * iteration_data[
                            'bucket_size']
                    iteration_data['buckets'] = [
                        iteration_data['buckets'][i] +
                        time_loop_data['buckets'][i]
                        for i in range(len(iteration_data['buckets']))
                    ]
                    t2_lat_tsc = time_loop_data['lat_tsc']
                    lat_avail = True
                t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc, tsc_hz = self.gen_machine.core_stats(
                )
                if t3_tsc != t2_tsc:
                    time_loop_data['actual_duration'] = (
                        t3_tsc - t2_tsc
                    ) * 1.0 / tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                    iteration_data['actual_duration'] = iteration_data[
                        'actual_duration'] + time_loop_data['actual_duration']
                    delta_rx = t3_rx - t2_rx
                    tot_rx += delta_rx
                    delta_non_dp_rx = t3_non_dp_rx - t2_non_dp_rx
                    tot_non_dp_rx += delta_non_dp_rx
                    delta_tx = t3_tx - t2_tx
                    tot_tx += delta_tx
                    delta_non_dp_tx = t3_non_dp_tx - t2_non_dp_tx
                    tot_non_dp_tx += delta_non_dp_tx
                    delta_dp_tx = delta_tx - delta_non_dp_tx
                    delta_dp_rx = delta_rx - delta_non_dp_rx
                    time_loop_data['abs_dropped'] = delta_dp_tx - delta_dp_rx
                    iteration_data['abs_dropped'] += time_loop_data[
                        'abs_dropped']
                    delta_drop = t3_drop - t2_drop
                    tot_drop += delta_drop
                    t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc = t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc
                    core_avail = True
                if self.sut_machine != None:
                    t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
                    )
                    if t3_sut_tsc != t2_sut_tsc:
                        single_sut_core_measurement_duration = (
                            t3_sut_tsc - t2_sut_tsc
                        ) * 1.0 / sut_tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                        tot_sut_core_measurement_duration = tot_sut_core_measurement_duration + single_sut_core_measurement_duration
                        tot_sut_rx += t3_sut_rx - t2_sut_rx
                        tot_sut_non_dp_rx += t3_sut_non_dp_rx - t2_sut_non_dp_rx
                        delta_sut_tx = t3_sut_tx - t2_sut_tx
                        tot_sut_tx += delta_sut_tx
                        delta_sut_non_dp_tx = t3_sut_non_dp_tx - t2_sut_non_dp_tx
                        tot_sut_non_dp_tx += delta_sut_non_dp_tx
                        t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc = t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc
                        sut_avail = True
                if self.test['test'] == 'fixed_rate':
                    if lat_avail == core_avail == True:
                        lat_avail = core_avail = False
                        time_loop_data['pps_req_tx'] = (
                            delta_tx + delta_drop - delta_rx
                        ) / time_loop_data['actual_duration'] / 1000000
                        time_loop_data['pps_tx'] = delta_tx / time_loop_data[
                            'actual_duration'] / 1000000
                        if self.sut_machine != None and sut_avail:
                            time_loop_data[
                                'pps_sut_tx'] = delta_sut_tx / single_sut_core_measurement_duration / 1000000
                            sut_avail = False
                        else:
                            time_loop_data['pps_sut_tx'] = None
                        time_loop_data['pps_rx'] = delta_rx / time_loop_data[
                            'actual_duration'] / 1000000
                        time_loop_data['abs_tx'] = delta_dp_tx
                        time_loop_data['abs_rx'] = delta_dp_rx
                        time_loop_prefix = {
                            'speed': '',
                            'lat_avg': '',
                            'lat_perc': '',
                            'lat_max': '',
                            'abs_drop_rate': '',
                            'drop_rate': ''
                        }
                        RapidLog.info(
                            self.report_result(flow_number, size,
                                               time_loop_data,
                                               time_loop_prefix))
                        time_loop_data['test'] = self.test['testname']
                        time_loop_data['environment_file'] = self.test[
                            'environment_file']
                        time_loop_data['Flows'] = flow_number
                        time_loop_data['Size'] = size
                        time_loop_data['RequestedSpeed'] = RapidTest.get_pps(
                            speed, size)
                        _ = self.post_data(time_loop_data)
            end_bg_gen_stats = []
            for bg_gen_machine in self.background_machines:
                bg_rx, bg_non_dp_rx, bg_tx, bg_non_dp_tx, _, _, bg_tsc, bg_hz = bg_gen_machine.core_stats(
                )
                bg_gen_stat = {
                    "bg_dp_rx": bg_rx - bg_non_dp_rx,
                    "bg_dp_tx": bg_tx - bg_non_dp_tx,
                    "bg_tsc": bg_tsc,
                    "bg_hz": bg_hz
                }
                end_bg_gen_stats.append(dict(bg_gen_stat))
            self.stop_background_traffic(self.background_machines)
            i = 0
            bg_rates = []
            while i < len(end_bg_gen_stats):
                bg_rates.append(0.000001 *
                                (end_bg_gen_stats[i]['bg_dp_rx'] -
                                 start_bg_gen_stats[i]['bg_dp_rx']) /
                                ((end_bg_gen_stats[i]['bg_tsc'] -
                                  start_bg_gen_stats[i]['bg_tsc']) * 1.0 /
                                 end_bg_gen_stats[i]['bg_hz']))
                i += 1
            if len(bg_rates):
                iteration_data['avg_bg_rate'] = sum(bg_rates) / len(bg_rates)
                RapidLog.debug(
                    'Average Background traffic rate: {:>7.3f} Mpps'.format(
                        iteration_data['avg_bg_rate']))
            else:
                iteration_data['avg_bg_rate'] = None
            #Stop generating
            self.gen_machine.stop_gen_cores()
            time.sleep(3.5)
            self.gen_machine.stop_latency_cores()
            iteration_data['r'] += 1
            iteration_data['lat_avg'] = old_div(
                iteration_data['lat_avg'], float(tot_lat_measurement_duration))
            iteration_data['lat_used'] = old_div(
                iteration_data['lat_used'],
                float(tot_lat_measurement_duration))
            t4_tsc = t2_tsc
            while t4_tsc == t2_tsc:
                t4_rx, t4_non_dp_rx, t4_tx, t4_non_dp_tx, t4_drop, t4_tx_fail, t4_tsc, abs_tsc_hz = self.gen_machine.core_stats(
                )
            if self.test['test'] == 'fixed_rate':
                iteration_data['lat_tsc'] = t2_lat_tsc
                while iteration_data['lat_tsc'] == t2_lat_tsc:
                    iteration_data.update(self.gen_machine.lat_stats())
                sample_count = 0
                for percentile, bucket in enumerate(iteration_data['buckets'],
                                                    start=1):
                    sample_count += bucket
                    if sample_count > sum(
                            iteration_data['buckets']) * LAT_PERCENTILE:
                        break
                iteration_data['lat_perc_max'] = (percentile == len(
                    iteration_data['buckets']))
                iteration_data[
                    'lat_perc'] = percentile * iteration_data['bucket_size']
                delta_rx = t4_rx - t2_rx
                delta_non_dp_rx = t4_non_dp_rx - t2_non_dp_rx
                delta_tx = t4_tx - t2_tx
                delta_non_dp_tx = t4_non_dp_tx - t2_non_dp_tx
                delta_dp_tx = delta_tx - delta_non_dp_tx
                delta_dp_rx = delta_rx - delta_non_dp_rx
                iteration_data['abs_tx'] = delta_dp_tx
                iteration_data['abs_rx'] = delta_dp_rx
                iteration_data['abs_dropped'] += delta_dp_tx - delta_dp_rx
                iteration_data['pps_req_tx'] = None
                iteration_data['pps_tx'] = None
                iteration_data['pps_sut_tx'] = None
                iteration_data['drop_rate'] = 100.0 * (
                    iteration_data['abs_tx'] -
                    iteration_data['abs_rx']) / iteration_data['abs_tx']
                iteration_data['actual_duration'] = None
                break  ## Not really needed since the while loop will stop when evaluating the value of r
            else:
                sample_count = 0
                for percentile, bucket in enumerate(iteration_data['buckets'],
                                                    start=1):
                    sample_count += bucket
                    if sample_count > sum(
                            iteration_data['buckets']) * LAT_PERCENTILE:
                        break
                iteration_data['lat_perc_max'] = (percentile == len(
                    iteration_data['buckets']))
                iteration_data[
                    'lat_perc'] = percentile * iteration_data['bucket_size']
                iteration_data['pps_req_tx'] = (
                    tot_tx + tot_drop - tot_rx
                ) / iteration_data[
                    'actual_duration'] / 1000000.0  # tot_drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
                iteration_data['pps_tx'] = tot_tx / iteration_data[
                    'actual_duration'] / 1000000.0  # tot_tx is all generated packets actually accepted by the interface
                iteration_data['pps_rx'] = tot_rx / iteration_data[
                    'actual_duration'] / 1000000.0  # tot_rx is all packets received by the nop task = all packets received in the gen VM
                if self.sut_machine != None and sut_avail:
                    iteration_data[
                        'pps_sut_tx'] = tot_sut_tx / tot_sut_core_measurement_duration / 1000000.0
                else:
                    iteration_data['pps_sut_tx'] = None
                iteration_data['abs_tx'] = (t4_tx - t1_tx) - (t4_non_dp_tx -
                                                              t1_non_dp_tx)
                iteration_data['abs_rx'] = (t4_rx - t1_rx) - (t4_non_dp_rx -
                                                              t1_non_dp_rx)
                iteration_data['abs_dropped'] = iteration_data[
                    'abs_tx'] - iteration_data['abs_rx']
                iteration_data['drop_rate'] = 100.0 * iteration_data[
                    'abs_dropped'] / iteration_data['abs_tx']
                if ((iteration_data['drop_rate'] <
                     self.test['drop_rate_threshold'])
                        or (iteration_data['abs_dropped'] ==
                            self.test['drop_rate_threshold'] == 0) or
                    (iteration_data['abs_dropped'] > self.test['maxz'])):
                    break
            self.gen_machine.stop_latency_cores()
        iteration_data['abs_tx_fail'] = t4_tx_fail - t1_tx_fail
        return (iteration_data)
Esempio n. 9
0
 def run_iteration(self, requested_duration, flow_number, size, speed):
     BUCKET_SIZE_EXP = self.gen_machine.bucket_size_exp
     LAT_PERCENTILE = self.test['lat_percentile']
     r = 0
     sleep_time = 2
     while (r < self.test['maxr']):
         time.sleep(sleep_time)
         # Sleep_time is needed to be able to do accurate measurements to check for packet loss. We need to make this time large enough so that we do not take the first measurement while some packets from the previous tests migth still be in flight
         t1_rx, t1_non_dp_rx, t1_tx, t1_non_dp_tx, t1_drop, t1_tx_fail, t1_tsc, abs_tsc_hz = self.gen_machine.core_stats(
         )
         t1_dp_rx = t1_rx - t1_non_dp_rx
         t1_dp_tx = t1_tx - t1_non_dp_tx
         self.gen_machine.start_gen_cores()
         time.sleep(
             2
         )  ## Needs to be 2 seconds since this 1 sec is the time that PROX uses to refresh the stats. Note that this can be changed in PROX!! Don't do it.
         if self.sut_machine != None:
             t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
             )
         t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc, tsc_hz = self.gen_machine.core_stats(
         )
         tx = t2_tx - t1_tx
         dp_tx = tx - (t2_non_dp_tx - t1_non_dp_tx)
         dp_rx = t2_rx - t1_rx - (t2_non_dp_rx - t1_non_dp_rx)
         tot_dp_drop = dp_tx - dp_rx
         if tx == 0:
             RapidLog.critical(
                 "TX = 0. Test interrupted since no packet has been sent.")
         if dp_tx == 0:
             RapidLog.critical(
                 "Only non-dataplane packets (e.g. ARP) sent. Test interrupted since no packet has been sent."
             )
         # Ask PROX to calibrate the bucket size once we have a PROX function to do this.
         # Measure latency statistics per second
         lat_min, lat_max, lat_avg, used_avg, t2_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
         )
         lat_samples = sum(buckets)
         sample_count = 0
         for sample_percentile, bucket in enumerate(buckets, start=1):
             sample_count += bucket
             if sample_count > (lat_samples * LAT_PERCENTILE):
                 break
         percentile_max = (sample_percentile == len(buckets))
         sample_percentile = sample_percentile * float(
             2**BUCKET_SIZE_EXP) / (old_div(float(lat_hz), float(10**6)))
         if self.test['test'] == 'fixed_rate':
             RapidLog.info(
                 self.report_result(flow_number, size, speed, None, None,
                                    None, None, lat_avg, sample_percentile,
                                    percentile_max, lat_max, dp_tx, dp_rx,
                                    None, None))
         tot_rx = tot_non_dp_rx = tot_tx = tot_non_dp_tx = tot_drop = 0
         lat_avg = used_avg = 0
         buckets_total = [0] * 128
         tot_lat_samples = 0
         tot_lat_measurement_duration = float(0)
         tot_core_measurement_duration = float(0)
         tot_sut_core_measurement_duration = float(0)
         tot_sut_rx = tot_sut_non_dp_rx = tot_sut_tx = tot_sut_non_dp_tx = tot_sut_drop = tot_sut_tx_fail = tot_sut_tsc = 0
         lat_avail = core_avail = sut_avail = False
         while (tot_core_measurement_duration - float(requested_duration) <=
                0.1) or (tot_lat_measurement_duration -
                         float(requested_duration) <= 0.1):
             time.sleep(0.5)
             lat_min_sample, lat_max_sample, lat_avg_sample, used_sample, t3_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
             )
             # Get statistics after some execution time
             if t3_lat_tsc != t2_lat_tsc:
                 single_lat_measurement_duration = (
                     t3_lat_tsc - t2_lat_tsc
                 ) * 1.0 / lat_hz  # time difference between the 2 measurements, expressed in seconds.
                 # A second has passed in between to lat_stats requests. Hence we need to process the results
                 tot_lat_measurement_duration = tot_lat_measurement_duration + single_lat_measurement_duration
                 if lat_min > lat_min_sample:
                     lat_min = lat_min_sample
                 if lat_max < lat_max_sample:
                     lat_max = lat_max_sample
                 lat_avg = lat_avg + lat_avg_sample * single_lat_measurement_duration  # Sometimes, There is more than 1 second between 2 lat_stats. Hence we will take the latest measurement
                 used_avg = used_avg + used_sample * single_lat_measurement_duration  # and give it more weigth.
                 lat_samples = sum(buckets)
                 tot_lat_samples += lat_samples
                 sample_count = 0
                 for sample_percentile, bucket in enumerate(buckets,
                                                            start=1):
                     sample_count += bucket
                     if sample_count > lat_samples * LAT_PERCENTILE:
                         break
                 percentile_max = (sample_percentile == len(buckets))
                 sample_percentile = sample_percentile * float(
                     2**BUCKET_SIZE_EXP) / (old_div(float(lat_hz),
                                                    float(10**6)))
                 buckets_total = [
                     buckets_total[i] + buckets[i]
                     for i in range(len(buckets_total))
                 ]
                 t2_lat_tsc = t3_lat_tsc
                 lat_avail = True
             t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc, tsc_hz = self.gen_machine.core_stats(
             )
             if t3_tsc != t2_tsc:
                 single_core_measurement_duration = (
                     t3_tsc - t2_tsc
                 ) * 1.0 / tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                 tot_core_measurement_duration = tot_core_measurement_duration + single_core_measurement_duration
                 delta_rx = t3_rx - t2_rx
                 tot_rx += delta_rx
                 delta_non_dp_rx = t3_non_dp_rx - t2_non_dp_rx
                 tot_non_dp_rx += delta_non_dp_rx
                 delta_tx = t3_tx - t2_tx
                 tot_tx += delta_tx
                 delta_non_dp_tx = t3_non_dp_tx - t2_non_dp_tx
                 tot_non_dp_tx += delta_non_dp_tx
                 delta_dp_tx = delta_tx - delta_non_dp_tx
                 delta_dp_rx = delta_rx - delta_non_dp_rx
                 delta_dp_drop = delta_dp_tx - delta_dp_rx
                 tot_dp_drop += delta_dp_drop
                 delta_drop = t3_drop - t2_drop
                 tot_drop += delta_drop
                 t2_rx, t2_non_dp_rx, t2_tx, t2_non_dp_tx, t2_drop, t2_tx_fail, t2_tsc = t3_rx, t3_non_dp_rx, t3_tx, t3_non_dp_tx, t3_drop, t3_tx_fail, t3_tsc
                 core_avail = True
             if self.sut_machine != None:
                 t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc, sut_tsc_hz = self.sut_machine.core_stats(
                 )
                 if t3_sut_tsc != t2_sut_tsc:
                     single_sut_core_measurement_duration = (
                         t3_sut_tsc - t2_sut_tsc
                     ) * 1.0 / tsc_hz  # time difference between the 2 measurements, expressed in seconds.
                     tot_sut_core_measurement_duration = tot_sut_core_measurement_duration + single_sut_core_measurement_duration
                     tot_sut_rx += t3_sut_rx - t2_sut_rx
                     tot_sut_non_dp_rx += t3_sut_non_dp_rx - t2_sut_non_dp_rx
                     delta_sut_tx = t3_sut_tx - t2_sut_tx
                     tot_sut_tx += delta_sut_tx
                     delta_sut_non_dp_tx = t3_sut_non_dp_tx - t2_sut_non_dp_tx
                     tot_sut_non_dp_tx += delta_sut_non_dp_tx
                     t2_sut_rx, t2_sut_non_dp_rx, t2_sut_tx, t2_sut_non_dp_tx, t2_sut_drop, t2_sut_tx_fail, t2_sut_tsc = t3_sut_rx, t3_sut_non_dp_rx, t3_sut_tx, t3_sut_non_dp_tx, t3_sut_drop, t3_sut_tx_fail, t3_sut_tsc
                     sut_avail = True
             if self.test['test'] == 'fixed_rate':
                 if lat_avail == core_avail == True:
                     lat_avail = core_avail = False
                     pps_req_tx = (
                         delta_tx + delta_drop - delta_rx
                     ) / single_core_measurement_duration / 1000000
                     pps_tx = delta_tx / single_core_measurement_duration / 1000000
                     if self.sut_machine != None and sut_avail:
                         pps_sut_tx = delta_sut_tx / single_sut_core_measurement_duration / 1000000
                         sut_avail = False
                     else:
                         pps_sut_tx = None
                     pps_rx = delta_rx / single_core_measurement_duration / 1000000
                     RapidLog.info(
                         self.report_result(
                             flow_number, size, speed, pps_req_tx, pps_tx,
                             pps_sut_tx, pps_rx, lat_avg_sample,
                             sample_percentile, percentile_max,
                             lat_max_sample, delta_dp_tx, delta_dp_rx,
                             tot_dp_drop, single_core_measurement_duration))
         #Stop generating
         self.gen_machine.stop_gen_cores()
         r += 1
         lat_avg = old_div(lat_avg, float(tot_lat_measurement_duration))
         used_avg = old_div(used_avg, float(tot_lat_measurement_duration))
         t4_tsc = t2_tsc
         while t4_tsc == t2_tsc:
             t4_rx, t4_non_dp_rx, t4_tx, t4_non_dp_tx, t4_drop, t4_tx_fail, t4_tsc, abs_tsc_hz = self.gen_machine.core_stats(
             )
         if self.test['test'] == 'fixed_rate':
             t4_lat_tsc = t2_lat_tsc
             while t4_lat_tsc == t2_lat_tsc:
                 lat_min_sample, lat_max_sample, lat_avg_sample, used_sample, t4_lat_tsc, lat_hz, buckets = self.gen_machine.lat_stats(
                 )
             sample_count = 0
             lat_samples = sum(buckets)
             for percentile, bucket in enumerate(buckets, start=1):
                 sample_count += bucket
                 if sample_count > lat_samples * LAT_PERCENTILE:
                     break
             percentile_max = (percentile == len(buckets))
             percentile = percentile * float(2**BUCKET_SIZE_EXP) / (old_div(
                 float(lat_hz), float(10**6)))
             lat_max = lat_max_sample
             lat_avg = lat_avg_sample
             delta_rx = t4_rx - t2_rx
             delta_non_dp_rx = t4_non_dp_rx - t2_non_dp_rx
             delta_tx = t4_tx - t2_tx
             delta_non_dp_tx = t4_non_dp_tx - t2_non_dp_tx
             delta_dp_tx = delta_tx - delta_non_dp_tx
             delta_dp_rx = delta_rx - delta_non_dp_rx
             dp_tx = delta_dp_tx
             dp_rx = delta_dp_rx
             tot_dp_drop += delta_dp_tx - delta_dp_rx
             pps_req_tx = None
             pps_tx = None
             pps_sut_tx = None
             pps_rx = None
             drop_rate = 100.0 * (dp_tx - dp_rx) / dp_tx
             tot_core_measurement_duration = None
             break  ## Not really needed since the while loop will stop when evaluating the value of r
         else:
             sample_count = 0
             for percentile, bucket in enumerate(buckets_total, start=1):
                 sample_count += bucket
                 if sample_count > tot_lat_samples * LAT_PERCENTILE:
                     break
             percentile_max = (percentile == len(buckets_total))
             percentile = percentile * float(2**BUCKET_SIZE_EXP) / (old_div(
                 float(lat_hz), float(10**6)))
             pps_req_tx = (
                 tot_tx + tot_drop - tot_rx
             ) / tot_core_measurement_duration / 1000000.0  # tot_drop is all packets dropped by all tasks. This includes packets dropped at the generator task + packets dropped by the nop task. In steady state, this equals to the number of packets received by this VM
             pps_tx = tot_tx / tot_core_measurement_duration / 1000000.0  # tot_tx is all generated packets actually accepted by the interface
             pps_rx = tot_rx / tot_core_measurement_duration / 1000000.0  # tot_rx is all packets received by the nop task = all packets received in the gen VM
             if self.sut_machine != None and sut_avail:
                 pps_sut_tx = tot_sut_tx / tot_sut_core_measurement_duration / 1000000.0
             else:
                 pps_sut_tx = None
             dp_tx = (t4_tx - t1_tx) - (t4_non_dp_tx - t1_non_dp_tx)
             dp_rx = (t4_rx - t1_rx) - (t4_non_dp_rx - t1_non_dp_rx)
             tot_dp_drop = dp_tx - dp_rx
             drop_rate = 100.0 * tot_dp_drop / dp_tx
             if ((drop_rate < self.test['drop_rate_threshold']) or
                 (tot_dp_drop == self.test['drop_rate_threshold'] == 0)
                     or (tot_dp_drop > self.test['maxz'])):
                 break
     return (pps_req_tx, pps_tx, pps_sut_tx, pps_rx, lat_avg, percentile,
             percentile_max, lat_max, dp_tx, dp_rx, tot_dp_drop,
             (t4_tx_fail - t1_tx_fail), drop_rate, lat_min, used_avg, r,
             tot_core_measurement_duration)