Beispiel #1
0
 def __restart(self):
     LOG.info("Restarting TRex ...")
     self.__stop_server()
     # Wait for server stopped
     for _ in xrange(self.config.generic_retry_count):
         time.sleep(1)
         if not self.client.is_connected():
             LOG.info("TRex is stopped...")
             break
     self.__start_local_server()
Beispiel #2
0
    def modify_rate(self, rate, reverse):
        """Change the rate per port.

        rate: new rate in % (0 to 100)
        reverse: 0 for port 0, 1 for port 1
        """
        port_index = int(reverse)
        port = self.port_handle[port_index]
        self.rates[port_index] = traffic_utils.to_rate_str(rate)
        LOG.info('Modified traffic stream for port %s, new rate=%s.', port, self.rates[port_index])
Beispiel #3
0
    def create_traffic(self,
                       l2frame_size,
                       rates,
                       bidirectional,
                       latency=True,
                       e2e=False):
        """Program all the streams in Trex server.

        l2frame_size: L2 frame size or IMIX
        rates: a list of 2 rates to run each direction
               each rate is a dict like {'rate_pps': '10kpps'}
        bidirectional: True if bidirectional
        latency: True if latency measurement is needed
        """
        r = self.__is_rate_enough(l2frame_size, rates, bidirectional, latency)
        if not r['result']:
            raise TrafficGeneratorException(
                'Required rate in total is at least one of: \n{pps}pps \n{bps}bps \n{load}%.'
                .format(pps=r['rate_pps'],
                        bps=r['rate_bps'],
                        load=r['rate_percent']))
        # a dict of list of streams indexed by port#
        # in case of fixed size, has self.chain_count * 2 * 2 streams
        # (1 normal + 1 latency stream per direction per chain)
        # for IMIX, has self.chain_count * 2 * 4 streams
        # (3 normal + 1 latency stream per direction per chain)
        streamblock = {}
        for port in self.port_handle:
            streamblock[port] = []
        stream_cfgs = [
            d.get_stream_configs() for d in self.generator_config.devices
        ]
        self.rates = [utils.to_rate_str(rate) for rate in rates]
        for chain_id, (fwd_stream_cfg,
                       rev_stream_cfg) in enumerate(zip(*stream_cfgs)):
            streamblock[0].extend(
                self.generate_streams(self.port_handle[0],
                                      chain_id,
                                      fwd_stream_cfg,
                                      l2frame_size,
                                      latency=latency,
                                      e2e=e2e))
            if len(self.rates) > 1:
                streamblock[1].extend(
                    self.generate_streams(self.port_handle[1],
                                          chain_id,
                                          rev_stream_cfg,
                                          l2frame_size,
                                          latency=bidirectional and latency,
                                          e2e=e2e))

        for port in self.port_handle:
            self.client.add_streams(streamblock[port], ports=port)
            LOG.info('Created %d traffic streams for port %s.',
                     len(streamblock[port]), port)
Beispiel #4
0
    def resolve_arp(self):
        """Resolve ARP sucessfully."""
        def get_macs(port, scc):
            return [
                '00:00:00:00:%02x:%02x' % (port, chain) for chain in range(scc)
            ]

        scc = self.traffic_client.generator_config.service_chain_count
        res = [get_macs(port, scc) for port in range(2)]
        LOG.info('Dummy TG ARP: %s', str(res))
        return res
Beispiel #5
0
 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):
         try:
             time.sleep(1)
             self.client.connect()
             break
         except Exception as ex:
             if it == (self.config.generic_retry_count - 1):
                 raise
             LOG.info("Retrying connection to TRex (%s)...", ex.message)
Beispiel #6
0
 def __stop_server(self):
     if self.generator_config.ip == '127.0.0.1':
         ports = self.client.get_acquired_ports()
         LOG.info('Release ports %s and stopping TRex...', ports)
         try:
             if ports:
                 self.client.release(ports=ports)
             self.client.server_shutdown()
         except STLError as e:
             LOG.warn('Unable to stop TRex. Error: %s', e)
     else:
         LOG.info('Using remote TRex. Unable to stop TRex')
Beispiel #7
0
    def connect(self):
        """Connect to the TRex server."""
        server_ip = self.generator_config.ip
        LOG.info("Connecting to TRex (%s)...", server_ip)

        # Connect to TRex server
        self.client = STLClient(server=server_ip, sync_port=self.generator_config.zmq_rpc_port,
                                async_port=self.generator_config.zmq_pub_port)
        try:
            self.__connect(self.client)
            if server_ip == '127.0.0.1':
                config_updated = self.__check_config()
                if config_updated or self.config.restart:
                    self.__restart()
        except (TimeoutError, STLError) as e:
            if server_ip == '127.0.0.1':
                self.__start_local_server()
            else:
                raise TrafficGeneratorException(e.message)

        ports = list(self.generator_config.ports)
        self.port_handle = ports
        # Prepare the ports
        self.client.reset(ports)
        # Read HW information from each port
        # this returns an array of dict (1 per port)
        """
        Example of output for Intel XL710
        [{'arp': '-', 'src_ipv4': '-', u'supp_speeds': [40000], u'is_link_supported': True,
          'grat_arp': 'off', 'speed': 40, u'index': 0, 'link_change_supported': 'yes',
          u'rx': {u'counters': 127, u'caps': [u'flow_stats', u'latency']},
          u'is_virtual': 'no', 'prom': 'off', 'src_mac': u'3c:fd:fe:a8:24:48', 'status': 'IDLE',
          u'description': u'Ethernet Controller XL710 for 40GbE QSFP+',
          'dest': u'fa:16:3e:3c:63:04', u'is_fc_supported': False, 'vlan': '-',
          u'driver': u'net_i40e', 'led_change_supported': 'yes', 'rx_filter_mode': 'hardware match',
          'fc': 'none', 'link': 'UP', u'hw_mac': u'3c:fd:fe:a8:24:48', u'pci_addr': u'0000:5e:00.0',
          'mult': 'off', 'fc_supported': 'no', u'is_led_supported': True, 'rx_queue': 'off',
          'layer_mode': 'Ethernet', u'numa': 0}, ...]
        """
        self.port_info = self.client.get_port_info(ports)
        LOG.info('Connected to TRex')
        for id, port in enumerate(self.port_info):
            LOG.info('   Port %d: %s speed=%dGbps mac=%s pci=%s driver=%s',
                     id, port['description'], port['speed'], port['src_mac'],
                     port['pci_addr'], port['driver'])
        # Make sure the 2 ports have the same speed
        if self.port_info[0]['speed'] != self.port_info[1]['speed']:
            raise TrafficGeneratorException('Traffic generator ports speed mismatch: %d/%d Gbps' %
                                            (self.port_info[0]['speed'],
                                             self.port_info[1]['speed']))
Beispiel #8
0
 def __start_local_server(self):
     try:
         LOG.info("Starting TRex ...")
         self.__start_server()
         self.__connect_after_start()
     except (TimeoutError, STLError) as e:
         LOG.error('Cannot connect to TRex')
         LOG.error(traceback.format_exc())
         logpath = '/tmp/trex.log'
         if os.path.isfile(logpath):
             # Wait for TRex to finish writing error message
             last_size = 0
             for _ in xrange(self.config.generic_retry_count):
                 size = os.path.getsize(logpath)
                 if size == last_size:
                     # probably not writing anymore
                     break
                 last_size = size
                 time.sleep(1)
             with open(logpath, 'r') as f:
                 message = f.read()
         else:
             message = e.message
         raise TrafficGeneratorException(message)
Beispiel #9
0
 def clear_streamblock(self):
     """Clear all streams from TRex."""
     self.rates = []
     self.client.reset(self.port_handle)
     LOG.info('Cleared all existing streams')
Beispiel #10
0
    def resolve_arp(self):
        """Resolve all configured remote IP addresses.

        return: None if ARP failed to resolve for all IP addresses
                else a dict of list of dest macs indexed by port#
                the dest macs in the list are indexed by the chain id
        """
        self.client.set_service_mode(ports=self.port_handle)
        LOG.info('Polling ARP until successful...')
        arp_dest_macs = {}
        for port, device in zip(self.port_handle, self.generator_config.devices):
            # there should be 1 stream config per chain
            stream_configs = device.get_stream_configs()
            chain_count = len(stream_configs)
            ctx = self.client.create_service_ctx(port=port)
            # all dest macs on this port indexed by chain ID
            dst_macs = [None] * chain_count
            dst_macs_count = 0
            # the index in the list is the chain id
            if self.config.vxlan:
                arps = [
                    ServiceARP(ctx,
                               src_ip=device.vtep_src_ip,
                               dst_ip=device.vtep_dst_ip,
                               vlan=device.vtep_vlan)
                    for cfg in stream_configs
                ]
            else:
                arps = [
                    ServiceARP(ctx,
                               src_ip=cfg['ip_src_tg_gw'],
                               dst_ip=cfg['mac_discovery_gw'],
                               # will be None if no vlan tagging
                               vlan=cfg['vlan_tag'])
                    for cfg in stream_configs
                ]

            for attempt in range(self.config.generic_retry_count):
                try:
                    ctx.run(arps)
                except STLError:
                    LOG.error(traceback.format_exc())
                    continue

                unresolved = []
                for chain_id, mac in enumerate(dst_macs):
                    if not mac:
                        arp_record = arps[chain_id].get_record()
                        if arp_record.dst_mac:
                            dst_macs[chain_id] = arp_record.dst_mac
                            dst_macs_count += 1
                            LOG.info('   ARP: port=%d chain=%d src IP=%s dst IP=%s -> MAC=%s',
                                     port, chain_id,
                                     arp_record.src_ip,
                                     arp_record.dst_ip, arp_record.dst_mac)
                        else:
                            unresolved.append(arp_record.dst_ip)
                if dst_macs_count == chain_count:
                    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)
            else:
                LOG.error('ARP timed out for port %s (resolved %d out of %d)',
                          port,
                          dst_macs_count,
                          chain_count)
                break

        self.client.set_service_mode(ports=self.port_handle, enabled=False)
        if len(arp_dest_macs) == len(self.port_handle):
            return arp_dest_macs
        return None
Beispiel #11
0
    def connect(self):
        """Connect to the TRex server."""
        server_ip = self.generator_config.ip
        LOG.info("Connecting to TRex (%s)...", server_ip)

        # Connect to TRex server
        self.client = STLClient(server=server_ip)
        try:
            self.__connect(self.client)
        except (TimeoutError, STLError) as e:
            if server_ip == '127.0.0.1':
                try:
                    self.__start_server()
                    self.__connect_after_start()
                except (TimeoutError, STLError) as e:
                    LOG.error('Cannot connect to TRex')
                    LOG.error(traceback.format_exc())
                    logpath = '/tmp/trex.log'
                    if os.path.isfile(logpath):
                        # Wait for TRex to finish writing error message
                        last_size = 0
                        for _ in xrange(self.config.generic_retry_count):
                            size = os.path.getsize(logpath)
                            if size == last_size:
                                # probably not writing anymore
                                break
                            last_size = size
                            time.sleep(1)
                        with open(logpath, 'r') as f:
                            message = f.read()
                    else:
                        message = e.message
                    raise TrafficGeneratorException(message)
            else:
                raise TrafficGeneratorException(e.message)

        ports = list(self.generator_config.ports)
        self.port_handle = ports
        # Prepare the ports
        self.client.reset(ports)
        # Read HW information from each port
        # this returns an array of dict (1 per port)
        """
        Example of output for Intel XL710
        [{'arp': '-', 'src_ipv4': '-', u'supp_speeds': [40000], u'is_link_supported': True,
          'grat_arp': 'off', 'speed': 40, u'index': 0, 'link_change_supported': 'yes',
          u'rx': {u'counters': 127, u'caps': [u'flow_stats', u'latency']},
          u'is_virtual': 'no', 'prom': 'off', 'src_mac': u'3c:fd:fe:a8:24:48', 'status': 'IDLE',
          u'description': u'Ethernet Controller XL710 for 40GbE QSFP+',
          'dest': u'fa:16:3e:3c:63:04', u'is_fc_supported': False, 'vlan': '-',
          u'driver': u'net_i40e', 'led_change_supported': 'yes', 'rx_filter_mode': 'hardware match',
          'fc': 'none', 'link': 'UP', u'hw_mac': u'3c:fd:fe:a8:24:48', u'pci_addr': u'0000:5e:00.0',
          'mult': 'off', 'fc_supported': 'no', u'is_led_supported': True, 'rx_queue': 'off',
          'layer_mode': 'Ethernet', u'numa': 0}, ...]
        """
        self.port_info = self.client.get_port_info(ports)
        LOG.info('Connected to TRex')
        for id, port in enumerate(self.port_info):
            LOG.info('   Port %d: %s speed=%dGbps mac=%s pci=%s driver=%s', id,
                     port['description'], port['speed'], port['src_mac'],
                     port['pci_addr'], port['driver'])
        # Make sure the 2 ports have the same speed
        if self.port_info[0]['speed'] != self.port_info[1]['speed']:
            raise TrafficGeneratorException(
                'Traffic generator ports speed mismatch: %d/%d Gbps' %
                (self.port_info[0]['speed'], self.port_info[1]['speed']))