3

I have an Asterisk 1.8 phone switch with a Digium T1 card. It runs using 5ESS PRI through our present phone provider without a problem. However, we're contemplating switching to Time Warner's fiber service (not TWTelecom) and then it fails with ISDN protocol errors.

Their service is essentially VOIP that they won't let you touch directly in spite of it working just fine with Asterisk, I know - I tried. Instead they expose it using a Cisco 2430 router and the only supported option there is to give you a T1 interface of some sort. PRI is the most sensible option, then. As soon as we transfer the plug from our existing phone provider's T1 demarcation point to the Cisco router, no calls go through - either outbound or inbound.

Upon enabling intensive pri debugging, it's apparent that things break on the first packet that libpri sends out - whether it's an incoming our outgoing call. Here's an example for the incoming call - the first three packets. The Cisco router barfs at something libpri is sending out. The question is: what, and how to fix it.

The Cisco router runs firmware c2430-ik9o3s-mz.124-15.T9.bin -- that's apparently TWC's corporate standard and they can't change it.

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

1 Answers1

2

Cause Data ? Cause Data!

libpri is not very clever in indicating what the cause data in the Cause information element (IE) means - in fact, as of 1.4.13, it only handles two cases out of a hundred given in Q.850! Thankfully, it's not just some random proprietary diagnostic data.

Referring to Q.850 Usage of cause and location ..., Table 1, we need to check what diagnostics are present for Cause 100 Invalid information element contents. Lo and behold, it's the information element identifier(s)! So, IE 0x18 (24) of the Call Proceeding message sent out by libpri was problematic. As it happens, IE 0x18 is the Channel ID element. So at least we know that the problem is in that particular element. For reference, here's the Cause IE that we received from 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)

Channel Identification IE -- To Identify or Not

Now that we've narrowed it down to an IE, Referring to Q.931, 4.5.13 Channel identification [IE], we note that the entire element is optional when responding to a call setup if, as is the case here, the user equipment simply wants to use the sole channel that was explicitly requested by the network (here: Cisco router).

Alas, libpri's internal API for sending the call proceeding message, q931_call_proceeding in q931.c, doesn't really make it easy not to send a complete channel id IE. In fact, libpri's struct q931_call doesn't retain the explicit most recently received channel id so there's no way to decide whether sending out a channel id IE is appropriate or not. Heck, it's an error that call_proceeding_ies[] contains Q931_CHANNEL_IDENT -- the call proceeding message does not always require this IE.

So, one fix would be simply not to send out the channel id.

But What is The Problem Within?

Alas, we may try and dig deeper and check what in the channel id IE did upset the Cisco's firmware.

Let's compare the channel id IE as received from Cisco, and as sent back in reply:

< [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]

The difference is fairly obvious: libpri replies with an entirely gratuituous DS1 Identifier octet. The DS1 Identifier is an identifier of a particular PRI span to be used on systems that use multiple links. This is not needed here at all since there's only one T1 span between libpri and the Cisco router.

This appears to be a bug in the Cisco firmware -- there's no reason it shouldn't accept the DS1 Identifier -- it's optional, but allowed by the standard. Unless of course the DS1 Identifier is somehow wrong -- I haven't investigated that.

The hack needed to get libpri to play ball is a one-liner in transmit_channel_id. All we need to do is suppress transmission of octet 3.1, the DS1 identifier. This patch does it:

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

It should be added that this is by no means a permanent fix meant for inclusion in libpri, just a temporary hack that would require some wider-ranging tweaks to libpri to properly fix.