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: 10 November, 2006 | 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 3 Appendices 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 proposal it is necessary to explain the new terminology introduced by this library. The 4 DLPI terms used in this proposal 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 the proposed 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 proposes an interface, dlpi_open(), that will provide 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 currently implement their own DLPI utility functions, and moreover, are intimately familiar with a variety of details regarding the DLPI programming model. Indeed, in the ON consolidation alone, there are nine overlapping- but-distinct sets of DLPI helper routines; dozens more exist in unbundled and third-party products. ON currently includes a Project-Private libdlpi library (PSARC/2003/375), which is sparsely used for a variety of reasons. This library proposes to update that library's interfaces and promote them to Evolving so that they may be used by all DLPI applications, both inside and outside of Sun. This will provide 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 the proposed interfaces will be public, included in the case materials is a set of manpages that completely describes the proposed public interfaces. Rather than repeat the contents of the manpages, this document provides an architectural overview of the proposed 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 we are proposing to make libdlpi stable, we have paid special attention to the proposed 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 proposed 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 proposes to provide support for only DLPI version 2 devices in connectionless mode; see 1.5 for justification. In order to provide meaningful error handling, the proposed library routines will 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) will be able to utilize the interfaces proposed in 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. Since the interfaces in the current libdlpi library are Consolidation Private there should not be any dependent consumers outside the ON consolidation. The proposed changes to the library interfaces will be fixed with all the current users. 1.3 DLPI Handles DLPI handles will be the basic currency for applications to use the interfaces proposed 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() will internally handle 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 can ensure 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 proposed 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 proposed 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 will return 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 will define 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 will 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_ERRMAX /* Highest + 1 libdlpi error code */ | }; Upon success, the library routines will 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 will be returned. As per the DLPI specification, if DL_SYSERR is returned, then errno will contain 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() will be 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 proposed have been 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 have been 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 can be split into four 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 will allow 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. Note that the native mode for DLPI was approved with the WiFi for GLDv3 (PSARC 2006/406) case but has not been implemented. Currently, DLPI applications in ON create a DLPI request message and wait for a reply message as an acknowledgment or error. All the proposed routines above will 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 proposes 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) implement their own utility functions to compose DLSAP addresses. This library proposes to handle this DLPI-specific detail internally. Thus, when requesting data to be sent over a DLPI link, applications will | simply provide the physical address and dlpi_send() will internally handle the composition of a full DLSAP address. Similarly, dlpi_recv() will handle decomposition of the DLSAP address and provide 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, we propose to provide dlpi_fd(). This routine will return 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. 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 proposed 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 proposed 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 will set 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 will be 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 proposes to provide 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 proposed 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 proposes to provide a type argument to dlpi_set_physaddr() symmetrical to dlpi_get_physaddr(). At present the only supported type will be 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 propose to 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 will allow DLPI consumers to specify the priority range for each data message sent (see 1.7.b), it does not propose to 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 will be providing. 2.1 Interface Table: +-------------------------------------------------------------------------+ | Interfaces Exported | |----------------------|----------------------|---------------------------| | Interface | Classification | manpages | |----------------------|----------------------|---------------------------| | libdlpi.so | Evolving | | | | Evolving | | | dlpi_handle_t | Evolving | | | dlpi_open | Evolving | dlpi_open(3DLPI) | | dlpi_close | Evolving | dlpi_close(3DLPI) | | dlpi_info | Evolving | dlpi_info(3DLPI) | | dlpi_bind | Evolving | dlpi_bind(3DLPI) | | dlpi_unbind | Evolving | dlpi_unbind(3DLPI) | | dlpi_enabmulti | Evolving | dlpi_enabmulti(3DLPI) | | dlpi_disabmulti | Evolving | dlpi_disabmulti(3DLPI) | | dlpi_promiscon | Evolving | dlpi_promiscon(3DLPI) | | dlpi_promiscoff | Evolving | dlpi_promiscoff(3DLPI) | | dlpi_get_physaddr | Evolving | dlpi_get_physaddr(3DLPI) | | dlpi_set_physaddr | Evolving | dlpi_set_physadrr(3DLPI) | | dlpi_mactype | Evolving | dlpi_mactype(3DLPI) | | dlpi_send | Evolving | dlpi_send(3DLPI) | | dlpi_recv | Evolving | dlpi_recv(3DLPI) | | dlpi_linkname | Evolving | dlpi_linkname(3DLPI) | | dlpi_fd | Evolving | dlpi_fd(3DLPI) | | dlpi_set_timeout | Evolving | dlpi_set_timeout(3DLPI) | | dlpi_strerror | Evolving | dlpi_strerror(3DLPI) | | | | | | DLPI_PASSIVE | Evolving | dlpi_open(3DLPI) | | DLPI_RAW | Evolving | dlpi_open(3DLPI) | | DLPI_NATIVE | Evolving | dlpi_open(3DLPI) | | DLPI_ANY_SAP | Evolving | dlpi_bind(3DLPI) | | DLPI_DEF_TIMEOUT | Evolving | dlpi_set_timeout(3DLPI) | | DLPI_LINKNAME_MAX | Evolving | dlpi_info(3DLPI) | | DLPI_PHYSADDR_MAX | Evolving | dlpi_info(3DLPI), | | | | dlpi_get_physaddr(3DLPI),| | | | dlpi_send(3DLPI), | | | | dlpi_recv(3DLPI) | | | | | | dlpi_info_t | Evolving | dlpi_info(3DLPI) | | dlpi_recvinfo_t | Evolving | dlpi_recv(3DLPI) | | dlpi_addrtype_t | Evolving | dlpi_recv(3DLPI) | | | dlpi_sendinfo_t | Evolving | 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 will remain 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 will remain Consolidation Private and | will be 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 will continue 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 will cause 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 will cause 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. 3 Appendices Appendix A: Changes from the old Consolidation Private library DLPI Handles ------------ Unlike in the old Consolidation Private library, where file descriptors were the method of communicating with the DLPI link, DLPI handles are used in this proposed library. Stateless to Stateful --------------------- With the implementation of DLPI handles the interfaces proposed will maintain a state where as the interfaces in the old Consolidation Private library are stateless. Only Connectionless mode ------------------------ This proposed library will only support connectionless mode where as the old Consolidation Private library supported a number of fields for connection-oriented mode but lacked the interfaces to be fully functional. DLPI Style 1/ Style 2 --------------------- The open routine proposed in this library opens a DLPI link without having to know the provider style. As a consequence to the fact that attaching to a PPA is handled by the proposed library routines, the DL_UNATTACHED state is hidden to the DLPI consumer. The dlpi_if_open() open routine in the Consolidation Private library allowed a DLPI link to be forced to be opened with style 2. | DLPI attach/detach | ------------------ | The open routines proposed in this library handles both DL_STYLE1 and | DL_STYLE2 DLPI links, thus DLPI applications do not have to explicitly | attach/detach to a physical point of attachment. Based on the usage of | attach by DLPI applications in the ON consolidation, it is not necessary | to allow applications to explicitly attach to any PPA. Thus, to discourage | this option, dlpi_attach() provided in the old Consolidation Private library | will be removed and libdlpi will handle the attach internally. By not | providing these routines as public routines, the library will have control | over when DLPI links need to be explicitly attached. | | We also found that dlpi_detach was only being used to explicitly detach a PPA| that had already been attached during the open routine so that ifconfig could| allow kernel modules to do the attach themselves. We are introducing a | DLPI_NOATTACH flag, which if set will not attach to a PPA during the open | routine if the flag is set. See 2.2.2 for further details. | Simplified routines ------------------- Due to the fact that the library will only support connectionless mode, it allows the library to provide routines with uncluttered arguments. Routines like dlpi_bind() and dlpi_info() in the old Consolidation Private library contained arguments that in common usage would all be set as NULL by DLPI consumers. In the case of rarely-used arguments, those arguments have been encapsulated into a single structure argument, like dlpi_info_t, dlpi_send_t and dlpi_recv_t. Timeout value ------------- Instead of providing a timeout value in each libdlpi routine the timeout value has been centralized in this proposed library. A dlpi_set_timeout() routine is provided if application need to modify the default timeout value set by the proposed library. DLSAP address information ------------------------- Unlike the old Consolidation Private library, the link-layer physical address and broadcast address can be specified without having to decompose/compose the DLSAP address in the proposed library routines. Routine to send/receive data ---------------------------- Data transfer being the essence of DLPI this library proposes to provide routines to send and receive data in both raw and normal mode. Error handling -------------- Routines proposed in the library will return error codes and provide a human readable error printing routine.