HP Hewlett Packard Network Card B2355 90138 User Manual

LLA to DLP I Migr a tion Gu id e  
Ed ition 4  
B2355-90138  
HP 9000 Netw or k in g  
E0497  
Printed in: United States  
© Copyright 1997 Hewlett-Packard Company.  
 
©copyright 1980, 1984, 1986 Novell, Inc. ©copyright 1986-1992 Sun  
Microsystems, Inc. ©copyright 1985-86, 1988 Massachusetts Institute of  
Technology. ©copyright 1989-93 The Open Software Foundation, Inc.  
©copyright 1986 Digital Equipment Corporation. ©copyright 1990  
Motorola, Inc. ©copyright 1990, 1991, 1992 Cornell University  
©copyright 1989-1991 The University of Maryland ©copyright 1988  
Carnegie Mellon University  
Tr a d em a r k Notices UNIX is a registered trademark in the United  
States and other countries, licensed exclusively through X/Open  
Company Limited.  
X Window System is a trademark of the Massachusetts Institute of  
Technology.  
MS-DOS and Microsoft are U.S. registered trademarks of Microsoft  
Corporation.  
OSF/Motif is a trademark of the Open Software Foundation, Inc. in the  
U.S. and other countries.  
3
 
4
 
Con ten ts  
1. LLA to DLP I Migr a tion  
Device Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .13  
ioctl Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14  
Transmitting Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16  
Receiving Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17  
2. LLA a n d DLP I Exa m p le P r ogr a m s  
DLPI Example Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21  
LLA Example Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .32  
5
 
Con ten ts  
6
 
P r in tin g Histor y  
The manual printing date and part number indicate its current edition.  
The printing date will change when a new edition is printed. Minor  
changes may be made at reprint without changing the printing date. the  
manual part number will change when extensive changes are made.  
Manual updates may be issued between editions to correct errors or  
document product changes. To ensure that you receive the updated or  
new editions, you should subscribe to the appropriate product support  
service. See your HP sales representative for details.  
First Edition: February 1991  
Second Edition: July 1992  
Third Edition: January 1995  
Fourth Edition: April 1997  
7
 
8
 
P r efa ce  
Link Level Access for the HP 9000 (LLA/9000) is a Hewlett-Packard data  
communications and data management product supported on earlier  
HP-UX releases. The Data Link Provider Interface (DLPI) is an industry  
standard which defines a STREAMS-based interface to the Logical Link  
Control (LLC) 802.3 services.  
The LLA to DLPI Migration Guide provides information about migrating  
LLA programs to DLPI programs.  
This manual is organized as follows:  
Chapter 1  
Chapter 2  
LLA to DLP I Migr a tion provides information about  
migrating programs from the HP proprietary LLA to  
the industry standard DLPI.  
LLA a n d DLP I Exa m p le P r ogr a m s includes  
example programs that compare LLA and DLPI.  
9
 
10  
 
1
LLA to DLP I Migr a tion  
11  
 
LLA to DLPI Migration  
As part of Hewlett-Packards movement toward industry standard  
networking, HP has discontinued the LLA/9000 product with the HP-UX  
10.30 release. HP recommends that you migrate all existing applications  
that use LLA to the industry standard Data Link Provider Interface  
(DLPI). HP provides DLPI with the LAN/9000 product.  
Before you begin the process of migrating your application, you may need  
to review the DLPI Programmers Guide.  
The following information explains the basic differences between LLA  
and DLPI. This information is the basis for performing migration.  
12  
Chapter1  
 
LLA to DLPI Migration  
Device Files  
Device Files  
Device files are used to identify the LAN driver, Ethernet/IEEE 802.3  
interface card, and protocol to be used. Each LAN driver/interface card  
and protocol combination (Ethernet or IEEE 802.3) is associated with a  
device file.  
A network device file is like any other HP-UX device file. When you write  
to a network device file after opening it, the data goes out on the  
network, just as when you write to a disk drive device file, the data goes  
out onto the disk.  
By convention, device files are kept in a directory called /dev. When the  
LAN/9000 product is installed, several special device files are created.  
Among these files are the network device files associated with the LAN  
interface. If default names are used during installation, these files are  
called /dev/lan0and /dev/ether0for IEEE 802.3 and Ethernet,  
respectively.  
LLA requires a separate device file for every LAN interface in the  
system. This device file is used by LLA to uniquely identify a specific  
device (e.g. /dev/lan0).  
DLPI only requires one device file (/dev/dlpi) to access all supported  
LAN interfaces. In addition, there are other device files (/dev/dlpiX,  
where Xis 0-100), used by DLPI, to access all supported LAN interfaces.  
The difference between /dev/dlpiand /dev/dlpiXis clone vs.  
non-cloneable devices. Basically, cloneable devices give you a separate  
stream for each open request.  
Non-cloneable devices only give you one stream no matter how many  
times you open the device. All of the LAN interfaces supported by HP  
DLPI support both cloneable and non-cloneable access.  
Chapter 1  
13  
 
LLA to DLPI Migration  
ioctl Requests  
ioctl Requ ests  
All general control requests (i.e. protocol logging, destination addresses,  
multicast addresses, etc.) for LLA are issued via the ioctlsystem call.  
The HP-UX ioctlcall is used to construct, inspect, and control the  
network environment in which an LLA application will operate. All LLA  
applications must use the ioctlcall to configure source and destination  
addresses before data can be sent or received using the HP-UX readand  
writecalls.  
ioctlrequests are used in DLPI only for device specific control  
requests. These ioctlrequests are not interpreted by DLPI, but passed  
directly to the driver for processing. All general control requests in DLPI  
are defined with a standard DLPI 2.0 primitive or extension. These  
primitives are passed to DLPI via the putmsgsystem call only.  
All of the standard DLPI primitives are defined in <sys/dlpi.h>. The  
DLPI Programmers Guide provides detailed descriptions of all the  
primitives. All HP DLPI extensions (denoted in the following table with  
an *) are defined in <sys/dlpi_ext.h>.  
Table 1-1 lists LLA ioctl request types and their corresponding DLPI  
primitives.  
Ta ble 1-1  
LLA ioctls a n d Cor r esp on d in g DLP I P r im itives  
LLA ioctl (r eq typ e)  
DLP I P r im itive  
DL_BIND_REQ or  
LOG_TYPE_FIELD  
DL_SUBS_BIND_REQ  
LOG_SSAP  
LOG_DSAP  
DL_BIND_REQ or  
DL_SUBS_BIND_REQ  
Not required with DLPI. The destination  
address is specified with each data  
request (see Transmitting data).  
LOG_DEST_ADDR  
Not required with DLPI. The destination  
address is specified with each data  
request (see Transmitting data).  
LOG_READ_CACHE  
Not defined  
14  
Chapter1  
 
LLA to DLPI Migration  
ioctl Requests  
LLA ioctl (r eq typ e)  
DLP I P r im itive  
LOG_READ_TIMEOUT  
LLA_SIGNAL_MASK  
FRAME_HEADER  
Not defined  
Not defined  
Frame headers are delivered with each  
individual packet via the control portion  
of the message.  
LOCAL_ADDRESS  
DEVICE_STATUS  
DL_PHYS_ADDR_REQ  
DL_HP_HW_STATUS_REQ*  
MULTICAST_ADDRESSES DL_HP_MULTICAST_LIST_REQ*  
MULTICAST_ADDR_LIST  
RESET_STATISTICS  
READ_STATISTICS  
DL_HP_MULTICAST_LIST_REQ*  
DL_HP_RESET_STATS_REQ*  
DL_GET_STATISTICS_REQ. This  
primitive returns mib and extended mib  
statistics for the device in one request.  
LOG_CONTROL  
Not required with DLPI. The control  
value (if any) is determined from the  
primitive.  
RESET_INTERFACE  
ENABLE_BROADCAST  
DISABLE_BROADCAST  
ADD_MULTICAST  
DL_HP_HW_RESET_REQ*  
Not defined  
Not defined  
DL_ENABMULTI_REQ  
DL_DISABMULTI_REQ  
DELETE_MULTICAST  
Chapter 1  
15  
 
