[asterisk-dev] A plan for span

Shaun Ruffell sruffell at digium.com
Tue Jul 8 10:27:35 CDT 2008

Oron Peled wrote:


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

It is also possible to get non-deterministic registration order without adding 
PCI cards (as long as you have cards that are serviced by two different dahdi 
drivers installed) since it's possible for each driver to be loaded in parallel 
by the autoloader.  The module that gets one of it's devices to dahdi_register 
first....is registered first, and it's not always the same module.

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

Another thought that wouldn't require any changes to chan_dahdi or dahdi_cfg, 
just control the order that devices are registered with dahdi.  This would't 
work if you had things that are constantly connected and disconnected (where 
you might want to leave holes in the channel numbers for certain devices), but 
otherwise, it would solve the problem of all your channels being renumbered 
when you added a new device, and with the problems of races when autoloading 
different modules at system start.

For example, you could export an sysfs attribute (register) that when written 
to, that driver will in order register all the spans it supports.  Then the 
hotplug script or init script can wait until all the devices it's been 
configured for are loaded and have exported their names in sysfs, and then 
instruct them to register with dahdi in the order that it wants.  So when you 
add a new card to your system, you would also add it to the list of devices to 
be registered.

A thought...


More information about the asterisk-dev mailing list