[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]
Communications Programming Concepts

Chapter 2. Data Link Provider Interface Implementation

The AIX Data Link Provider Interface (DLPI) implementation is designed to follow AT&T's "UNIX International OSI Work Group Data Link Provider Interface" Version 2 (DRAFT) specification. You can obtain a copy electronically if you have Internet access. Refer to "Obtaining Copies of the DLPI Specifications" for information about obtaining the DLPI specification.

It is assumed that you are familiar with the DLPI Version 2 specification published by UNIX International, RFC1042, and the various IEEE 802.x documents.

Note: In the text below, the term dlpi refers to the driver, while DLPI refers to the specification.

The dlpi driver is implemented as a style 2 provider and supports both the connectionless and connection-oriented modes of communication. For a list of the primitives supported by the dlpi driver, see "DLPI Primitives" .

Primitive Implementation Specifics

Information pertinent to specific primitives implemented in the dlpi driver is documented in the man page for that primitive.

Packet Format Registration Specifics

The dlpi driver supports generic Common Data Link Interface (CDLI) network interfaces by allowing the user to specify the particular packet format necessary for the transmission media over which the stream is created. Using the M_IOCTL or M_CTL streams message, the user can specify the packet format. If no packet format is specified, the default is NS_PROTO.

The DLPI user specifies the packet format through the STREAMS I_STR ioctl. For example, to change the address format to one compatible with AIX Version 3.2.5:

int
fixaddr(int fd) {
      int old=NS_PROTO_DL_COMPAT;
      return istr(fd, DL_PKT_FORMAT, (char *)&old, sizeof(int));
}

To select a raw stream, enter:

int
beraw(int fd) {
      int raw=NS_INCLUDE_MAC;
      return istr(fd, DL_PKT_FORMAT, (char *)&raw, sizeof(int));
}

The DLPI user is allowed one packet format specification per stream. This packet format must be specified after the attach and before the bind. Otherwise, an error is generated.

The packet formats defined in /usr/include/sys/cdli.h follow:

NS_PROTO Remove all link-level headers. Sub-Network Access Protocol (SNAP) is not used.
NS_PROTO_SNAP Remove all link-level headers including SNAP.
NS_INCLUDE_LLC Leave LLC headers in place.
NS_INCLUDE_MAC Do not remove any headers.

The packet formats defined in the /usr/include/sys/dlpi_aix.h file are:

NS_PROTO_DL_COMPAT Use the AIX Version 3.2.5 DLPI address format.
NS_PROTO_DL_DONTCARE No addresses present in DL_UNITDATA_IND. For the DL_UNITDATA_IND primitive, DLPI provides the header information in the dl_unitdata_ind_t structure.

All packet formats except NS_INCLUDE_MAC accept downstream addresses in the following form:

mac_addr.dsap[.snap].  

Individually, packet formats have the following requirements:

NS_PROTO or NS_PROTO_SNAP Medium access control (MAC) and logical link control (LLC) are included in the DLPI header, and the data portion of the message contains only data. The NS_PROTO header does not include SNAP; the NS_PROTO_SNAP header does. Both packet formats present destination addresses as mac_addr and source addresses as mac_addr.ssap.dsap.ctrl[.snap].

For the DL_UNITDATA_REQ primitive, the DLPI user must provide the destination address and an optional destination service access point (DSAP) in the DLPI header. If the DLPI user does not specify the DSAP, the DSAP specified at bind time is used.

NS_PROTO_DONTCARE The dlpi driver places no addresses in the upstream DL_UNITDATA_IND. Addresses are still required on the DL_UNITDATA_REQ.
NS_PROTO_DL_COMPAT The dlpi driver uses the address format used in the AIX Version 3.2.5 dlpi driver, which is identical both upstream and downstream. The source and destination addresses are presented as mac_addr.dsap[.snap].
NS_INCLUDE_LLC The DLPI header contains only the destination and source addresses. Only the LLC is placed in the M_DATA portion of the DL_UNITDATA_IND message. Both the source and destination addresses are presented as mac_addr.

