This chapter describes the
ifnet
STREAMS module and
dlb
STREAMS pseudodriver communication
bridges.
Before reading it, you should be familiar with basic STREAMS and
sockets concepts and have reviewed the information in
Chapter 4
and
Chapter 5.
The operating system's network programming environment supports the
STREAMS and sockets frameworks for network programming.
However, there is
no native communication path at the data link layer between the two frameworks.
The term
coexistence
refers to the ability to exchange data between the sockets and
STREAMS frameworks.
The term
communication bridge
refers
to the software (ifnet
STREAMS module or the
dlb
STREAMS pseudodriver) that enables the two frameworks to exchange
data at the data link layer.
Programs written to sockets and STREAMS must intercommunicate for the following reasons:
A system cannot have two drivers for the same device.
Programs may need to access STREAMS-based device drivers from BSD protocol stacks or, conversely, may need to access BSD device drivers from STREAMS-based protocol stacks.
For example, if your system is running a STREAMS device driver and you
have an application that uses the TCP/IP implemented on Tru64 UNIX, which
is sockets-based, you need a path by which the data gets from the sockets-based
protocols stack to the STREAMS device driver and back again.
The
ifnet
STREAMS module allows an application using TCP/IP to exchange
data with a STREAMS device driver.
Section 8.1
describes
the
ifnet
STREAMS module.
Conversely, if you have a STREAMS protocol stack implemented on your
system but want to use the BSD device driver implemented on Tru64 UNIX,
you need a path by which the data gets from the STREAMS protocol stack to
the BSD device driver and back again.
The
dlb
STREAMS pseudodriver
allows the STREAMS protocol stack to route its data to the BSD device driver.
Section 8.2
describes the
dlb
STREAMS
pseudodriver.
8.1 Bridging STREAMS Drivers to Sockets Protocol Stacks
The
ifnet
STREAMS module is a communication bridge that allows STREAMS
network drivers to access sockets-based network protocols.
The
ifnet
STREAMS module functions like any other STREAMS module, being pushed
on the Stream above the STREAMS device driver.
Once it is on the Stream, it
handles all of the translation required between the DLPI interface of the
STREAMS driver and the BSD
ifnet
layer.
The
ifnet
STREAMS module exports both standard STREAMS interfaces as well
as
ifnet
layer interfaces.
Note that STREAMS network drivers can also continue to use STREAMS-based
network protocols while using the
ifnet
STREAMS module.
Figure 8-1
highlights the
ifnet
STREAMS module
and shows its place in the network programming environment.
Figure 8-1: The ifnet STREAMS module
This
section describes how to prepare the system running the STREAMS driver to
use the
ifnet
STREAMS module.
Note
The
ifnet
STREAMS module only supports Ethernet STREAMS device drivers.
This section also lists the DLPI primitives that the STREAMS driver
must support in order for the
ifnet
STREAMS module to operate
successfully.
8.1.1.1 Using the ifnet STREAMS Module
If your device driver supports the
primitives listed in
Section 8.1.1.2, no source code changes
to either the driver or STREAMS kernel code are needed for you to use the
ifnet
STREAMS module.
To use the
ifnet
STREAMS module, the STRIFNET and DLPI options must be configured
in your kernel and you must set up STREAMS for the driver.
The STRIFNET and DLPI options may have been configured into your system at installation time. (For information on configuring options during installation, see the Installation Guide.) You can check to see if the options are configured, by issuing the following command:
#
/usr/sbin/strsetup -c
If
ifnet
and
dlb
appear in the
Name column, the options are configured in your kernel.
If not, you must add
them using the
doconfig
command.
To configure STRIFNET and DLPI into your kernel, perform the following steps:
Log in as superuser.
Enter the
/usr/sbin/doconfig
command.
If
you have a customized configuration file, you should use the
/usr/sbin/doconfig
-c
command.
For more information, see
doconfig
(8).
Enter a name for the kernel configuration file. It should be the name of your system in uppercase letters, and will probably be the default provided in square brackets ([]); for example:
Enter a name for the kernel configuration file. [HOST1]:
[RETURN]
Enter
y
when the system asks whether you
want to replace the system configuration file; for example:
A configuration file with the name 'HOST1' already exists.
Do you want to replace it? (y/n) [n]:
y
Saving /sys/conf/HOST1 as /sys/conf/HOST1.bck
*** KERNEL CONFIGURATION AND BUILD PROCEDURE ***
Select the options you want to include in your kernel.
Note
The STRIFNET and DLPI options are not available from this menu. To include these options, you must edit the configuration file, as shown in the following step.
Add DLPI and STRIFNET to the options section of the kernel configuration file.
Enter
y
when the system asks whether you want to
edit the kernel configuration file.
The
doconfig
command
allows you to edit the configuration file with the
ed
editor.
For information about using the
ed
editor, see
ed
(1).
The following
ed
editing session shows how to add
the DLPI and STRIFNET options to the kernel configuration file for
host1
.
Note that the number of the line after which you append the
new lines can differ between kernel configuration files:
Do you want to edit the configuration file? (y/n) [n]:
y
Using ed to edit the configuration file. Press return when ready,
or type 'quit' to skip the editing session:
2153
48a
options DLPI
options STRIFNET
.
1,$w
2185
q
*** PERFORMING KERNEL BUILD ***
After the new kernel is built, you must move it from the directory
where
doconfig
places it to the root directory (/
) and reboot your system.
When you reboot, the
strsetup -i
command runs
automatically, and creates the device special files for any new STREAMS modules.
Run the
strsetup -c
command to verify
that the device is configured properly.
The following example shows the output
from the
strsetup -c
command:
#
/usr/sbin/strsetup -c
STREAMS Configuration Information...Thu Nov 9 08:38:17 1995 Name Type Major Module ID ---- ---- ----- --------- clone 32 0 dlb device 52 5010 dlpi device 53 800 kinfo device 54 5020 log device 55 44 nuls device 56 5001 echo device 57 5000 sad device 58 45 pipe device 59 5304 xtisoUDP device 60 5010 xtisoTCP device 61 5010 xtisoUDP+ device 62 5010 xtisoTCP+ device 63 5010 ptm device 64 7609 pts device 6 7608 bba device 65 24880 lat device 5 5 pppif module 6002 pppasync module 6000 pppcomp module 6001 bufcall module 0 ifnet module 5501 null module 5002 pass module 5003 errm module 5003 ptem module 5003 spass module 5007 rspass module 5008 pipemod module 5303 timod module 5006 tirdwr module 0 ldtty module 7701 Configured devices = 16, modules = 15
For more detailed information on reconfiguring your kernel or the
doconfig
command see the
System Administration
manual and
doconfig
(8).
To set up STREAMS for the driver you must do the following:
Write an application program similar to the following:
/* * Application program to set up the "pifnet" streams for IP * and ARP. This must be run prior to ifconfig */ #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <stropts.h> #include <sys/ioctl.h> #include <signal.h> #include "dlpihdr.h" #define IP_PROTOCOL 0x800 #define ARP_PROTOCOL 0x806 #define PIFNET_IOCTL_UNIT 1236 main(argc, argv) int argc; char *argv[]; { extern char *getenv(); char *p; short unit = 0; char devName[256]; if (argc != 3) usage(); strcpy(devName, argv[1]); unit = atoi(argv[2]); sigignore(SIGHUP); setupStream(devName, unit, IP_PROTOCOL); setupStream(devName, unit, ARP_PROTOCOL); /* * sleep forever to keep the Streams alive. */ if (fork()) /* detach */ exit(); pause(); } usage() { fprintf(stderr, "usage: pifnetd devname unit-number\n"); exit(1); } setupStream(devName, unit, serviceClass) char *devName; short unit; u_long serviceClass; { int fd, status; dl_bind_req_t bindreq; dl_bind_ack_t bindack; int flags; struct strioctl str; struct strbuf pstrbufctl, pstrbufdata, gstrbufctl, \ gstrbufdata; char ebuf[256]; /* * build the stream */ fd = open(devName, O_RDWR, 0); if (fd < 0) { sprintf(ebuf, " open '%s' failed", devName); perror(ebuf); exit(1); } if (ioctl(fd, I_PUSH, "ifnet") < 0) { sprintf(ebuf, " ioctl I_PUSH failed"); perror(ebuf); exit(1); } /* * tell pifnet the unit number for the device */ str.ic_cmd = PIFNET_IOCTL_UNIT; str.ic_timout = 15; str.ic_len = sizeof (short); str.ic_dp = (char *) &unit; status = ioctl(fd, I_STR, &str); if (status < 0) { sprintf(ebuf, " %s - ioctl"); perror(ebuf); exit(1); } /* * bind the stream to a protocol */ bindreq.dl_primitive = DL_BIND_REQ; bindreq.dl_sap = serviceClass; bindreq.dl_max_conind = 0; bindreq.dl_service_mode = DL_CLDLS; bindreq.dl_conn_mgmt = 0; bindreq.dl_xidtest_flg = 0; pstrbufctl.len = sizeof(dl_bind_req_t); pstrbufctl.buf = (void *)&bindreq; pstrbufdata.buf = (char *)0; pstrbufdata.len = -1; pstrbufdata.maxlen = 0; status = putmsg(fd, &pstrbufctl, (struct strbuf *)0, 0); if (status < 0) { perror("putmsg"); exit(1); } /* * Check requested binding */ gstrbufctl.buf = (char *)&bindack; gstrbufctl.maxlen = sizeof(dl_bind_ack_t); gstrbufctl.len = 0; status = getmsg(fd, &gstrbufctl, (struct strbuf *)0, &flags); if (status < 0) { perror("getmsg"); exit(1); } if (bindack.dl_primitive != DL_BIND_ACK) { errno = EPROTO; perror(" DL_BIND_ACK"); exit(1); } }
In this sample application the driver's name is
/dev/streams/ln
.
The application creates two Streams; one for the
Internet Protocol (IP) and one for the Address Resolution Protocol (ARP).
After setting up the Streams, the application must keep running, using the
pause
command, in order to keep the Streams alive.
Note that, if the driver is a style-2 driver, you must add a DL_ATTACH_REQ
primitive to the application program.
For more information about the
DL_ATTACH_REQ
primitive or style-2 drivers, see the DLPI specification
in
/usr/share/doclib/dlpi/dlpi.ps
.
Generate an executable file for the application. Compile, link, and debug the program until it runs without errors.
Move the executable into a directory that is convenient for you.
The executable can be located in any directory.
Add a line invoking the program to the
/sbin/init.d/inet
file.
Although you can manually start the program each time you reboot, it
is easiest to add a line to the
/sbin/init.d/inet
file
to run it automatically when the system reboots.
Be sure to add the line before
the system's
ifconfig
lines.
In the following example, each time the system reboots, the
/sbin/init.d/inet
file runs a program called
run_ifnet
, which resides in the
/etc
directory:
.
.
.
# # Enable network # case $1 in echo "Configuring network" /sbin/hostname $HOSTNAME echo "hostname: \c" /sbin/hostname if [ "$NETDEV_0" != '' ]; then echo >/tmp/ifconfig_"$NETDEV_0".tmp# place command invoking executable BEFORE \
ifconfig lines
/etc/run_ifnet
/sbin/ifconfig $NETDEV_0 $IFCONFIG_0 > \ /tmp/ifconfig_"$NETDEV_0".tmp 2>&1 if [ $? != 0 ]; then ERROR=`cat /tmp/ifconfig_"$NETDEV_0".tmp` if [ "$ERROR" = "$ERRSTRING" ]; then /sbin/ifconfig $NETDEV_0 up else echo "$0: $ERROR" fi fi rm /tmp/ifconfig_"$NETDEV_0".tmp fi
.
.
.
Reboot the system.
Use the
/usr/sbin/shutdown -r
command to shut
down your system and have it reboot automatically; for example:
#
/usr/sbin/shutdown -r now
8.1.1.2 Data Link Provider Interface Primitives
Note that the STREAMS device driver
can be a style-1 or a style-2 DLPI provider, as described in the Data Link
Provider Interface specification, which is located in
/usr/share/doclib/dlpi/dlpi.ps
.
Note that you must have the OSFPGMRnnn
subset installed to access the DLPI specification on line.
The driver must support the following DLPI primitives. For detailed information about these primitives and how to use them, see the DLPI specification:
DL_PHYS_ADDR_REQ/DL_PHYS_ADDR_ACK
DL_BIND_REQ/DL_BIND_ACK
DL_UNBIND_REQ
DL_UNITDATA_REQ/DL_UNITDATA_IND/DL_UDERROR_IND
DL_OK_ACK/DL_ERROR_ACK
8.2 Bridging BSD Drivers to STREAMS Protocol Stacks
The
dlb
STREAMS pseudodevice
driver allows you to bridge BSD-style device drivers and STREAMS protocol
stacks.
The STREAMS pseudodevice driver is the Stream end in a Stream wanting
to communicate with BSD-based drivers.
The STREAMS pseudodevice driver provided
with this operating system has two interfaces, a subset of the DLPI interface
that communicates with STREAMS protocol stacks and another interface that
accesses the
ifnet
layer interface of the sockets framework.
Figure 8-2
highlights the
dlb
STREAMS pseudodriver and shows its place in the network programming environment.
Figure 8-2: DLPI STREAMS Pseudodriver
8.2.1 Supported DLPI Primitives and Media Types
The
dlb
STREAMS pseudodriver supports the following
connectionless mode primitive and media types.
For detailed information about
these primitives and how to use them, see the Data Link Provider Interface
specification which is in
/usr/share/doclib/dlpi/dlpi.ps
.
DL_ATTACH_REQ/DL_DETACH_REQ/DL_OK_ACK
DL_BIND_REQ/DL_BIND_ACK/DL_UNBIND_REQ
DL_ENABMULTI_REQ/DL_DISABLMULTI_REQ
DL_PROMISCON_REQ/DL_PROMISCONOFF_REQ
DL_PHYS_ADDR_REQ/DL_PHYS_ADDR_ACK
DL_SET_PHYS_ADDR_REQ
DL_UNITDATA_REQ/DL_UNITDATA_IND
DL_SUBS_BIND_REQ/DL_SUBS_BIND_ACK
DL_SUBS_UNBIND_REQ/DL_SUBS_UNBIND_ACK
The Ethernet bus (DL_ETHER
) is the
media type supported by the STREAMS pseudodriver.
8.2.2 Using the STREAMS Pseudodriver
To use
the
dlb
STREAMS pseudodriver the DLPI option must be configured
into your kernel.
The DLPI option may have been configured into your system
at installation time.
You can check to see if the DLPI option is configured by issuing the following command:
#
/usr/sbin/strsetup -c
If
dlb
appears in the Name column, the option is
configured in your kernel.
If not, you must add it using the
doconfig
command.
For a description of how to reconfigure your kernel with the
doconfig
command, see
Section 8.1.1.1.
For more information on reconfiguring your kernel or the
doconfig
command see the
System Administration
manual and
doconfig
(8).
For
information on configuring options during installation, see the
Installation Guide.