
Tengo un conmutador telefónico Asterisk 1.8 con una tarjeta Digium T1. Funciona utilizando 5ESS PRI a través de nuestro actual proveedor de telefonía sin problemas. Sin embargo, estamos contemplando cambiar al servicio de fibra de Time Warner (no a TWTelecom) y luego falla con errores de protocolo ISDN.
Su servicio es esencialmente VOIP que no te permiten tocar directamente a pesar de que funciona bien con Asterisk, lo sé, lo intenté. En su lugar, lo exponen utilizando un enrutador Cisco 2430 y la única opción admitida es brindarle una interfaz T1 de algún tipo. Entonces, el PRI es la opción más sensata. Tan pronto como transferimos el enchufe del punto de demarcación T1 de nuestro proveedor de telefonía existente al enrutador Cisco, no se realizan llamadas, ni salientes ni entrantes.
Al habilitar la depuración intensiva de pri, es evidente que las cosas se rompen en el primer paquete que envía libpri, ya sea una llamada entrante o saliente. A continuación se muestra un ejemplo de la llamada entrante: los primeros tres paquetes. El enrutador Cisco vomita ante algo que está enviando libpri. La pregunta es: qué y cómo solucionarlo.
El enrutador Cisco ejecuta firmware c2430-ik9o3s-mz.124-15.T9.bin
; aparentemente ese es el estándar corporativo de la TWC y no pueden cambiarlo.
< TEI: 0 State 7(Multi-frame established)
< V(A)=2, V(S)=2, V(R)=2
< K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
< T200_id=0, N200=3, T203_id=8192
< [ 02 01 04 04 08 02 00 91 05 .... ]
< 59 bytes of data
< Protocol Discriminator: Q.931 (8) len=59
< TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent from originator)
< Message Type: SETUP (5)
< [04 03 80 90 a2]
< Bearer Capability (len= 5) [ Ext: 1 Coding-Std: 0 Info transfer capability: Speech (0)
< Ext: 1 Trans mode/rate: 64kbps, circuit-mode (16)
< User information layer 1: u-Law (34)
< [18 03 a9 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit Other(PRI) Spare: 0 Exclusive Dchan: 0
< ChanSel: As indicated in following octets
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 Type: CPE]
< [28 0f ...]
< Display (len=15) [ ... ]
< [6c 0c 21 80 ...]
< Calling Party Number (len=14) [ Ext: 0 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1)
< Presentation: Presentation allowed, User-provided, not screened (0) '...' ]
< [70 0b a1 ...]
< Called Party Number (len=13) [ Ext: 1 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1) '...' ]
> DL-DATA request
> Protocol Discriminator: Q.931 (8) len=11
> TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent to originator)
> Message Type: CALL PROCEEDING (2)
TEI=0 Transmitting N(S)=2, window is open V(A)=2 K=7
> TEI: 0 State 7(Multi-frame established)
> V(A)=2, V(S)=2, V(R)=3
> K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
> T200_id=0, N200=3, T203_id=8192
> [ 00 01 04 06 08 02 80 91 02 18 04 e9 81 83 81 ]
> Informational frame:
> SAPI: 00 C/R: 0 EA: 0
> TEI: 000 EA: 1
> N(S): 002 0: 0
> N(R): 003 P: 0
> 11 bytes of data
> Protocol Discriminator: Q.931 (8) len=11
> TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent to originator)
> Message Type: CALL PROCEEDING (2)
> [18 04 e9 81 83 81]
> Channel ID (len= 6) [ Ext: 1 IntID: Explicit Other(PRI) Spare: 0 Exclusive Dchan: 0
> ChanSel: As indicated in following octets
> Ext: 1 DS1 Identifier: 1
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 Type: CPE]
< TEI: 0 State 7(Multi-frame established)
< V(A)=3, V(S)=4, V(R)=3
< K=7, RC=0, l3_initiated=0, reject_except=0, ack_pend=0
< T200_id=8192, N200=3, T203_id=0
< [ 02 01 06 06 08 02 00 91 7d 08 03 80 e4 18 14 01 01 ]
< Informational frame:
< SAPI: 00 C/R: 1 EA: 0
< TEI: 000 EA: 1
< N(S): 003 0: 0
< N(R): 003 P: 0
< 13 bytes of data
< Protocol Discriminator: Q.931 (8) len=13
< TEI=0 Call Ref: len= 2 (reference 145/0x91) (Sent from originator)
< Message Type: STATUS (125)
< [08 03 80 e4 18]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) Spare: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (e.g. unknown message) (6) ]
< Cause data 1: 18 (24)
< [14 01 01]
< Call State (len= 3) [ Ext: 0 Coding: CCITT (ITU) standard (0) Call state: Call Initiated (1)
Respuesta1
¿Datos de causa? ¡Datos de causa!
libpri no es muy inteligente al indicar qué significan los datos de causa en el elemento de información de causa (IE); de hecho, a partir de 1.4.13, solo maneja dos casos de cien dados enQ.850! Afortunadamente, no se trata sólo de datos de diagnóstico propietarios aleatorios.
Refiriéndose aQ.850 Uso de causa y ubicación..., Tabla 1, debemos verificar qué diagnósticos están presentes para la Causa 100Contenidos de elementos de información no válidos. He aquí, es elidentificador(es) de elemento de información! Entonces, IE 0x18 (24) del mensaje de llamada en curso enviado por libpri fue problemático. Da la casualidad de que IE 0x18 es el elemento ID del canal. Así al menos sabemos que el problema está en ese elemento en particular. Como referencia, aquí está la Causa IE que recibimos de Cisco:
< [08 03 80 e4 18]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) Spare: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (e.g. unknown message) (6) ]
< Cause data 1: 18 (24)
Identificación de canal IE: identificar o no
Ahora que lo hemos reducido a IE, refiriéndose aP.931, 4.5.13 Identificación de canal [IE], observamos que todo el elemento es opcional al responder a un establecimiento de llamada si, como es el caso aquí, el equipo del usuario simplemente desea utilizar el único canal que fue solicitado explícitamente por la red ( aquí: enrutador Cisco).
Por desgracia, la API interna de libpri para enviar el mensaje de llamada en curso, q931_call_proceeding
enq931.c, realmente no hace que sea fácil no enviar una identificación de canal completa, IE. De hecho, libpri struct q931_call
no retiene la identificación explícita del canal recibido más recientemente, por lo que no hay forma de decidir si enviar una identificación de canal, IE, es apropiado o no. Diablos, es un error que call_proceeding_ies[]
contiene Q931_CHANNEL_IDENT
: el mensaje de llamada en curso no siempre requiere este IE.
Entonces, una solución sería simplemente no enviar la identificación del canal.
Pero quees¿El problema interno?
Por desgracia, podemos intentar profundizar más y comprobar qué en el ID del canal IE alteró el firmware de Cisco.
Comparemos la identificación del canal IE recibida de Cisco y enviada en respuesta:
< [18 03 a9 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit Other(PRI) Spare: 0 Exclusive Dchan: 0
< ChanSel: As indicated in following octets
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 Type: CPE]
> [18 04 e9 81 83 81]
> Channel ID (len= 6) [ Ext: 1 IntID: Explicit Other(PRI) Spare: 0 Exclusive Dchan: 0
> ChanSel: As indicated in following octets
> Ext: 1 DS1 Identifier: 1
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 Type: CPE]
La diferencia es bastante obvia: libpri responde con un octeto de identificador DS1 totalmente gratuito. El identificador DS1 es un identificador de un tramo PRI particular que se utilizará en sistemas que utilizan múltiples enlaces. Esto no es necesario aquí en absoluto ya que solo hay un tramo T1 entre libpri y el enrutador Cisco.
Esto parece ser un error en el firmware de Cisco; no hay ninguna razón para que no acepte el identificador DS1; es opcional, pero está permitido por el estándar. A menos, por supuesto, que el identificador DS1 sea incorrecto de alguna manera; no lo he investigado.
El truco necesario para que libpri entre en juego es una frase ingeniosa transmit_channel_id
. Todo lo que tenemos que hacer es suprimir la transmisión del octeto 3.1, el identificador DS1. Este parche lo hace:
--- libpri-1.4.14/q931.c.org 2013-04-16 15:22:24.910001979 -0400
+++ libpri-1.4.14/q931.c 2013-04-16 15:22:49.454001959 -0400
@@ -1441,7 +1441,7 @@
return 0;
}
- if (!ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
+ if (0 && !ctrl->bri && (((ctrl->switchtype != PRI_SWITCH_QSIG) && (call->ds1no > 0)) || call->ds1explicit)) {
/* We are specifying the interface. Octet 3.1 */
ie->data[pos++] |= 0x40;
ie->data[pos++] = 0x80 | call->ds1no;
Debe agregarse que esto no es de ninguna manera una solución permanente destinada a incluirse en libpri, solo un truco temporal que requeriría algunos ajustes más amplios en libpri para solucionarlo adecuadamente.