[asterisk-dev] A plan for span

Oron Peled oron.peled at xorcom.com
Mon Jul 7 15:01:04 CDT 2008


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

     - Another option is to use the fully qualified PCI address:
       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).

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:



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

   * 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 ':')

   * 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

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

        # Analog channels (new style)
        channels=fxsks,1-4  # Look Ma, relative numbers
        # dahdi_cfg should now config /dev/zap/spans/PCI-slot2/1 etc.

        # PRI (new style)
        bchannels=1-23      # Local numbers independent from other cards

        # More old syle definitions
        # 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.
        # 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

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