Controle de banda para VoIP no Linux

Publicado por André Carezia em 02/11/2008

[ Hits: 10.730 ]

Blog: http://www.carezia.srv.br/

 


Controle de banda para VoIP no Linux



1. Introdução

Um produto comum para fazer chamadas telefônicas via Internet é o ATA.

Muitas empresas compram esses adaptadores VoIP e ligam em suas redes locais, mas percebem um problema frequente com as ligações: elas ficam entrecortadas, principalmente para o lado remoto da conversa.

Minha solução é usar um script no roteador Linux que faz a interface com a Internet. Esse script implementa um controle de banda simples usando a política HTB, reservando uma parte da banda para o adaptador VoIP. O script é o seguinte:

#!/bin/sh

IPTABLES="/sbin/iptables"
TC="/sbin/tc"

# parâmetros
IF_INET=eth0
IF_LOCAL=eth1
DOWN_MAX=1000kbit
UP_MAX=1000kbit
IP_ATA=192.168.1.50
BW_ATA=120kbit
ID_ATA=1000

start_tc() {
  # download
  $TC qdisc add dev $IF_LOCAL root handle 1: htb default 5
  $TC class add dev $IF_LOCAL parent 1: classid 1:1 htb rate $DOWN_MAX ceil $DOWN_MAX prio 1
  $TC class add dev $IF_LOCAL parent 1: classid 1:5 htb rate 100000kbit ceil 100000kbit prio 5
  $TC qdisc add dev $IF_LOCAL parent 1:5 handle 20: sfq perturb 10

  # sip (internet -> empresa)
  $IPTABLES -t mangle -A POSTROUTING -o $IF_LOCAL -d $IP_ATA -j MARK --set-mark $ID_ATA
  $TC class add dev $IF_LOCAL parent 1:1 classid 1:$ID_ATA htb rate $BW_ATA ceil $BW_ATA prio 1
  $TC filter add dev $IF_LOCAL parent 1: protocol ip prio 1 handle $ID_ATA fw flowid 1:$ID_ATA

  # upload
  $TC qdisc add dev $IF_INET root handle 1: htb default 5
  $TC class add dev $IF_INET parent 1: classid 1:1 htb rate $UP_MAX ceil $UP_MAX prio 1
  $TC class add dev $IF_INET parent 1: classid 1:5 htb rate $UP_MAX ceil $UP_MAX prio 5
  $TC qdisc add dev $IF_INET parent 1:5 handle 20: sfq perturb 10

  # sip (empresa -> internet)
  $IPTABLES -t mangle -A PREROUTING -i $IF_LOCAL -s $IP_ATA -j MARK --set-mark $ID_ATA
  $TC class add dev $IF_INET parent 1:1 classid 1:$ID_ATA htb rate $BW_ATA ceil $BW_ATA prio 1
  $TC filter add dev $IF_INET parent 1: protocol ip prio 1 handle $ID_ATA fw flowid 1:$ID_ATA
}

stop_tc() {
  $TC qdisc del dev $IF_INET root
  $TC qdisc del dev $IF_LOCAL root
  $IPTABLES -t mangle -F
}

case "$1" in
  start)
     echo -n "Iniciando controle de banda..."
     start_tc
     echo " ok"
     ;;
  stop)
     echo -n "Desligando controle de banda..."
     stop_tc
     echo " ok"
     ;;

  *)
     echo "Usage: $0 {start|stop}"
     exit 1
esac

2. Parâmetros

Os parâmetros no início do script devem ser ajustados para cada caso. IF_INET é o nome da interface ligada à Internet, IF_LOCAL é o nome da interface ligada à rede local.

DOWN_MAX é a velocidade nominal da conexão Internet no sentido da Internet para a empresa (download). UP_MAX é a velocidade no sentido da empresa para a Internet (upload). Note que a sintaxe do comando tc é 'kbit' e não 'kbps'.

IP_ATA é o endereço IP do adaptador VoIP. BW_ATA é a banda reservada para o adaptador. Cada ligação VoIP usa aproximadamente 30 kbps, então o script acima está configurado com 120 kbps para priorizar 4 ligações VoIP.

O parâmetro ID_ATA é um número qualquer, e serve para permitir o acréscimo de mais adaptadores VoIP ao script. Se quiser controlar 2 adaptadores, basta trocar ID_ATA por ID_ATA1 e ID_ATA2 e copiar os blocos de linhas marcados com "sip (internet -> empresa)" e "sip (empresa -> internet)".

3. Dependências

O script depende dos comandos tc e iptables, que em distribuições Debian estão nos pacotes iproute e iptables, respectivamente. O roteador Linux deve rodar pelo menos o kernel 2.6.18, que tem suporte ao protocolo SIP.

4. Instalação e uso

O script pode ser instalado em /etc/init.d/htb-voip ou em /usr/local/bin/htb-voip. Para ativar, basta fazer:

# /etc/init.d/htb-voip start

E para desativar, o comando é similar:

# /etc/init.d/htb-voip stop

