Artigos/Otimizando conexões ADSL

De juliano.info

Icon Crystal Info.png
Nota:

Tenho recebido bastante tráfego para este artigo em específico. É bom salientar que este artigo se refere a otimização de conexões ADSL no sistema operacional Linux.

Se você utiliza o sistema operacional Windows, este artigo não lhe será útil.
Figura 1: Comportamento típico de uma conexão ADSL, download (acima) e upload (abaixo).

Se você usa uma conexão ADSL (Speedy, Velox...) ou cabo (Vírtua, Ajato...), e dependendo da configuração feita pelo seu provedor no modem que lhe é fornecido, há chances que você já tenha observado um comportamento em sua rede semelhante à figura 1 ao lado.

Este gráfico mostra a quantidade de tráfego recebido e enviado através da conexão enquanto um download e um upload eram executados concorrentemente. Este gráfico foi obtido através de uma conexão Speedy Power 500 da Telefonica (500 kbit/s downstream, 128 kbit/s upstream); primeiro foi iniciado o download de um arquivo via HTTP, e segundos depois foi feito o upload de um e-mail grande. Observa-se uma situação bem desagradável: no momento que o e-mail começa a ser enviado, o recebimento do arquivo é severamente prejudicado, permanecendo assim até o término do envio.

Nosso primeiro impulso é de maldizer o provedor, que incoerentemente reduz nosso download de 500 kbit/s a quase zero enquanto fazemos um upload limitado a 128 kbit/s. Mas isso não significa necessariamente que o provedor tenha planejado isso de má fé. Pelo menos, a navalha de Hanlon diz: "Nunca atribua à malícia o que pode ser adequadamente explicado pela estupidez".

O efeito observado é característico de um controle de consumo de banda mal-feito. Uma regra básica do controle de consumo de banda é que só temos controle sobre o que enviamos, nunca sobre o que recebemos. Sem levar isso em conta, há uma chance muito grande de você dar um tiro no próprio pé, que é justamente o efeito que observamos aqui. O único capaz de corrigir o problema de fato é o próprio provedor, que por sua vez parece não se importar com a qualidade do serviço oferecido ao consumidor.

Mas você, como usuário, pode contornar essa limitação, de forma a obter o máximo que sua conexão oferece. Muitos usuários descobrem com algumas semanas de prática com programas P2P que é possível limitar o envio de dados a um valor bem próximo ao máximo da conexão, mas sem exaurí-la. Dessa forma, a velocidade de download não é prejudicada.

Infelizmente, pouquíssimos programas além de clientes P2P permitem esse ajuste. Clientes de e-mail, mensageiros instantâneos, navegadores e outros programas raramente permitem ajustar a velocidade máxima de transmissão. Mesmo que todos os programas permitissem, você ainda teria problemas quando usar mais de um programa ao mesmo tempo.

Por outro lado, felizmente, os usuários Linux podem se beneficiar de toda uma infraestrutura de gerenciamento de largura de banda embutida no núcleo do sistema. Através dela, é possível otimizar o uso da conexão de forma a obter o máximo de transmissão sem prejudicar em nada o recebimento.

Tabela de conteúdo

Gerenciamento de tráfego no Linux

Figura 2: Comportamento da conexão ADSL "disciplinada" pelo Hierarchical Token Bucket.

O sistema operacional Linux possui todas as ferramentas necessárias para permitir um gerenciamento bastante refinado do tráfego de rede, com recursos comparáveis com as caras soluções comerciais fornecidas por empresas especializadas.

Através das ferramentas de gerenciamento de tráfego, é possível aplicar uma queueing discipline na interface da conexão ADSL, de forma a controlar a transmissão de dados. Assim, podemos garantir que a conexão nunca será esgotada, e podemos ajustar a prioridade dos pacotes e minimizar o impacto de uma transmissão sobre a outra.

A figura 2 ao lado mostra o resultado do mesmo teste quando aplicamos o Hierarchical Token Bucket na conexão ADSL, Observa-se que o upload não afetou o desempenho do download, pois a conexão não foi exaurida.

Disciplinas de enfileiramento (queueing disciplines) e classes

No Linux, o controle de tráfego nas interfaces de rede são controladas por queueing disciplines (disciplinas de enfileiramento, ou qdiscs). Há dois tipos de qdiscs: classless, que não possuem classes internas, e portanto, apenas controlam o tráfego e escolhem quais pacotes serão enviados primeiro; e classful, que possuem classes e outras qdiscs internas, permitindo também a classificação de pacotes de acordo com configurações definidas pelo usuário.

Toda interface de rede do sistema já é inicializada com uma qdisc classless padrão, baseada em FIFO (first-in, first-out). Essa qdisc é suficiente para o tráfego normal da rede. O usuário pode trocar a qdisc que gerencia cada interface de rede do sistema, e também configurá-las.

