Interconexión de Asterisk con otros conmutadores por R2 modificado

29 Nov

En el mundo del VoIP, todos los que nos dedicamos a esto nos hemos encontrado con clientes que poseen conmutadores convencionales que les han representado una inversión de la que no quieren deshacerse tan pronto. Tan solo imaginen haber gastado $30K+ USD hace apenas un par de años y que ahora deban reemplazarlo para acceder a funcionalidades que no estaban incluidas (IVRs, buzón de voz, llamadas por VoIP, etc). Muchos clientes no están dispuestos a dejarlo atrás, por lo que es necesario sacarle más jugo a lo que ya tienen.

Soluciones como Nortel/Avaya, Ericsson, Panasonic y otras, son muy buenas, pero también pueden resultar muy caras cuando agregas todas las bondades que Asterisk en comparación puede ofrecer de manera gratuita. Algunas requieren comprar tarjetas adicionales para soportar las nuevas funcionalidades, mientras que otras requieren de el pago de alguna licencia (y aún así, muchas veces con limitaciones). La solución que existe para poder seguir aprovechando estos conmutadores es muy simple: confiarle el trabajo a Asterisk haciendo una interconexión entre los PBXs.

La opción más común en este tipo de entornos es usar un enlace E1 entre equipos. En este artículo buscaré mostrar como configurar la conexión mediante R2 MFC, que es la señalización más utilizada en México. En el ejemplo usaré una tarjeta Sangoma A102E (2 puertos E1). Si desean profundizar más sobre la configuración habitual de un enlace R2, les recomiendo la guía de OpenR2 escrita por Moisés Silva, autor de dicha librería.

Empezaré partiendo por los siguientes supuestos:

  • Tenemos un sistema Asterisk instalado con soporte para OpenR2.
  • Usaremos la variante Mexicana de R2.
  • Tenemos un conmutador convencional (PBX) con un puerto E1 disponible.
  • Asterisk actuará como gateway del E1. Es decir: PSTN <–> Asterisk <–> PBX. Todas las llamadas del PBX hacia la PSTN deberán pasar por Asterisk (y viceversa).
  • Tenemos ya una tarjeta A102E instalada físicamente, y sabemos configurarla utilizando wancfg_dahdi. Usaremos los puertos como sigue:
    • Puerto 1 (wanpipe1.conf): Conexión hacia la PSTN.
    • Puerto 2 (wanpipe2.conf): Conexión hacia el PBX convencional.
  • El cable que se usará para conectar Asterisk <–> PSTN es un cable recto convencional.
  • El cable que se usará para conectar Asterisk <–> PBX es un cable cruzado para E1
    • El pinout de este cable NO es igual que un cable ethernet cruzado.
    • Puedes encontrar muchas imágenes de como hacer este cable buscando en Google

Configuración:

Primero debemos cerciorarnos que nuestros archivos /etc/wanpipe/wanpipe1.conf y wanpipe2.conf estén correctamente configurados para cada caso. Este es el wanpipe1.conf:

FE_FRAME	= NCRC4
TE_CLOCK 	= NORMAL
TE_SIG_MODE     = CAS
TE_RX_SLEVEL    = 120

Para el wanpipe2.conf (PBX), asegurémonos que las siguientes líneas tienen estos valores:

FE_FRAME	= NCRC4
TE_CLOCK 	= MASTER
TE_SIG_MODE     = CAS
TE_RX_SLEVEL    = 120

Algunas observaciones sobre estos valores:

  • El valor de FE_FRAME puede cambiar ya sea NCRC4 o CRC4, pero en nuestra experiencia, prácticamente ningún proveedor pide el uso de CRC4. Por tal motivo, la mayoría de los PBXs reciben SIN CRC4, de manera que nuestro Asterisk deberá tener el mismo valor en ambos archivos, ya que lo mismo que configuramos de un lado (PSTN), lo pasamos al otro (PBX).
  • TE_CLOCKes importante declarar la diferencia:
    • MASTER indica que nosotros generaremos la señal de reloj. Por lo tanto, esto debe ir en el archivo que conectará al PBX (nosotros simularemos ser la PSTN para el PBX)
    • NORMAL indica que seremos esclavos del maestro del otro lado. Por lo tanto, esto debe ir configurado en el lado que conectará a la PSTN (nos comportaremos ante el carrier como si fuéramos cualquier PBX convencional)
  • TE_SIG_MODE=CAS es solo para dejar en claro que estamos usando R2. Si tuviéramos CCS es porque estamos usando ISDN PRI, pero esa es otra historia.
  • TE_RX_SLEVEL debe estar en 120. Por alguna razón que no entiendo, el configurador de Sangoma wancfg_dahdi siempre te lo pone en 430, pero esto es un valor incorrecto. Siempre debemos tenerlo en 120.

Ahora, los valores del /etc/dahdi/system.conf:

# Span 1: PSTN
span=1,1,0,cas,hdb3
cas=1-15:1101
cas=17-31:1101
hardhdlc=16

# Span 2: PBX
span=2,0,0,cas,hdb3
cas=32-46:1101
cas=48-62:1101
hardhdlc=47

# Opcional: Canceladores de eco en software
echocanceller=mg2,1-15,17-31,32-46,48-62

# Global data
loadzone	= mx
defaultzone	= mx

Nuevamente comentamos el por qué de estos valores:

  • En span=1,1,0 , el primer 1 está indicando que se trata del primer puerto (PSTN), mientras que el segundo 1 significa que esta es la fuente primaria de reloj de nuestro sistema. Es decir, acataremos la sincronía entregada por el carrier, ya que normalmente sus equipos son más precisos que los nuestros.
  • En span=2,0,0 , por el otro lado, especificamos que estamos hablando del segundo puerto (PBX). El primer 0 significa que NO debemos hacerle caso al reloj que recibamos desde este enlace. En otras palabras, que ignoremos lo que está del otro lado y le hagamos caso solo a lo que nosotros ya tenemos. Estamos actuando como maestro ante el esclavo (que es el PBX).
  • El término cas demuestra una vez más que estamos usando R2. En la guía de OpenR2 arriba mencionada pueden encontrar más documentación de lo que significa el 1101.
  • Los canceladores de eco, aunque no son óptimos, son los default. Si quieren un mejor cancelador de eco prueben siguiendo los pasos de nuestro artículo pasado «Instalando OSLEC y usando fxotune«

Vamos con el siguiente archivo, el /etc/asterisk/chan_dahdi.conf

;------------------
; SPAN 1 - PSTN
;------------------
signalling=mfcr2
mfcr2_variant=mx
mfcr2_category=national_subscriber

mfcr2_get_ani_first=no
mfcr2_max_ani=10
mfcr2_max_dnis=4
mfcr2_forced_release=no
context=from-pstn
group=1
channel => 1-15,17-31

;------------------
; SPAN 2 - PBX
;------------------
signalling=mfcr2
mfcr2_variant=mx
mfcr2_category=national_priority_subscriber

mfcr2_allow_collect_calls=yes
mfcr2_skip_category=yes
mfcr2_max_ani=0
mfcr2_max_dnis=16

context=from-internal
group=2
channel => 32-46,48-62

Estos quizá son los valores más importantes del resto de los archivos (al menos, al tratar de implementarlos en un Nortel fueron los que más trabajo nos costó conseguir):

  • mfcr2_max_ani especifica la longitud máxima del ANI (Caller ID) que estamos dispuestos a recibir. Dado que en México todos los números nacionales tienen 10 dígitos, es necesario configurar 10 como valor en el enlace que va hacia la PSTN. Sin embargo, para el PBX este NO nos va a proporcionar un Caller ID, por lo tanto, debemos dejarlo en 0 (cero).
  • mfcr2_max_dnis por el otro lado, especifica la longitud máxima del número destino marcado. Cuando recibimos una llamada de la PSTN, el carrier nos entrega 4 dígitosúnicamente que corresponden al DID marcado. Cuando el PBX nos envía el destino, este puede ser cualquier cosa:
    • ZXXXXXXX (8 dígitos) para una llamada local.
    • 01ZXXXXXXXXX (12 dígitos) para una llamada de larga distancia nacional.
    • 045ZXXXXXXXXX (13 dígitos) para una llamada a celular nacional.
    • 00ZXXXXXXX. (cantidad variable) para una llamada de larga distancia internacional.
    • Por tal motivo, es necesario dejar un poco de holgura en el número a marcar para darle la posibilidad al PBX a que marque a donde quiera. Decidimos que 16 dígitos es un número que cubre la suficiente cantidad de combinaciones posibles para permitir marcar a todos lados.
  • El campo de mfcr2_allow_collect_calls lo pusimos en yes en el PBX porque de otra manera nos colgaba las llamadas al momento de enviarlas PBX -> Asterisk.
  • mfcr2_skip_category=yes lo usamos para que Asterisk le permitiera al PBX no especificar la categoría de MFCR2 (algunos PBX como el caso de este Nortel no la entregan)
  • Los contextos de from-pstn from-internal demuestran quien es la entidad de confianza/interna (PBX) y quien es la de desconfianza/externa (PSTN)
  • El group debe ser diferente en ambos casos para que podamos diferenciar por donde sale cada llamada. La PSTN es el 1 y el PBX es el 2.

Por último, aplicamos todos los cambios:

/etc/init.d/asterisk stop
wanrouter restart
dahdi_cfg -vv
/etc/init.d/asterisk start

Ya dentro de Asterisk nos podemos cerciorar que todo esté en orden:

*CLI> mfcr2 show channels
Chan Variant Max ANI Max DNIS ANI First Immediate Accept Tx CAS   Rx CAS
   1 MX      10      4        No        No               IDLE     IDLE
   2 MX      10      4        No        No               IDLE     IDLE
   3 MX      10      4        No        No               IDLE     IDLE
   4 MX      10      4        No        No               IDLE     IDLE
   5 MX      10      4        No        No               IDLE     IDLE
   6 MX      10      4        No        No               IDLE     IDLE
   7 MX      10      4        No        No               IDLE     IDLE
   8 MX      10      4        No        No               IDLE     IDLE
   9 MX      10      4        No        No               IDLE     IDLE
  10 MX      10      4        No        No               IDLE     IDLE
  11 MX      10      4        No        No               IDLE     BLOCK
  12 MX      10      4        No        No               IDLE     BLOCK
  13 MX      10      4        No        No               IDLE     BLOCK
  14 MX      10      4        No        No               IDLE     BLOCK
  15 MX      10      4        No        No               IDLE     BLOCK
  17 MX      10      4        No        No               IDLE     BLOCK
  18 MX      10      4        No        No               IDLE     BLOCK
  19 MX      10      4        No        No               IDLE     BLOCK
  20 MX      10      4        No        No               IDLE     BLOCK
  21 MX      10      4        No        No               IDLE     BLOCK
  22 MX      10      4        No        No               IDLE     BLOCK
  23 MX      10      4        No        No               IDLE     BLOCK
  24 MX      10      4        No        No               IDLE     BLOCK
  25 MX      10      4        No        No               IDLE     BLOCK
  26 MX      10      4        No        No               IDLE     BLOCK
  27 MX      10      4        No        No               IDLE     BLOCK
  28 MX      10      4        No        No               IDLE     BLOCK
  29 MX      10      4        No        No               IDLE     BLOCK
  30 MX      10      4        No        No               IDLE     BLOCK
  31 MX      10      4        No        No               IDLE     BLOCK
  32 MX      0       30       No        No               IDLE     IDLE
  33 MX      0       30       No        No               IDLE     IDLE
  34 MX      0       30       No        No               IDLE     IDLE
  35 MX      0       30       No        No               IDLE     IDLE
  36 MX      0       30       No        No               IDLE     IDLE
  37 MX      0       30       No        No               IDLE     IDLE
  38 MX      0       30       No        No               IDLE     IDLE
  39 MX      0       30       No        No               IDLE     IDLE
  40 MX      0       30       No        No               IDLE     IDLE
  41 MX      0       30       No        No               IDLE     IDLE
  42 MX      0       30       No        No               IDLE     IDLE
  43 MX      0       30       No        No               IDLE     IDLE
  44 MX      0       30       No        No               IDLE     IDLE
  45 MX      0       30       No        No               IDLE     IDLE
  46 MX      0       30       No        No               IDLE     IDLE
  48 MX      0       30       No        No               IDLE     IDLE
  49 MX      0       30       No        No               IDLE     IDLE
  50 MX      0       30       No        No               IDLE     IDLE
  51 MX      0       30       No        No               IDLE     IDLE
  52 MX      0       30       No        No               IDLE     IDLE
  53 MX      0       30       No        No               IDLE     IDLE
  54 MX      0       30       No        No               IDLE     IDLE
  55 MX      0       30       No        No               IDLE     IDLE
  56 MX      0       30       No        No               IDLE     IDLE
  57 MX      0       30       No        No               IDLE     IDLE
  58 MX      0       30       No        No               IDLE     IDLE
  59 MX      0       30       No        No               IDLE     IDLE
  60 MX      0       30       No        No               IDLE     IDLE
  61 MX      0       30       No        No               IDLE     IDLE
  62 MX      0       30       No        No               IDLE     IDLE

En el caso de este cliente, es normal que los canales del 11-31 aparezcan como bloqueados, ya que solo dispone de 10 canales de 30 posibles en su E1 (tiene contratado un servicio fraccionado). Lo mismo verían si contratan 20 de 30 canales con su proveedor. Noten que el segundo E1 (hacia el PBX) si debe aparecer completamente desbloqueado.

Con esta configuración, ambos enlaces aparecen levantados. El último paso sería configurar el /etc/asterisk/extensions.conf para que de acuerdo a los contextos declarados, permita el paso transparente de un E1 hacia el otro:

[from-internal]
exten => _X.,1,Dial(DAHDI/g1/${EXTEN})

[from-pstn]
exten => _X.,1,Dial(DAHDI/g2/${EXTEN})

No olviden hacer el dialplan reload después de haber hecho estos cambios.

De esta manera, todo lo que llega por el Span 1 se manda hacia el Span 2 (y viceversa). Ya les dejo a ustedes analizar el plan de llamadas para determinar como activar las grabaciones que vayan de un sentido hacia el otro.

Espero les sirva. Esta configuración es tal cual la que aplicamos tal cual con uno de nuestros clientes, y funcionó a la perfección.

¡Suerte!

Reparar todas las tablas de MySQL en un sistema Vicidial

28 Nov

El domingo pasado recibí el correo de un cliente: su sistema de marcación predictiva con vicidial había tenido fallas eléctricas durante el fin de semana, ocasionando que las tablas de MySQL se corrompieran y que el sistema quedara inservible (al menos lo relacionado con la marcación predictiva).

Tras cerca de una hora reparé todas las tablas usando unos comandos simples como los que siguen:

/etc/init.d/mysql stop
cd /var/lib/mysql/asterisk
myisamchk -r *.MYI
/etc/init.d/mysql start

Sin embargo, me percaté que al hacer esto, estaba solo reparando las tablas una por una. El sistema tenía 4 núcleos, por lo que era posible hacer mucho más trabajo al mismo tiempo (4 tareas a la vez) en vez de ir una por una.

El sistema terminó de manera habitual tras el paso de 1 1/2 hrs. Para evitar que tanto tiempo se perdiera en nuevas ocasiones, decidí crear un script en bash que reparara todas las tablas de manera simultánea (limitándose a 1 proceso por cada núcleo del sistema), y me quedó el código así:

#!/bin/bash

# Editar estos valores:
## CORES 		debe ser igual al número de núcleos en el sistema 
##				(revisar el comando "cat /proc/cpuinfo")
## MYSQLDBDIR	debe ser igual a la carpeta de MySQL que contiene la BD
##				que debamos reparar (default: "/var/lib/mysql/asterisk")

CORES=4
MYSQLDBDIR=/var/lib/mysql/asterisk

# Enlistar los archivos
FILES=`ls $MYSQLDBDIR/*.MYI`
RUNS=0
for i in $FILES
do
	SALIR=0
	while [ $SALIR -eq 0 ]
	do
		# Obtener la cantidad de procesos en el sistema
		PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`

		# Ejecutamos el while los procesos activos sean menor a CORES
		if [ $CORES -gt $PROCS ]
		then
			echo `date +"%X"` Revisando/Reparando tabla $i
			myisamchk -r $i &
			# Descansamos 1 segundo
			sleep 1
			SALIR=1
		else
			# Esperamos 3 segundos
			sleep 3
		fi
	done

done

# Ya se terminaron de correr todas las instrucciones de reparación,
# pero existe la posibilidad de que algunas de ellas aún estén ejecutándose.
# Revisamos para ver si hay procesos corriendo y avisar al usuario
while [ $SALIR -eq 0 ]
do
	# Obtener la cantidad de procesos en el sistema
	PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`
	if [ $PROCS -gt 0 ]
	then
		echo `date +"%X"` Hay $PROCS procesos corriendo. Esperando 10s...
		sleep 10
	else
		echo "No hay procesos corriendo"
		SALIR=1
	fi
done
echo `date +"%X"` Fin. Ya puedes reiniciar MySQL

Los siguientes pasos son algo obvios:

  1. Hay que guardar este script como un archivo checar.sh
  2. Editamos el archivo y cambiamos el número de cores de nuestro sistema, así como la ubicación de la carpeta de MySQL que contiene los archivos de la BD
  3. Darle permisos de ejecución (chmod 755 checar.sh)
  4. Ejecutarlo: ./checar.sh
El script correrá varios procesos en paralelo para revisar cada uno una tabla. Mientras más núcleos tenga nuestro procesador, más rápido el script aprovechará los recursos para crear la reparación.
Espero les sirva.
¡Suerte!

 

Advertencia: Aunque este script puede ayudarnos a reparar nuestras tablas en caso de algún problema (falla eléctrica, corrupción del sistema de archivos, fallo en el disco duro, etc) no hay nada más seguro que respaldar nuestra información periódicamente. Siempre ten a la mano copias de seguridad de aquella información crítica, ya que no podemos hacernos responsables por la pérdida de información causada por el mal uso de las directivas que se muestran en este artículo. Úsalo bajo tu propio riesgo.

Distribución uniforme del consumo de llamadas entre líneas (AGI-PHP)

27 Nov

Tarde o temprano nos vemos en la necesidad de considerar el gasto individual de las lineas telefónicas conectadas a nuestro Asterisk y encontrar una forma en que las llamadas se distribuyan de forma uniforme entre las lineas, no es lo mismo que 90% de la llamadas al exterior se realicen por la primera linea desocupada a que en caso de tener 4 se repartan en un 25% entre ellas.

Debido a esta necesidad me vi en la necesidad de crear un script en AGI PHP que junto con el dialplan nos haga este trabajo:

Para llevar el contador de las llamadas haremos uso de la asteriskdb, la base de datos integrada en asterisk. Lo que haremos es establecer primero las familias y las llaves que llevaran los datos, usando los siguientes comandos desde adentro del Asterisk CLI (*CLI): Continue reading