LLA to DLPI Migration  
Transmitting Data  
Tr a n sm ittin g Da ta  
LLA requires the user to log a destination address (LOG_DEST_ADDR)  
and a destination service access point (LOG_DSAP) prior to sending any  
data.  
DLPI requires the user to specify the destination address and  
destination service access point (dsap) as part of the data transfer  
request. The combination of destination MAC address and dsap is  
referred to as the DLSAP address.  
The DLSAP address format is basically the destination MAC address  
followed by the LLC protocol value. A complete description of the DLSAP  
address format is described in the DLPI Programmer's Guide.  
LLA supports the writesystem call for sending data requests.  
DLPI only supports the putmsgsystem call for sending data over RAW  
(see the DLPI Programmer's Guide) and connectionless mode streams.  
The writesystem call is only supported over connection oriented  
streams in the DATA_XFER state (i.e. a connection must be established).  
16  
Chapter1  
 
LLA to DLPI Migration  
Receiving Data  
Receivin g Da ta  
LLA does not automatically return LLC header information when  
packets are read by the user. The user is required to issue a separate  
control request (FRAME_HEADER) to get the LLC header information  
for the last packet received.  
DLPI returns the LLC header information in the control portion of each  
individually received packet (i.e. DL_UNITDATA_IND, DL_XID_IND,  
DL_TEST_IND, etc). The user is not required to issue a separate control  
request to get LLC header information.  
LLA only allows a maximum of 16 packets (for normal users and 64 for  
super users) to be queued before it starts dropping data.  
DLPI will read as many packets as possible until both the stream head  
read queue (default is about 10k bytes) and DLPI read queue (default is  
about 60K bytes) fill. When both these queues are full, DLPI will begin  
dropping data until the queues start draining.  
Chapter 1  
17  
 
LLA to DLPI Migration  
Receiving Data  
18  
Chapter1  
 
2
LLA a n d DLP I Exa m p le  
P r ogr a m s  
This chapter contains two example programs.  
19  
 
LLA and DLPI Example Programs  
The first example shows a data transfer program using DLPI. The  
second example shows the same type of program using LLA for  
comparison.  
20  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
DLP I Exa m p le P r ogr a m  
/*********************************************************************  
(C) COPYRIGHT HEWLETT-PACKARD COMPANY 1992. ALL RIGHTS  
RESERVED. NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED,  
REPRODUCED, OR TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT  
THE PRIOR WRITTEN CONSENT OF HEWLETT PACKARD COMPANY  
*********************************************************************/  
/*********************************************************************  
The main part of this program is composed of two parts.  
The first part demonstrates data transfer over a connectionless  
stream with LLC SAP headers. The second part of this program  
demonstrates data transfer over a connectionless stream with  
LLC SNAP headers.  
*********************************************************************/  
#include <stdio.h>  
#include <fcntl.h>  
#include <memory.h>  
#include <sys/types.h>  
#include <sys/stream.h>  
#include <sys/stropts.h>  
#include <sys/dlpi.h>  
#include <sys/dlpi_ext.h>  
#define SEND_SAP  
#define RECV_SAP  
#define SNAP_SAP  
0x80  
0x82  
0xAA  
/* sending SAP */  
/* receiving SAP */  
/* SNAP SAP */  
/*********************************************************************  
SNAP protocol values.  
*********************************************************************/  
u_char SEND_SNAP_SAP[5] = {0x50, 0x00, 0x00, 0x00, 0x00};  
u_char RECV_SNAP_SAP[5] = {0x60, 0x00, 0x00, 0x00, 0x00};  
/*********************************************************************  
global areas for sending and receiving messages  
*********************************************************************/  
#define AREA_SIZE  
5000 /* bytes; big enough for largest possible msg */  
#define LONG_AREA_SIZE (AREA_SIZE / sizeof(u_long)) /* AREA_SIZE / 4 */  
u_long ctrl_area[LONG_AREA_SIZE];/* for control messages */  
u_long data_area[LONG_AREA_SIZE];/* for data messages */  
struct strbuf ctrl_buf = {  
AREA_SIZE,  
0,  
/* maxlen = AREA_SIZE */  
/* len gets filled in for each message */  
/* buf = control area */  
ctrl_area  
};  
Chapter 2  
21  
 
LLA and DLPI Example Programs  
DLPI Example Program  
struct strbuf data_buf = {  
AREA_SIZE,  
0,  
/* maxlen = AREA_SIZE */  
/* len gets filled in for each message */  
/* buf = data area */  
data_area  
};  
/*********************************************************************  
get the next message from a stream; get_msg() returns one of the  
following defines  
*********************************************************************/  
#define GOT_CTRL  
#define GOT_DATA  
#define GOT_BOTH  
1
2
3
/* message has only a control part */  
/* message has only a data part */  
/* message has control and data parts */  
int  
get_msg(fd)  
int  
fd;  
/* file descriptor */  
{
int  
int  
/*  
flags = 0;  
result = 0;  
/* 0 ---> get any available message */  
/* return value */  
zero first byte of control area so the caller can call check_ctrl  
without checking the get_msg return value; if only data was  
in the message and the user was expecting control or control +  
data, then when he calls check_ctrl it will compare the expected  
primitive zero and print information about the primitive  
that it got.  
*/  
ctrl_area[0] = 0;  
/* call getmsg and check for an error */  
if(getmsg(fd, &ctrl_buf, &data_buf, &flags) < 0) {  
printf(”error: getmsg failed, errno = %d\n”, errno);  
exit(1);  
}
if(ctrl_buf.len > 0) {  
result |= GOT_CTRL;  
}
if(data_buf.len > 0) {  
result |= GOT_DATA;  
}
return(result);  
}
/*********************************************************************  
check that control message is the expected message  
*********************************************************************/  
void  
check_ctrl(ex_prim)  
int  
ex_prim; /* the expected primitive */  
{
dl_error_ack_t*err_ack = (dl_error_ack_t *)ctrl_area;  
/* did we get the expected primitive? */  
if(err_ack->dl_primitive != ex_prim) {  
22  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
/* did we get a control part */  
if(ctrl_buf.len) {  
/* yup; is it an ERROR_ACK? */  
if(err_ack->dl_primitive == DL_ERROR_ACK) {  
/* yup; format the ERROR_ACK info */  
printf(”error: expected primitive  
0x%02x, ”, ex_prim);  
printf(”got DL_ERROR_ACK\n”);  
printf(” dl_error_primitive =  
0x%02x\n”, err_ack->  
dl_error_primitive);  
printf(” dl_errno = 0x%02x\n”,  
err_ack->dl_errno);  
printf(” dl_unix_errno = %d\n”,  
err_ack->dl_unix_errno);  
exit(1);  
} else {  
/*  
didn't get an ERROR_ACK either; print  
whatever primitive we did get  
*/  
printf(”error: expected primitive  
0x%02x, ”, ex_prim);  
printf(”got primitive 0x%02x\n”,  
err_ack->dl_primitive);  
exit(1);  
}
} else {  
/* no control; did we get data? */  
if(data_buf.len) {  
/* tell user we only got data */  
printf(”error: check_ctrl found only  
data\n”);  
exit(1);  
} else {  
/*  
no message???; well, it was probably an  
interrupted system call  
*/  
printf(”error: check_ctrl found no  
message\n”);  
exit(1);  
}
}
}
}
/*********************************************************************  
put a message consisting of only a data part on a stream  
*********************************************************************/  
void  
put_data(fd, length)  
int  
int  
fd;  
/* file descriptor */  
length;  
/* length of data message */  
{
/* set the len field in the strbuf structure */  
Chapter 2  
23  
 
LLA and DLPI Example Programs  
DLPI Example Program  
data_buf.len = length;  
/* call putmsg and check for an error */  
if(putmsg(fd, 0, &data_buf, 0) < 0) {  
printf(”error: put_data putmsg failed, errno = %d\n”, errno);  
exit(1);  
}
}
/*********************************************************************  
put a message consisting of only a control part on a stream  
*********************************************************************/  
void  
put_ctrl(fd, length, pri)  
int  
int  
int  
fd;  
/* file descriptor */  
length;  
pri;  
/* length of control message */  
/* priority of message: either 0 or RS_HIPRI */  
{
/* set the len field in the strbuf structure */  
ctrl_buf.len = length;  
/* call putmsg and check for an error */  
if(putmsg(fd, &ctrl_buf, 0, pri) < 0) {  
printf(”error: put_ctrl putmsg failed, errno = %d\n”,  
errno);  
exit(1);  
}
}
/*********************************************************************  
put a message consisting of both a control part and a control  
part on a stream  
*********************************************************************/  
void  
put_both(fd, ctrl_length, data_length, pri)  
int  
int  
int  
int  
fd;  
/* file descriptor */  
ctrl_length;  
data_length;  
pri;  
/* length of control part */  
/* length of data part */  
/* priority of message: either 0  
or RS_HIPRI */  
{
/* set the len fields in the strbuf structures */  
ctrl_buf.len = ctrl_length;  
data_buf.len = data_length;  
/* call putmsg and check for an error */  
if(putmsg(fd, &ctrl_buf, &data_buf, pri) < 0) {  
printf(”error: put_both putmsg failed, errno = %d\n”,  
errno);  
exit(1);  
}
}
/*********************************************************************  
open the DLPI cloneable device file, get a list of available  
PPAs, and attach to the first PPA; returns a file descriptor  
for the stream  
*********************************************************************/  
24  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
int  
attach() {  
int  
int  
fd;  
ppa;  
/* file descriptor */  
/* PPA to attach to */  
dl_hp_ppa_req_t  
*ppa_req = (dl_attach_req_t *)ctrl_area;  
dl_hp_ppa_ack_t *ppa_ack = (dl_hp_ppa_ack_t *)ctrl_area;  
dl_hp_ppa_info_t *ppa_info;  
dl_attach_req_t *attach_req = (dl_attach_req_t *)ctrl_area;  
char *mac_name;  
/* open the device file */  
if((fd = open(”/dev/dlpi”, O_RDWR)) == -1) {  
printf(”error: open failed, errno = %d\n”, errno);  
exit(1);  
}
/*  
find a PPA to attach to; we assume that the first PPA on the  
remote is on the same media as the first local PPA  
*/  
/* send a PPA_REQ and wait for the PPA_ACK */  
ppa_req->dl_primitive = DL_HP_PPA_REQ;  
put_ctrl(fd, sizeof(dl_hp_ppa_req_t), 0);  
get_msg(fd);  
check_ctrl(DL_HP_PPA_ACK);  
/* make sure we found at least one PPA */  
if(ppa_ack->dl_length == 0) {  
printf(”error: no PPAs available\n”);  
exit(1);  
}
/* examine the first PPA */  
ppa_info = (dl_hp_ppa_info_t *)((u_char *)ctrl_area +  
ppa_ack->dl_offset);  
ppa = ppa_info->dl_ppa;  
switch(ppa_info->dl_mac_type) {  
case DL_CSMACD:  
case DL_ETHER:  
mac_name = ”Ethernet”;  
break;  
case DL_TPR:  
mac_name = ”Token Ring”;  
break;  
case DL_FDDI:  
mac_name = ”FDDI”;  
break;  
default:  
printf(”error: unknown MAC type in ppa_info\n”);  
exit(1);  
}
printf(”attaching to %s media on PPA %d\n”, mac_name, ppa);  
/*  
fill in ATTACH_REQ with the PPA we found, send the ATTACH_REQ,  
and wait for the OK_ACK  
*/  
attach_req->dl_primitive = DL_ATTACH_REQ;  
Chapter 2  
25  
 
LLA and DLPI Example Programs  
DLPI Example Program  
attach_req->dl_ppa = ppa;  
put_ctrl(fd, sizeof(dl_attach_req_t), 0);  
get_msg(fd);  
check_ctrl(DL_OK_ACK);  
/* return the file descriptor for the stream to the caller */  
return(fd);  
}
/*********************************************************************  
bind to a sap with a specified service mode and max_conind;  
returns the local DLSAP and its length  
*********************************************************************/  
void  
bind(fd, sap, max_conind, service_mode, dlsap, dlsap_len)  
intfd;/* file descriptor */  
intsap;/* 802.2 SAP to bind on */  
intmax_conind;/* max # connect indications to accept */  
intservice_mode;/* either DL_CODLS or DL_CLDLS */  
u_char*dlsap;/* return DLSAP */  
int*dlsap_len;/* return length of dlsap */  
{
dl_bind_req_t* bind_req = (dl_bind_req_t *)ctrl_area;  
dl_bind_ack_t* bind_ack = (dl_bind_ack_t *)ctrl_area;  
u_char*  
dlsap_addr;  
/* fill in the BIND_REQ */  
bind_req->dl_primitive = DL_BIND_REQ;  
bind_req->dl_sap = sap;  
bind_req->dl_max_conind = max_conind;  
bind_req->dl_service_mode = service_mode;  
bind_req->dl_conn_mgmt = 0;/*  
bind_req->dl_xidtest_flg = 0;  
conn_mgmt is NOT supported */  
/* user handles TEST/XID pkts */  
/* send the BIND_REQ and wait for the OK_ACK */  
put_ctrl(fd, sizeof(dl_bind_req_t), 0);  
get_msg(fd);  
check_ctrl(DL_BIND_ACK);  
/* return the DLSAP to the caller */  
*dlsap_len = bind_ack->dl_addr_length;  
dlsap_addr = (u_char *)ctrl_area + bind_ack->dl_addr_offset;  
memcpy(dlsap, dlsap_addr, *dlsap_len);  
}
/*********************************************************************  
bind to a SNAP sap via the DL_PEER_BIND, or DL_HIERARCHICAL_BIND  
subsequent bind class; returns the local DLSAP and its length  
*********************************************************************/  
void  
subs_bind(fd, snapsap, snapsap_len, subs_bind_class, dlsap, dlsap_len)  
int  
fd;  
u_char*  
int  
snapsap;  
subs_bind_class;  
*dlsap;  
u_char  
int  
{
*dlsap_len;  
26  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
dl_subs_bind_req_t *subs_bind_req = (dl_subs_bind_req_t*)ctrl_area;  
dl_subs_bind_ack_t *subs_bind_ack = (dl_subs_bind_ack_t*)ctrl_area;  
u_char *dlsap_addr;  
/* Fill in Subsequent bind req */  
subs_bind_req->dl_primitive = DL_SUBS_BIND_REQ;  
subs_bind_req->dl_subs_sap_offset = DL_SUBS_BIND_REQ_SIZE;  
subs_bind_req->dl_subs_sap_length = snapsap_len;  
subs_bind_req->dl_subs_bind_class = subs_bind_class;  
memcpy((caddr_t)&subs_bind_req[1], snapsap, snapsap_len);  
/* send the SUBS_BIND_REQ and wait for the OK_ACK */  
put_ctrl(fd, sizeof(dl_subs_bind_req_t)+snapsap_len, 0);  
get_msg(fd);  
check_ctrl(DL_SUBS_BIND_ACK);  
/* return the DLSAP to the caller */  
*dlsap_len = subs_bind_ack->dl_subs_sap_length;  
dlsap_addr = (u_char *)ctrl_area +subs_bind_ack->dl_subs_sap_offset;  
memcpy(dlsap, dlsap_addr, *dlsap_len);  
}
/*********************************************************************  
unbind, detach, and close  
*********************************************************************/  
void  
cleanup(fd)  
int  
fd;  
/* file descriptor */  
{
dl_unbind_req_t*unbind_req = (dl_unbind_req_t *)ctrl_area;  
dl_detach_req_t*detach_req = (dl_detach_req_t *)ctrl_area;  
/* unbind */  
unbind_req->dl_primitive = DL_UNBIND_REQ;  
put_ctrl(fd, sizeof(dl_unbind_req_t), 0);  
get_msg(fd);  
check_ctrl(DL_OK_ACK);  
/* detach */  
detach_req->dl_primitive = DL_DETACH_REQ;  
put_ctrl(fd, sizeof(dl_detach_req_t), 0);  
get_msg(fd);  
check_ctrl(DL_OK_ACK);  
/* close */  
close(fd);  
}
/*********************************************************************  
receive a data packet;  
*********************************************************************/  
int  
recv_data(fd)  
int  
fd;  
/* file descriptor */  
{
dl_unitdata_ind_t *data_ind = (dl_unitdata_ind_t *)ctrl_area;  
Chapter 2  
27  
 
LLA and DLPI Example Programs  
DLPI Example Program  
char  
int  
*rdlsap;  
msg_res;  
msg_res = get_msg(fd);  
check_ctrl(DL_UNITDATA_IND);  
if(msg_res != GOT_BOTH) {  
printf(”error: did not receive data part of message\n”);  
exit(1);  
}
return(data_buf.len);  
}
/*********************************************************************  
send a data packet; assumes data_area has already been filled in  
*********************************************************************/  
void  
send_data(fd, rdlsap, rdlsap_len, len)  
int  
fd;  
/* file descriptor */  
u_char* rdlsap;/* remote dlsap */  
int  
int  
rdlsap_len;/* length of rdlsap */  
len;/* length of the packet to send */  
{
dl_unitdata_req_t *data_req = (dl_unitdata_req_t *)ctrl_area;  
u_char*out_dlsap;  
/* fill in data_req */  
data_req->dl_primitive = DL_UNITDATA_REQ;  
data_req->dl_dest_addr_length = rdlsap_len;  
data_req->dl_dest_addr_offset = sizeof(dl_unitdata_req_t);  
/* copy dlsap */  
out_dlsap = (u_char *)ctrl_area + sizeof(dl_unitdata_req_t);  
memcpy(out_dlsap, rdlsap, rdlsap_len);  
put_both(fd, sizeof(dl_unitdata_req_t) + rdlsap_len, len, 0);  
}
/*********************************************************************  
print a string followed by a DLSAP  
*********************************************************************/  
void  
print_dlsap(string, dlsap, dlsap_len)  
char  
*string;  
/* label */  
/* the DLSAP */  
/* length of dlsap */  
u_char *dlsap;  
int  
dlsap_len;  
{
}
int  
i;  
printf(”%s”, string);  
for(i = 0; i < dlsap_len; i++) {  
printf(”%02x”, dlsap[i]);  
printf(”\n”);  
}
28  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
/*********************************************************************  
main  
*********************************************************************/  
main() {  
int  
send_fd, recv_fd;  
/* file descriptors */  
/* sending DLSAP */  
/* receiving DLSAP */  
u_char sdlsap[20];  
u_char rdlsap[20];  
int  
int  
sdlsap_len, rdlsap_len; /* DLSAP lengths */  
i, j, recv_len;  
/*  
PART 1 of program. Demonstrate connectionless data  
transfer with LLC SAP header.  
*/  
/*  
First, we must open the DLPI device file, /dev/dlpi, and attach  
to a PPA. attach() will open /dev/dlpi, find the first PPA  
with the DL_HP_PPA_INFO primitive, and attach to that PPA.  
attach() returns the file descriptor for the stream. Here we  
do an attach for each file descriptor.  
*/  
send_fd = attach();  
recv_fd = attach();  
/*  
Now we have to bind to a IEEESAP. We will ask for connectionless  
data link service with the DL_CLDLS service mode. Since we are  
connectionless, we will not have any incoming connections so we  
set max_conind to 0. bind() will return our local DLSAP and its  
length in the last two arguments we pass to it.  
*/  
bind(send_fd, SEND_SAP, 0, DL_CLDLS, sdlsap, &sdlsap_len);  
bind(recv_fd, RECV_SAP, 0, DL_CLDLS, rdlsap, &rdlsap_len);  
/* print the DLSAPs we got back from the binds */  
print_dlsap(”sending DLSAP = ”, sdlsap, sdlsap_len);  
print_dlsap(”receiving DLSAP = ”, rdlsap, rdlsap_len);  
/*  
Time to send some data. We'll send 5 data packets in sequence.  
*/  
for(i = 0; i < 5; i++) {  
/* send (i+1)*10 data bytes with the first byte = i */  
data_area[0] = i;  
/* Initialize data area */  
for (j = 1; j < (i+1)*10; j++)  
data_area[j] = ”a”;  
print_dlsap(”sending data to ”,rdlsap, rdlsap_len);  
send_data(send_fd, rdlsap, rdlsap_len, (i + 1) * 10);  
/* receive the data packet */  
recv_len = recv_data(recv_fd);  
printf(”received %d bytes, first word = %d\n”, recv_len,  
(u_int)data_area[0]);  
Chapter 2  
29  
 
LLA and DLPI Example Programs  
DLPI Example Program  
}
/*  
We're finished with PART 1. Now call cleanup to unbind, then  
detach, then close the device file.  
*/  
cleanup(send_fd);  
cleanup(recv_fd);  
/*  
PART 2 of program. Demonstrate connectionless data transfer  
with LLC SNAP SAP header.  
*/  
/*  
As demonstrated in the first part of this program we must first  
open the DLPI device file, /dev/dlpi, and attach to a PPA.  
*/  
send_fd = attach();  
recv_fd = attach();  
/*  
The first method for binding a SNAP protocol value (which is  
demonstrated below) requires the user to first bind the SNAP  
SAP 0xAA, then issue a subsequent bind with class  
DL_HIERARCHICAL_BIND with the 5 bytes of SNAP information.  
The second method (which is not demonstrated in this program) is  
to bind any supported protocol value (see section 5) and then  
issue a subsequent bind with class DL_PEER_BIND. The data area  
area of the subsequent bind should include 6 bytes of data, the  
first byte being the SNAP SAP 0xAA followed by 5 bytes of SNAP  
information.  
*/  
bind(send_fd, SNAP_SAP, 0, DL_CLDLS, sdlsap, &sdlsap_len);  
bind(recv_fd, SNAP_SAP, 0, DL_CLDLS, rdlsap, &rdlsap_len);  
/*  
Now we must complete the binding of the SNAP protocol value  
with the subsequent bind request and a subsequent bind class  
of DL_HIERARCHICAL_BIND.  
*/  
subs_bind(send_fd, SEND_SNAP_SAP, 5, DL_HIERARCHICAL_BIND,  
sdlsap,&sdlsap_len);  
subs_bind(recv_fd, RECV_SNAP_SAP, 5, DL_HIERARCHICAL_BIND,  
rdlsap,&rdlsap_len);  
/* print the DLSAPs we got back from the binds */  
print_dlsap(”sending DLSAP = ”, sdlsap, sdlsap_len);  
print_dlsap(”receiving DLSAP = ”, rdlsap, rdlsap_len);  
/*  
Time to send some data. We'll send 5 data packets in sequence.  
*/  
for(i = 0; i < 5; i++) {  
/* send (i+1)*10 data bytes with the first byte = i */  
30  
Chapter2  
 
LLA and DLPI Example Programs  
DLPI Example Program  
data_area[0] = i;  
/* Initialize data area */  
for (j = 1; j < (i+1)*10; j++)  
data_area[j] = ”a”;  
print_dlsap(”sending data to ”,rdlsap, rdlsap_len);  
send_data(send_fd, rdlsap, rdlsap_len, (i + 1) * 10);  
/* receive the data packet */  
recv_len = recv_data(recv_fd);  
printf(”received %d bytes, first word = %d\n”, recv_len,  
data_area[0]);  
}
/*  
We're finished. Now call cleanup to unbind, then detach,  
then close the device file.  
*/  
cleanup(send_fd);  
cleanup(recv_fd);  
}
Chapter 2  
31  
 
LLA and DLPI Example Programs  
LLA Example Program  
LLA Exa m p le P r ogr a m  
/***************************************************************************  
(C) COPYRIGHT HEWLETT-PACKARD COMPANY 1992. ALL RIGHTS  
RESERVED. NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED,  
REPRODUCED, OR TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT  
THE PRIOR WRITTEN CONSENT OF HEWLETT PACKARD COMPANY  
***************************************************************************/  
/**************************************************************************  
The main part of this program is composed of two parts.  
The first part demonstrates data transfer over LLA  
with LLC SAP headers. The second part of this program  
demonstrates data transfer over LLA with LLC SNAP headers.  
**************************************************************************/  
#include <stdio.h>  
#include <fcntl.h>  
#include <memory.h>  
#include <errno.h>  
#include <sys/types.h>  
#include <sys/netio.h>  
#define SEND_SAP  
#define RECV_SAP  
#define SNAP_SAP  
0x80  
0x82  
0xAA  
/* sending SAP */  
/* receiving SAP */  
/* SNAP SAP */  
/*************************************************************************  
SNAP protocol values.  
**************************************************************************/  
u_char SEND_SNAP_SAP[5] = {0x50, 0x00, 0x00, 0x00, 0x00};  
u_char RECV_SNAP_SAP[5] = {0x60, 0x00, 0x00, 0x00, 0x00};  
/*************************************************************************  
global areas for sending and receiving messages  
**************************************************************************/  
#define MAX_PKT_SIZE  
1500  
/* Maximum packet size for Ethernet */  
u_long data_area[MAX_PKT_SIZE];  
struct fis ctrl_buf;  
/* for data messages */  
/*************************************************************************  
Read a packet on LLA file descriptor fd.  
**************************************************************************/  
int  
get_pkt(fd)  
int  
fd;  
/* file descriptor */  
{
int recv_cnt;  
32  
Chapter2  
 
LLA and DLPI Example Programs  
LLA Example Program  
/*  
* Read a packet from the device.  
*/  
/* call read and check for an error */  
if((recv_cnt = read(fd, data_area, MAX_PKT_SIZE)) < 0) {  
printf(”error: read failed, errno = %d\n”, errno);  
exit(1);  
}
return(recv_cnt);  
}
/**************************************************************************  
Send a packet over LLA  
***************************************************************************/  
void  
put_data(fd, length)  
int  
int  
fd;  
/* file descriptor */  
/* length of data message */  
length;  
{
/* call putmsg and check for an error */  
if(write(fd, data_area, length) < 0) {  
printf(”error: put_data putmsg failed, errno = %d\n”, errno);  
exit(1);  
}
}
/***************************************************************************  
Send a control request to the driver.  
****************************************************************************/  
void  
put_ctrl(fd, cmd)  
int  
int  
fd;  
/* file descriptor */  
/* NETCTRL or NETSTAT */  
cmd;  
{
/* Send control request to driver */  
if(ioctl(fd, cmd, &ctrl_buf) < 0) {  
printf(”error: put_ctrl putmsg failed, errno = %d\n”, errno);  
exit(1);  
}
}
/****************************************************************************  
Open an LLA device. The device file specifies which device you  
attaching to. There is no need to issue a seperate attach control  
request to designate which device you are using. In this example  
we will default to /dev/lan0.  
*****************************************************************************  
*/  
int  
attach() {  
Chapter 2  
33  
 
LLA and DLPI Example Programs  
LLA Example Program  
intfd;  
char *mac_name;  
/* file descriptor */  
/* open the device file */  
if((fd = open(”/dev/lan0”, O_RDWR)) == -1) {  
printf(”error: open failed, errno = %d\n”, errno);  
exit(1);  
}
/* return the file descriptor for the LLA device to the caller */  
return(fd);  
}
/****************************************************************************  
Bind to a sap. LLA does not automatically return the local MAC  
address and local sap information when binding a protocol value.  
You must explicitly request the local MAC address via the  
LOCAL_ADDRESS control request.  
****************************************************************************/  
void  
bind(fd, sap)  
int  
int  
fd;  
sap;  
/* file descriptor */  
/* 802.2 SAP to bind on */  
{
ctrl_buf.reqtype = LOG_SSAP;  
ctrl_buf.vtype = INTEGERTYPE;  
ctrl_buf.value.i = sap;  
/* send the LOG_SSAP request. LLA will return success or  
failure when the ioctl completes, so there is no need to  
wait for an acknowledgement.  
*/  
put_ctrl(fd, NETCTRL);  
}
/****************************************************************************  
Get the local MAC address.  
****************************************************************************/  
void  
get_local_address(fd, ret_addr)  
int  
fd;  
/* file descriptor */  
caddr_tret_addr;/* return local address here */  
{
ctrl_buf.reqtype = LOCAL_ADDRESS;  
/* send the LOCAL_ADDRESS request. LLA will return success or  
failure when the ioctl completes, so there is no need to  
wait for an acknowledgement.  
*/  
put_ctrl(fd, NETSTAT);  
34  
Chapter2  
 
LLA and DLPI Example Programs  
LLA Example Program  
/* Copy the address to ret_addr */  
memcpy(ret_addr, (caddr_t)ctrl_buf.value.s, 6);  
}
/****************************************************************************  
Set the destination MAC and SAP address.  
****************************************************************************/  
void  
set_dst_address(fd, dest_addr, dsap, length)  
int  
fd;  
/* file descriptor */  
caddr_t dest_addr;/* return local address here */  
int  
int  
dsap;/* destination sap */  
length;/* destination sap length */  
{
ctrl_buf.reqtype = LOG_DEST_ADDR;  
ctrl_buf.vtype = 6;  
memcpy((caddr_t)ctrl_buf.value.s, dest_addr, 6);  
/* send the LOG_DEST_ADDR request. LLA will return success or  
failure when the ioctl completes, so there is no need to  
wait for an acknowledgement.  
*/  
put_ctrl(fd, NETCTRL);  
/* Only log sap addresses, SNAP addresses do not need to  
be logged twice.  
*/  
if (length == INTEGERTYPE) {  
ctrl_buf.reqtype = LOG_DSAP;  
ctrl_buf.vtype = INTEGERTYPE;  
ctrl_buf.value.i = dsap;  
put_ctrl(fd, NETCTRL);  
}
}
/****************************************************************************  
bind to a SNAP sap.  
****************************************************************************/  
void  
bind_snap(fd, snapsap)  
int  
fd;  
u_char *snapsap;  
{
/* Fill in SNAP req */  
ctrl_buf.reqtype = LOG_SNAP_TYPE;  
ctrl_buf.vtype = 5;  
memcpy((caddr_t)ctrl_buf.value.s, snapsap, 5);  
/* send the SNAP request. */  
put_ctrl(fd, NETCTRL);  
}
Chapter 2  
35  
 
LLA and DLPI Example Programs  
LLA Example Program  
/****************************************************************************  
Close the file descriptor. This will automatically unbind the  
protocol.  
****************************************************************************/  
void  
cleanup(fd)  
int  
fd;  
/* file descriptor */  
{
/* close */  
close(fd);  
}
/****************************************************************************  
receive a data packet;  
****************************************************************************/  
int  
recv_data(fd)  
int  
fd;  
/* file descriptor */  
{
int  
length;  
length = get_pkt(fd);  
if(length == 0) {  
printf(”error: did not receive any data part \n”);  
exit(1);  
}
return(length);  
}
/****************************************************************************  
send a data packet; assumes data_area has already been filled in  
and a destination address has already been logged.  
****************************************************************************/  
void  
send_data(fd, len)  
int  
int  
fd;  
/* file descriptor */  
/* length of the packet to send */  
len;  
{
}
put_data(fd, len);  
/****************************************************************************  
print a string followed by a destination MAC and SAP address.  
****************************************************************************/  
void  
print_dest_addr(string, dest_addr, dest_addr_len)  
char  
*string;  
/* label */  
/* the destination address */  
u_char *dest_addr;  
36  
Chapter2  
 
LLA and DLPI Example Programs  
LLA Example Program  
int  
int  
dest_addr_len; /* length of dest_addr */  
i;  
{
}
printf(”%s”, string);  
for(i = 0; i < dest_addr_len; i++) {  
printf(”%02x”, dest_addr[i]);  
}
printf(”\n”);  
/****************************************************************************  
main  
****************************************************************************/  
main() {  
int  
send_fd, recv_fd;  
/* file descriptors */  
/* local MAC address */  
u_char local_addr[20];  
int  
/*  
i, j, recv_len;  
PART 1 of program. Demonstrate connectionless data transfer with  
LLC SAP header.  
*/  
/*  
First, we must open the LLA device file, /dev/lan0. LLA does  
not require a seperate control request to specify which device  
you want to use, it is explicit in the open request (via the  
device file minor number).  
*/  
send_fd = attach();  
recv_fd = attach();  
/*  
Now we have to bind to a IEEESAP. Since LLA only supports  
connectionless services there is no need to specify a specific  
service mode. LLA also does not return the local MAC address  
automatically when binding, so we need to issue a seperate control  
request (LOCAL_ADDRESS)to get this information (see below).  
*/  
bind(send_fd, SEND_SAP);  
bind(recv_fd, RECV_SAP);  
/*  
The following calls to get_local_address and set_dst_address  
are required for LLA because of one primary difference in sending  
data over LLA and DLPI. The difference is that DLPI  
requires you to specify the destination address as part of the  
data request and LLA requires the destination address to be  
logged prior to the data request.  
Get the local MAC address so that we can send loopback packets.  
*/  
get_local_address(send_fd, local_addr);  
Chapter 2  
37  
 
LLA and DLPI Example Programs  
LLA Example Program  
/*  
Set the destination MAC and SAP address to the local address.  
This will allow us to send loopback packets.  
*/  
set_dst_address(send_fd, local_addr, RECV_SAP, INTEGERTYPE);  
/* print the MAC and SAP addresses we are sending and receiving on */  
local_addr[6] = SEND_SAP;  
print_dest_addr(”sending too = ”, local_addr, 7);  
local_addr[6] = RECV_SAP;  
print_dest_addr(”receiving on = ”, local_addr, 7);  
/*  
Time to send some data. We'll send 5 data packets in sequence.  
*/  
for(i = 0; i < 5; i++) {  
/* send (i+1)*10 data bytes with the first byte = i */  
data_area[0] = i;  
/* Initialize data area */  
for (j = 1; j < (i+1)*10; j++)  
data_area[j] = ”a”;  
print_dest_addr(”sending data to ”,local_addr, 7);  
send_data(send_fd, (i + 1) * 10);  
/* receive the data packet */  
recv_len = recv_data(recv_fd);  
printf(”received %d bytes, first word = %d\n”, recv_len,  
(u_int)data_area[0]);  
}
/*  
We're finished with PART 1. Now call cleanup to close the device file.  
*/  
cleanup(send_fd);  
cleanup(recv_fd);  
/*  
PART 2 of program. Demonstrate connectionless data transfer with  
LLC SNAP SAP header.  
*/  
/*  
As demonstrated in the first part of this program we must first  
open the DLPI device file, /dev/dlpi, and attach to a PPA.  
*/  
send_fd = attach();  
recv_fd = attach();  
/*  
Bind the send and recv SNAP protocols. When binding SNAP over  
LLA the SNAP address will be used as both the sending and receiving  
protocol address. Therefore, there is no need to issue a seperate  
request to log the destination SNAP protocol. However, we still need  
to set the destination MAC address.  
*/  
bind_snap(send_fd, SEND_SNAP_SAP);  
38  
Chapter2  
 
LLA and DLPI Example Programs  
LLA Example Program  
/*  
The following bind is not needed because we are running in loopback  
mode with only one LAN interface. Since the sending LLA device  
will use the same SNAP address for sending and receiving we'll  
just loopback on the same LLA file descriptor.  
bind_snap(recv_fd, RECV_SNAP_SAP);  
*/  
get_local_address(send_fd, local_addr);  
/*  
Set the destination MAC and SAP address to the local address.  
This will allow us to send loopback packets. As mention above,  
the SNAP address does not need to be logged, it is used here  
only to distinguish SAPs and SNAP values.  
*/  
set_dst_address(send_fd, local_addr, RECV_SNAP_SAP, 6);  
/* print the MAC and SAP addresses we are sending and receiving on */  
memcpy((caddr_t)&local_addr[6], SEND_SNAP_SAP, 5);  
print_dlsap(”sending too = ”, local_addr, 11);  
print_dlsap(”receiving on = ”, local_addr, 11);  
/*  
Time to send some data. We'll send 5 data packets in sequence.  
*/  
for(i = 0; i < 5; i++) {  
/* send (i+1)*10 data bytes with the first byte = i */  
data_area[0] = i;  
/* Initialize data area */  
for (j = 1; j < (i+1)*10; j++)  
data_area[j] = ”a”;  
print_dlsap(”sending data to ”,local_addr, 11);  
send_data(send_fd, (i + 1) * 10);  
/* receive the data packet. Since we are sending  
to the SNAP address we enabled on the send_fd we  
must also receive on this file descriptor.  
*/  
recv_len = recv_data(send_fd);  
printf(”received %d bytes, first word = %d\n”, recv_len,  
data_area[0]);  
}
/*  
We're finished. Now call cleanup to then close the device file.  
*/  
cleanup(send_fd);  
cleanup(recv_fd);  
}
Chapter 2  
39  
 
LLA and DLPI Example Programs  
LLA Example Program  
40  
Chapter2  
 
In d ex  
D
DLPI example program, 20  
E
example programs, 20  
L
LLA example program, 20  
LLA ioctls vs DLPI primitives,  
14  
LLA migration, 12  
M
migrating to DLPI, 12  
41  
 

Graco Baby Playpen PD187711B User Manual
Hamilton Beach Blender 840066200 User Manual
Harbor Freight Tools Outdoor Fountain 95781 User Manual
Hayter Mowers Lawn Mower 422V User Manual
Honeywell Air Cleaner HHT 080 User Manual
Hotpoint Cooktop GE75DX User Manual
Hotpoint Microwave Oven BS63E User Manual
Hyundai Flat Panel Television 0090509536 User Manual
IBM Marine RADAR SY33 0193 00 User Manual
Image Treadmill IMTL11995 User Manual