Public libdlpi.so release binding: patch/micro Author: Sagun Shakya Project Clearview I-Team clearview-iteam@sun.com Network Approachability Sun Microsystems, Inc. Date of Document: 17 May, 2007 Version 1.3 Contents Background on DLPI 1 Introduction 1.1 Purpose 1.2 Overview 1.3 DLPI Handles 1.4 Multithreading/Reentrancy 1.5 Modes of Communication 1.6 Error Handling 1.7 Routines 1.8 Timeout Intervals 1.9 dlpi_info_t structure 1.10 Set Physical Address 1.11 Notification 1.12 QoS 1.13 IP Observability 2 Programming Interfaces 2.1 Interface Table 2.2 Consolidation Private Interfaces and Flags 2.2.1 Interfaces 2.2.2 dlpi_open() flag usage 2.2.3 DLPI_MODS_MAX constant Background on DLPI While most Solaris networking applications are written to the sockets API, the sockets API does not provide direct access to the data link layer. Hence, in Solaris, DLPI is used for networking applications that need to directly access the data link layer rather than via IP. For additional Solaris specific DLPI information see the dlpi(7P) manpage and for detail on the standard DLPI specification access the URL: http://www.opengroup.org/pubs/catalog/c811.htm In order to orient the readers of this document it is necessary to explain the new terminology introduced by this library. The 4 DLPI terms used in this document are: * DLPI handle * DLPI stream * DLPI link * DLPI link instance The relationship between these terms is: a DLPI link is a STREAMS device that provides access to the data link-layer in accordance with the DLPI standard. The stream established when a DLPI link is opened is called a DLPI stream. A DLPI link instance is an open instance of a DLPI link. With this library, the DLPI link instance is abstracted by and accessed through a DLPI handle. 1 Introduction 1.1 Purpose The Clearview (PSARC/2005/132) project will be introducing new features that require an extensible way to open DLPI links under different directories. Currently, DLPI applications accessing data links assume DLPI filesystem nodes are directly under /dev and use open() to directly access such DLPI links. With Clearview's introduction of vanity naming, this assumption above will create a problem because all vanity-named DLPI nodes will be placed under a /dev/net directory. This libdlpi library provides an interface, dlpi_open(), that provides an abstraction around this so that DLPI applications do not need to know where the actual DLPI link is located in the filesystem. This issue gives us the opportunity to address a related problem, which is that all DLPI-based applications implemented their own DLPI utility functions, and moreover, were intimately familiar with a variety of details regarding the DLPI programming model. Indeed, prior to the introduction of this library, the ON consolidation alone had nine overlapping-but-distinct sets of DLPI helper routines. ON previously included a Project-Private libdlpi library (PSARC/2003/375), which was sparsely used for a variety of reasons. This library has updated that library's interfaces and promoted them to Committed so that they may be used by all DLPI applications, both inside and outside of Sun. This provides additional benefit to our customers and ISV's, who will no longer need to implement and test their own DLPI helper routines. 1.2 Overview At a high level, the libdlpi library aims to: * Provide a simple, synchronous programming interface for DLPI-based applications, by abstracting away tedious and error-prone aspects of the underlying message-based DLPI programming interface. * Enable the underlying DLPI implementation to change with minimal impact to applications. Since most of interfaces are public, included in the case materials is a set of manpages that completely describes the public interfaces. Rather than repeat the contents of the manpages, this document provides an architectural overview of the programming model, along with the justification behind it. In addition, this document describes a few additional interfaces that are not intended for public use. Because our goal is to make libdlpi stable, we have paid special attention to the programming interfaces. We examined DLPI usage across the ON consolidation, and built the API to make common DLPI-related tasks easy and unusual DLPI-related tasks possible. While we anticipate that DLPI will continue to evolve, and that new functions will be added to this library over time, we have tried to ensure that no function signatures will need to change. Further, in cases where structures are passed between libdlpi and its consumers, we have either provided a versioning mechanism or justified why we feel one is not necessary. The library abstracts each open DLPI stream to a DLPI link by introducing the concept of an opaque DLPI handle, as covered in section 1.3. The DLPI handle serves several purposes, including simplifying the programming interface by allowing the library to keep state across DLPI operations, and shielding applications from the underlying library implementation. While multithreading is supported, it is not safe for a single DLPI handle to be shared between multiple threads; see section 1.4 for details. This library provides support for only DLPI version 2 devices in connectionless mode; see 1.5 for justification. In order to provide meaningful error handling, the library routines define a set of error codes in addition to the error codes provided by and a routine to convert them to human-readable strings, as covered in section 1.6. Both event driven applications like dhcpagent(1M) and synchronous applications like ifconfig(1M) are able to utilize the interfaces provided by this library. In addition, a facility is provided to allow DLPI applications to directly use the underlying DLPI file descriptor (such as to push STREAMS modules like pfmod(7D)). See sections 1.7 and 1.8 for details. 1.3 DLPI Handles DLPI handles are the basic currency for applications to use the interfaces provided by libdlpi. Applications using libdlpi must call dlpi_open() to open a DLPI link instance and acquire a DLPI handle, which can then be passed to other libdlpi operations to perform DLPI tasks. Once all DLPI tasks are completed, dlpi_close() can be used to close the DLPI link instance and destroy the DLPI handle. Each DLPI handle has a state that reflects the underlying state of the DLPI link instance -- either DL_IDLE or DL_UNBOUND. Applications using the routines provided by this library will need to make sure the DLPI handle is in the correct state. The DLPI handle must be in a DL_UNBOUND state while binding to the DLPI link. The DLPI handle must be in a DL_IDLE state when sending and receiving data as well as unbinding from a DLPI link. All other operations can be performed in any state of the handle. Note that dlpi_open() internally handles the attach of a PPA for style 2 provider, thus the number of states to keep track are minimized to just DL_UNBOUND and DL_IDLE. Using DLPI handles instead of raw file descriptors give the following benefits: * Simplified programming model. For example, most applications use the same timeout for each DLPI operation (see section 1.8). Rather than require each function to take a timeout, the value is instead stored in the DLPI handle. In addition, as above, the DLPI handle minimizes the number of possible DLPI states the programmer must interact with. * Opportunity for optimizations. By restricting access to the underlying DLPI stream, the library ensures that the state of the DLPI stream has not changed across function calls. This enables additional state to be tracked that can in turn simplify the programming model or reduce the overhead of specific operations. For example, the library stores the bound SAP of each DLPI handle, and therefore the application does not need to track or pass it explicitly to dlpi_send(). * Extensibility and backward compatibility. As new features are added, new fields can be added to the DLPI handle without affecting applications. 1.4 Multithreading/Reentrancy Each DLPI handle is associated with an open DLPI stream. For each DLPI stream, only one transaction (request/reply) is permitted at a time, and therefore there is no way to allow DLPI handles to be used simultaneously by multiple threads. However, multiple threads can coordinate use of a single DLPI handle through synchronization primitives, or each open their own DLPI handle to a given DLPI link. In the case where an application with open DLPI handles calls fork(), either interprocess communication must be used to synchronize access to the DLPI handle, or the handle's use must be restricted to either the parent or the child process. Otherwise, if operations that change the state of the DLPI handle are performed on either the parent or child process, the interfaces may not behave as documented. 1.5 Modes of Communications There are three modes of communications that DLPI supports: * The Connectionless mode is message-oriented and supports data transfer in self-contained units with no logical relationship between units. * The Acknowledged Connectionless mode provides the means by which a data link user can send data and request the return of data at the same time. * The Connection-Oriented mode is circuit-oriented and enables data to be transferred over a pre-established connection in a sequenced manner. However, all known DLPI drivers supported by Solaris support connectionless mode, and only a single driver (llc2(7D)) provides support for any additional DLPI communication modes. Further, we are unaware of any applications that use anything other than connectionless mode. Therefore, the interfaces provided in this library only supports the DL_CLDLS mode. However, in the future if other communication modes need to be supported by libdlpi, additional interfaces can be introduced. For example, to provide bind services for a connection-oriented service mode, an additional dlpi_bindx() interface could be provided. 1.6 Error Handling Each library routine returns a single integer to indicate whether the routine succeeded or failed. As error codes defined in do not cover all the error conditions that libdlpi needs to report, this library defines a supplemental set of error codes in . For example, DLPI_EINHANDLE is returned when an invalid handle is passed to a libdlpi routine. Since either a or error code may be returned, all libdlpi error codes start at value 10000 to avoid overlap: enum { DLPI_SUCCESS = 10000, /* DLPI operation succeeded */ DLPI_EINVAL, /* invalid argument */ DLPI_ELINKNAMEINVAL, /* invalid DLPI linkname */ DLPI_ENOLINK, /* DLPI link does not exist */ DLPI_EBADLINK, /* bad DLPI link */ DLPI_EINHANDLE, /* invalid DLPI handle */ DLPI_ETIMEDOUT, /* DLPI operation timed out */ DLPI_EVERNOTSUP, /* unsupported DLPI Version */ DLPI_EMODENOTSUP, /* unsupported DLPI connection mode */ DLPI_EUNAVAILSAP, /* unavailable DLPI SAP */ DLPI_FAILURE, /* DLPI operation failed */ DLPI_ENOTSTYLE2, /* DLPI style-2 node reports style-1 */ DLPI_EBADMSG, /* bad DLPI message */ DLPI_ERAWNOTSUP, /* DLPI raw mode not supported */ }; Upon success, the library routines return DLPI_SUCCESS. (Unfortunately, DLPI_SUCCESS cannot be 0 because 0 is already DL_BADSAP in .) Otherwise, one of the non-negative errors in or is returned. As per the DLPI specification, if DL_SYSERR is returned, then errno contains the UNIX system error. Currently, DL_SYSERR is returned in two scenarios: * A DLPI stream receives a DL_ERROR_ACK with a UNIX system error code set. * A libdlpi routine encounters a system call error. To make it easy for applications to print human-readable error messages, dlpi_strerror() is provided to translate UNIX system errors, the error codes listed above and the error codes listed in . 1.7 Routines Based on usage of DLPI in the ON code, the routines are designed to be simple to use in the common case, while still providing complete DLPI functionality. For instance, rather than providing functions that take long sequences of rarely-used arguments, those arguments are encapsulated into a single structure argument which most callers can simply pass as NULL. This both simplifies the interfaces and makes it easier for DLPI consumers to use. The routines are split into five subcategories: a. Control Routines This category is comprised of interfaces that setup, teardown, provide information of the DLPI handle/link or control the way in which packets can be sent or received over a given DLPI link: dlpi_open/close() open/close the DLPI link dlpi_bind/unbind() bind/unbind the DLPI handle dlpi_enabmulti()/disabmulti() enable/disable multicast addresses dlpi_promiscon()/promiscoff() enable/disable promiscuous mode dlpi_set_physaddr() set link-layer address dlpi_get_physaddr() get link-layer address dlpi_info() get information of DLPI handle/link (see section 1.9 for further details) The dlpi_open() routine allows applications to create an open instance of a DLPI version 2 device. As raw mode, native mode and passive mode are enabled while a DLPI link is being initialized, these modes are enabled through DLPI_RAW, DLPI_NATIVE and DLPI_PASSIVE flags to dlpi_open(), rather than through distinct libdlpi routines. Previously, DLPI applications in ON created a DLPI request message and waited for a reply message as an acknowledgment or error. All the routines listed above synchronously handle the requested operation while abstracting the message-driven mechanism in the underlying DLPI link. All of these routines use poll(2) to wait for a reply, or for the operation to timeout (see 1.8 Timeout intervals). b. Data Transfer Routines Data transfer being the main objective of DLPI, libdlpi has routines to send and receive data over a DLPI stream in normal and raw mode: dlpi_send() send a data message using DLPI dlpi_recv() receive a data message using DLPI In order to simplify the programming model, rarely-used send and receive features are relegated to a pointer-to-structure argument that can usually be passed as NULL. Specifically: * The final argument to dlpi_send() is a pointer to a dlpi_sendinfo_t that allows DLPI consumers to send data using a SAP value other than the one the DLPI handle is bound to, or to specify QoS parameters. * The final argument to dlpi_recv() is a pointer to a dlpi_recvinfo_t that allows DLPI consumers to get the destination address to whom the data was sent to, and to check whether the packet was unicast or broadcast/multicast. In addition, the original total length of the message can be obtained. If in the future, other features need to be provided an extended version, dlpi_sendx() and/or dlpi_recvx() could be provided. Currently, in order to send and receive data traffic, DLPI applications must interact with "data link service access point" or "DLSAP" addresses, which are a composition of the physical address associated with a DLPI link and the SAP associated with a given DLPI consumer. To complicate matters further, the way in which the SAP and address are composed varies depending on the specific DLPI link being used for communication. Although, DLPI consumers need to know the SAP value, it does not need to know this DLPI specific detail. Unfortunately, there is no way for consumers of DLPI to send data or retrieve the physical address without composing/decomposing the full DLSAP address. Due to this constraint, applications like dhcpagent(1M) implemented their own utility functions to compose DLSAP addresses. This library handles this DLPI-specific detail internally. Thus, when requesting data to be sent over a DLPI link, applications can simply provide the physical address and dlpi_send() internally handles the composition of a full DLSAP address. Similarly, dlpi_recv() handles decomposition of the DLSAP address and provides only the source and/or destination link-layer physical address. c. Non-DLPI Operations dlpi_fd() Occasionally, applications need to have access to the DLPI file descriptor to perform non-DLPI operations. For example, packet monitoring applications need to configure packet filtering and buffering modules (e.g. pfmod and bufmod) on top of a DLPI link in order to efficiently process packets. As such, these applications will open a DLPI link, issue a sequence of ioctl()'s to configure the filtering and buffering modules, and then return to using DLPI to receive packets. Similarly, event-driven applications like dhcpagent need to access the file descriptor of the open DLPI link instance to listen to events. To address these needs, libdlpi provides dlpi_fd(). This routine returns the integer file descriptor for applications that need to use the DLPI file descriptor. However, as covered in the dlpi_fd() manpage, if DLPI operations are directly performed on the file descriptor, or a STREAMS module is pushed that alters the message-passing interface then future libdlpi operations may not behave as documented. Note that no facility is provided for converting a DLPI file descriptor to a DLPI handle. While such functionality could theoretically be useful (e.g., to allow handoff of a DLPI file descriptor between unrelated applications), we are not aware of any actual need for the functionality at present. It could be added in the future, if necessary. | d. DLPI MAC-Type mapping functions | | dlpi_iftype() convert a DLPI MAC type to a BSD socket | interface type | dlpi_arptype() convert a DLPI MAC type to an ARP hardware | type | | This library provides functions to map a DLPI MAC-Type value to either | a BSD sockets interface type value or an ARP hardware type value (which | are already defined in and respectively). | Although these types represent the same concept, they are defined in | separate public namespaces with different numbering schemes. The types | defined in represent the link types for BSD sockets | interface types. Similarly, the types in represent the | hardware types in the ARP protocol. The dlpi_arptype() function are | useful when below the socket level, mapping between DLPI MAC-Types to ARP | hardware types is needed. Like for example in the DHCP client. Without | a dlpi_arptype() function the DHCP client would need to have its own | mapping function. Currently, there are no consumers of the dlpi_iftype() | interface. One potential use of this function could be with the socket | interfaces. The mapped link types can be used when dealing with AF_LINK | socket in the BSD sockets API (for example, when setting the sdl_type | field in struct sockaddr_dl). Thus, rather than applications writing | their own mapping functions, libdlpi provides such interfaces. If in the | future a new media type is introduced, having one common routine will also | allow us to add the new type easily. | | Note that it can be reasonably argued that a reverse function that maps | ARP types and BSD sockets interface types to DLPI MAC-Types should also | be provided. In that case, libdlpi can provide such functions as well. e. Miscellaneous dlpi_linkname() Return link name of the DLPI link dlpi_mactype() Return description of specified MAC type dlpi_strerror() Return error message string dlpi_set_timeout() set DLPI handle timeout Note that although the link name of a DLPI link is also accessible through dlpi_info(), dlpi_linkname() provides more convenient access for easy use in messages output using printf(). 1.8 Timeout Intervals Many interfaces in this library are synchronous interfaces atop a message passing interface (see section 1.7.a for details). Therefore, a timeout interval to wait for the response from the underlying DLPI link is needed. Applications require one of three timeout behaviors: 1. Don't wait (non-blocking). 2. Wait forever. 3. Wait a specific amount of time before giving up. The first behavior cannot be truly supported due to the synchronous behavior of the provided interfaces, but an approximation or short timeout can be provided. For example dhcpagent(1M) is an application, which exists today in the ON code that is an event driven application but is partially implemented with a short timeout mechanisms. The second behavior is for applications that do not care how long the operation takes to complete. Most DLPI applications will fall under this case. Thus, in order to simplify the common behavior, libdlpi sets a default value DLPI_DEF_TIMEOUT when the DLPI link instance is opened. This default value is intended to ensure that DLPI_ETIMEDOUT will only be returned if the DLPI link has truly become unresponsive. The logic behind setting a default value -- if there is no response for a certain period of time, something fundamentally has to be wrong and most likely there will be no response at all. The third behavior is for applications that cannot wait more than a specified amount of time. Applications requiring this behavior can modify the timeout value or restore the default timeout value via dlpi_set_timeout(). The timeout value is stored in the DLPI handle and used for all synchronous operations except dlpi_recv() (see below). Centralizing the timeout variable removes the need for each routine to require a timeout argument. More importantly, DLPI-based applications typically use the same timeout for all DLPI operations, but still must repeatedly respecify that value. Although dlpi_recv() also waits for a period of time for a message, its timeout value is typically dictated by the particular network protocol being used by the application. For instance, an application might send a request packet and wait a certain number of seconds for a response packet, as dictated by specification. This timeout has no relationship to the amount of time it may take to perform a DLPI operation. Therefore, dlpi_recv() takes an explicit timeout argument, rather than make use of the DLPI handle timeout. Note that unlike an operation like dlpi_bind(), dlpi_recv() does not send a DLPI request and wait for a DLPI response, but merely waits for an incoming packet. Thus, the timeout argument in dlpi_recv() can and will be of finer granularity, i.e. milliseconds as opposed to seconds. 1.9 dlpi_info_t structure In order to obtain information about the DLPI handle and DLPI link, this library provides a dlpi_info_t structure that is returned by the dlpi_info() routine. The information contained in the structure has been optimized to provide information for only DLPI Version 2 devices in connectionless mode. Most of the information provided in this structure are derived from the DL_INFO_ACK primitive and are documented in the manpage for dlpi_info(3DLPI). However, there are some fields that are not part of the DL_INFO_ACK primitive: di_linkname This field is retrieved from the DLPI handle. This field provides the DLPI link name associated with the DLPI link instance. Similarly, if other fields are needed to provide information about the DLPI link the structure members of dlpi_info_t may be extended. See di_opts for how backward compatibility will be maintained. di_opts This field can be used as a way for DLPI consumers and the library to check versions of the structure in order to know which fields are supported. For now this field will be set to zero. If new fields need to be added then the value of this field will be changed. For example, if dlpi_info() is later extended to return the factory hardware address for a given DLPI link, then two new members could be added to the dlpi_info_t, and di_opts would include DI_FACTPHYS: enum { DI_FACTPHYS = 1 }; typedef struct { uint_t di_opts = DI_FACTPHYS; ... [ existing dlpi_info_t members ] ... uchar_t di_factaddr[DLPI_PHYSADDR_MAX]; uint_t di_factaddrlen; } dlpi_info_t; To safely use this field, an application would have to check di_opts for DI_FACTPHYS prior to dereferencing the new fields: dlpi_info_t dli; if (dlpi_info(dh, &dli, DI_FACTPHYS) == DLPI_SUCCESS) { if (dli.di_opts & DI_FACTPHYS) { /* use factory address fields */ } } di_timeout This field is retrieved from the DLPI handle. This field provides the timeout interval set on the DLPI handle. See section 1.8 Timeout intervals for details. 1.10 Set Physical Address Currently, DLPI only allows the current physical address to be set for a DLPI link instance. However, in the future, there may be a need to set more than one type of physical address. Thus, in order to provide an extensible solution for setting the physical address, this library provides a type argument to dlpi_set_physaddr() symmetrical to dlpi_get_physaddr(). At present the only supported type is the current physical address, DL_CURR_PHYS_ADDR. 1.11 Notification Solaris supports a notification mechanism that allows applications to be notified of certain events documented in dlpi(7P). However, such notification events are only being used by DLPI consumers in the kernel. Thus, this library does not provide such interfaces. In order to be notified about events of interest, DLPI consumers can register for such events by issuing a DL_NOTIFY_REQ primitive. In response, DLPI consumer will be notified with a DL_NOTIFY_IND message upon a change in the requested event (see dlpi(7P) for detailed information). Note that DLPI notifications also provide access to information that is otherwise unavailable, such as whether the underlying link is up or down. Accordingly, we may extend the library in two ways in the future: 1) Provide a mechanism for "synchronous" asynchronous notification. This could be done by adding a new dlpi_notify() operation that would accept a set of DLPI notifications to wait for, along with a callback function and callback argument to use when the events arrive. Applications could then create a thread which would pass the DLPI handle to dlpi_notify() and wait for notifications to occur. It would be the responsibility of the callback function to update the state of other threads in the application based on the event. 2) Provide a synchronous interface that allows the current values of information only available through notifications to be retrieved. This could be done by further extending the dlpi_info() interface to include information retrieved from DL_NOTIFY_IND in addition to the information currently retrieved from DL_INFO_ACK and the DLPI handle. 1.12 QoS Although this library allows DLPI consumers to specify the priority range for each data message sent (see 1.7.b), it does not provide a routine that allows to specify the QOS parameter values (DL_UDQOS_REQ primitive) to every data message transmitted. Currently in the DLPI specification, there is no way to use this primitive since there is no mechanism to request the default priority being used by the DLPI link. If a provision to request for the default priority is provided a dlpi_qosreq() routine can be added. 1.13 IP Observability Another component of Clearview, IP Observability, will be introducing a /dev/ipnet name space for IP-layer "DLPI" devices. Thus applications will need to be able to open such devices in the future. A subsequent case will introduce an additional flag to dlpi_open(), which will later be used to indicate that /dev/ipnet should be searched instead of /dev/net. 2 Programming Interfaces This section describes the functionality and user interfaces that this library provides. 2.1 Interface Table: +-------------------------------------------------------------------------+ | Interfaces Exported | |----------------------|----------------------|---------------------------| | Interface | Classification | manpages | |----------------------|----------------------|---------------------------| | libdlpi.so | Committed | | | | Committed | | | dlpi_handle_t | Committed | | | dlpi_open | Committed | dlpi_open(3DLPI) | | dlpi_close | Committed | dlpi_close(3DLPI) | | dlpi_info | Committed | dlpi_info(3DLPI) | | dlpi_bind | Committed | dlpi_bind(3DLPI) | | dlpi_unbind | Committed | dlpi_unbind(3DLPI) | | dlpi_enabmulti | Committed | dlpi_enabmulti(3DLPI) | | dlpi_disabmulti | Committed | dlpi_disabmulti(3DLPI) | | dlpi_promiscon | Committed | dlpi_promiscon(3DLPI) | | dlpi_promiscoff | Committed | dlpi_promiscoff(3DLPI) | | dlpi_get_physaddr | Committed | dlpi_get_physaddr(3DLPI) | | dlpi_set_physaddr | Committed | dlpi_set_physadrr(3DLPI) | | dlpi_iftype | Committed | dlpi_iftype(3DLPI) | | dlpi_arptype | Committed | dlpi_arptype(3DLPI) | | dlpi_mactype | Committed | dlpi_mactype(3DLPI) | | dlpi_send | Committed | dlpi_send(3DLPI) | | dlpi_recv | Committed | dlpi_recv(3DLPI) | | dlpi_linkname | Committed | dlpi_linkname(3DLPI) | | dlpi_fd | Committed | dlpi_fd(3DLPI) | | dlpi_set_timeout | Committed | dlpi_set_timeout(3DLPI) | | dlpi_strerror | Committed | dlpi_strerror(3DLPI) | | | | | | DLPI_PASSIVE | Committed | dlpi_open(3DLPI) | | DLPI_RAW | Committed | dlpi_open(3DLPI) | | DLPI_NATIVE | Committed | dlpi_open(3DLPI) | | DLPI_ANY_SAP | Committed | dlpi_bind(3DLPI) | | DLPI_DEF_TIMEOUT | Committed | dlpi_set_timeout(3DLPI) | | DLPI_LINKNAME_MAX | Committed | dlpi_info(3DLPI) | | DLPI_PHYSADDR_MAX | Committed | dlpi_info(3DLPI), | | | | dlpi_get_physaddr(3DLPI),| | | | dlpi_send(3DLPI), | | | | dlpi_recv(3DLPI) | | | | | | dlpi_info_t | Committed | dlpi_info(3DLPI) | | dlpi_recvinfo_t | Committed | dlpi_recv(3DLPI) | | dlpi_addrtype_t | Committed | dlpi_recv(3DLPI) | | dlpi_sendinfo_t | Committed | dlpi_send(3DLPI) | | | | | | | Consolidation Private| Not Shipped | | dlpi_parselink | Consolidation Private| Not documented | | dlpi_makelink | Consolidation Private| Not documented | | DLPI_EXCL | Consolidation Private| Not documented | | DLPI_SERIAL | Consolidation Private| Not documented | | DLPI_NOATTACH | Consolidation Private| Not documented | | DLPI_MODS_MAX | Consolidation Private| Not documented | +----------------------+----------------------+---------------------------+ 2.2 Consolidation Private Interfaces and Flags 2.2.1 Interfaces There are two interfaces provided by libdlpi that are Consolidation Private, namely: int dlpi_parselink(const char *linkname, char *provider, uint_t *ppa); int dlpi_makelink(char *linkname, const char *provider, uint_t *ppa); These operations provided by libdlpi are Consolidation Private and are undocumented. We anticipate that they will only be used by ifconfig and libdladm (e.g. when interacting with the device tree). The dlpi_parselink() routine parses and returns the provider name and the PPA from a specified "linkname". The dlpi_makelink() routine forms a "linkname" from a specified "provider" name and "PPA". If the "provider" name already has a PPA then just the "provider" name is returned. 2.2.2 dlpi_open() flag usage DLPI_SERIAL Although the synchronous serial line interface is not a true DLPI link, it uses a DLPI-like message passing interface to communicate with serial devices. With the intention of not leaving any raw users of DLPI message types in the ON Consolidation, libdlpi continues to support the synchronous serial line commands (syncinit(1M), syncstat(1M), syncloop(1M)) by providing a special Consolidation private flag DLPI_SERIAL to the dlpi_open() routine. This flag minimizes the impact of supporting the above mentioned commands by allowing special treatment during the open of such synchronous serial line interfaces. DLPI_EXCL The DLPI_EXCL dlpi_open() flag causes libdlpi to open the device with the O_EXCL flag. This is needed to allow the syncinit(1M) to be ported to libdlpi, since it uses a DLPI-like message passing interface to communicate with serial devices, and the serial device needs to be opened O_EXCL in certain cases. Since O_EXCL has no defined meaning on true DLPI links, there is no need to make this flag available for public use. DLPI_NOATTACH The DLPI_NOATTACH dlpi_open() flag causes libdlpi to open a DLPI style-2 device without attaching to a PPA. This is needed because ifconfig must detach the PPA from DLPI style-2 devices to workaround an oddity in the IP and ARP kernel modules. Thus, instead of libdlpi doing the attach for a DLPI style-2 device and the application doing the detach, the DLPI_NOATTACH flag tells libdlpi to open a dlpi style-2 device without attaching to a PPA. 2.2.3 DLPI_MODS_MAX constant Due to a feature that allows STREAMS plumbing to be embedded in a DLPI link name, which was implemented in the old Consolidation Private libdlpi library, this constant needs to be defined as the maximum size of a STREAMS module list. However, the ability to embed STREAMS plumbing into link names is currently Consolidation Private and slated for removal by the upcoming Clearview IP Tunneling work. Once that work is complete, DLPI_MODS_MAX will be removed.