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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# 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.
""" Trex acts as traffic generation and vnf definitions based on IETS Spec """
from __future__ import absolute_import
from __future__ import print_function
import logging
import os
import yaml
from yardstick.common.utils import mac_address_to_hex_list, try_int
from yardstick.network_services.utils import get_nsb_option
from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
LOG = logging.getLogger(__name__)
class TrexDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
APP_NAME = "t-rex-64"
CFG_CONFIG = ""
CFG_SCRIPT = ""
PIPELINE_COMMAND = ""
VNF_TYPE = "TG"
class TrexResourceHelper(ClientResourceHelper):
CONF_FILE = '/tmp/trex_cfg.yaml'
QUEUE_WAIT_TIME = 1
RESOURCE_WORD = 'trex'
RUN_DURATION = 0
ASYNC_PORT = 4500
SYNC_PORT = 4501
def generate_cfg(self):
port_names = self.vnfd_helper.port_pairs.all_ports
vpci_list = []
port_list = []
port_nums = sorted(self.vnfd_helper.port_nums(port_names))
for port_num in port_nums:
interface = self.vnfd_helper.find_interface_by_port(port_num)
virtual_interface = interface['virtual-interface']
dst_mac = virtual_interface["dst_mac"]
# why skip?, ordering is based on DPDK port number so we can't skip
if not dst_mac:
continue
# TRex ports must be in DPDK port number, so order of append matters
vpci_list.append(virtual_interface["vpci"])
local_mac = virtual_interface["local_mac"]
port_list.append({
"src_mac": mac_address_to_hex_list(local_mac),
"dest_mac": mac_address_to_hex_list(dst_mac),
})
trex_cfg = {
'interfaces': vpci_list,
'port_info': port_list,
"port_limit": len(port_names),
"version": '2',
}
cfg_file = [trex_cfg]
cfg_str = yaml.safe_dump(cfg_file, default_flow_style=False, explicit_start=True)
self.ssh_helper.upload_config_file(os.path.basename(self.CONF_FILE), cfg_str)
def check_status(self):
status, _, _ = self.ssh_helper.execute("sudo lsof -i:%s" % self.SYNC_PORT)
return status
# temp disable
DISABLE_DEPLOY = True
def setup(self):
super(TrexResourceHelper, self).setup()
if self.DISABLE_DEPLOY:
return
trex_path = self.ssh_helper.join_bin_path('trex')
err = self.ssh_helper.execute("which {}".format(trex_path))[0]
if err == 0:
return
LOG.info("Copying %s to destination...", self.RESOURCE_WORD)
self.ssh_helper.run("sudo mkdir -p '{}'".format(os.path.dirname(trex_path)))
self.ssh_helper.put("~/.bash_profile", "~/.bash_profile")
self.ssh_helper.put(trex_path, trex_path, True)
ko_src = os.path.join(trex_path, "scripts/ko/src/")
self.ssh_helper.execute(self.MAKE_INSTALL.format(ko_src))
def start(self, ports=None, *args, **kwargs):
cmd = "sudo fuser -n tcp {0.SYNC_PORT} {0.ASYNC_PORT} -k > /dev/null 2>&1"
self.ssh_helper.execute(cmd.format(self))
self.ssh_helper.execute("sudo pkill -9 rex > /dev/null 2>&1")
# We MUST default to 1 because TRex won't work on single-queue devices with
# more than one core per port
# We really should be trying to find the number of queues in the driver,
# but there doesn't seem to be a way to do this
# TRex Error: the number of cores should be 1 when the driver
# support only one tx queue and one rx queue. Please use -c 1
threads_per_port = try_int(self.scenario_helper.options.get("queues_per_port"), 1)
trex_path = self.ssh_helper.join_bin_path("trex", "scripts")
path = get_nsb_option("trex_path", trex_path)
cmd = "./t-rex-64 --no-scapy-server -i -c {} --cfg '{}'".format(threads_per_port,
self.CONF_FILE)
if self.scenario_helper.options.get("trex_server_debug"):
# if there are errors we want to see them
redir = ""
else:
redir = ">/dev/null"
# we have to sudo cd because the path might be owned by root
trex_cmd = """sudo bash -c "cd '{}' ; {}" {}""".format(path, cmd, redir)
LOG.debug(trex_cmd)
self.ssh_helper.execute(trex_cmd)
def terminate(self):
super(TrexResourceHelper, self).terminate()
cmd = "sudo fuser -n tcp %s %s -k > /dev/null 2>&1"
self.ssh_helper.execute(cmd % (self.SYNC_PORT, self.ASYNC_PORT))
class TrexTrafficGen(SampleVNFTrafficGen):
"""
This class handles mapping traffic profile and generating
traffic for given testcase
"""
APP_NAME = 'TRex'
def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
if resource_helper_type is None:
resource_helper_type = TrexResourceHelper
if setup_env_helper_type is None:
setup_env_helper_type = TrexDpdkVnfSetupEnvHelper
super(TrexTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
resource_helper_type)
def _check_status(self):
return self.resource_helper.check_status()
def _start_server(self):
super(TrexTrafficGen, self)._start_server()
self.resource_helper.start()
def scale(self, flavor=""):
pass
def listen_traffic(self, traffic_profile):
pass
def terminate(self):
self.resource_helper.terminate()
|