Cisco TRex Traffic Generator: iniciando o teste de carga de dispositivos de rede





Ao desenvolver outro roteador, testamos o desempenho da rede usando um componente de código aberto útil - o gerador de tráfego Cisco TRex. O que é essa ferramenta? Como usá-lo? E como isso pode ser útil para engenheiros de desenvolvimento? Abaixo estão as respostas para essas perguntas.



1. O que é o Cisco TRex



É um gerador de tráfego de software de código aberto que roda em processadores padrão baseados no Intel DPDK e suporta modos sem estado / sem estado. Comparativamente simples e totalmente escalável.



A documentação em inglês para esta ferramenta está disponível no site .



O Trex permite gerar diferentes tipos de tráfego e analisar os dados quando eles são recebidos. O trabalho no nível MAC e IP é suportado. Você pode definir o tamanho dos pacotes e seu número, controlar a taxa de transferência de dados.



O trabalho com o gerador é organizado no ambiente Linux.



Uma das diferenças importantes entre o gerador Trex é o uso da tecnologia DPDK, que permite ignorar os gargalos de desempenho na pilha de rede Linux. O DPDK ou Data Plane Development Kit é um conjunto de bibliotecas e drivers para processamento rápido de pacotes que permitem excluir a pilha de rede Linux do processamento de pacotes e interagir diretamente com um dispositivo de rede.



O DPDK transforma um processador de uso geral em um servidor de encaminhamento de pacotes. Essa transformação elimina a necessidade de switches e roteadores caros. No entanto, o DPDK impõe restrições ao uso de adaptadores de rede específicos, a lista de hardware suportado é indicada no link - aqui está a plataforma mais popular da Intel, ou seja, É fornecido suporte de hardware que funciona com os drivers linux e1000, ixgbe, i40e, ice, fm10k, ipn3ke, ifc, igc.



Também é importante entender que, para um servidor TRex operar a 10 Gbps, é necessário um processador multinúcleo - a partir de 4 núcleos ou mais, de preferência uma CPU Intel com suporte para multiencadeamento simultâneo (hiperencadeamento).



2. Como obter e experimentar o TRex



1) Faça o download do arquivo no servidor trex-tgn.cisco.com: trex-tgn.cisco.com/trex/release/



Descompacte o arquivo no diretório inicial do usuário "/ home / user", onde user é o nome de usuário.



[bash]>wget --no-cache https://trex-tgn.cisco.com/trex/release/latest
[bash]>tar -xzvf latest


2) Configurando as interfaces para enviar e receber dados



Vamos executar a configuração usando o utilitário "dpdk_setup_ports.py" que vem no arquivo morto com o TRex. Você pode configurar as interfaces de rede que o TRex usa no nível MAC ou IP. Para começar, você precisa executar este utilitário com a chave de configuração interativa "sudo ./dpdk_setup_ports.py –i".



O primeiro passo é abandonar a configuração no nível MAC (você deseja usar a configuração baseada em MAC? (S / N) n).



O segundo passo é selecionar um par de interfaces de rede com as quais trabalharemos; no nosso caso, a placa de rede Intel X710 funciona com 4 interfaces de rede, usaremos o 1º e o 4º soquete da placa de rede.







Na terceira etapa, o sistema oferecerá a criação automática de uma configuração fechada - quando os dados saírem da porta 1 e chegarem à porta 2 (e vice-versa), tudo em um PC. Tivemos que abandonar esse esquema e configurar o esquema de roteamento para 2 PCs.



Nas quarta e quinta etapas, concordamos em salvar a configuração no arquivo /etc/trex_cfg.yaml.



Por exemplo, considere a configuração no nível do IP para o seguinte esquema de conexão:







O arquivo de configuração está localizado aqui: "/etc/trex_cfg.yaml". Um arquivo de configuração simples é mostrado abaixo para uma NIC de 2 portas com uma CPU que suporta 8 threads:



### Config file generated by dpdk_setup_ports.py ###
- version: 2
  interfaces: ['01:00.0', '01:00.3']
  port_info:
      - ip: 192.168.253.106
        default_gw: 192.168.253.107
      - ip: 192.168.254.106
        default_gw: 192.168.254.107
 
  platform:
      master_thread_id: 0
      latency_thread_id: 1
      dual_if:
    	- socket: 0
      	threads: [2,3,4,5,6,7]


Na configuração:



  • '01: 00.0 ', '01: 00.3' - o nome das interfaces Eth no sistema Linux usado.
  • ip: 192.168.253.106 - o endereço da porta do servidor TRex PC a partir do qual o tráfego é gerado.
  • default_gw: 192.168.253.107 - endereço de 1 porta do PC DUT (dispositivo em teste).
  • ip: 192.168.254.106 - o endereço da porta do servidor TRex PC, a partir da qual o tráfego é retornado após a passagem pelas regras de QOS.
  • default_gw: 192.168.253.107 - endereço de 2 portas do PC DUT.


Atenção! O sistema TRex proíbe o uso da mesma sub-rede ao gerar fluxos usados ​​pelo sistema; para isso, ao gerar pacotes, são utilizadas as sub-redes 16.0.0.0 e 48.0.0.0.



3) Configurando as interfaces na máquina remota



É necessário configurar o encaminhamento e as rotas para que o sistema (DUT) pelo qual passaremos o tráfego saiba para onde receber e para onde enviar pacotes.



Configure as regras de roteamento de fluxo no PC do DUT:



sudo echo 1 > /proc/sys/net/ipv4/ip_forward
sudo route add -net 16.0.0.0 netmask 255.0.0.0 gw 192.168.253.106
sudo route add -net 48.0.0.0 netmask 255.0.0.0 gw 192.168.254.106


4) Inicie o servidor TRex no modo astf:



cd v2.XX
sudo ./t-rex-64 -i --astf


Se o servidor TRex for iniciado com sucesso, veremos informações sobre as portas Ethernet usadas para teste:



The ports are bound/configured.
port : 0 
------------
link         :  link : Link Up - speed 10000 Mbps - full-duplex
promiscuous  : 0 
port : 1 
------------
link         :  link : Link Up - speed 10000 Mbps - full-duplex
promiscuous  : 0 
number of ports         : 2 
max cores for 2 ports   : 1 
tx queues per port      : 3


5) Iniciando o console TRex



Usando o console, em uma janela separada, comece a gerar um fluxo a partir de exemplos prontos (a pasta com exemplos astf está no arquivo morto para TRex):



cd v2.XX
./trex-console
start -f astf/http_simple.py -m 1
 
start (options):
-a (all ports)
-port 1 2 3 (ports 1 2 3)
-d duration (-d 100 -d 10m -d 1h)
-m stream strength (-m 1 -m 1gb -m 40%)
-f load from disk the streams file


Se o lançamento for bem-sucedido, veremos as estatísticas do fluxo de tráfego no console do servidor TRex:



Global stats enabled
Cpu Utilization : 0.3  %  0.6 Gb/core 
Platform_factor : 1.0  
Total-Tx        :     759.81 Kbps  
Total-Rx        :     759.81 Kbps  
Total-PPS       :      82.81  pps  
Total-CPS       :       2.69  cps  
 
Expected-PPS    :       0.00  pps  
Expected-CPS    :       0.00  cps  
Expected-L7-BPS :       0.00  bps  
 
Active-flows    :        2  Clients :        0   Socket-util : 0.0000 %    
Open-flows      :      641


3. Automação de desenvolvimento e teste com TRex



No processo de desenvolvimento de um roteador de rede, escrevemos muitos testes para o TRex, então surgiu a questão de executá-los no modo automático usando python. Como organizamos:



Iniciamos o servidor TRex no modo stl:



cd v2.XX
sudo ./t-rex-64 -i --stl


Defina a variável de ambiente para python, pois o TRex funciona em conjunto com python.



exportar PYTHONPATH = / home / !!! usuário !!! / v2.XX / automation / trex_control_plane / interativo, onde "!!! usuário !!!" - nome de usuário e diretório inicial, v2.XX - versão do software TRex baixada e descompactada nesta pasta.



Iniciamos o gerador de tráfego usando python, a lista da configuração de exemplo é fornecida abaixo.



python example_test_2bidirectstream.py



Saída esperada:



Transmit: 10000.24576MByte/s Receive: 10000.272384MByte/s
Stream 1 TX: 4487179200 Bit/s RX: 4487179200 Bit/s
Stream 2 TX: 2492873600 Bit/s RX: 2492873600 Bit/s
Stream 3 TX: 1994294400 Bit/s RX: 1994294400 Bit/s
Stream 4 TX: 997147200 Bit/s RX: 997147200 Bit/s


Vamos analisar este exemplo:



c = STLClient (server = '127.0.0.1')



Crie uma conexão com o servidor TRex; nesse caso, a conexão é criada para a mesma máquina que o servidor.



  • "Base_pkt_dir_a, base_pkt_dir_b, base_pkt_dir_c, base_pkt_dir_d" - modelos de pacotes, que contêm endereços de origem e destino, portas de origem e destino. Neste exemplo, 4 fluxos são criados, 2 em uma direção e 2 na direção oposta.
  • "S1, s2, s3, s4" - solicite os parâmetros do fluxo gerado da classe STLStream, como ID e taxa de bits do fluxo, no nosso caso ID1 = 4,5 Gbps, ID2 = 2,5 Gbps, ID3 = 2 Gbps, ID4 = 1 Gbps.


Listagem do arquivo de configuração do fluxo example_test_2bidirectstream.py



# get TRex APIs
from trex_stl_lib.api import *
 
c = STLClient(server = '127.0.0.1')
c.connect()
 
