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 """ PING acts as traffic generation and vnf definitions based on IETS Spec """
16 from __future__ import absolute_import
17 from __future__ import print_function
19 import multiprocessing
24 from yardstick import ssh
25 from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
26 from yardstick.network_services.utils import provision_tool
28 LOG = logging.getLogger(__name__)
31 class PingParser(object):
32 """ Class providing file-like API for talking with SSH connection """
34 def __init__(self, q_out):
38 def write(self, chunk):
39 """ 64 bytes from 10.102.22.93: icmp_seq=1 ttl=64 time=0.296 ms """
40 match = re.search(r"icmp_seq=(\d+).*time=([0-9.]+)", chunk)
41 LOG.debug("Parser called on %s", chunk)
43 # IMPORTANT: in order for the data to be properly taken
44 # in by InfluxDB, it needs to be converted to numeric types
45 self.queue.put({"packets_received": float(match.group(1)),
46 "rtt": float(match.group(2))})
49 ''' close the ssh connection '''
53 ''' clear queue till Empty '''
54 while self.queue.qsize() > 0:
58 class PingTrafficGen(GenericTrafficGen):
60 This traffic generator can ping a single IP with pingsize
61 and target given in traffic profile
64 def __init__(self, vnfd):
65 super(PingTrafficGen, self).__init__(vnfd)
69 self._traffic_process = None
71 mgmt_interface = vnfd["mgmt-interface"]
72 self.connection = ssh.SSH.from_node(mgmt_interface)
73 self.connection.wait()
75 def _bind_device_kernel(self, connection):
77 provision_tool(self.connection,
78 os.path.join(self.bin_path, "dpdk_nic_bind.py"))
80 drivers = {intf["virtual-interface"]["vpci"]:
81 intf["virtual-interface"]["driver"]
82 for intf in self.vnfd["vdu"][0]["external-interface"]}
85 ['"{0}" --force -b "{1}" "{2}"'.format(dpdk_nic_bind, value, key)
86 for key, value in drivers.items()]
87 for command in commands:
88 connection.execute(command)
90 for index, out in enumerate(self.vnfd["vdu"][0]["external-interface"]):
91 vpci = out["virtual-interface"]["vpci"]
92 net = "find /sys/class/net -lname '*{}*' -printf '%f'".format(vpci)
93 out = connection.execute(net)[1]
94 ifname = out.split('/')[-1].strip('\n')
95 self.vnfd["vdu"][0]["external-interface"][index][
96 "virtual-interface"]["local_iface_name"] = ifname
98 def scale(self, flavor=""):
99 ''' scale vnfbased on flavor input '''
100 super(PingTrafficGen, self).scale(flavor)
102 def instantiate(self, scenario_cfg, context_cfg):
103 self._result = {"packets_received": 0, "rtt": 0}
104 self._bind_device_kernel(self.connection)
106 def run_traffic(self, traffic_profile):
107 self._queue = multiprocessing.Queue()
108 self._parser = PingParser(self._queue)
109 self._traffic_process = \
110 multiprocessing.Process(target=self._traffic_runner,
111 args=(traffic_profile, self._parser))
112 self._traffic_process.start()
113 # Wait for traffic process to start
115 return self._traffic_process.is_alive()
117 def listen_traffic(self, traffic_profile):
118 """ Not needed for ping
120 :param traffic_profile:
125 def _traffic_runner(self, traffic_profile, filewrapper):
127 mgmt_interface = self.vnfd["mgmt-interface"]
128 self.connection = ssh.SSH.from_node(mgmt_interface)
129 self.connection.wait()
130 external_interface = self.vnfd["vdu"][0]["external-interface"]
131 virtual_interface = external_interface[0]["virtual-interface"]
132 target_ip = virtual_interface["dst_ip"].split('/')[0]
133 local_ip = virtual_interface["local_ip"].split('/')[0]
135 virtual_interface["local_iface_name"].split('/')[0]
136 packet_size = traffic_profile.params["traffic_profile"]["frame_size"]
140 run_cmd.append("ip addr flush %s" % local_if_name)
141 run_cmd.append("ip addr add %s/24 dev %s" % (local_ip, local_if_name))
142 run_cmd.append("ip link set %s up" % local_if_name)
145 self.connection.execute(cmd)
147 ping_cmd = ("ping -s %s %s" % (packet_size, target_ip))
148 self.connection.run(ping_cmd, stdout=filewrapper,
149 keep_stdin_open=True, pty=True)
151 def collect_kpi(self):
152 if not self._queue.empty():
153 kpi = self._queue.get()
154 self._result.update(kpi)
158 if self._traffic_process is not None:
159 self._traffic_process.terminate()