我有一个带有Digium T1卡的Asterisk 1.8电话交换机。 它运行使用5ESS PRI通过我们目前的电话提供商没有问题。 但是,我们正在考虑切换到时代华纳的光纤服务(而不是TWTelecom),然后由于ISDN协议错误而失败。
他们的服务基本上是VOIP,尽pipe它和Asterisk一起工作,但他们不会让你直接接触,我知道 – 我试过了。 相反,他们使用Cisco 2430路由器公开它,唯一支持的选项是为您提供某种types的T1接口。 那么PRI是最明智的select。 只要我们将插头从现有的电话提供商的T1分界点转移到Cisco路由器,就不会有呼叫通过 – 出站或入站。
启用密集的pridebugging后,很明显,libpri发出的第一个数据包就会中断 – 无论是我们的传出呼叫。 这是来电的例子 – 前三个数据包。 思科路由器barf在libpri上发送。 问题是:什么,以及如何解决它。
Cisco路由器运行固件c2430-ik9o3s-mz.124-15.T9.bin – 这显然是TWC的公司标准,他们不能改变它。
< 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 (eg 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)
libpri不是很聪明地指出原因信息元素(IE)中的原因数据是什么意思 – 实际上,从1.4.13开始,它只能处理Q.850中给出的两种情况中的两种情况! 谢天谢地,这不仅仅是一些随机的专有诊断数据。
参考Q.850使用原因和位置… ,表1,我们需要检查原因100 无效的信息单元内容有什么诊断。 你看,这是信息元素的标识符 ! 因此,由libpri发出的呼叫处理消息的IE 0x18(24)是有问题的。 碰巧,IE 0x18是Channel ID元素。 所以至less我们知道问题出在那个特定的元素上。 作为参考,这里是我们从思科收到的原因IE:
< [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 (eg unknown message) (6) ] < Cause data 1: 18 (24)
现在我们已经把它缩小到一个IE了,参考Q.931,4.5.13信道标识[IE],我们注意到当响应呼叫build立时,整个元素是可选的,如果这样的话,用户设备只是想使用networking明确请求的唯一信道(这里是Cisco路由器)。
唉,libpri的内部API用于发送q931_call_proceeding中的q931_call_proceeding调用进程消息,并不真正使发送一个完整的信道id IE变得简单。 实际上,libpri的struct q931_call并不保留显式的最近收到的频道id,所以没有办法决定是否发出一个频道id IE是否合适。 哎呀, call_proceeding_ies[]包含Q931_CHANNEL_IDENT是错误的 – 呼叫处理消息并不总是需要这个IE。
所以,一个修正就是不发送频道ID。
唉,我们可能会尝试深入挖掘,并检查通道id中IE是干扰思科固件的。
我们来比较从Cisco接收到的信道ID IE,并在回复中发回:
< [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]
差异是相当明显的:libpri答复一个完全免费的DS1标识符八位字节。 DS1标识符是要在使用多个链接的系统上使用的特定PRI跨度的标识符。 这根本不需要,因为libpri和Cisco路由器之间只有一个T1跨度。
这似乎是思科固件中的一个错误 – 没有理由不接受DS1标识符 – 它是可选的,但是被标准所允许。 当然,除非DS1标识符在某种程度上是错误的 – 我还没有调查过。
需要获得libpri玩球的hack是transmit_channel_id中的单线。 我们所要做的就是抑制字节3.1的DS1标识符的传输。 这个补丁做到这一点:
--- 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;
需要补充的是,这绝不是一个永久性的修复,意味着包含在libpri中,只是一个临时的黑客,需要一些更广泛的调整来libpri才能正确修复。