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) interface 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:
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; }
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:
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:
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 %ld\n", 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:
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 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 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:
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: