aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/network_services/vnf_generic/vnf/tg_ping.py
blob: a3b5afa39d736a97dac07154f341c4c3a5a12786 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Copyright (c) 2016-2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" PING acts as traffic generation and vnf definitions based on IETS Spec """

from __future__ import absolute_import
import logging
import re

from multiprocessing import Queue
from ipaddress import IPv4Interface

from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper

LOG = logging.getLogger(__name__)


class PingParser(object):
    """ Class providing file-like API for talking with SSH connection """

    def __init__(self, q_out):
        self.queue = q_out
        self.closed = False

    def write(self, chunk):
        """ 64 bytes from 10.102.22.93: icmp_seq=1 ttl=64 time=0.296 ms """
        match = re.search(r"icmp_seq=(\d+).*time=([0-9.]+)", chunk)
        LOG.debug("Parser called on %s", chunk)
        if match:
            # IMPORTANT: in order for the data to be properly taken
            # in by InfluxDB, it needs to be converted to numeric types
            self.queue.put({
                "packets_received": float(match.group(1)),
                "rtt": float(match.group(2)),
            })

    def close(self):
        """ close the ssh connection """
        self.closed = True

    def clear(self):
        """ clear queue till Empty """
        while self.queue.qsize() > 0:
            self.queue.get()


class PingSetupEnvHelper(DpdkVnfSetupEnvHelper):

    def setup_vnf_environment(self):
        for intf in self.vnfd_helper.interfaces:
            vi = intf['virtual-interface']
            vi['local_iface_name'] = self.get_local_iface_name_by_vpci(vi['vpci'])


class PingResourceHelper(ClientResourceHelper):

    def __init__(self, setup_helper):
        super(PingResourceHelper, self).__init__(setup_helper)
        self._queue = Queue()
        self._parser = PingParser(self._queue)

    def run_traffic(self, traffic_profile, *args):
        # drop the connection in order to force a new one
        self.ssh_helper.drop_connection()

        self.client_started.value = 1
        cmd_list = [
            "sudo ip addr flush {local_if_name}",
            "sudo ip addr add {local_ip}/24 dev {local_if_name}",
            "sudo ip link set {local_if_name} up",
        ]

        self.cmd_kwargs['packet_size'] = traffic_profile.params['traffic_profile']['frame_size']

        for cmd in cmd_list:
            self.ssh_helper.execute(cmd.format(**self.cmd_kwargs))

        ping_cmd = "nohup ping -s {packet_size} {target_ip}&"
        self.ssh_helper.run(ping_cmd.format(**self.cmd_kwargs),
                            stdout=self._parser,
                            keep_stdin_open=True, pty=True)


class PingTrafficGen(SampleVNFTrafficGen):
    """
    This traffic generator can ping a single IP with pingsize
    and target given in traffic profile
    """

    TG_NAME = 'Ping'
    APP_NAME = 'Ping'
    RUN_WAIT = 4

    def __init__(self, name, vnfd, task_id, setup_env_helper_type=None,
                 resource_helper_type=None):
        if setup_env_helper_type is None:
            setup_env_helper_type = PingSetupEnvHelper
        if resource_helper_type is None:
            resource_helper_type = PingResourceHelper
        super(PingTrafficGen, self).__init__(
            name, vnfd, task_id, setup_env_helper_type, resource_helper_type)
        self._result = {}

    def _check_status(self):
        return self._tg_process.is_alive()

    def instantiate(self, scenario_cfg, context_cfg):
        self._start_server()
        self._result = {
            "packets_received": 0,
            "rtt": 0,
        }
        self.setup_helper.setup_vnf_environment()
        intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
        self.resource_helper.cmd_kwargs = {
            'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
            'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
            'local_if_name': intf["local_iface_name"].split('/')[0],
        }