Para maiores detalhes sobre as qdiscs disponíveis e sua configuração, consulte o capítulo 9 do Linux Advanced Routing & Traffic Control HOWTO. Nós utilizaremos as qdiscs htb (Hierarchical Token Bucket) e sfq (Stochastic Fair Queueing) para essa configuração.

A qdisc htb é uma qdisc classful, que usa uma estrutura hierárquica para classificar e limitar o tráfego. Com ela, é possível classificar e limitar o tráfego em vários níveis. Por exemplo, podemos definir que 60% da largura de banda será reservada para tráfego HTTP, 15% para peer-to-peer e 25% para outros, e ainda, dentro dos 25% dos outros, 80% será para e-mail e 20% para não-e-mail. É possível definir tetos, de forma que, por exemplo, se só houver tráfego peer-to-peer, este poderá usar até 70% da conexão. Enfim, as possibilidades são bem grandes.

Nas folhas da árvore da hierarquia da qdisc htb, instalamos outras qdiscs para gerenciar o tráfego que passará por aquela folha. A qdisc sfq é uma qdisc classless que pode ser usada nas folhas da árvore hierárquica da qdisc htb. Esta qdisc usa um método estocástico para enfileirar os pacotes de forma justa, de forma que nenhuma conexão monopolize a aquela ramificação.

Ferramentas necessárias

Para configurar o gerenciamento de tráfego no Linux, você precisará de um kernel versão 2.6.x, e das ferramentas listadas abaixo. Essas ferramentas podem ser encontradas no CD de instalação ou no repositório de pacotes da sua distribuição. Consulte a documentação da sua distribuição para descobrir como instalá-los.

  • net-tools (ifconfig)
  • iproute2 (ip, tc, route)
  • iptables (iptables)

Entendendo o problema

Antes de partirmos para a configuração, é interessante entender por que o problema ocorre, e como vamos resolvê-lo. Se você não faz questão de entender o problema e quer apenas vê-lo resolvido, pule esta seção e vá direto para a configuração.

A primeira coisa que precisamos saber é que são, não um, mas dois fatores que fazem com que o upload interfira no desempenho do download. Se você tiver um conhecimento um pouco mais profundo de TCP/IP, você deverá saber que quando recebemos um pacote de dados, nosso sistema também precisa enviar uma pequena confirmação devolta, que é usada pelo transmissor para saber que a conexão ainda está estabelecida, e que ele pode continuar mandando dados.

O primeiro fator é que quando fazemos um upload, usamos toda a banda de transmissão, que também estava sendo usada pelo download para enviar a confirmação de que os dados estavam chegando. Você tem a banda de transmissão sendo competida por uma grande carga do upload, e uma pequena carga da confirmação do download.

O segundo fator é que os pacotes das duas conexões possuem a mesma prioridade, se precisarem ser descartados, o serão na mesma proporção. Os pacotes de confirmação do download são pequenos e necessários para manter um grande fluxo de recebimento, enquanto que os pacotes de dados do upload são grandes e mantém um pequeno fluxo de transmissão.

A solução

Figura 3: Hierarquia de classes de tráfego.

Portanto, devemos não apenas limitar o tráfego de forma a não exaurir a banda de transmissão, mas também devemos priorizar os pacotes de confirmação do download, por serem pequenos e importantes para sustentar o recebimento. Como dissemos acima, não temos como controlar o que recebemos, portanto não vamos mexer na banda de recebimento, e nem é necessário.

A figura 3 ao lado mostra a configuração da hierarquia de classes da qdisc htb que vamos construir. Na figura, o tráfego transmitido é classificado e entra por uma das qdiscs que estão nas folhas (10, 11 e 12), subindo até a raiz (ppp0). O ramo mais à esquerda será atribuído a todos os pacotes pequenos que forem transmitidos (incluindo pacotes de confirmação de downloads), enquanto que o ramo mais à direita será atribuído a todos os outros pacotes (pacotes grandes, de uploads).

No caso da conexão em questão (ADSL Speedy), o limite teórico da banda de transmissão é 128 kbit/s, o que daria 16 kbytes/s. Contudo, na prática, a transmissão se sustenta a aproximadamente 13,4 kbytes/s, e para não interferir no download, precisa ser limitada a 12,0 kbytes/s. Se sua conexão não for ADSL Speedy, você terá que realizar testes a fim de determinar os valores mais adequados.

Portanto, logo abaixo da qdisc htb (1), configuramos uma classe (1:1) que limita todo o tráfego que passar por ela a 12 kbytes/s. Abaixo dessa classe, configuramos uma classe (1:10) para o tráfego leve, limitada a 10 kbytes/s; uma classe (1:12) para o tráfego pesado, podendo usar todos os 12 kbytes/s da rede; e também uma classe intermediária (1:11) que terá um pouco mais de prioridade que a 1:12. Essa classe intermediária não será usada inicialmente, ficará a sua disposição caso queira priorizar algum tráfego específico sobre os outros (por exemplo, atribuir uma maior prioridade a envio de e-mails do que a transferência de arquivos via FTP).

