Building a FreeBSD small office IPBX server. Part 2: Installing and configuring the ISDN Card


March 2015.
The FreeBSD logo Image Image

Introduction


In part 1, we installed FreeBSD 10.1 on a Soekris net5501-70.

Now we're going to plug in a ISDN BRI card, and configure the FreeBSD kernel to use it.

Step 4: plugging the card


I bought a second hand QuadBRI card: the Digium B410P. It features a HFC-4S chipset from Cologne and it has 4 BRI ports.

A Digium Euro ISDN BRI - B410P

Notice the BRI ports have jumpers, which should be set to the right position depending on whether those ports should behave in TE or in NT mode.
The jumber configuration of the B410P

The card is correctly detected by FreeBSD:

pciconf -lv
...
none1@pci0:0:14:0: class=0x020400 card=0xb410d161 chip=0xb410d161 rev=0x01 hdr=0x00
vendor = 'Digium, Inc.'
device = 'Wildcard B410 quad-BRI card'
class = network
subclass = ISDN

Step 5: installing and configuring the driver


I'll be using the FreebSD port of DAHDI.

The kernel modules can be installed from the port, as well as the userland binaries.

make -C /usr/ports/misc/dahdi-kmod26 install clean
make -C /usr/ports/misc/dahdi install clean

I'll be loading only the modules I need, hence the following configuration in rc.conf

dahdi_enable="YES"
dahdi_modules="/usr/local/lib/dahdi/wcb4xxp.ko /usr/local/lib/dahdi/dahdi_transcode.ko"

If you load the modules manually using kldload, you'll need to set the correct permission to the /dev/dahdi devices, or asterisk won't be able to access them. This is done by the rc script.

Now the driver needs to be configured, in /usr/local/etc/dahdi/system.conf

The router (a OneAccess 150) from my ISP (Completel) provides 4 French T0 ports, which can be characterized by the following (somewhat hard to find, some are synonyms) keywords:

Hence, the driver configuration:

loadzone = fr
defaultzone=fr

span=1,1,0,ccs,ami
bchan=1,2
hardhdlc=3

span=2,2,0,ccs,ami
bchan=4,5
hardhdlc=6

span=3,0,0,ccs,ami
bchan=7,8
hardhdlc=9

span=4,0,0,ccs,ami
bchan=10,11
hardhdlc=12

The scan correctly detects the 4 spans:

# dahdi_scan
[1]
active=yes
alarms=OK
description=B4XXP (PCI) Card 0 Span 1
name=B4/0/1
manufacturer=Digium
devicetype=Wildcard B410P
location=PCI Bus 00 Slot 14
basechan=1
totchans=3
irq=0
type=digital-TE
syncsrc=0
lbo=0 db (CSU)/0-133 feet (DSX-1)
coding_opts=B8ZS,AMI,HDB3
framing_opts=ESF,D4,CCS,CRC4
coding=AMI
framing=CCS
[2]
active=yes
alarms=OK
description=B4XXP (PCI) Card 0 Span 2
name=B4/0/2
manufacturer=Digium
devicetype=Wildcard B410P
location=PCI Bus 00 Slot 14
basechan=4
totchans=3
irq=0
type=digital-TE
syncsrc=0
lbo=0 db (CSU)/0-133 feet (DSX-1)
coding_opts=B8ZS,AMI,HDB3
framing_opts=ESF,D4,CCS,CRC4
coding=AMI
framing=CCS
[3]
active=yes
alarms=OK
description=B4XXP (PCI) Card 0 Span 3
name=B4/0/3
manufacturer=Digium
devicetype=Wildcard B410P
location=PCI Bus 00 Slot 14
basechan=7
totchans=3
irq=0
type=digital-TE
syncsrc=0
lbo=0 db (CSU)/0-133 feet (DSX-1)
coding_opts=B8ZS,AMI,HDB3
framing_opts=ESF,D4,CCS,CRC4
coding=AMI
framing=CCS
[4]
active=yes
alarms=OK
description=B4XXP (PCI) Card 0 Span 4
name=B4/0/4
manufacturer=Digium
devicetype=Wildcard B410P
location=PCI Bus 00 Slot 14
basechan=10
totchans=3
irq=0
type=digital-TE
syncsrc=0
lbo=0 db (CSU)/0-133 feet (DSX-1)
coding_opts=B8ZS,AMI,HDB3
framing_opts=ESF,D4,CCS,CRC4
coding=AMI
framing=CCS

The configuration correctly detects the 4*2 B channels (1,2,4,5,7,8,10,11) and the 4 D channels (3,6,9,12).

# dahdi_cfg -vvv
DAHDI Tools Version - 2.4.0-rc1

DAHDI Version:
Echo Canceller(s): HWEC
Configuration
======================

SPAN 1: CCS/ AMI Build-out: 0 db (CSU)/0-133 feet (DSX-1)
SPAN 2: CCS/ AMI Build-out: 0 db (CSU)/0-133 feet (DSX-1)
SPAN 3: CCS/ AMI Build-out: 0 db (CSU)/0-133 feet (DSX-1)
SPAN 4: CCS/ AMI Build-out: 0 db (CSU)/0-133 feet (DSX-1)

Channel map:

Channel 01: Clear channel (Default) (Echo Canceler: none) (Slaves: 01)
Channel 02: Clear channel (Default) (Echo Canceler: none) (Slaves: 02)
Channel 03: Hardware assisted D-channel (Default) (Echo Canceler: none) (Slaves: 03)
Channel 04: Clear channel (Default) (Echo Canceler: none) (Slaves: 04)
Channel 05: Clear channel (Default) (Echo Canceler: none) (Slaves: 05)
Channel 06: Hardware assisted D-channel (Default) (Echo Canceler: none) (Slaves: 06)
Channel 07: Clear channel (Default) (Echo Canceler: none) (Slaves: 07)
Channel 08: Clear channel (Default) (Echo Canceler: none) (Slaves: 08)
Channel 09: Hardware assisted D-channel (Default) (Echo Canceler: none) (Slaves: 09)
Channel 10: Clear channel (Default) (Echo Canceler: none) (Slaves: 10)
Channel 11: Clear channel (Default) (Echo Canceler: none) (Slaves: 11)
Channel 12: Hardware assisted D-channel (Default) (Echo Canceler: none) (Slaves: 12)

12 channels to configure.

Setting echocan for channel 1 to none
Setting echocan for channel 2 to none
Setting echocan for channel 3 to none
Setting echocan for channel 4 to none
Setting echocan for channel 5 to none
Setting echocan for channel 6 to none
Setting echocan for channel 7 to none
Setting echocan for channel 8 to none
Setting echocan for channel 9 to none
Setting echocan for channel 10 to none
Setting echocan for channel 11 to none
Setting echocan for channel 12 to none

Step 6: Configuring the card in Asterisk


Let's install Asterisk.

make -C /usr/ports/net/asterisk/ install clean

Makes sure you configured to build to have support for DAHDI.

Configure DAHDI accordingly to your requirements in /usr/local/etc/asterisk/chan_dahdi.conf. Here's my configuration:

[trunkgroups]

[channels]
language=fr
switchtype=euroisdn
usecallerid=yes
cidsignalling=v23
callwaiting=no
usecallingpres=yes
callwaitingcallerid=yes
threewaycalling=no
transfer=no
canpark=no
cancallforward=no
callreturn=yes
echocancel=yes
echocancelwhenbridged=no
;pridialplan=dynamic
pridialplan=unknown
prilocaldialplan=dynamic
context=from-isdn
callerid = Rien SAS <0400000000>
group=1
callgroup=1
pickupgroup=1
signalling=bri_cpe
channel => 1,2,4,5,7,8,10,11

Start Asterisk and check the card status:

ipbx50*CLI> dahdi show status
Description Alarms IRQ bpviol CRC Fra Codi Options LBO
B4XXP (PCI) Card 0 Span 1 OK 0 0 0 CCS AMI 0 db (CSU)/0-133 feet (DSX-1)
B4XXP (PCI) Card 0 Span 2 OK 0 0 0 CCS AMI 0 db (CSU)/0-133 feet (DSX-1)
B4XXP (PCI) Card 0 Span 3 OK 0 0 0 CCS AMI 0 db (CSU)/0-133 feet (DSX-1)
B4XXP (PCI) Card 0 Span 4 OK 0 0 0 CCS AMI 0 db (CSU)/0-133 feet (DSX-1)

List the available channels:

ipbx50*CLI> dahdi show channels
Chan Extension Context Language MOH Interpret Blocked State Description
pseudo default default In Service
1 from-isdn fr default In Service
2 from-isdn fr default In Service
4 from-isdn fr default In Service
5 from-isdn fr default In Service
7 from-isdn fr default In Service
8 from-isdn fr default In Service
10 from-isdn fr default In Service
11 from-isdn fr default In Service

If everything's fine, you should be able to call a phone number that should end up in Asterisk, and see in the console that the extension does not exist.

