Merge "Configure n_rxq DPDK port option when adding the port"
[yardstick.git] / yardstick / network_services / traffic_profile / prox_profile.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """ Fixed traffic profile definitions """
15
16 from __future__ import absolute_import
17
18 import logging
19 import multiprocessing
20
21 from yardstick.network_services.traffic_profile.base import TrafficProfile
22 from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxProfileHelper
23
24 LOG = logging.getLogger(__name__)
25
26
27 class ProxProfile(TrafficProfile):
28     """
29     This profile adds a single stream at the beginning of the traffic session
30     """
31
32     @staticmethod
33     def sort_vpci(traffic_gen):
34         """Return the list of external interfaces ordered by vpci and name
35
36         :param traffic_gen: (ProxTrafficGen) traffic generator
37         :return: list of ordered interfaces
38         """
39         def key_func(interface):
40             return interface['virtual-interface']['vpci'], interface['name']
41
42         return sorted(traffic_gen.vnfd_helper['vdu'][0]['external-interface'],
43                       key=key_func)
44
45     @staticmethod
46     def fill_samples(samples, traffic_gen):
47         vpci_if_name_ascending = ProxProfile.sort_vpci(traffic_gen)
48         for vpci_idx, intf in enumerate(vpci_if_name_ascending):
49             name = intf[1]
50             # TODO: VNFDs KPIs values needs to be mapped to TRex structure
51             xe_port = traffic_gen.resource_helper.sut.port_stats([vpci_idx])
52             samples[name] = {
53                 "in_packets": xe_port[6],
54                 "out_packets": xe_port[7],
55             }
56
57     def __init__(self, tp_config):
58         super(ProxProfile, self).__init__(tp_config)
59         self.queue = None
60         self.done = multiprocessing.Event()
61         self.results = []
62
63         # TODO: get init values from tp_config
64         self.prox_config = tp_config["traffic_profile"]
65         self.pkt_sizes = [int(x) for x in self.prox_config.get("packet_sizes", [])]
66         self.pkt_size_iterator = iter(self.pkt_sizes)
67         self.duration = int(self.prox_config.get("duration", 5))
68         self.precision = float(self.prox_config.get('test_precision', 1.0))
69         self.tolerated_loss = float(self.prox_config.get('tolerated_loss', 0.0))
70
71         # TODO: is this ever a function of packet size?
72         self.lower_bound = float(self.prox_config.get('lower_bound', 10.0))
73         self.upper_bound = float(self.prox_config.get('upper_bound', 100.0))
74         self.step_value = float(self.prox_config.get('step_value', 10.0))
75         self._profile_helper = None
76
77     def make_profile_helper(self, traffic_gen):
78         if self._profile_helper is None:
79             self._profile_helper = ProxProfileHelper.make_profile_helper(traffic_gen)
80         return self._profile_helper
81
82     def init(self, queue):
83         self.pkt_size_iterator = iter(self.pkt_sizes)
84         self.queue = queue
85         self.queue.cancel_join_thread()
86
87     def bounds_iterator(self, logger=None):
88         if logger:
89             logger.debug("Interval [%s, %s), step: %d", self.lower_bound,
90                          self.upper_bound, self.step_value)
91
92         test_value = self.lower_bound
93         while test_value <= self.upper_bound:
94             if logger:
95                 logger.info("Testing with value %s", test_value)
96             yield test_value
97             test_value += self.step_value
98
99     @property
100     def min_pkt_size(self):
101         """Return the minimum required packet size for the test.
102
103         Defaults to 64. Individual test must override this method if they have
104         other requirements.
105
106         Returns:
107             int. The minimum required packet size for the test.
108         """
109         return 64
110
111     def run_test_with_pkt_size(self, traffic_generator, pkt_size, duration):
112         raise NotImplementedError
113
114     def execute_traffic(self, traffic_generator):
115         self.make_profile_helper(traffic_generator)
116
117         try:
118             pkt_size = next(self.pkt_size_iterator)
119         except StopIteration:
120             self.done.set()
121             return
122
123         # Adjust packet size upwards if it's less than the minimum
124         # required packet size for the test.
125         if pkt_size < self.min_pkt_size:
126             pkt_size += self.min_pkt_size - 64
127
128         duration = self.duration
129         self.run_test_with_pkt_size(traffic_generator, pkt_size, duration)