Outras dicas deste autor

Tela sensível ao toque - ativar e desativar

Leitura recomendada

Curso para certificação Linux Essentials

Doode - Sua rede Linux de amigos de casa nova

Bloquear Windows Live Messenger (MSN) no firewall

Firefox + Opera: Operafox!

Baixando uma lista de downloads com o wget

  

Comentários
[1] Comentário enviado por celta em 12/11/2008 - 12:36h

Olá.
Eu coloquei meus ATA numa classe diferente daquela usada na minha rede.

O IP setado na variável IP_ATA poderia ser 192.168.0.1/24? (Estou pensando em implementar seu script para marcar os pacotes que chegam na minha rede também).

[2] Comentário enviado por carezia em 12/11/2008 - 15:23h

@celta:

Sim, pode usar IP_ATA=192.168.0.0/24

[3] Comentário enviado por rickshinigami em 16/02/2009 - 23:46h


Quando executo o script aparece a mensagem:

RTNETLINK answers: File exists

Oque pode estar acontecendo?

[4] Comentário enviado por carezia em 17/02/2009 - 09:07h

@rickshinigami:

Já existe outro controle de banda rodando. Qual a distribuição Linux rodando na máquina onde ocorre o problema?

[5] Comentário enviado por rickshinigami em 19/02/2009 - 01:57h

Correto...

Eu estava executando o script novamente, sem antes dar stop.


Estou usando o CentOS 5.2

Aparentemente está tudo OK, mas o controle ainda não está funcionando.

Para fazer o teste, coloquei o ip de uma maquina de minha rede como se fosse o ATA, coloquei um download nessa maquina e outro em outra maquina da rede. As duas maquinas dividiram a banda em 50% / 50%.

Oque pode estar errado? ou faltando ?

Carreguei os seguintes módulos do Kernel:

sch_htb
sch_sfq

Agradeço pela atenção

[6] Comentário enviado por carezia em 19/02/2009 - 11:42h

@rickshinigami:

Você ajustou os parâmetros de acordo com sua rede?

[7] Comentário enviado por rickshinigami em 19/02/2009 - 12:30h

@carezia:

Sim, acredito que não exista nenhum erro, pois rodamos o script e o sistema não responde com erro algum, tudo indica estar funcionando normalmente, porém quando inicio o teste citado anteriormente a banda é dividida igualmente entre as máquinas, o que acredito que não deveria ocorrer utilizando o script a seguir:

#!/bin/sh

IPTABLES="/sbin/iptables"
TC="/sbin/tc"

# parâmetros
NET=eth1
LOCAL=eth0
DOWN_MAX=3000kbit
UP_MAX=3000kbit
IP=192.168.1.10
BW=2500kbit
ID=1000

start_tc() {
# download
$TC qdisc add dev $LOCAL root handle 1: htb default 5
$TC class add dev $LOCAL parent 1: classid 1:1 htb rate $DOWN_MAX ceil $DOWN_MAX prio 1
$TC class add dev $LOCAL parent 1: classid 1:5 htb rate 100000kbit ceil 100000kbit prio 5
$TC qdisc add dev $LOCAL parent 1:5 handle 20: sfq perturb 10

# sip (internet -> empresa)
$IPTABLES -t mangle -A POSTROUTING -o $LOCAL -d $IP -j MARK --set-mark $ID
$TC class add dev $LOCAL parent 1:1 classid 1:$ID htb rate $BW ceil $BW prio 1
$TC filter add dev $LOCAL parent 1: protocol ip prio 1 handle $ID fw flowid 1:$ID

# upload
$TC qdisc add dev $NET root handle 1: htb default 5
$TC class add dev $NET parent 1: classid 1:1 htb rate $UP_MAX ceil $UP_MAX prio 1
$TC class add dev $NET parent 1: classid 1:5 htb rate $UP_MAX ceil $UP_MAX prio 5
$TC qdisc add dev $NET parent 1:5 handle 20: sfq perturb 10

# sip (empresa -> internet)
$IPTABLES -t mangle -A PREROUTING -i $LOCAL -s $IP -j MARK --set-mark $ID
$TC class add dev $NET parent 1:1 classid 1:$ID htb rate $BW ceil $BW prio 1
$TC filter add dev $NET parent 1: protocol ip prio 1 handle $ID fw flowid 1:$ID
}

Poderia ser algo relacionado a minha distro? centOS 5.2 ?
Desde já agradeço

[8] Comentário enviado por carezia em 19/02/2009 - 14:23h

@rickshinigami:

Tente com BW=200kbit

[9] Comentário enviado por rickshinigami em 19/02/2009 - 15:23h

Amigos,

realmente o problema é da distro, ou melhor, o kernel utilizado por ela.
Instalamos o Ubuntu server e aplicamos o mesmo script, o controle de bando funcionou maravilhosamente!!!
Se alguem souber o que ocorre no CentOS 5.2, por favor, deixe-nos saber.
Por hora queremos apenas distância desse bendito CentOS.

Agradeço



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts