[asterisk-dev] A plan for span
Oron Peled
oron.peled at xorcom.com
Mon Jul 7 15:01:04 CDT 2008
Hi,
This is a renewed version of a paper distributed internally in Xorcom
(and addressed to one of the Digium developers handling zaptel)
some 6 months ago.
In this (long) mail I'd like to present:
* How Dahdi/Zaptel currently address spans and channels
and why this is a big problem.
* How do I propose to solve it. What parts of the solution already
exist. What is still missing. Backward compatibility.
* Final discussion.
Problem statement
-----------------
1. Span and channel registration today:
* Spans are identified by their numbers and channels by a numbering
which is *global* across all spans.
* Span number are determined according to their registration order
to Dahdi. Therefore, this determines the channel numbering.
* Most Dahdi low-level drivers registers their spans when they detect
the relevant hardware devices.
RESULT: global channel numbering depends on hardware probing order.
2. Hardware probing:
* Some types of hardware have inherently non-deterministic probing
order. An obvious example is hot-pluggable hardware like our USB
Astribanks. Although we solved our specific case ages ago, other
hardware types may gradually face the same problems.
* Even with relatively static devices like PCI cards, the addition
of a single PCI device to an Asterisk server can change the
probing order and thus affect the channel numbering of other cards.
(Do you think an addition of single SCSI controller would affect
the probing order of Zaptel/Dahdi cards? ... yes it may).
RESULT: Current span and channel numeric addressing is naive for
big systems.
An addition of a single card to an existing PBX with several
PCI cards may force a global change to the dialplan that
already handle a couple hundred of lines.
This is totally unacceptable in a production environment.
Proposed Solution Components
----------------------------
1. Unique span naming: We must have unique names that identify spans
and do not depend on their registration order:
* The names should be assigned by low-level drivers. They can
identify the cards however they like, for example:
- One possibility is to read it from some property stored on
the card itself (like a MAC address on a NIC).
E.g:
F00-1234-fee1-dead-5678
- Another option is to use the fully qualified PCI address:
bridge->bus->slot->function
as a unique identifier. E.g: PCI-bridge1-slot4-func2
* Although low-level drivers are assigning these "labels" they
should be globally unique. It can be trivially achieved by
prefixing them with the driver name (low-level drivers should
have limited character set for these labels).
Examples:
wctdm:PCI-slot2
wctc4xxp:ID-4567-E3F4
xpp:USB-0000:00:1d.7/5-2
2. Exporting these names to user-space:
* These names should be available to high-level driver and
to user space. The mechanism for this already exist, since
Digium introduced the 'location' field in the SPANINFO ioctl()
We should only mandate the limitations for the strings that
may be stored in this field (or add another field?)
* However, we would like to create device files named according
to these span identities. Therefore:
- We need sysfs representation for spans.
- Tzafrir already started some work in a branch long time ago.
- Doing it right will also clean up the deprecated class_device
usage for channels (Kevin already #defined around this in Dahdi)
* The basic sysfs model maps nicely to Dahdi:
- Spans are devices on the (virtual) dahdi bus.
- Each span is a (virtual) bus on its own containing the channels
as devices. Channels would have local (relative) numbers.
- Obviously the span unique label would be one of the attributes
of every span object in sysfs. Another attribute should be the
span number.
* Now using UDEV rules, we can create a naming scheme for both the
spans and the channels. Since UDEV rules can access SYSFS
attributes, the names should be based on the identity string of
the span. One possible scheme may be:
/dev/dahdi/span/<span_identity>/<channum_in_the_span>
E.g:
/dev/dahdi/spans/PCI-slot5/1
/dev/dahdi/spans/PCI-slot5/2
...
/dev/dahdi/spans/PCI-slot5/24
/dev/dahdi/spans/PCI-bridge1-slot8/1
/dev/dahdi/spans/PCI-bridge1-slot8/2
...
/dev/dahdi/spans/PCI-bridge1-slot8/4
[Note that channel numbering is *local* to each span]
* We can even run a trivial script from UDEV that provides an
*optional* mapping of physical span labels into logical
user defined names.
E.g: the script can read something like /etc/dahdi/span_map:
# Name by driver Human usable name
PCI-slot5 fat_trunk
PCI-bridge1-slot8 main_office
And either map the names (if present) of leave them unmapped
otherwise. This way the user will have:
/dev/dahdi/spans/fat_trunk/1
/dev/dahdi/spans/fat_trunk/2
...
/dev/dahdi/spans/fat_trunk/24
/dev/dahdi/spans/main_office/1
/dev/dahdi/spans/main_office/2
...
/dev/dahdi/spans/main_office/4
* Backward compatibility device files:
- Proper udev rules can create symlinks from /dev/dahdi/[1-]
to the new names.
3. Changes to chan_dahdi:
* We need to decide on some unused separator character that
would separate span name from relative channel number
in modernized dialplans (let's assume ':')
Example:
Zap/main_office:5
* Channel parsing should be done as two steps:
- Try to parse as the following regex: Zap/[^:]+:\d+
In that case, we save the span name and the (relative)
channel number.
- Otherwise, try to parse the traditional way: Zap/\d+
* When chan_dahdi opens the channel, it should be respectively
done as:
- Map span name + local channel number to
/dev/dahdi/span/<name>/<number>
- Otherwise, open /dev/dahdi/channel + ioctl(...SPECIFY...)
* The result should be that existing dialplans are not changed
(but don't have the benefits of the new scheme). On the other hand
new dialplans (especially if they use the span name mapping) are
very protected against hardware changes.
4. Changes to dahdi_cfg
* We need to optionally enable the alternative naming in
/etc/dahdi/system.conf as well. dahdi_cfg should be able to
translate the names in system.conf into device file names in /dev
so it can open them and issue the required ioctl's.
* The new syntax must preserve the ability to use old style
syntax. This means we need to differentiate absolute channel
numbers (legacy) from span-relative channel numbers.
I suggest to use different keywords for new syntax.
An example may be:
# Analog channels (legacy numbering)
fxsks=1-4
# Analog channels (new style)
spanname=PCI-slot2
channels=fxsks,1-4 # Look Ma, relative numbers
# dahdi_cfg should now config /dev/zap/spans/PCI-slot2/1 etc.
# PRI (new style)
spanname=PCI-slot5,1,0,esf,b8zs
bchannels=1-23 # Local numbers independent from other cards
dchannel=24
# More old syle definitions
span=1,1,0,esf,b8zs
# Hmmm. that may be duplicate of a previous named span
# if it incidentally got span number 1. The revised dahdi_cfg
# should issue a warning/error in this case.
bchan=1-23
dchan=24
# Again, if we already configured these channels, issue
# a warning/error. That's easy to detect since we can check:
# stat("/dev/dahdi/1") and stat("/dev/dahdi/PCI-slot5/1")
# for st_dev, st_ino equality.
* Most of the work here is implementing improved parsing in dahdi_cfg
which seems pretty easy, taking into account the limited syntax
of system.conf.
Hmmm.... maybe it's time to rewrite dahdi_cfg in perl... that would
probably result in a 5-liner with three horrendous
regular-expressions and one ioctl() in the end...
[OK, that one was a joke]
Final Thoughts
--------------
1. Implementing span names and exporting them is fairly trivial.
The missing part is proper sysfs representation which isn't too
bad. Even that alone would bring a lot of benefits.
Span and channel properties can be represented properly
and be used by user-space (e.g: for (semi)automatic configuration
generation).
2. chan_dahdi and dahdi_cfg looks like more work, but since we only
want to touch the parsing and opening of devices, it does not look
like a very big code change.
The big prize for implementing it:
You add a new T1 span to a PBX with some 300 phones and have to
configure only the new 24 lines. Other phones keep running as usual.
We can make it even simpler. If dahdi_cfg would implement an "includedir"
directive and in /etc/dahdi/system.conf we have:
includedir /etc/dahdi/spans/*.conf
Then configuring the new span amounts to dropping a small file into
this directory and rerunning dahdi_cfg.
Thoughts, comments, ideas, flames?
[Almost forgot: the Subject of this mail was cheerfully adapted from
the infamous Paul Graham: http://www.paulgraham.com/spam.html ]
--
Oron Peled Voice/Fax: +972-4-8228492
oron at actcom.co.il http://www.actcom.co.il/~oron
Linux lasts longer!
-- "Kim J. Brand" <kim at kimbrand.com>
More information about the asterisk-dev
mailing list