You now have a default Asterisk server which can now act as a BRI gateway.

A Soekris net5501 in a case with a B410P ISDN PCI Card

A Soekris net5501 in a case with a B410P ISDN PCI Card, plugged to a router

Incoming calls


Incoming calls are handled exactly like with any other channel type:

[from-isdn]
exten => 1234,1,Dial(SIP/undeuxtroisquatre,20)
exten => 1234,n,Hangup()

exten => s,1,Dial(SIP/mydefaultsipaccount,20)
exten => s,n,Hangup()

Here's a log on my system for an incoming call (from 0100000000 to XXXXXX1211):

-- Accepting call from '0100000000' to '1211' on channel 0/1, span 2
-- Executing [1211@from-isdn:1] Dial("DAHDI/i2/0100000000-2", "SIP/sipaccount2,20") in new stack
-- Called SIP/sipaccount2
-- SIP/sipaccount2-00000001 is ringing
-- SIP/sipaccount2-00000001 answered DAHDI/i2/0100000000-2
> 0x2a1aa000 -- Probation passed - setting RTP source address to 192.168.6.100:5010
-- Span 2: Channel 0/1 got hangup request, cause 16
== Spawn extension (from-isdn, 1211, 1) exited non-zero on 'DAHDI/i2/0100000000-2'
-- Hungup 'DAHDI/i2/0100000000-2'

Outgoing calls


Here's the format of the Dial function:


/*
* data is —v
* Dial(DAHDI/pseudo[/extension[/options]])
* Dial(DAHDI/[c|r|d][/extension[/options]])
* Dial(DAHDI/![c|r|d][/extension[/options]])
* Dial(DAHDI/i[/extension[/options]])
* Dial(DAHDI/[i-](g|G|r|R)[c|r|d][/extension[/options]])
*
* i – ISDN span channel restriction.
* Used by CC to ensure that the CC recall goes out the same span.
* Also to make ISDN channel names dialable when the sequence number
* is stripped off. (Used by DTMF attended transfer feature.)
*
* g – channel group allocation search forward
* G – channel group allocation search backward
* r – channel group allocation round robin search forward
* R – channel group allocation round robin search backward
*
* c – Wait for DTMF digit to confirm answer
* r – Set distintive ring cadance number
* d – Force bearer capability for ISDN/SS7 call to digital.
*/

For instance, to have french numbers get through group 1:

[from-sip]
exten => _0XXXXXXXXX,1,Dial(DAHDI/g1/${EXTEN})
exten => _0XXXXXXXXX,n,Hangup()

Since I defined that group with all the card's channels, I should be able to make 8 concurrent outgoing calls.

Here's a log from my system for an outgoing call (from a SIP phone to 0600000000, setting 0400000000 as caller id):

== Spawn extension (from-sip, 0600000001, 4) exited non-zero on 'SIP/sipaccount-00000002'
-- Executing [0600000000@from-sip:1] Verbose("SIP/sipaccount-00000003", "0, sipaccount") in new stack
sipaccount
-- Executing [0600000000@from-sip:2] Set("SIP/sipaccount-00000003", "CALLERID(name)=Erwan Martin") in new stack
-- Executing [0600000000@from-sip:3] Set("SIP/sipaccount-00000003", "CALLERID(num)=0400000000") in new stack
-- Executing [0600000000@from-sip:4] Dial("SIP/sipaccount-00000003", "DAHDI/g1/0600000000") in new stack
-- Requested transfer capability: 0x00 - SPEECH
-- Called DAHDI/g1/0600000000
-- DAHDI/i1/0600000000-4 is proceeding passing it to SIP/sipaccount-00000003
-- DAHDI/i1/0600000000-4 is making progress passing it to SIP/sipaccount-00000003
-- DAHDI/i1/0600000000-4 is ringing
-- DAHDI/i1/0600000000-4 answered SIP/sipaccount-00000003
-- Span 1: Channel 0/1 got hangup request, cause 16
-- Hungup 'DAHDI/i1/0600000000-4'
== Spawn extension (from-sip, 0600000000, 4) exited non-zero on 'SIP/sipaccount-00000003'

Conclusion


This two part article shows that FreeBSD can be successfully used on a small server as a SIP IPBX with a 4 port ISDN connection.
The RAM usage is 64MB when the system is idle, and the CPU doesn't flinch when making 4 concurrent calls.

That setup is perfect to make a cheap, low power, very reliable and very customizable small office IPBX.

512 MHz and 512 MB of RAM may seem very little nowadays, but this shows once again that you don't need much when you have good reliable hardware and good reliable software.