NSB update
[yardstick.git] / yardstick / network_services / vnf_generic / vnf / tg_ping.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 """ PING acts as traffic generation and vnf definitions based on IETS Spec """
15
16 from __future__ import absolute_import
17 from __future__ import print_function
18 import logging
19 import re
20
21 from multiprocessing import Queue
22 from ipaddress import IPv4Interface
23
24 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
25 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
26
27 LOG = logging.getLogger(__name__)
28
29
30 class PingParser(object):
31     """ Class providing file-like API for talking with SSH connection """
32
33     def __init__(self, q_out):
34         self.queue = q_out
35         self.closed = False
36
37     def write(self, chunk):
38         """ 64 bytes from 10.102.22.93: icmp_seq=1 ttl=64 time=0.296 ms """
39         match = re.search(r"icmp_seq=(\d+).*time=([0-9.]+)", chunk)
40         LOG.debug("Parser called on %s", chunk)
41         if match:
42             # IMPORTANT: in order for the data to be properly taken
43             # in by InfluxDB, it needs to be converted to numeric types
44             self.queue.put({
45                 "packets_received": float(match.group(1)),
46                 "rtt": float(match.group(2)),
47             })
48
49     def close(self):
50         """ close the ssh connection """
51         self.closed = True
52
53     def clear(self):
54         """ clear queue till Empty """
55         while self.queue.qsize() > 0:
56             self.queue.get()
57
58
59 class PingSetupEnvHelper(DpdkVnfSetupEnvHelper):
60
61     def setup_vnf_environment(self):
62         self._bind_kernel_devices()
63
64
65 class PingTrafficGen(SampleVNFTrafficGen):
66     """
67     This traffic generator can ping a single IP with pingsize
68     and target given in traffic profile
69     """
70
71     TG_NAME = 'Ping'
72     RUN_WAIT = 4
73
74     def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
75         if setup_env_helper_type is None:
76             setup_env_helper_type = PingSetupEnvHelper
77
78         super(PingTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
79                                              resource_helper_type)
80         self._queue = Queue()
81         self._parser = PingParser(self._queue)
82         self._result = {}
83
84     def scale(self, flavor=""):
85         """ scale vnf-based on flavor input """
86         pass
87
88     def _check_status(self):
89         return self._tg_process.is_alive()
90
91     def instantiate(self, scenario_cfg, context_cfg):
92         self._result = {
93             "packets_received": 0,
94             "rtt": 0,
95         }
96         self.setup_helper.setup_vnf_environment()
97
98     def listen_traffic(self, traffic_profile):
99         """ Not needed for ping
100
101         :param traffic_profile:
102         :return:
103         """
104         pass
105
106     def _traffic_runner(self, traffic_profile):
107         intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
108         profile = traffic_profile.params["traffic_profile"]
109         cmd_kwargs = {
110             'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
111             'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
112             'local_if_name': intf["local_iface_name"].split('/')[0],
113             'packet_size': profile["frame_size"],
114         }
115
116         cmd_list = [
117             "sudo ip addr flush {local_if_name}",
118             "sudo ip addr add {local_ip}/24 dev {local_if_name}",
119             "sudo ip link set {local_if_name} up",
120         ]
121
122         for cmd in cmd_list:
123             self.ssh_helper.execute(cmd.format(**cmd_kwargs))
124
125         ping_cmd = "ping -s {packet_size} {target_ip}"
126         self.ssh_helper.run(ping_cmd.format(**cmd_kwargs),
127                             stdout=self._parser,
128                             keep_stdin_open=True, pty=True)