For the DL_UNITDATA_REQ primitive, the DLPI user must provide the destination address and an optional DSAP in the DLPI header. If the DLPI user does not specify the DSAP, the DSAP specified at bind time is used.

NS_INCLUDE_MAC The MAC and LLC are both placed in the data portion of the message. Thus, the DLPI user must have knowledge of the MAC header and LLC architecture for a specific interface to retrieve the MAC header and LLC from the data portion of the message. This format sets the stream to raw mode, which does not process incoming or outgoing messages.

For the DL_UNITDATA_REQ primitive, the DLPI user must provide the destination address and an optional DSAP in the DLPI header. If the DLPI user does not specify the DSAP, the DSAP specified at bind time is used.

Downstream messages do not require the DL_UNITDATA_REQ header and must be received as M_DATA messages. Downstream messages must contain a completed MAC header, which will be copied to the medium without further translation.

Address Resolution Routine Registration Specifics

The dlpi driver can support all generic interface types. DLPI is implemented to allow the user to specify address resolution routines for input and output using the STREAMS I_STR ioctl or to rely on the system default routines. AIX provides default address resolution routines (stored in the /usr/include/sys/ndd.h file) that are interface specific.

The default input address resolution routine is:

ndd->ndd_demuxer->nd_address_input

The dlpi driver calls the input address resolution routine with a pointer to the MAC header (and, optionally, the LLC header) and a pointer to a memory buffer (mbuf) structure containing data. The actual contents of the data area depend on which type of packet format was specified. (See "Packet Format Registration Specifics" .)

The default output address resolution routine is:

ndd->ndd_demuxer->nd_address_resolve

The dlpi driver calls the output address resolution routine with a pointer to an output_bundle structure (described in /usr/include/net/nd_lan.h), an mbuf structure, and an ndd structure. The driver assigns the destination address to key_to_find and copies the pkt_format and bind time llc into helpers. If the user has provided a different DSAP than what was set at bind time, the driver also copies the DSAP values into helpers.The output resolution routine completes the MAC header and calls the ndd_output subroutine.

If you choose to specify an input and/or output address resolution routine, use the following sample code:

noinres(int fd) {
       return istr(fd, DL_INPUT_RESOLVE, 0);
}

ioctl Specifics

The dlpi driver supports the following ioctl operations:

These commands and their associated data structures are described in the /usr/include/sys/dlpi_aix.h header file.

Note: The ioctl commands that require an argument longer than one long word, or that specify a pointer for either reading or writing, must use the I_STR format, as in the following example:
int
istr(int fd, int cmd, char *data, int len) {
       struct strioctl  ic;
       ic.cmd = cmd;
       ic.timout = -1;
       ic.dp = data;
       ic.dp = data;
       ic.len = len;
       return ioctl(fd, I_STR, &ic);
}
DL_ROUTE Disables the source routing on the current stream, queries the Dynamic Route Discovery (DRD) for a source route, or statically assigns a source route to this stream. It is only accepted when the stream is idle (DL_IDLE).
  • If the argument length is 0, no source route is used on outgoing frames.
  • If the argument length is equal to the length of the MAC address for the current medium (for example, 6 for most 802.x providers), the DRD algorithm is used to obtain the source route for the address specified in the argument. The MAC address is replaced with the source route on return from the ioctl.
  • Otherwise, the argument is assumed to contain an address of the form mac_addr.source_route, and the source_route portion is used as the source route for this stream in all communications.

As an example, the following code can be used to discover the source route for an arbitrary address:

char *
getroute(int fd, char *addr, int len) {
        static char route[MAXROUTE_LEN];
        bcopy(addr, route, len);
        if (istr(fd, DL_ROUTE, route, len))
                return 0;
        return route;
}
DL_TUNE_LLC Allows the DLS user to alter the default LLC tunable parameters. The argument must point to an llctune_t data structure.

