Merge "Add "duration" parameter to test case definition"
[yardstick.git] / yardstick / network_services / traffic_profile / ixia_rfc2544.py
index ddb41f3..73806f9 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import absolute_import
 import logging
-import json
 
-from yardstick.network_services.traffic_profile.traffic_profile import \
+from yardstick.network_services.traffic_profile.trex_traffic_profile import \
     TrexProfile
 
 LOG = logging.getLogger(__name__)
 
 
 class IXIARFC2544Profile(TrexProfile):
-    def _get_ixia_traffic_profile(self, profile_data, mac={},
-                                  xfile=None, static_traffic={}):
+
+    UPLINK = 'uplink'
+    DOWNLINK = 'downlink'
+
+    def _get_ixia_traffic_profile(self, profile_data, mac=None):
+        if mac is None:
+            mac = {}
+
         result = {}
-        if xfile:
-            with open(xfile, 'r') as stream:
+        for traffickey, values in profile_data.items():
+            if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
+                continue
+
+            try:
+                # values should be single-item dict, so just grab the first item
+                try:
+                    key, value = next(iter(values.items()))
+                except StopIteration:
+                    result[traffickey] = {}
+                    continue
+
+                port_id = value.get('id', 1)
+                port_index = port_id - 1
                 try:
-                    static_traffic = json.load(stream)
-                except Exception as exc:
-                    LOG.debug(exc)
-
-        for traffickey, trafficvalue in static_traffic.items():
-            traffic = static_traffic[traffickey]
-            # outer_l2
-            index = 0
-            for key, value in profile_data[traffickey].items():
-                framesize = value['outer_l2']['framesize']
-                traffic['outer_l2']['framesize'] = framesize
-                traffic['framesPerSecond'] = True
-                traffic['bidir'] = False
-                traffic['outer_l2']['srcmac'] = \
-                    mac["src_mac_{}".format(traffic['id'])]
-                traffic['outer_l2']['dstmac'] = \
-                    mac["dst_mac_{}".format(traffic['id'])]
-
-                # outer_l3
-                if "outer_l3v6" in list(value.keys()):
-                    traffic['outer_l3'] = value['outer_l3v6']
-                    srcip4 = value['outer_l3v6']['srcip6']
-                    traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
-                    dstip4 = value['outer_l3v6']['dstip6']
-                    traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
+                    ip = value['outer_l3v6']
+                except KeyError:
+                    ip = value['outer_l3v4']
+                    src_key, dst_key = 'srcip4', 'dstip4'
                 else:
-                    traffic['outer_l3'] = value['outer_l3v4']
-                    srcip4 = value['outer_l3v4']['srcip4']
-                    traffic['outer_l3']['srcip4'] = srcip4.split("-")[0]
-                    dstip4 = value['outer_l3v4']['dstip4']
-                    traffic['outer_l3']['dstip4'] = dstip4.split("-")[0]
-
-                traffic['outer_l3']['type'] = key
-                traffic['outer_l3']['count'] = value['outer_l3v4']['count']
-                # outer_l4
-                traffic['outer_l4'] = value['outer_l4']
-                index = index + 1
-            result.update({traffickey: traffic})
+                    src_key, dst_key = 'srcip6', 'dstip6'
+
+                result[traffickey] = {
+                    'bidir': False,
+                    'iload': '100',
+                    'id': port_id,
+                    'outer_l2': {
+                        'framesize': value['outer_l2']['framesize'],
+                        'framesPerSecond': True,
+                        'srcmac': mac['src_mac_{}'.format(port_index)],
+                        'dstmac': mac['dst_mac_{}'.format(port_index)],
+                    },
+                    'outer_l3': {
+                        'count': ip['count'],
+                        'dscp': ip['dscp'],
+                        'ttl': ip['ttl'],
+                        src_key: ip[src_key].split("-")[0],
+                        dst_key: ip[dst_key].split("-")[0],
+                        'type': key,
+                        'proto': ip['proto'],
+                    },
+                    'outer_l4': value['outer_l4'],
+                }
+            except KeyError:
+                continue
 
         return result
 
-    def _ixia_traffic_generate(self, traffic_generator, traffic, ixia_obj):
+    def _ixia_traffic_generate(self, traffic, ixia_obj):
         for key, value in traffic.items():
-            if "public" in key or "private" in key:
-                traffic[key]["iload"] = str(self.rate)
-        ixia_obj.ix_update_frame(traffic)
-        ixia_obj.ix_update_ether(traffic)
-        ixia_obj.add_ip_header(traffic, 4)
-        ixia_obj.ix_start_traffic()
-        self.tmp_drop = 0
-        self.tmp_throughput = 0
-
-    def update_traffic_profile(self):
-        self.profile = 'private_1'
-        for key, value in self.params.items():
-            if "private" in key or "public" in key:
-                self.profile_data = self.params[key]
+            if key.startswith((self.UPLINK, self.DOWNLINK)):
+                value['iload'] = str(self.rate)
+        ixia_obj.update_frame(traffic)
+        ixia_obj.update_ip_packet(traffic)
+        ixia_obj.start_traffic()
+
+    def update_traffic_profile(self, traffic_generator):
+        def port_generator():
+            for vld_id, intfs in sorted(traffic_generator.networks.items()):
+                if not vld_id.startswith((self.UPLINK, self.DOWNLINK)):
+                    continue
+                profile_data = self.params.get(vld_id)
+                if not profile_data:
+                    continue
+                self.profile_data = profile_data
                 self.get_streams(self.profile_data)