Se a soma das ramificações for maior que a capacidade limitada pela classe pai (1:1), a distribuição de prioridades será de 10 para 6 para 3 respectivamente para as classes 1:10, 1:11 e 1:12. Dessa forma, a classe para tráfego leve (1:10) será efetivamente priorizada sobre a classe intermediária (1:11), que por sua vez será priorizada sobre a classe para tráfego pesado (1:12).

Configuração

Configuração das qdiscs e da hierarquia de classes

Para configurar as qdiscs e a hierarquia de classes, os comandos abaixos devem ser executados depois que a interface for levantada. No caso de ADSL, você deverá colocar estes comandos no script localizado em /etc/ppp/ip-up.local (crie se não existir) ou correspondente na sua distribuição.

Note que esses comandos limitam sua conexão a 12 kbytes/s de transmissão, que é adequado para conexões ADSL Speedy. Se a sua conexão não for ADSL Speedy, você terá que alterar os valores abaixo para se adequarem à sua situação.

PPP="ppp0"
ifconfig $PPP txqueuelen 1000
tc qdisc add dev $PPP root handle 1:0 htb default 12
tc class add dev $PPP parent 1:0 classid 1:1 htb rate 12kbps
tc class add dev $PPP parent 1:1 classid 1:10 htb rate 10kbps prio 0
tc class add dev $PPP parent 1:1 classid 1:11 htb rate 6kbps ceil 12kbps prio 1
tc class add dev $PPP parent 1:1 classid 1:12 htb rate 3kbps ceil 12kbps prio 1
tc qdisc add dev $PPP parent 1:10 handle 10:0 sfq perturb 10
tc qdisc add dev $PPP parent 1:11 handle 11:0 sfq perturb 10
tc qdisc add dev $PPP parent 1:12 handle 12:0 sfq perturb 10

Esses comandos apenas criam a estrutura de classes. Por padrão, todo o tráfego será direcionado através da classe 1:12. Precisamos agora classificar os pacotes que serão transmitidos para as classes corretas.

Classificação do tráfego nas classes corretas

A classificação de pacotes é feita no firewall do sistema, na tabela mangle. Execute os comandos abaixo, e adicione-os ao seu script de inicialização do firewall.

PPP="ppp0"
iptables -t mangle -A OUTPUT -o $PPP -m length --length 0:128 -j CLASSIFY --set-class 1:10

O comando acima ajusta classifica todos os pacotes que saírem pela interface do modem ADSL, com tamanhos menores ou iguais a 128 bytes, como pertencentes à classe 1:10. Dessa forma, os pacotes pequenos e que causam pouco impacto na rede serão priorizados, enquanto que todos os outros continuarão sendo direcionados através da classe 1:12.

Como foi dito antes, a classe intermediária fica a sua disposição caso queira priorizar algum tipo de tráfego sobre o resto do tráfego pesado. Por exemplo, para priorizar a transmissão de e-mails sobre os outros:

iptables -t mangle -A OUTPUT -o $PPP -p tcp --dport 25 -j CLASSIFY --set-class 1:11

Testando a classificação

Para testar se a classificação está funcionando, use os seguintes comandos:

tc -s qdisc show dev ppp0
tc -s class show dev ppp0

Estes comandos mostram cada uma das qdiscs e classes associadas à interface de rede. Entre as informações exibidas, você encontrará o número de pacotes e de bytes trafegados através de cada qdisc ou classe. Faça alguns downloads e uploads, e observe a alteração destes valores para cada execução dos comandos.

Sugestões futuras

Este artigo mostrou apenas uma pequena parte dos recursos do gerenciamento de tráfego do Linux. Como você deve ter percebido, configurações muito mais complexas são possíveis. Caso tenha interesse, consulte a bibliografia abaixo para aprender mais sobre estas ferramentas e o que elas são capazes de fazer.

Conforme foi dito, só podemos controlar o que enviamos, não temos controle sobre o que recebemos. A limitação é imposta pela forma como a rede funciona. Não temos como estabelecer um contrato com o resto da rede dizendo para nos enviar os dados com uma determinada velocidade, numa determinada proporção. Uma vez que o pacote chega na interface de rede o sistema precisa recebê-lo, pois o pacote não pode ficar esperando no cabo. Uma vez dentro do sistema, ou o pacote é processado ou é descartado.

Uma forma de contornar esse problema é ter um outro sistema Linux servindo como roteador/firewall entre as redes externa e interna. Dessa forma, você pode pode configurar também a disciplina de enfileiramento para os dados que entram na rede. Mas continua valendo a afirmação do parágrafo anterior. Neste caso, os pacotes continuarão entrando até esse sistema intermediário, permanecendo em memória (buffers) até serem distribuídos para a rede interna. O tamanho dos buffers define o quanto esse sistema comportará. Se estes buffers ficarem cheios, o sistema começará a descartar pacotes, independente da prioridade que seriam classificados.

Bibliografia consultada

Visualizações