Pular para o conteúdo

Controle de banda para VoIP no Linux

Dica publicada em Linux / Internet
André Carezia carezia
Hits: 11.303 Categoria: Linux Subcategoria: Internet
  • Indicar
  • Impressora
  • Denunciar

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

Tela sensível ao toque - ativar e desativar

Captura de tela com ótima resolução e pouco uso de banda - ffmpeg + mencoder

Instalando o flash-player no Debian 6.0

Abrir vídeos (protocolo MMS) no Mozilla/Firefox

Squid x Hotmail

Ubuntu 8.04 - Wireless conecta mas não transmite pacotes

#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
#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

Entre na sua conta para comentar.