The flags field is examined to determine which, if any, parameters should be changed. Each bit in the flags field corresponds to a similarly named field in the llctune_t; if the bit is set, the corresponding parameter is set to the value in llctune_t. Only the current stream is affected, and changes are discarded when the stream is closed.

If the F_LLC_SET flag is set and the user has root authority, the altered parameters are saved as the new default parameters for all new streams.

This command returns as its argument an update of the current tunable parameters.

For example, to double the t1 value, the following code might be used:

int
more_t1(int fd) {
        llctune_t t;
        t.flags = 0;
        if (istr(fd, DL_TUNE_LLC, &t, sizeof(t)))
           return -1;
        t.flags = F_LLC_T1;
        t.t1 *= 2;
        return istr(fd, DL_TUNE_LLC, &t, sizeof(t));
}

To query the tunables, issue DL_TUNE_LLC with the flags field set to zero. This will alter no parameters and return the current tunable values.

DL_ZERO_STATS Resets the statistics counters to zero. The driver maintains two independent sets of statistics, one for each stream (local), and another that is the cumulative statistics for all streams (global).

This command accepts a simple boolean argument. If the argument is True (nonzero), the global statistics are zeroed. Otherwise, only the current stream's statistics are zeroed.

For example, to zero the statistics counters on the current stream, the following code might be used:

int
zero_stats(int fd) {
        return ioctl(fd, DL_ZERO_STATS, 0);
}
DL_SET_REMADDR Allows XID/TEST exchange on connection-oriented streams while still in the DL_IDLE state.

The dlpi driver uses both the source (remote) address and the dl_sap to determine where to route incoming messages for connection-oriented streams. The remote address is ordinarily specified in DL_CONNECT_REQ. If the DLS user needs to exchange XID or TEST messages before connecting to the remote station, DL_SET_REMADDR must be used.

Note: Note that this command is not necessary if XID and TEST messages are to be exchanged only when the state is DL_DATAXFER.

The argument to this command is the remote MAC address. One possible code fragment might be:

int
setaddr(int fd, char *addr, int len) {
        return istr(fd, DL_SET_REMADDR, addr, len);
}

Dynamic Route Discovery

Dynamic Route Discovery (DRD) is an algorithm used to automatically discover the proper source route that reaches a remote station on either a token ring or a Fiber Distributed Data Interface (FDDI) network. It relieves the DLS user from discovering and maintaining source routes. The algorithm implements the spanning tree, as recommended by 802.5.

When the DLS user issues a transmission request (for example, DL_CONNECT_REQ or DL_UNITDATA_REQ) on a medium supporting source routing, the DRD algorithm consults a local cache of source routes. If there is a hit, the cached source route is used immediately. Otherwise, the DRD queues the transmission request and starts the discovery algorithm. If the algorithm finds a source route, the new route is cached, and the queued requests are transmitted using this new route. If the algorithm times out with no replies (approximately 10 seconds), the queued requests are rejected.

The cache is periodically flushed of stale entries. An entry becomes stale after 5 minutes of no new requests.

Note: After a connection is established, the source route discovered during the connection setup is used to the exclusion of the DRD. This has two effects:

DRD Configuration

The DRD is selectable on a per-media basis when the dlpi driver is first loaded into the kernel. By default, the DRD is disabled for all media types. It can be enabled by appending the string ",r" (uses routing) to the argument field in /etc/dlpi.conf. Once selected, it is used by all physical points of attachment (PPAs) for that media type. The following example configurations both show token ring and FDDI configured, first in a default configuration and then with DRD enabled.

Default configuration:

d+      dlpi    tr       /dev/dlpi/tr
d+      dlpi    fi       /dev/dlpi/fi

DRD-enabled configuration:

d+      dlpi    tr,r       /dev/dlpi/tr
d+      dlpi    fi,r       /dev/dlpi/fi

Connectionless Mode Only DLPI Driver versus Connectionless/Connection-Oriented DLPI Driver

