
Ich habe einen Asterisk 1.8-Telefonschalter mit einer Digium T1-Karte. Er läuft mit 5ESS PRI über unseren derzeitigen Telefonanbieter problemlos. Wir überlegen jedoch, auf den Glasfaserdienst von Time Warner (nicht TWTelecom) umzusteigen, und dann schlägt er mit ISDN-Protokollfehlern fehl.
Ihr Service ist im Wesentlichen VOIP, das Sie nicht direkt nutzen können, obwohl es mit Asterisk einwandfrei funktioniert. Ich weiß das – ich habe es versucht. Stattdessen stellen sie es über einen Cisco 2430-Router bereit und die einzige unterstützte Option besteht darin, Ihnen eine Art T1-Schnittstelle bereitzustellen. PRI ist also die vernünftigste Option. Sobald wir den Stecker vom T1-Demarkationspunkt unseres bestehenden Telefonanbieters zum Cisco-Router übertragen, werden keine Anrufe mehr durchgestellt – weder ausgehend noch eingehend.
Beim Aktivieren des intensiven PRI-Debuggings ist es offensichtlich, dass die Dinge beim ersten Paket, das libpri aussendet, kaputt gehen – egal, ob es sich um einen eingehenden oder ausgehenden Anruf handelt. Hier ist ein Beispiel für den eingehenden Anruf – die ersten drei Pakete. Der Cisco-Router kotzt bei etwas, das libpri aussendet. Die Frage ist: Was und wie lässt sich das beheben?
Auf dem Cisco-Router läuft Firmware c2430-ik9o3s-mz.124-15.T9.bin
– das ist offenbar der Unternehmensstandard von TWC und sie können ihn nicht ändern.
< 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)
Antwort1
Ursache Daten? Ursache Daten!
libpri ist nicht sehr geschickt darin anzugeben, was die Ursachendaten im Cause Information Element (IE) bedeuten - tatsächlich behandelt es ab 1.4.13 nur zwei von hundert Fällen, die inQ.850! Zum Glück handelt es sich dabei nicht einfach um irgendwelche zufälligen proprietären Diagnosedaten.
In Bezug aufF. 850 Verwendung von Ursache und Ort ..., Tabelle 1, müssen wir prüfen, welche Diagnosen für Ursache 100 vorliegenUngültiger Inhalt des InformationselementsUnd siehe da, es ist dasInformationselementkennung(en)! Also war IE 0x18 (24) der von libpri gesendeten Call Proceeding-Nachricht problematisch. Zufällig ist IE 0x18 das Channel-ID-Element. Wir wissen also zumindest, dass das Problem bei diesem bestimmten Element liegt. Als Referenz ist hier der Cause-IE, den wir von Cisco erhalten haben:
< [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)
Kanalidentifikation IE – Identifizieren oder nicht
Nachdem wir es nun auf einen IE eingegrenzt haben,F.931, 4.5.13 Kanalidentifikation [IE], weisen wir darauf hin, dass das gesamte Element bei der Beantwortung eines Rufaufbaus optional ist, wenn, wie hier der Fall, das Benutzergerät lediglich den einzigen Kanal verwenden möchte, der vom Netzwerk (hier: Cisco-Router) explizit angefordert wurde.
Leider ist die interne API von libpri zum Senden der Call-Processing-Nachricht q931_call_proceeding
inq931.c, macht es nicht wirklich einfach, keinen vollständigen Kanal-ID-IE zu senden. Tatsächlich struct q931_call
speichert libpri die explizit zuletzt empfangene Kanal-ID nicht, sodass es keine Möglichkeit gibt, zu entscheiden, ob das Senden eines Kanal-ID-IE angemessen ist oder nicht. Verdammt, es ist ein Fehler, der call_proceeding_ies[]
enthält Q931_CHANNEL_IDENT
– die Anruffortsetzungsnachricht erfordert diesen IE nicht immer.
Eine Lösung wäre, die Kanal-ID einfach nicht zu senden.
Aber wasIstDas Problem im Inneren?
Leider müssen wir versuchen, tiefer zu graben und zu prüfen, was im Kanal-ID-IE die Firmware von Cisco durcheinandergebracht hat.
Vergleichen wir die Kanal-ID IE, wie sie von Cisco empfangen und als Antwort zurückgesendet wurde:
< [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]
Der Unterschied ist ziemlich offensichtlich: libpri antwortet mit einem völlig überflüssigen DS1-Identifier-Oktett. Der DS1-Identifier ist ein Identifier eines bestimmten PRI-Spans, der auf Systemen mit mehreren Links verwendet werden soll. Dies ist hier überhaupt nicht erforderlich, da es zwischen libpri und dem Cisco-Router nur einen T1-Span gibt.
Dies scheint ein Fehler in der Cisco-Firmware zu sein – es gibt keinen Grund, warum sie die DS1-Kennung nicht akzeptieren sollte – sie ist optional, aber vom Standard zugelassen. Es sei denn natürlich, die DS1-Kennung ist irgendwie falsch – das habe ich nicht untersucht.
Der Hack, der nötig ist, um libpri zum Mitspielen zu bringen, ist ein Einzeiler in transmit_channel_id
. Alles, was wir tun müssen, ist die Übertragung von Oktett 3.1, dem DS1-Bezeichner, zu unterdrücken. Dieser Patch erledigt das:
--- 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;
Es sollte hinzugefügt werden, dass dies keineswegs eine permanente Lösung ist, die zur Aufnahme in libpri gedacht ist, sondern nur ein temporärer Hack, für dessen ordnungsgemäße Behebung einige umfangreichere Anpassungen an libpri erforderlich wären.