Simulando links com o netem

Uma das etapas do meu trabalho de conclusão de curso é simular um link de internet em um pc-gateway entre dois hosts como na ilustração abaixo:

Ambiente

Ambiente

Neste ambiente serão executados simulações de tráfego VoIP e colhidas informações estatísticas para análise de desempenho das configurações de QoS em rede do PABX. Para isto irá-se utilizar um Linux configurado como roteador e nele simular um link de internet, adicionando latência, delay, jitter e traffic Shapping ao tráfego roteado por ele.

O pc-gateway possui duas interfaces, eth0 e eth1, onde a interface eth0 está diretamente ligada a um Desktop Linux, que irá executar o cliente da ferramenta de benchmark, e a interface eth1 está diretamente ligada ao PABX que irá executar o servidor da ferramenta de benchmark. Ambos, Desktop e PABX, estão em sub-redes diferentes e possuem como roteador padrão o pc-gateway.

Para simular o Link de internet irá-se configurar o netem, que é uma disciplina de escalonamento de pacotes no kernel do Linux que possibilita simular:

  • delay;

  • perda;

  • jitter;

  • corrupção de pacote;

  • duplicação de pacotes; e

  • reordenação de pacotes.

O netem (Network Emulator)

O netem provê a funcionalidade de emulação de tráfego de rede para testes de protocolos, com ele é possível simular delay, perda, duplicação de pacotes e reordenação de pacotes, etc.

Para utilizar o netem é preciso habilitar o suporte no kernel do Linux e instalar utilitário tc do pacote iproute2.

Para adicionar suporte no kernel ao netem habilite as opções:

CONFIG_NET
CONFIG_NET_SCHED
CONFIG_NET_SCH_NETEM

Para habilitar no menuconfig:

Networking support  --->
  Networking options  --->
    [*] QoS and/or fair queueing  --->
      <*>   Network emulator (NETEM)

O iproute2 faz parte da maioria das distribuições Linux, para instala-lo no Fedora GNU/Linux execute o seguinte comando:

yum -y install iproute2

Usando o netem

Agora vamos ver alguns exemplos de uso do netem.

Delay

O primeiro exemplo mostra como adicionar delay fixo de 100ms em uma interface, neste exemplo eth0.

tc qdisc add dev eth0 root netem delay 100ms

Também é possivel emular o jitter, isto é a variação do delay durante o tempo:

tc qdisc add dev eth0 root netem delay 100ms 10ms

Isto irá adicionar delay de 100ms com jitter de ±10ms aleatoriamente. Também possível adicionar uma correlação entre os de delay e jitter durante o tempo:

tc qdisc add dev eth0 root netem delay 100ms 10ms 25%

Isto fará com que o valor do delay dependa 25% do último tempo utilizado.

A variação do delay também pode variar de acordo com uma distribuição probabilística como: normal, pareto, paretonormal. Por exemplo, para simular uma distribuição normal de delay no exemplo anterior:

tc qdisc add dev eth0 root netem delay 100ms 10ms distribution normal

Perda de pacotes

Para simular a perda de 3% dos pacotes:

tc qdisc add dev eth0 root netem loss 3%

Assim, 3 de 100 pacotes serão descartados aleatoriamente. Como o delay, é possível manter correlação entre os pacotes descartados a cada iteração:

tc qdisc add dev eth0 root netem loss 3% 25%

Assim, os pacotes serão descartados a taxa de 3% onde um quarto da probabilidade dos pacotes a serem descartados depende da iteração anterior.

Duplicação de pacotes

A duplicação é especificada de forma semelhante a perda de pacotes.

tc qdisc add dev eth0 root netem duplicate 1%

Com isto 1 em cada 100 pacotes serão duplicados.

Alteração de pacotes

Também é possível corromper os pacotes por adicionar um bit de erro no pacote.

tc qdisc add dev eth0 root netem corrupt 0.1%

Com isto 1 em cada 1000 pacotes serão alterados/corrompidos.

Reordenação de pacotes

Por fim, é possível também alterar a sequência dos pacotes de duas formas, denominadas gap e reorder. A primeira maneira usa uma sequência fixa, reordenando um pacotes a cada N pacotes, como exemplo:

