OpenSS7 |
© Copyright 2000, Brian F. G. Bidulock, All Rights Reserved. |
All OpenSS7 website, www.openss7.org resources have provided as a courtesy of the OpenSwitch Project and Herlein Engineering. |
Writing SS7 device drivers is similar to writing device drivers for serial device drivers for WAN IP interfaces. Many of the facilities of the SS7 interface are borrowed from the Linux IP NET4 distribution by Alan Cox, et al. Some of these facilities are as follows:
struct device
;
For an example of how to use the facilities of the SS7/LINK ss7 signalling
link interface facility, see acb56.c
in drivers/net
(or here). The file acb56.c
is a complete working example of a
serial interface card implementation to this driver interface for the Sealevel
ACB56 card.
You must use the struct device structure from
include/linux/netdevice.h
in the kernel sources. This device
structure is shared by IP and SS7.
There are three ways to register a device as an SS7 interface and attach a level 2 SS7 link state machine to a device (in order of preference):
Fill out your device structure wtih all the necessary interface service
routines (as per IP) and set the dev->type
to
ARPHRD_SS7,
and then register the device with
register_netdevice().
The netdevice notifier will invoke the
attach automagically via the ss7mtp
module.
This is the preferred method because the netdevice notifier is for notification of other changes to the SS7/MTP protocol layer. In particular, it has the ability to be extended to provide notification of card insertion and removal events for cPCI, and is consistent with the approach used for IP network devices.
Fill out your device structure with all necessary interface service
routines (as per IP) and call the exported ss7if_attach()
routine from the ss7link
module.
This is a BSD-like approach and is preferrable for device drivers which are attempting to maintain consistency with future BSD implementations of OpenSS7.
Fill out an ss7if_regs
structure with the interface
service routines which would normally be in the device structure and call
ss7if_register()
from the ss7link
module with a
master device and the register structure.
This approach is particularly useful for multichannel devices which do not require or maintain a full device structure per channel.
There are only two ways to detach from an SS7 interface and undo what was done during the attach:
Deregister the device with the unregister_netdevice()
which
will automagically detach (from the destructor of the device structure
which was set by the attach operation).
Call either ss7if_unregister()
or ss7if_detach()
(which are really the same function call).
NOTE: devices should be closed with dev_close()
before calling
unregister_netdevice().
dev_close()
should not be
called on an operating signalling link (you'll get lots of error messages, but
the device will close and unregister correctly).
As shown in Figure 1, below, the SS7 LINK interface attaches itself
between the struct device
provided or allocated for the device
driver and the device driver itself. The device driver's private interface
service routines are saved in the struct ss7if_regs
structure in
the SS7 LINK state machine and used to invoke the driver. The SS7 MTP or
SCCP protocol layers communicate to the SS7 LINK interface through the
replaced device service routines.
Figure 1 - Interface Service Routines
Pertinent driver service routines are those routines which are normally
completed against the struct device
structure as follows:
destructor() |
The device driver can have a private destructor service routine. The SS7 LINK
interface will interpose its own destructor service routine which is used by
|
open() |
The device driver provides its own open service routine. The SS7 LINK interface will interpose its own open service routine which will initialize the L2 state machines associated with the driver. |
stop() |
The device driver provides its own close service routine. The SS7 LINK interface will interpose its own close service routine which will gracefully shut-down the SS7 LINK state machines associated with the driver before calling the driver's private close service routine. |
hard_start_xmit() |
The device driver must provide a hard start transmit service routine. This service routine must follow the behavior specified later under Transmit Interrupt Service Routine. The SS7 LINK interface interposes its own hard start transmit service routine which is responsible for queuing and processing frames and service primitives for processing in the L2 state machine. Only when the L2 state machine deems it necessary to transmit a frame does it call the device's private hard start transmit service routine. |
do_ioctl() |
The device driver may (if necessary) provide its own ioctl service routine. The SS7 LINK interface interposes its own ioctl service routine which is used to control characteristics and attributes of the SS7 LINK state machines; however, this interface will call the device private ioct service routine for all device private ioctls within the private range. |
get_stats() |
The device driver should (if possible) provide its own statistics service routine. The SS7 LINK interposes its own statistics service routine which is responsible for gathering statistics collected by the SS7 LINK state machines on L2 operation. This interposed routine; however, calls the device driver private routine to collect information which is not possible to collect in the L2 state machines (such as compressed FISUs, repeated FISUs, types of errors, etc). |
The SS7 LINK interface interposes its own driver service routines by replacing
the service routines in the device's struct device
structure and
saving the device drivers private service routines in an interface
registration structure (struct ss7if_regs
) at the time of
registration or attachment. At the time that the driver is deregistered or
detached from the SS7 LINK interface, these driver service routines are
reinstated back into the device driver's struct device
structure
and the internal registration structure and associated link state machine
structures are freed.
When delivering received packets in the driver, the driver should not call
netif_rx()
as it would in the IP case, but, instead, should call
ss7if_rx()
so that the SS7 L2 state machine has a crack at the
packet. Failing to do so will result in erroneous operation.
ss7if_rx()
processes each frame through the L2 state machines
which is part of the ss7link
module, before ultimately delivering
each packet up using the actual netif_rx()
call.
Please see the acb56.c
file in drivers/net
for more
detail.
Following is the Rx ISR API to the SS7 LINK state machines. There are four functions which must be called in different circumstances and have different behaviors which must be followed in the driver. These are a diversion from the calls which one would normally see in an IP WAN driver. To summarize, they are:
ss7if_rx() |
Called with an
The | |
ss7if_los() |
Called with the device pointer when the driver loses flag syncrhonization on the line. The driver must enter octet counting mode after sending this indication. | |
ss7if_err() |
Called with the device pointer when the driver detects frame-related error such as an abort, residue error, framing error, CRC error. The driver must enter octet counting mode after sending this indication. | |
ss7if_oct() |
Called wtih the device pointer when the driver is in octet counting mode. It must be called every 16 octet times (128 bit times) when the driver is in octet counting mode. | |
ss7if_rpt() |
Called with the device pointer when the driver receives a repeat of the last received FISU or LSSU (while not in octet counting mode). This is used because the driver has extremely critical timings while the line is idling FISUs or LSSUs. The state machine does not do its own FISU/LSSU compression, it must be done in the driver. |
All in all, these calls to the SS7 interface are sufficient to meet the requirements of the SS7 Level 2 driver interface and provide full SS7 Level 2 capabilities.
The driver receivers can be in one of three states as illustrated in Figure 2, below. The driver receiver must move throught the proscribed states in the proscribed manner for the SS7 L2 state machines to operate correctly.
Note that the state diagram illustrated in Figure 2 is similar to the Delimitation, Alignment, and Error Detection for Receive (DAEDR) state machine provided in Q.703.
Figure 2 - Receiver State Diagram
The receivers can be in one of three modes as illustrated in Figure 2 above, and described as follows:
Normal Mode
In this state, the receivers are synchronized on frames and unique frames are being received. This is the normal situation which corresponds to the state of the receivers in most IP WAN drivers. This is also the power-on reset state of the driver receivers.
Whenever a correct MSU is received (as contrasted with a FISU or LSSU), the
ss7if_rx()
interface method is called with the received frame and
the receivers stay in the normal mode. Whenever a correct FISU or LSSU is
received, the driver calls ss7if_rx()
with the received frame and
moves to the compression mode. Whenever an erroneous frame (aborted frame,
frame with residual bits, frames greater than SS7_MTU in length, frames with
erroneous length indicators) or a loss of synchronization wtih flags occurs,
the receiver calls ss7if_err()
or ss7if_los()
and
moves to the octet counting mode state.
Compression Mode
In this state, a FISU or LSSU has been received and the receiver is compressing repeating occurences of identical FISU or LSSU frames.
One of the reasons for requiring the driver to peform this function is that the overhead associated with compressing repeating FISUs or LSSUs can be most efficiently achieved from within the Rx ISR itself, rather than in the SS7 interface L2 state machines.
For example, the acb56.c
driver keeps an sk_buff
as
a compression buffer and compares the 3 to 5 bytes of the previously received
FISU or LSSU with the currently received FISU or LSSU to determine whether to
call ss7if_rx()
with the received frame or
ss7if_rpt()
and discard the frame.
Whenever a correct MSU is received, the driver calls ss7if_rx()
with the received frame and moves to the normal mode. Whenever a correct FISU
or LSSU is received, the driver calls ss7if_rx()
with the
received frame and moves to the compression mode. When no correct SU has been
received, the driver calls ss7if_oct()
every 16 octet times (or
128 line rate bit times).
Octet Counting Mode
In this state, the receivers have lost synchronization with flags and are generating an erroneous SU indication to the L2 state machines every 16 octets (or 128 bit times) at the line rate.
One of the major reasons for requiring the driver to perform this function is the lack of a sub-millisecond timing reference in the Linux kernel. Most device drivers are capable of generating a higher precision interrupt which is used to generate the erroneous SU indications to the L2 state machines when in this mode. Furthermore, some chips support octet counting mode directly.
For example, the acb56.c
driver sets an interrupt which is based
on the Baud Rate Generator in the Z80530 which generates an interrupt every
bit time at 56 kbps. The ISR for this interrupt counts the bits until 128
bit times have been accumulated and then calls the ss7if_oct()
interface method while in octet counting mode. When not in octet
counting mode the driver does not request that the chip generate the
interrupt (to reduce ISR overheads).
Whenever a correct and duplicate FISU or LSSU is received, the driver calls
ss7if_rpt()
and discards the repeated frame and stays in the
compression mode. Whenever a correct and unique FISU or LSSU is received, the driver
calls ss7if_rx()
with the received frame and stays in the
compression mode. Whenever a correct MSU is received, the driver calls
ss7if_rx()
with the received frame and moves to the normal mode.
Whenever an erroneous frame (see above) or loss of synchronization with flags
occurs, the driver calls ss7if_err()
or ss7if_los()
and moves to the octet counting mode.
When transmitting packets provided to the driver for transmission using the
driver's hard_start_xmit()
driver service routine, the driver
must behave somewhat differently that for normal IP WAN operation. This is
because the transmitters in SS7 are always busy and must idle FISUs or repeat
LSSUs as required to fill times when there are no packets available for
transmission.
All retransmissions are handled within the L2 state machines and MSUs which
are to be retransmitted are provided to the driver using the driver's
hard_start_xmit()
routine in the same manner that new frames for
transmission are provided (in an sk_buff
with the level 2 header
already provided).
The interface to the tranmitters in the device driver is the driver's
hard_start_xmit()
driver method which the device driver filled
into the struct device
structure at registration with the SS7
LINK interface. This is the method that the SS7 LINK interface uses to send
frames for transmission to the device driver.
When an new or retransmitted SU is available for transmission or
retransmission, the SS7 LINK interface will call the device driver's
hard_start_xmit()
driver service routine with an
sk_buff
which contains the frame for transmission. The driver
should queue the frame (if possible) and return the depth of the driver's
queue. The SS7 LINK interface should not let this queue depth increase beyond
1; however, for short sequences, the SS7 LINK interface may send 2 or 3 frames
win rapid succession.
When the transmitters are available to transmit a new frame (at the completion of the previous frame which was transmitted), the driver should check the internal queue to see if there are new frames for transmission. If there are no frames for transmission, the transmitter behaviour depends on the previous frame which was transmitted, as illustrated in Figure 3 below.
Note that the state diagram illustrated in Figure 3 is similar to the Delimitation, Alignment, and Error Detection for Transmit (DAEDT) state machine provided in Q.703.
Figure 3 - Transmitter State Diagram
The behavior of the transmitters in the driver are dependent upon the last transmitted frame as illustrated in Figure 3 above, and described as follows:
BSN/BIB
and
FSN/FIB
of the last transmitted MSU and the FISU is transmitted
(moving to the Transmit FISU state). If a frame is available for
transmission, that frame is transmitted and the appropriate state entered.
BSN/BIB
and
FSN/FIB
of the last transmitted SIB and the FISU is transmitted
(moving to the Transmit FISU state). If a frame is available for
transmission, that frame is transmitted and the appropriate state entered.
With this approach, it is possible for the SS7 LINK interface and state
machines to interface to the driver through the single
hard_start_xmit()
function.
The SS7 LINK interface provides a simple and straightforward mechanism for attaching an SS7 L2 state machine onto a device driver and providing and interface mechanism which permits the simplified design of an SS7 LINK device driver. This design permits a simple and straightforward DAEDR and DEADT implemenation in the device driver, without the driver having to worry about the other details of the SS7 LINK state machine.
The writing of SS7 LINK device drivers is somewhat different from the development of IP WAN drivers for synchronous serial interfaces, because of the need to peform octet counting mode and SU Compression capabilities in the receiver and FISU/LSSU Idling capabilities in the transmitter; however, these mechanisms are simple and straightforward to implement.
For an example implementation of a synchronous serial SS7 LINK interface
driver, see the Sealevel ACB56 driver in acb56.c
in the
drivers/net
directory.
OpenSS7 |
© 2000, Brian F. G. Bidulock, All Rights Reserved. Last modified: $Date: 2000/10/04 03:52:24 $ |