The Connection Management Module (CMM) provides an
interface that allows any ATM module to exchange configuration and management
information with application processes without the usual need for kernel modifications
and new
/dev
nodes.
The Module Management Interface (MMI)
is the standard DIGITAL UNIX
ioctl
interface, but it allows
applications to communicate with specific ATM modules directly through the
CMM.
See
ioctl
(2)
for more information.
To exchange information with any ATM module, applications must open
the
/dev/atm_cmm
device and issue
ioctl
system calls.
The
ioctl
commands are executed either by
the CMM directly or passed to a selected ATM module.
The ATM module transfers
all data associated with the
ioctl
commands to and from
user space; the MMI always has a user context since it is executed as part
of a system call.
New ATM modules can define their own
ioctl
commands
independently since commands are routed only to a module selected by using
an
ioctl
call.
Modules can also define their own structures
and protocols for exchanging data with applications since interpretation of
the
ioctl
data argument is done by agreement between the
module and its application, not by the CMM.
Applications cannot send the CMM any commands other than those commands for establishing MMI paths. Only applications that DIGITAL has written to manage the ATM subsystem can select the CMM as the target for commands. Also, a module can restrict the establishment of an MMI path through the use of key values that are known only to the module and applications that are allowed to communicate with it. This prevents applications from illegally communicating with ATM modules.
This chapter describes the following:
How to create an MMI command path
How to define new MMI
ioctl
commands
The MMI calling conventions
Device driver, signaling, and convergence module interfaces
To send
ioctl
commands to an ATM module, you
must create a path through the CMM to the module.
The following code fragment
shows a routine that creates an MMI path:
#include <sys/atm.h> make_mmi_path(char *name) { int atm_fd; struct atm_mmi_path path; [1] atm_fd = open("/dev/atm_cmm",O_RDWR); [2] if(atm_fd == -1) { perror("open of /dev/atm_cmm"); exit(errno); } path.name = name; path.length = strlen(name); path.key = 0x123456789abcdef; if(ioctl(atm_fd,GIOC_MMI_PATH,&path) == -1) [3] { perror("GIOC_MMI_PATH"); exit(errno); } return atm_fd; }
Declares the
atm_mmi_path
structure.
[Return to example]
Opens the
/dev/atm_cmm
device.
[Return to example]
Issues the
ioctl
call with the
GIOC_MMI_PATH
command.
The argument to the
GIOC_MMI_PATH
command is the name of the module to which the path is to be established;
each module must register with a unique name.
[Return to example]
After the path is created, all subsequent
ioctl
commands
not understood by the CMM are sent to the selected module.
The
/dev/atm_cmm
device has the following restrictions:
You can use this device only for the management and administration of ATM modules, not for transferring data across the network.
Only one application can have the device opened at any time. Multiple accesses to this interface are not permitted.
Only applications with root permissions can open the device.
Since all ATM modules, including the CMM, share a common interface,
an application can inadvertently or deliberately issue an incorrect or damaging
ioctl
call.
To prevent this from occurring, applications can identify
themselves to ATM modules when the MMI path is created so their privilege
to contact the module can be confirmed.
You are not required to implement
this in your module, but should for added safety.
The application performs extra validation by passing a 64-bit key to the ATM module when the MMI path is created. The ATM module checks this key to verify that it is valid. Since only applications written specifically to communicate with certain modules know the key the module expects, it is more difficult for another module to create the MMI path to the ATM module.
Table 8-1
lists member names of the
atm_mmi_path
structure, with their associated data types, that modules might
reference.
Member Name | Data Type |
*name |
char |
length |
int |
key |
long |
The
name
member is a pointer to the name of the ATM
module to which the MMI path is to be established.
This name is a standard
NULL-terminated ASCII string that must exactly match the string the module
used when it registered with the CMM.
The
length
member is the length (in bytes) of the
string pointed to by the name member.
This length does not include the NULL
termination.
The
key
member is a value that the application and
the target ATM module agree to use to identify the application to the ATM
module.
Only target ATM modules use this member.
All MMI
ioctl
commands are in the "g"
ioctl
group and are named
GIOC_command_name
.
Each
ioctl
command group can
contain up to 256 commands; each
ioctl
command encodes
the group, the command within the group, the data transfer direction, and
the size of the data to transfer.
The GIOC group is divided into CMM-specific
commands (with a range of 0 to 127, inclusive) and module commands (with a
range of 128 to 255, inclusive).
The CMM does not interpret commands in the
module command range.
Also, modules are not passed commands in the CMM command
range.
As a rule, the module and application program must agree on the command
number and the format of the command data passed as the third argument to
the ATM
ioctl
system calls for a module.
You do this with
a module specific header file in which the commands and structures are defined.
This header file should include
sys/ioctl.h
, which contains
the macros used to define
ioctl
commands.
To define a new
ioctl
command, you need the following
pieces of information:
The direction of any data transfer between the application and the ATM module (input from the application, output to the application, or both). This determines which macro to use for command definition (_IOR, _IOW, or _IORW).
The definition of the data structures to be passed between
the application and the ATM module as the argument to the command.
This, along
with the transfer direction information, controls how much data the kernel
will move between user space and the kernel when the
ioctl
is processed.
The number of the command (between 128 and 255).
Once you know this information, you can define a new
ioctl
command.
For example, suppose an application needs to pass information
contained in a single longword and receive information from the ATM module
in the same word.
You would define the command as follows:
#define GIOC_NEW_CMD _IOWR('g',128,sizeof(long))
Note that the "g" must be in lowercase.
Using this example, the application executes the following call to send the new command to the ATM module:
long arg = some_value; int atm_fd; atm_fd = make_mmi_path("module name"); if(ioctl(atm_fd, GIOC_NEW_CMD, &arg) == -1) { perror("GIOC_NEW_CMD"); exit(errno); } printf("GIOC_NEW_CMD returned %ld0", arg);
An
ioctl
system call can copy only fixed-size data directly addressed by
the argument.
If a command requires the exchange of variable size data, the
argument to the
ioctl
system call must be a fixed size
structure that contains pointers to and lengths of variable size data in the
application's memory space.
The ATM module is responsible for copying data
from or to this memory when processing the command; the kernel
ioctl
call copies the contents of the structure.
All modules that provide an MMI routine must adhere to the following rules when handling arguments from the CMM:
All MMI routines are called while in a system call context with no external locks held. This means that the MMI routines can block, if necessary, provided they do not hold simple locks while blocking.
All MMI routines must return
ESUCCESS
to
indicate successful completion of the operation or a DIGITAL UNIX error number
to indicate the type of error that occurred.
MMI modules can use the
retval
pointer to provide a nonzero return value to the calling program.
This value
is the return value from the
ioctl
when the MMI function
returns
ESUCCESS
to the CMM.
This follows the normal DIGITAL UNIX
ioctl
processing conventions.
MMI
routines are required to process only their own commands and one global command:
the
GIOC_MMI_PATH
command.
This command instructs the
MMI function to verify that it is willing to accept the establishment of an
MMI path from the CMM as requested by an application program.
The argument
to this command is a pointer to an
atm_mmi_path
structure
that the MMI function is to evaluate.
The MMI routine should verify that the key provided in the
atm_mmi_path
structure is correct, but might also verify the specified
module name.
This is redundant since the CMM already verifies the module
name.
If the key or module name provided is acceptable, the MMI function returns
ESUCCESS
, otherwise, it returns
ENXIO
.
The MMI function is informed only when MMI paths are established, not when they are destroyed.
See
Appendix A
for information on the
xxx_mmi
function.
When an ATM device driver registers with the CMM, it provides the CMM with the address of the following management functions:
The internal management function that the CMM uses to manage driver resources and VCs. Only the CMM uses this interface; it is not available through the MMI. This function is not allowed to block at any time.
The
xxx_mmi
function.
This function receives
only MMI commands through the
ioctl
system call from an
application that has been written specifically to manage the device driver.
The standard DIGITAL UNIX ATM interface defines no generic driver management
through the MMI.
If a device driver does not need to process MMI commands,
it should set this argument in the
atm_cmm_register_dd
routine to NULL.
The device driver's MMI function is passed the following arguments when called:
The device driver's module handle, which the device driver module provided the CMM at registration time
The
ioctl
command and data value
The MMI function is permitted to block, if necessary, at any time and has access to the user context of the calling application.
The signaling module MMI is similar to the convergence module and device driver MMIs. The signaling module is passed the following arguments when called:
The signaling module handle, which the signaling module provided the CMM at registration time. The signaling module can use this value in any way it chooses. The CMM does not modify this value.
The
ioctl
command and data value.
When a convergence module registers with the CMM, it can supply the address of an MMI function to be called when an application creates an MMI path to the convergence module. If a convergence module does not provide an MMI management function, the module writer should register an address of NULL for the MMI management function when the convergence module registers with the CMM.
The convergence module MMI function is passed the following arguments when called:
The convergence module's internal handle, which the convergence module provided to the CMM at registration time. This value is internal to the convergence module; the CMM does not modify this value.
The
ioctl
command and data value.