Attention:
  1. For binary compatibility purposes, there are no new statistics added for the connection-oriented functions. Statistics for the connection-oriented functions will be provided in a future release of AIX.
  2. For binary compatibility purposes, a DL_UNITDATA_IND header is provided in the messages for promiscuous mode and raw mode. Be aware that this header will be removed in a future release of AIX.

    The following sample code fragment works with the 4.1 and later versions of DLPI:

    if (raw_mode) {
            if (mp->b_datap->db_type == M_PROTO) {
                    union DL_primitives *p;
                    p = (union DL_primitives *)mp->b_rptr;
                    if (p->dl_primitive == DL_UNITDATA_IND) {
                            mblk_t *mpl = mp->b_cont;
                            freeb(mp);
                            mp = mpl;
                    }
            }
    } 
    The above code fragment discards the DL_UNITDATA_IND header. For compatibility with future releases, it is recommended that you parse the frame yourself. The MAC and LLC headers are presented in the M_DATA message for both promiscuous mode and raw mode.

    Raw mode currently accepts, but does not require, a DL_UNITDATA_REQ. In a future release of AIX, raw mode will not accept a DL_UNITDATA_REQ; only M_DATA will be accepted.

The dlpi driver supports the 802.2 connection-oriented service over the CDLI-based media 802.3, token ring, and FDDI. Other CDLI-based media can be supported provided the media implementation follows the IEEE 802.x recommendations.

The DL_BIND_REQ primitive accepts values for some fields (refer to the DL_BIND_REQ primitive in AIX Version 4.3 Technical Reference: Communications Volume 1).

The DL_OUTPUT_RESOLVE and DL_INPUT_RESOLVE ioctl commands replace the default address resolution routines for the current stream. They are no longer accepted from user space; the message type must be M_CTL (not M_IOCTL), and they are only accepted before the stream is bound. DL_INPUT_RESOLVE is accepted as an M_IOCTL message only if its argument is zero; this allows the user to disable input address resolution. Output address resolution cannot be disabled--use the raw mode if transparent access to the medium is required.

The DL_PKT_FORMAT ioctl command now recognizes and handles the following packet formats: NS_PROTO, NS_PROTO_SNAP, NS_PROTO_DL_DONTCARE, NS_PROTO_DL_COMPAT, NS_INCLUDE_LLC, and NS_INCLUDE_MAC.

New ioctl commands are now supported: DL_ROUTE, DL_TUNE_LLC, DL_ZERO_STATS, and DL_SET_REMADDR. Refer to "ioctl Specifics .

DLPI Primitives

The following primitives are supported by DLPI:

The following connection-oriented service primitives are supported:

The following primitives are not supported:

The following acknowledged connectionless-mode primitives are not supported:

Obtaining Copies of the DLPI Specifications

You can obtain copies of the Data Link Provider Interface (DLPI) specifications electronically using File Transfer Protocol (FTP) commands. A postscript version of the DLPI specifications may be retrieved electronically by anonymous ftp from any of the following list of Internet hosts.

To retrieve the postscript DLPI specifications through anonymous ftp, use the following example:

ftp ftp.eu.net
Connected to eunet.EU.net.
220-
220-Welcome to the central EUnet Archive,
220-
220 eunet.EU.net FTP server (Version wu-2.4(2) Jul 09 1993) ready.
Name (ftp.eu.net:jhaug):anonymous
ftp> user anonymous
331 Guest login ok, send your complete e-mail address as password.
Password:
ftp> cd /network/netman/dlpi
250 CWD command successful.
ftp> bin
200 Type set to I.
ftp> get dlpi.ps.Z     
200 PORT command successful.
150 Opening BINARY mode data connection for dlpi.ps.Z (479345 bytes).
226 Transfer complete.
1476915 bytes received in 39.12 seconds (11.97 Kbyte/s)
ftp> quit
221 Goodbye.

There is no guarantee that a public Internet server will always be available. If the above public Internet server host is not available, you might try using one of the Internet archive server listing services, such as Archie, to search for a public server that has the DLPI specifications.


[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]