X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=nfvbench%2Ftraffic_gen%2Ftrex_gen.py;h=189c3e599aa98e22dc534b2ed5bf54543cb2f8e2;hb=057486b092e0a4bb1989121588eb5f8afdb8e1d3;hp=53786f7a0cd7c6f848c6bc46ee7a1aa159817e43;hpb=24314713446b6411cedce4329ab5ebfd6da678a2;p=nfvbench.git diff --git a/nfvbench/traffic_gen/trex_gen.py b/nfvbench/traffic_gen/trex_gen.py index 53786f7..189c3e5 100644 --- a/nfvbench/traffic_gen/trex_gen.py +++ b/nfvbench/traffic_gen/trex_gen.py @@ -20,17 +20,14 @@ import time import traceback from itertools import count +# pylint: disable=import-error +from scapy.contrib.mpls import MPLS # flake8: noqa +# pylint: enable=import-error from nfvbench.log import LOG from nfvbench.traffic_server import TRexTrafficServer from nfvbench.utils import cast_integer from nfvbench.utils import timeout from nfvbench.utils import TimeoutError -from traffic_base import AbstractTrafficGenerator -from traffic_base import TrafficGeneratorException -import traffic_utils as utils -from traffic_utils import IMIX_AVG_L2_FRAME_SIZE -from traffic_utils import IMIX_L2_SIZES -from traffic_utils import IMIX_RATIOS # pylint: disable=import-error from trex.common.services.trex_service_arp import ServiceARP @@ -57,9 +54,15 @@ from trex.stl.api import ThreeBytesField from trex.stl.api import UDP from trex.stl.api import XByteField - # pylint: enable=import-error +from .traffic_base import AbstractTrafficGenerator +from .traffic_base import TrafficGeneratorException +from . import traffic_utils as utils +from .traffic_utils import IMIX_AVG_L2_FRAME_SIZE +from .traffic_utils import IMIX_L2_SIZES +from .traffic_utils import IMIX_RATIOS + class VXLAN(Packet): """VxLAN class.""" @@ -363,6 +366,17 @@ class TRex(AbstractTrafficGenerator): op="random") vm_param = [vxlan_udp_src_fv, STLVmWrFlowVar(fv_name="vxlan_udp_src", pkt_offset="UDP.sport")] + elif stream_cfg['mpls'] is True: + encap_level = '0' + pkt_base = Ether(src=stream_cfg['vtep_src_mac'], dst=stream_cfg['vtep_dst_mac']) + if stream_cfg['vtep_vlan'] is not None: + pkt_base /= Dot1Q(vlan=stream_cfg['vtep_vlan']) + if stream_cfg['mpls_outer_label'] is not None: + pkt_base /= MPLS(label=stream_cfg['mpls_outer_label'], cos=1, s=0, ttl=255) + if stream_cfg['mpls_inner_label'] is not None: + pkt_base /= MPLS(label=stream_cfg['mpls_inner_label'], cos=1, s=1, ttl=255) + # Flow stats and MPLS labels randomization TBD + pkt_base /= Ether(src=stream_cfg['mac_src'], dst=stream_cfg['mac_dst']) else: encap_level = '0' pkt_base = Ether(src=stream_cfg['mac_src'], dst=stream_cfg['mac_dst']) @@ -373,19 +387,28 @@ class TRex(AbstractTrafficGenerator): udp_args = {} if stream_cfg['udp_src_port']: udp_args['sport'] = int(stream_cfg['udp_src_port']) + udp_args['sport_step'] = int(stream_cfg['udp_port_step']) + udp_args['sport_max'] = int(stream_cfg['udp_src_port_max']) if stream_cfg['udp_dst_port']: udp_args['dport'] = int(stream_cfg['udp_dst_port']) - pkt_base /= IP() / UDP(**udp_args) + udp_args['dport_step'] = int(stream_cfg['udp_port_step']) + udp_args['dport_max'] = int(stream_cfg['udp_dst_port_max']) + pkt_base /= IP(src=stream_cfg['ip_src_addr'], dst=stream_cfg['ip_dst_addr']) / \ + UDP(dport=udp_args['dport'], sport=udp_args['sport']) + if stream_cfg['ip_src_static'] is True: + src_max_ip_value = stream_cfg['ip_src_addr'] + else: + src_max_ip_value = stream_cfg['ip_src_addr_max'] if stream_cfg['ip_addrs_step'] == 'random': - src_fv = STLVmFlowVarRepeatableRandom( + src_fv_ip = STLVmFlowVarRepeatableRandom( name="ip_src", min_value=stream_cfg['ip_src_addr'], - max_value=stream_cfg['ip_src_addr_max'], + max_value=src_max_ip_value, size=4, seed=random.randint(0, 32767), limit=stream_cfg['ip_src_count']) - dst_fv = STLVmFlowVarRepeatableRandom( + dst_fv_ip = STLVmFlowVarRepeatableRandom( name="ip_dst", min_value=stream_cfg['ip_dst_addr'], max_value=stream_cfg['ip_dst_addr_max'], @@ -393,14 +416,14 @@ class TRex(AbstractTrafficGenerator): seed=random.randint(0, 32767), limit=stream_cfg['ip_dst_count']) else: - src_fv = STLVmFlowVar( + src_fv_ip = STLVmFlowVar( name="ip_src", min_value=stream_cfg['ip_src_addr'], - max_value=stream_cfg['ip_src_addr'], + max_value=src_max_ip_value, size=4, op="inc", step=stream_cfg['ip_addrs_step']) - dst_fv = STLVmFlowVar( + dst_fv_ip = STLVmFlowVar( name="ip_dst", min_value=stream_cfg['ip_dst_addr'], max_value=stream_cfg['ip_dst_addr_max'], @@ -408,18 +431,49 @@ class TRex(AbstractTrafficGenerator): op="inc", step=stream_cfg['ip_addrs_step']) - vm_param.extend([ - src_fv, + if stream_cfg['udp_port_step'] == 'random': + src_fv_port = STLVmFlowVarRepeatableRandom( + name="p_src", + min_value=udp_args['sport'], + max_value=udp_args['sport_max'], + size=2, + seed=random.randint(0, 32767), + limit=udp_args['udp_src_count']) + dst_fv_port = STLVmFlowVarRepeatableRandom( + name="p_dst", + min_value=udp_args['dport'], + max_value=udp_args['dport_max'], + size=2, + seed=random.randint(0, 32767), + limit=stream_cfg['udp_dst_count']) + else: + src_fv_port = STLVmFlowVar( + name="p_src", + min_value=udp_args['sport'], + max_value=udp_args['sport_max'], + size=2, + op="inc", + step=udp_args['sport_step']) + dst_fv_port = STLVmFlowVar( + name="p_dst", + min_value=udp_args['dport'], + max_value=udp_args['dport_max'], + size=2, + op="inc", + step=udp_args['dport_step']) + vm_param = [ + src_fv_ip, STLVmWrFlowVar(fv_name="ip_src", pkt_offset="IP:{}.src".format(encap_level)), - dst_fv, - STLVmWrFlowVar(fv_name="ip_dst", pkt_offset="IP:{}.dst".format(encap_level)) - ]) - - for encap in range(int(encap_level), -1, -1): - # Fixing the checksums for all encap levels - vm_param.append(STLVmFixChecksumHw(l3_offset="IP:{}".format(encap), - l4_offset="UDP:{}".format(encap), - l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP)) + src_fv_port, + STLVmWrFlowVar(fv_name="p_src", pkt_offset="UDP:{}.sport".format(encap_level)), + dst_fv_ip, + STLVmWrFlowVar(fv_name="ip_dst", pkt_offset="IP:{}.dst".format(encap_level)), + dst_fv_port, + STLVmWrFlowVar(fv_name="p_dst", pkt_offset="UDP:{}.dport".format(encap_level)), + STLVmFixChecksumHw(l3_offset="IP:{}".format(encap_level), + l4_offset="UDP:{}".format(encap_level), + l4_type=CTRexVmInsFixHwCs.L4_TYPE_UDP) + ] pad = max(0, frame_size - len(pkt_base)) * 'x' return STLPktBuilder(pkt=pkt_base / pad, @@ -443,7 +497,7 @@ class TRex(AbstractTrafficGenerator): if l2frame == 'IMIX': for ratio, l2_frame_size in zip(IMIX_RATIOS, IMIX_L2_SIZES): pkt = self._create_pkt(stream_cfg, l2_frame_size) - if e2e: + if e2e or stream_cfg['mpls']: streams.append(STLStream(packet=pkt, mode=STLTXCont(pps=ratio))) else: @@ -466,8 +520,10 @@ class TRex(AbstractTrafficGenerator): else: l2frame_size = int(l2frame) pkt = self._create_pkt(stream_cfg, l2frame_size) - if e2e: + if e2e or stream_cfg['mpls']: streams.append(STLStream(packet=pkt, + # Flow stats is disabled for MPLS now + # flow_stats=STLFlowStats(pg_id=pg_id), mode=STLTXCont())) else: if stream_cfg['vxlan'] is True: @@ -511,7 +567,7 @@ class TRex(AbstractTrafficGenerator): def __connect_after_start(self): # after start, Trex may take a bit of time to initialize # so we need to retry a few times - for it in xrange(self.config.generic_retry_count): + for it in range(self.config.generic_retry_count): try: time.sleep(1) self.client.connect() @@ -519,7 +575,7 @@ class TRex(AbstractTrafficGenerator): except Exception as ex: if it == (self.config.generic_retry_count - 1): raise - LOG.info("Retrying connection to TRex (%s)...", ex.message) + LOG.info("Retrying connection to TRex (%s)...", ex.msg) def connect(self): """Connect to the TRex server.""" @@ -584,7 +640,7 @@ class TRex(AbstractTrafficGenerator): if os.path.isfile(logpath): # Wait for TRex to finish writing error message last_size = 0 - for _ in xrange(self.config.generic_retry_count): + for _ in range(self.config.generic_retry_count): size = os.path.getsize(logpath) if size == last_size: # probably not writing anymore @@ -609,7 +665,7 @@ class TRex(AbstractTrafficGenerator): LOG.info("Restarting TRex ...") self.__stop_server() # Wait for server stopped - for _ in xrange(self.config.generic_retry_count): + for _ in range(self.config.generic_retry_count): time.sleep(1) if not self.client.is_connected(): LOG.info("TRex is stopped...") @@ -625,7 +681,7 @@ class TRex(AbstractTrafficGenerator): self.client.release(ports=ports) self.client.server_shutdown() except STLError as e: - LOG.warn('Unable to stop TRex. Error: %s', e) + LOG.warning('Unable to stop TRex. Error: %s', e) else: LOG.info('Using remote TRex. Unable to stop TRex') @@ -648,7 +704,7 @@ class TRex(AbstractTrafficGenerator): dst_macs = [None] * chain_count dst_macs_count = 0 # the index in the list is the chain id - if self.config.vxlan: + if self.config.vxlan or self.config.mpls: arps = [ ServiceARP(ctx, src_ip=device.vtep_src_ip, @@ -690,12 +746,12 @@ class TRex(AbstractTrafficGenerator): arp_dest_macs[port] = dst_macs LOG.info('ARP resolved successfully for port %s', port) break - else: - retry = attempt + 1 - LOG.info('Retrying ARP for: %s (retry %d/%d)', - unresolved, retry, self.config.generic_retry_count) - if retry < self.config.generic_retry_count: - time.sleep(self.config.generic_poll_sec) + + retry = attempt + 1 + LOG.info('Retrying ARP for: %s (retry %d/%d)', + unresolved, retry, self.config.generic_retry_count) + if retry < self.config.generic_retry_count: + time.sleep(self.config.generic_poll_sec) else: LOG.error('ARP timed out for port %s (resolved %d out of %d)', port, @@ -833,8 +889,8 @@ class TRex(AbstractTrafficGenerator): bpf_filter = "ether dst %s or ether dst %s" % (src_mac_list[0], src_mac_list[1]) # ports must be set in service in order to enable capture self.client.set_service_mode(ports=self.port_handle) - self.capture_id = self.client.start_capture(rx_ports=self.port_handle, - bpf_filter=bpf_filter) + self.capture_id = self.client.start_capture \ + (rx_ports=self.port_handle, bpf_filter=bpf_filter) def fetch_capture_packets(self): """Fetch capture packets in capture mode."""