try:
    # create a base packet with scapy
    base_pkt_dir_a = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=5001,sport=50001)
    base_pkt_dir_b = Ether()/IP(src="48.0.0.1",dst="16.0.0.1")/UDP(dport=50001,sport=5001)
 
    base_pkt_dir_c = Ether()/IP(src="16.0.0.2",dst="48.0.0.2")/UDP(dport=5002,sport=50002)
    base_pkt_dir_d = Ether()/IP(src="48.0.0.2",dst="16.0.0.2")/UDP(dport=50002,sport=5002)
 
    # pps : float
    # Packets per second
    #
    # bps_L1 : float
    # Bits per second L1 (with IPG)
    #
    # bps_L2 : float
    # Bits per second L2 (Ethernet-FCS)
    packet_size = 1400
 
    def pad(base_pkt):
        pad = (packet_size - len(base_pkt)) * 'x'
        return pad
 
    s1 = STLStream(packet=STLPktBuilder(base_pkt_dir_a/pad(base_pkt_dir_a)), mode=STLTXCont(bps_L2=4500000000), flow_stats=STLFlowStats(pg_id=1))
    s2 = STLStream(packet=STLPktBuilder(base_pkt_dir_b/pad(base_pkt_dir_b)), mode=STLTXCont(bps_L2=2500000000), flow_stats=STLFlowStats(pg_id=2))
    s3 = STLStream(packet=STLPktBuilder(base_pkt_dir_c/pad(base_pkt_dir_c)), mode=STLTXCont(bps_L2=2000000000), flow_stats=STLFlowStats(pg_id=3))
    s4 = STLStream(packet=STLPktBuilder(base_pkt_dir_d/pad(base_pkt_dir_d)), mode=STLTXCont(bps_L2=1000000000), flow_stats=STLFlowStats(pg_id=4))
 
    my_ports = [0, 1]
 
    c.reset(ports = [my_ports[0], my_ports[1]])
 
    # add the streams
    c.add_streams(s1, ports = my_ports[0])
    c.add_streams(s2, ports = my_ports[1])
    c.add_streams(s3, ports = my_ports[0])
    c.add_streams(s4, ports = my_ports[1])
 
    # start traffic with limit of 10 seconds (otherwise it will continue forever)
    # bi direction
    testduration = 10
    c.start(ports=[my_ports[0], my_ports[1]], duration=testduration)
    # hold until traffic ends
    c.wait_on_traffic()
 
    # check out the stats
    stats = c.get_stats()
 
    # get global stats
    totalstats = stats['global']
    totaltx = round(totalstats.get('tx_bps'))
    totalrx = round(totalstats.get('rx_bps'))
    print('Transmit: {}MByte/s Receive: {}MByte/s'.format((totaltx / 1000000), (totalrx / 1000000)))
    c.clear_stats(ports = [my_ports[0], my_ports[1]])
 
    # get flow stats
    totalstats = stats['flow_stats']
    stream1 = totalstats[1]
 
    stream2 = totalstats[2]
    stream3 = totalstats[3]
    stream4 = totalstats[4]
    totaltx_1 = stream1.get('tx_pkts')
    totalrx_1 = stream1.get('rx_pkts')
    print('Stream 1 TX: {} Bit/s RX: {} Bit/s'.format((totaltx_1['total'] / testduration * packet_size * 8),
                                                               (totalrx_1['total'] / testduration * packet_size * 8)))
    totaltx_2 = stream2.get('tx_pkts')
    totalrx_2 = stream2.get('rx_pkts')
    print('Stream 2 TX: {} Bit/s RX: {} Bit/s'.format((totaltx_2['total'] / testduration * packet_size * 8),
                                                               (totalrx_2['total'] / testduration * packet_size * 8)))
    totaltx_3 = stream3.get('tx_pkts')
    totalrx_3 = stream3.get('rx_pkts')
    print('Stream 3 TX: {} Bit/s RX: {} Bit/s'.format((totaltx_3['total'] / testduration * packet_size * 8),
                                                               (totalrx_3['total'] / testduration * packet_size * 8)))
    totaltx_4 = stream4.get('tx_pkts')
    totalrx_4 = stream4.get('rx_pkts')
    print('Stream 4 TX: {} Bit/s RX: {} Bit/s'.format((totaltx_4['total'] / testduration * packet_size * 8),
                                                               (totalrx_4['total'] / testduration * packet_size * 8)))
except STLError as e:
    print(e)
 
finally:
    c.disconnect()


Conclusão



Ao preparar este guia para a Habr, lançamos e testamos a operação do sistema DUT com 4 threads, coletamos informações sobre threads e estatísticas globais.



A operação descrita acima é iniciada usando python, o que significa que, usando TRex, você pode automatizar o teste e a depuração de dispositivos de rede e produtos de software - em um loop ou ao executar sequencialmente testes em python.



Então, por que o TRex da Cisco é melhor ou pior que outros geradores de tráfego semelhantes? Por exemplo, o popular programa cliente-servidor iperf? No cenário de uso do TRex, vemos uma descrição da configuração e do trabalho com fluxos. As ferramentas de teste e depuração são boas: iperf - para testes rápidos de funcionalidade em movimento, e o TRex faz um excelente trabalho de automação de testes e desenvolvimento de dispositivos e sistemas de rede complexos, onde a capacidade de configurar fluxos multithread é importante para configurar cada fluxo para uma tarefa específica e analisar os resultados de saída ...



O TRex permite criar modelos para quase qualquer tipo de tráfego e amplificá-los para gerar ataques DDoS em larga escala, incluindo fluxos TCP-SYN, UDP e ICMP. A capacidade de gerar fluxos de tráfego maciços permite simular ataques de vários clientes em vários servidores de destino.



Portanto, se você ainda não experimentou essa ferramenta, faça uma anotação. E se você tentou - compartilhe seus exemplos e feedback nos comentários. É interessante saber no que o TRex está sendo pensado e usado por outros engenheiros.



All Articles