tc qdisc add dev eth0 root netem gap 5 delay 10ms

Isto irá enviar o 5º (10º, 15º,…) pacote logo após o anterior, os demais sofrerão atraso de 10ms.

A segunda forma (reorder) é mais realística, fazendo com que uma percentagem aleatória de pacotes seja reordenada, como no exemplo:

tc qdisc change dev eth0 root netem delay 10ms reorder 25% 50%

Vinte e cinco porcento dos pacotes serão reordenados (com 50% de correlação com a iteração anterior), os demais serão enviados com 10ms de delay.

Exemplo de uso

No ambiente de estudo, é preciso simular um Link de dados de 256kbit/s, com latência média de 100ms de RTT (tempo de ida e volta), jitter de 10ms e 1% de perda, em ambos os sentidos. Como o netem não faz controle de banda irá-se utilizar a disciplina de enfileiramento tbf para fazer o limite de banda.

Para isto, irá-se configurar cada interfaces de rede, eth0 e eth1, com limite de banda de 256kbps, 50 ms de delay, 5ms de jitter e 0.5% de perda. Os comandos a serem executados são os seguintes:

# tc qdisc add dev eth0 handle 1: root tbf rate 256kbit buffer 1600 limit 3000
# tc qdisc add dev eth0 parent 1:10 handle 10:10 netem delay 50ms 5ms\
 distribution normal loss 0.5%
# tc qdisc add dev eth1 handle 1: root tbf rate 256kbit buffer 1600 limit 3000
# tc qdisc add dev eth1 parent 1:10 handle 10:10 netem delay 50ms 5ms\

distribution normal loss 0.5%

A primeira linha adiciona o limite de banda a interface eth0 em 256kbit/s, e a segunda linha configura o netem para adicionar latência de 50ms, jitter de ± 5ms e perda de 0.5%. As outras duas linhas replicam a configuração para a interface eth1.

Também é possível fazer esta simulação utilizando somente uma interface de rede, para isto deve-se utilizar o device IFB, o mesmo exemplo anterior é feito utilizando a interface IFB:

# tc qdisc add dev eth0 handle 1: root tbf rate 256kbit buffer 1600 limit 3000
# tc qdisc add dev eth0 parent 1:10 handle 10:10 netem delay 50ms 5ms\
  distribution normal loss 0.5%
# tc qdisc add dev eth0 ingress
# tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 flowid \
  1:1 action mirred egress redirect dev ifb0
# tc qdisc add dev ifb0 handle 1: root tbf rate 256kbit buffer 1600 limit 3000
# tc qdisc add dev ifb0 parent 1:10 handle 10:10 netem delay 50ms 5ms\
distribution normal loss 0.5%

Neste exemplo as duas primeiras linhas são como a do exemplo anterior, a terceira adiciona a qdisc ingress na interface eth0, a segunda espelha o tráfego da eth0 como egress para a interface ifb0 e finalmente as duas últimas linhas configuram o limite de banda e o netem para a interface ifb0.

Testando com o ping:

# ping -c3 192.168.0.135
PING 192.168.0.135 (192.168.0.135) 56(84) bytes of data.
64 bytes from 192.168.0.135: icmp_seq=1 ttl=64 time=98.1 ms
64 bytes from 192.168.0.135: icmp_seq=2 ttl=64 time=108 ms
64 bytes from 192.168.0.135: icmp_seq=3 ttl=64 time=109 ms
--- 192.168.0.135 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2111ms
rtt min/avg/max/mdev = 98.175/105.161/109.067/4.965 ms 

A latencia está em cerca de 100ms, variando em 10ms e não houve perda, isto porque a taxa de perda é muito pequena e uma pequena amostra foi feita.

Considerações Finais

O netem será utilizado para simulação de links de internet pois possibilita adicionar perda, delay e jitter no pc-gateway utilizado nos experimentos.

Ele se mostrou bastante simples de configurar e em experimentos pilotos (não exibidos aqui) se mostrou bastante estável e coerente como as configurações aplicadas.

Referências

http://www.linuxfoundation.org/en/Net:Netem

http://www.linuxfoundation.org/en/Net:IFB

http://henrydu.com/blog/how-to/simulate-a-slow-link-by-linux-bridge-123.html

http://lartc.org