-                self.full_profile.update({key: self.profile_data})
+                self.full_profile.update({vld_id: self.profile_data})
+                for intf in intfs:
+                    yield traffic_generator.vnfd_helper.port_num(intf)
 
-    def execute(self, traffic_generator, ixia_obj, mac={}, xfile=None):
+        self.ports = [port for port in port_generator()]
+
+    def execute_traffic(self, traffic_generator, ixia_obj=None, mac=None):
+        mac = {} if mac is None else mac
+        first_run = self.first_run
         if self.first_run:
+            self.first_run = False
             self.full_profile = {}
             self.pg_id = 0
-            self.update_traffic_profile()
-            traffic = \
-                self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
+            self.update_traffic_profile(traffic_generator)
             self.max_rate = self.rate
             self.min_rate = 0
-            self.get_multiplier()
-            self._ixia_traffic_generate(traffic_generator, traffic, ixia_obj)
-
-    def get_multiplier(self):
-        self.rate = round((self.max_rate + self.min_rate) / 2.0, 2)
-        multiplier = round(self.rate / self.pps, 2)
-        return str(multiplier)
-
-    def start_ixia_latency(self, traffic_generator, ixia_obj,
-                           mac={}, xfile=None):
-        self.update_traffic_profile()
-        traffic = \
-            self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
-        self._ixia_traffic_generate(traffic_generator, traffic,
-                                    ixia_obj, xfile)
-
-    def get_drop_percentage(self, traffic_generator, samples, tol_min,
-                            tolerance, ixia_obj, mac={}, xfile=None):
-        status = 'Running'
+        else:
+            self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 2)
+
+        traffic = self._get_ixia_traffic_profile(self.full_profile, mac)
+        self._ixia_traffic_generate(traffic, ixia_obj)
+        return first_run
+
+    def get_drop_percentage(self, samples, tol_min, tolerance, duration=30.0,
+                            first_run=False):
+        completed = False
         drop_percent = 100
-        in_packets = sum([samples[iface]['in_packets'] for iface in samples])
-        out_packets = sum([samples[iface]['out_packets'] for iface in samples])
-        rx_throughput = \
-            sum([samples[iface]['RxThroughput'] for iface in samples])
-        tx_throughput = \
-            sum([samples[iface]['TxThroughput'] for iface in samples])
-        packet_drop = abs(out_packets - in_packets)
+        num_ifaces = len(samples)
+        in_packets_sum = sum(
+            [samples[iface]['in_packets'] for iface in samples])
+        out_packets_sum = sum(
+            [samples[iface]['out_packets'] for iface in samples])
+        rx_throughput = sum(
+            [samples[iface]['RxThroughput'] for iface in samples])
+        rx_throughput = round(float(rx_throughput), 2)
+        tx_throughput = sum(
+            [samples[iface]['TxThroughput'] for iface in samples])
+        tx_throughput = round(float(tx_throughput), 2)
+        packet_drop = abs(out_packets_sum - in_packets_sum)
+
         try:
-            drop_percent = round((packet_drop / float(out_packets)) * 100, 2)
+            drop_percent = round(
+                (packet_drop / float(out_packets_sum)) * 100, 2)
         except ZeroDivisionError:
             LOG.info('No traffic is flowing')
-        samples['TxThroughput'] = round(tx_throughput / 1.0, 2)
-        samples['RxThroughput'] = round(rx_throughput / 1.0, 2)
-        samples['CurrentDropPercentage'] = drop_percent
-        samples['Throughput'] = self.tmp_throughput
-        samples['DropPercentage'] = self.tmp_drop
-        if drop_percent > tolerance and self.tmp_throughput == 0:
-            samples['Throughput'] = round(rx_throughput / 1.0, 2)
-            samples['DropPercentage'] = drop_percent
-        if self.first_run:
-            max_supported_rate = out_packets / 30.0
-            self.rate = max_supported_rate
-            self.first_run = False
-            if drop_percent <= tolerance:
-                status = 'Completed'
+
+        samples['TxThroughput'] = tx_throughput
+        samples['RxThroughput'] = rx_throughput
+        samples['DropPercentage'] = drop_percent
+
+        if first_run:
+            self.rate = out_packets_sum / duration / num_ifaces
+            completed = True if drop_percent <= tolerance else False
+
         if drop_percent > tolerance:
             self.max_rate = self.rate
         elif drop_percent < tol_min:
             self.min_rate = self.rate
-            if drop_percent >= self.tmp_drop:
-                self.tmp_drop = drop_percent
-                self.tmp_throughput = round((rx_throughput / 1.0), 2)
-                samples['Throughput'] = round(rx_throughput / 1.0, 2)
-                samples['DropPercentage'] = drop_percent
         else:
-            samples['Throughput'] = round(rx_throughput / 1.0, 2)
-            samples['DropPercentage'] = drop_percent
-            return status, samples
-        self.get_multiplier()
-        traffic = self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
-        self._ixia_traffic_generate(traffic_generator, traffic, ixia_obj)
-        return status, samples
+            completed = True
+
+        return completed, samples