1 # Copyright (c) 2016-2017 Intel Corporation
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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 """ Base class implementation for generic vnf implementation """
21 from yardstick.common import messaging
22 from yardstick.common.messaging import producer
23 from yardstick.network_services.helpers.samplevnf_helper import PortPairs
26 LOG = logging.getLogger(__name__)
29 class QueueFileWrapper(object):
30 """ Class providing file-like API for talking with SSH connection """
32 def __init__(self, q_in, q_out, prompt):
41 """ read chunk from input queue """
42 if self.q_in.qsize() > 0 and size:
43 in_data = self.q_in.get()
46 def write(self, chunk):
47 """ write chunk to output queue """
48 self.buf.append(chunk)
49 # flush on prompt or if we exceed bufsize
51 size = sum(len(c) for c in self.buf)
52 if self.prompt in chunk or size > self.bufsize:
53 out = ''.join(self.buf)
58 """ close multiprocessing queue """
63 while self.q_out.qsize() > 0:
67 class VnfdHelper(dict):
69 def __init__(self, *args, **kwargs):
70 super(VnfdHelper, self).__init__(*args, **kwargs)
71 self.port_pairs = PortPairs(self['vdu'][0]['external-interface'])
72 # port num is not present until binding so we have to memoize
73 self._port_num_map = {}
76 def mgmt_interface(self):
77 return self["mgmt-interface"]
89 return self.vdu0['external-interface']
93 return self['benchmark']['kpi']
95 def find_virtual_interface(self, **kwargs):
96 key, value = next(iter(kwargs.items()))
97 for interface in self.interfaces:
98 virtual_intf = interface["virtual-interface"]
99 if virtual_intf[key] == value:
103 def find_interface(self, **kwargs):
104 key, value = next(iter(kwargs.items()))
105 for interface in self.interfaces:
106 if interface[key] == value:
110 # hide dpdk_port_num key so we can abstract
111 def find_interface_by_port(self, port):
112 for interface in self.interfaces:
113 virtual_intf = interface["virtual-interface"]
114 # we have to convert to int to compare
115 if int(virtual_intf['dpdk_port_num']) == port:
119 def port_num(self, port):
120 # we need interface name -> DPDK port num (PMD ID) -> LINK ID
121 # LINK ID -> PMD ID is governed by the port mask
127 if isinstance(port, dict):
130 intf = self.find_interface(name=port)
131 return self._port_num_map.setdefault(intf["name"],
132 int(intf["virtual-interface"]["dpdk_port_num"]))
134 def port_nums(self, intfs):
135 return [self.port_num(i) for i in intfs]
137 def ports_iter(self):
138 for port_name in self.port_pairs.all_ports:
139 port_num = self.port_num(port_name)
140 yield port_name, port_num
143 class TrafficGeneratorProducer(producer.MessagingProducer):
144 """Class implementing the message producer for traffic generators
146 This message producer must be instantiated in the process created
147 "run_traffic" process.
149 def __init__(self, pid):
150 super(TrafficGeneratorProducer, self).__init__(messaging.TOPIC_TG,
154 @six.add_metaclass(abc.ABCMeta)
155 class GenericVNF(object):
156 """Class providing file-like API for generic VNF implementation
158 Currently the only class implementing this interface is
159 yardstick/network_services/vnf_generic/vnf/sample_vnf:SampleVNF.
162 # centralize network naming convention
163 UPLINK = PortPairs.UPLINK
164 DOWNLINK = PortPairs.DOWNLINK
166 def __init__(self, name, vnfd):
168 self.vnfd_helper = VnfdHelper(vnfd)
169 # List of statistics we can obtain from this VNF
170 # - ETSI MANO 6.3.1.1 monitoring_parameter
171 self.kpi = self.vnfd_helper.kpi
172 # Standard dictionary containing params like thread no, buffer size etc
174 self.runs_traffic = False
177 def instantiate(self, scenario_cfg, context_cfg):
178 """Prepare VNF for operation and start the VNF process/VM
180 :param scenario_cfg: Scenario config
181 :param context_cfg: Context config
186 def wait_for_instantiate(self):
187 """Wait for VNF to start
194 """Kill all VNF processes"""
197 def scale(self, flavor=""):
200 :param flavor: Name of the flavor.
205 def collect_kpi(self):
206 """Return a dict containing the selected KPI at a given point of time
208 :return: {"kpi": value, "kpi2": value}
212 def start_collect(self):
213 """Start KPI collection
218 def stop_collect(self):
219 """Stop KPI collection
224 @six.add_metaclass(abc.ABCMeta)
225 class GenericTrafficGen(GenericVNF):
226 """ Class providing file-like API for generic traffic generator """
228 def __init__(self, name, vnfd):
229 super(GenericTrafficGen, self).__init__(name, vnfd)
230 self.runs_traffic = True
231 self.traffic_finished = False
232 self._mq_producer = None
235 def run_traffic(self, traffic_profile):
236 """Generate traffic on the wire according to the given params.
238 This method is non-blocking, returns immediately when traffic process
239 is running. Mandatory.
241 :param traffic_profile:
247 """After this method finishes, all traffic processes should stop.
254 def listen_traffic(self, traffic_profile):
255 """Listen to traffic with the given parameters.
257 Method is non-blocking, returns immediately when traffic process
258 is running. Optional.
260 :param traffic_profile:
265 def verify_traffic(self, traffic_profile):
266 """Verify captured traffic after it has ended.
270 :param traffic_profile:
275 def wait_for_instantiate(self):
276 """Wait for an instance to load.
284 def start_collect(self):
285 """Start KPI collection.
287 Traffic measurements are always collected during injection.
295 def stop_collect(self):
296 """Stop KPI collection.
304 def _setup_mq_producer(self, pid):
305 """Setup the TG MQ producer to send messages between processes
307 :return: (derived class from ``MessagingProducer``) MQ producer object
309 return TrafficGeneratorProducer(pid)