Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

incd(8)

open(2)

close(2)

getmsg(2)

ioctl(2)

putmsg(2)

clone(7)

streamio(7)

tren(7)



  et(7)                               CLIX                               et(7)



  NAME

    et - STREAMS Ethernet interface devices

  DESCRIPTION

    The et STREAMS devices et0 ... etn provide the service described in the
    AT&T Logical Link Interface for the CLIX Ethernet ports from 0-n.  CLIX
    computers may have one or more ports for connecting the computer to
    Ethernet local area networks.

    The clone opens may be performed on et devices to find the first available
    free minor device.

    Before frames can be transmitted and received on an opened et device, an
    Ethernet type called the Service Access Point (SAP) must be bound to the
    device.  Binding indicates to the device that frames transmitted should
    contain the specified SAP in the type SAP field of the Ethernet header and
    that only frames containing the specified SAP in the type field of the
    Ethernet header should be received on the device.

    Once bound, frames may be transmitted on the device.  Incoming frames with
    type fields matching the bound SAP will be received on the device if the
    address field contains one of the following: the local individual address,
    the Ethernet broadcast address, or an active Ethernet multicast address.
    The SAP may be unbound and a new SAP bound without closing the device.
    When a close() is performed on the device and a SAP is still bound to the
    device, the SAP will automatically be unbound as part of close().

    Two special SAPs allow access to a range of SAP values with only one bound
    stream.  The two values ISO_SAP and TRLR_SAP are defined in <sys/lihdr.h>.

    When ISO_SAP is bound to an et device, the type field in the Ethernet
    header is treated as a length field, indicating the number of bytes that
    follow the Ethernet header in the frame.  All frames received by the
    system with length values less than or equal to MAX_ISO_SAP are passed
    upstream on et streams bound to ISO_SAP.  Likewise, all frames transmitted
    on et streams bound to ISO_SAP should have the length field set to the
    amount of data following the Ethernet header.  On et streams bound to
    ISO_SAP, unpredictable results will occur if the SAP indicated in a unit
    datagram (unitdata) request does not match the length of the data to be
    sent.

    All frames received by the system with Ethernet header type values between
    TRLR_SAP and MAX_TRLR_SAP are passed upstream on et streams bound to
    TRLR_SAP.  Streams bound to TRLR_SAP should not be used to transmit
    frames.

    The Logical Link Interface (LLI) accesses et services.  putmsg() sends
    request primitives to et.  getmsg() receives acknowledgement and
    indication primitives from et.  A primitive is a message passed upstream



  2/94 - Intergraph Corporation                                              1






  et(7)                               CLIX                               et(7)



    or downstream on an et stream.

    The format of the control part of each message that composes an LLI
    primitive is described by the appropriate structure and constant
    definition in the file <sys/lihdr.h>.  The first longword in each LLI
    primitive's control part is the primitive type identifier field PRIM_type.
    A unique constant definition exists for each of the 10 LLI primitive
    identifiers, and each primitive structure will always contain the type of
    primitive identified in the PRIM_type field.  As a convenience, the union
    DL_primitives defined in <sys/lihdr.h> is a union of all LLI primitive
    control structures.

    The primitives that are initiated (sent downstream to et) by the et user
    are the information request, bind request, unbind request, and unitdata
    request.

    The primitives that are initiated by et (sent upstream to the user) are
    the information acknowledgement, bind acknowledgement, error
    acknowledgement, OK acknowledgement, unitdata indication, and unitdata
    error indication.  The primitives initiated by et will be sent upstream to
    the user as the result of a request sent to et by the user or, in the case
    of the unitdata indication, when data has arrived from the network on the
    SAP bound to the stream.

    The only primitives that have a data part associated with the message are
    the unitdata request and unitdata indication primitives.  All the other
    primitives use only the control part of a message to perform their
    functions.  Fields in any of the primitive structures named GROWTH or
    FILLER are present for future expansion of the LLI interface and are
    ignored by et.

  Information Request Primitive

    The information request primitive requests that an LLI device return
    information about the size of relevant parameters plus the current state
    of the device.  It is passed to et as a priority message.  The control
    part of this message is a buffer containing a DL_info_req structure.  The
    information request primitive may be issued on an open et stream while the
    stream is in any state.

  Information Acknowledgement Primitive

    The information acknowledgement returned by et in response to an
    information request will be a priority message containing the following
    DL_info_ack structure in its control part:

    struct DL_info_ack {
         ulong PRIM_type;    /* always DL_INFO_ACK             */
         long  SDU_max;      /* maximum service data unit size */
         long  SDU_min;      /* minimum service data unit size */
         long  ADDR_length;  /* address length                 */



  2                                              Intergraph Corporation - 2/94






  et(7)                               CLIX                               et(7)



         long  SUBNET_type;  /* subnet type                    */
         long  SERV_class;   /* service class                  */
         long  CURRENTstate; /* link layer state               */
         long  GROWTH;       /* for future enhancement         */
    };

    The PRIM_type field in a DL_info_ack is always DL_INFO_ACK.  The fields
    SDU_max and SDU_min indicate the maximum and minimum allowed sizes
    (respectively) of the data part of unitdata request and indication
    primitives.  The field ADDR_length returns the size of the Ethernet
    address that et will use for local and remote addresses in unitdata
    request and indication primitives.  The SUBNET_type field will indicate
    the subnetwork type provided by et.  The SERVICE_class field will indicate
    whether et supports different levels of service.  The CURRENT_state field
    will hold the value of the state of the et device associated with the
    stream when the information request arrived.

  Bind Request Primitive

    The bind request primitive requests an LLI device to bind a SAP to the
    stream and return the entire Ethernet address associated with the stream.
    It is passed to et as a nonpriority message.  The control part of this
    message is a buffer containing a DL_bind_req structure.  The bind request
    primitive may be issued only on an open et stream that is in the unbound
    state (DL_UNBND).  The LLC_sap field of the DL_bind_req contains the SAP,
    in host order, that et should bind to the stream for the user.  Many of
    the SAP constants are defined in <sys/lihdr.h>.  These constants all have
    the _SAP suffix.  An et stream will be in the unbound state immediately
    after it has been opened.  Then, once it has been bound, the et stream
    will enter the unbound state again after an unbind primitive succeeds on
    the stream.

    If the bind request succeeds, et will return a bind acknowledgement in a
    priority message containing a DL_bind_ack structure.  If the bind fails,
    et will return a negative acknowledgement in a priority message containing
    a DL_error_ack structure.

  Bind Acknowledgement Primitive

    The DL_bind_ack has the following structure:

    struct DL_bind_ack {
         ulong PRIM_type;   /* always DL_BIND_ACK       */
         long  LLC_sap;     /* LLC service access point */
         long  ADDR_length; /* address length           */
         long  ADDR_offset; /* address offset           */
         long  GROWTH[2];   /* for future enhancement   */
    };

    The PRIM_type field in a DL_bind_ack is always DL_BIND_ACK.  The LLC_sap
    field in the DL_bind_ack returns the SAP that was actually bound to the



  2/94 - Intergraph Corporation                                              3






  et(7)                               CLIX                               et(7)



    stream and may be different than the one specified in the DL_bind_request.
    The ADDR_offset field is the byte offset from the beginning of the
    message's control part at which the Ethernet address associated with the
    stream is returned.  The ADDR_length field indicates the length (in bytes)
    of the returned Ethernet address associated with the stream.

    The format of the returned Ethernet address is the lli_ud_addr structure
    defined in <sys/lli.h>.  The host field of the lli_ud_addr structure
    contains the 48-bit Ethernet host address in network order.  The sap field
    of the lli_ud_addr structure contains the 16-bit Ethernet type field (or
    SAP) bound to the stream in network order.  (Network order is most-
    significant-byte first.  An example will follow in the sample unitdata
    request primitive.)

    Once a successful bind has been performed on an et stream, the stream will
    be in the idle state (DL_IDLE) where it can perform unitdata requests and
    indications.  In other words, it can transmit and receive Ethernet frames.

  Unbind Request Primitive

    The unbind request primitive requests an LLI device to unbind the SAP
    previously bound to a stream and return the device to the unbound state.
    It is passed to et as a nonpriority message.  The control part of this
    message is a buffer containing a DL_unbind_req structure.  The unbind
    request primitive may be issued only on an et stream that is in the idle
    state.

    If the unbind request succeeds, et will return an OK acknowledgement in a
    priority message containing a DL_ok_ack structure.  If the unbind fails,
    Lt will return a negative acknowledgement in a priority message containing
    a DL_error_ack structure.

  OK Acknowledgement Primitive

    The DL_ok_ack is always passed upstream in a priority message, which has
    the following structure:

    struct DL_ok_ack {
         ulong PRIM_type;    /* always DL_OK_ACK        */
         long  CORRECT_prim; /* correct primitive being */
                             /*    acknowledged         */
    }

    The PRIM_type field in a DL_ok_ack is always DL_OK_ACK.  The DL_ok_ack
    positively acknowledges primitives that require only a positive or
    negative acknowledgement.  The CORRECT_prim field in the DL_ok_ack
    contains the value of the PRIM_type field of the primitive being
    positively acknowledged.

  Error Acknowledgement Primitive




  4                                              Intergraph Corporation - 2/94






  et(7)                               CLIX                               et(7)



    The DL_error_ack is always passed upstream in a priority message, which
    has the following structure:

    struct DL_error_ack {
         ulong PRIM_type;  /* always DL_ERROR_ACK */
         long  ERROR_prim; /* primitive in error  */
         long  LLC_error;  /* LLC error code      */
         long  UNIX_error; /* UNIX error code     */
    };

    The PRIM_type field in a DL_error_ack is always DL_ERROR_ACK.  The
    DL_error_ack negatively acknowledges primitives that require only a
    positive or negative acknowledgement.  The ERROR_prim field in the
    DL_error_ack contains the value of the PRIM_type field of the primitive
    being negatively acknowledged.  The LLC_error field returns the LLC error
    code indicating the nature of the error.  The UNIX_error field should be
    ignored unless the LLC_error field is set to DLSYSERR.  In this case the
    UNIX_error field will contain a CLIX error code indicating the nature of
    the failure.

  Unit Datagram Request Primitive

    The unitdata request primitive requests et to transmit an Ethernet frame.
    A unitdata request is passed to et as a nonpriority message.  The control
    part of the message is a buffer containing a DL_unitdata_req structure
    followed by an lli_ud_addr structure.  The lli_ud_addr structure contains
    the destination Ethernet address and Ethernet type value to be used in the
    frame's Ethernet header.  The data part of the message is a buffer
    containing the data to be sent in the Ethernet frame (between the Ethernet
    header and the frame check sequence).

    The DL_unitdata_req structure has the following format:

    struct DL_unitdata_req {
         ulong PRIM_type;  /* always DL_UNITDATA_REQ             */
         long  RA_length;  /* remote address length              */
         long  RA_offset;  /* remote address offset              */
         long  SERV_class; /* service class                      */
         long  FILLER[2];  /* to make as big as a DL_uderror_ind */
    };

    The PRIM_type field in a DL_unitdata_req is always DL_UNITDATA_REQ.  The
    RA_length field should be set to the size of the lli_ud_addr structure.
    The RA_offset field is the byte offset from the beginning of the control
    part of the message at which the lli_ud_addr structure begins.  The
    RA_offset should be at least the size of a DL_unitdata_req structure.  The
    SERV_class field should be set to the constant DL_NOSERV.

    The host field of the lli_ud_addr structure contains the six-byte Ethernet
    address, in network order, that will be used as the destination address
    for the frame.  The sap field of the lli_ud_addr structure should contain



  2/94 - Intergraph Corporation                                              5






  et(7)                               CLIX                               et(7)



    the two-byte representation, in network order, of the SAP that was bound
    on the stream.  If ISO_SAP was bound to the stream, the sap field should
    contain, in network order, the frame length.

    When et receives a unitdata request primitive, it checks the sizes of the
    control part of the message, the address size specified by RA_length, and
    the size of the message's data part to verify that they are within
    appropriate limits.  et then checks to ensure that the SAP specified in
    the sap field of the lli_ud_addr matches the SAP bound on the stream.  Or,
    it ensures that the SAP matches the length of the frame to be sent if the
    ISO_SAP was bound on the stream.  If these tests succeed, et builds an
    Ethernet header for the frame to be transmitted.  The Ethernet header's
    destination address is the one specified in the host field of the
    lli_ud_addr passed in the message.  The Ethernet header's source address
    will be the one et returns with the bind acknowledgement when this stream
    was bound.  The Ethernet header's type field will match the sap field of
    the lli_ud_addr passed with the message.  This header is prepended to the
    data part of the message and the frame is sent to the destination host.

    If an error is encountered in the processing of a unitdata request, a
    unitdata error primitive is sent upstream.  If no errors are encountered
    in the processing of a unitdata request, it may be assumed that a best
    effort was made by et to deliver the frame to its destination.  No
    positive acknowledgement is sent upstream in response to a successfully
    processed unitdata request primitive.

    An example of sending a unitdata request primitive is shown in the
    EXAMPLES section.

  Unit Datagram Error Primitive

    The unitdata error primitive reports to the user any errors in processing
    unitdata requests.  et passes it upstream as a priority message.  The
    control part of this message is a buffer containing a DL_uderror_ind
    structure followed by an lli_ud_addr structure.

    The DL_uderror_ind structure has the following format:

    struct DL_uderror_ind {
         ulong PRIM_type;  /* always DL_UDERROR_IND */
         long  RA_length;  /* remote address length */
         long  RA_offset;  /* remote address offset */
         long  SERV_class; /* service class         */
         long  ERROR_type; /* error type            */
    };

    The PRIM_type field in a DL_uderror_ind is always DL_UDERROR_IND.  The
    RA_length field is the length of the remote address specified in the
    unitdata request.  The RA_offset field is the byte offset from the
    beginning of the message's control part at which the lli_ud_addr structure
    begins.  The SERV_class is the subnetwork service class of the packet in



  6                                              Intergraph Corporation - 2/94






  et(7)                               CLIX                               et(7)



    error.  The ERROR_type field defines the protocol-dependent error code.
    Errors returned by et are defined constants in <sys/lihdr.h> with the
    _UDERR suffix.

    The lli_ud_addr structure contains the host and sap fields that were
    specified in the lli_ud_addr structure of the unitdata request that had
    the error.

  Unit Datagram Indication Primitive

    The unitdata indication primitive delivers a received Ethernet frame to
    the user.  A unitdata indication is passed upstream as a nonpriority
    message.  The control part of the message contains a DL_unitdata_ind
    structure, followed by an lli_addr structure, followed by an lli_ud_addr
    structure.  The address structures contain the source and destination
    addresses and Ethernet type from the received frame as described below.

    The data part of the message is a buffer containing the data received in
    the Ethernet frame between the Ethernet header and the frame check
    sequence.

    The DL_unitdata_ind structure has the following format:

    struct DL_unitdata_ind {
         ulong PRIM_type;  /* always DL_UNITDATA_IND */
         long  RA_length;  /* remote address length  */
         long  RA_offset;  /* remote address offset  */
         long  LA_length;  /* local address length   */
         long  LA_offset;  /* local address offset   */
         long  SERV_class; /* service class          */
    };

    The PRIM_type field in a DL_unitdata_ind is always DL_UNITDATA_IND.  The
    RA_length field will be set to the size of the lli_addr structure.  The
    RA_offset field is the byte offset from the beginning of the message's
    control part at which the lli_addr structure begins.  The LA_length field
    will be set to the size of the lli_ud_addr structure.  The LA_offset field
    is the byte offset from the beginning of the message's control part at
    which the lli_ud_addr structure begins.  The SERV_class will be set to the
    subnetwork service class of the received frame.

    The lli_addr structure contains the six-byte Ethernet source address, in
    network order, from the Ethernet header in the received frame.

    The host field of the lli_ud_addr structure contains the six-byte Ethernet
    destination address, in network order, from the Ethernet header in the
    received frame.  The sap field of the lli_ud_addr structure contains the
    two-byte representation, in network order, of the Ethernet type in the
    received frame.

    Once an et stream has been successfully bound and enters the DL_IDLE



  2/94 - Intergraph Corporation                                              7






  et(7)                               CLIX                               et(7)



    state, et will deliver inbound frames addressed to the local host and
    bound SAP upstream as they arrive.  The delivery of unitdata indications
    does not depend on a user's request for their delivery.  There is no way,
    short of unbinding the stream, to keep these frames from arriving.  If the
    user does not remove the frames from the queue as fast as they arrive over
    the network, the stream head between et and the user will queue only
    STRHIGH (defined in <sys/stream.h>) bytes worth of frames before becoming
    full.  When the stream head's queue becomes full, et will begin discarding
    incoming frames instead of delivering them upstream.  This prevents one et
    stream from using up all of the streams resources on the system.  It also
    means that applications that wish to receive all the Ethernet frames
    received by et on the bound SAP must read the frames from the stream as
    fast as they arrive.

    An example of receiving a unitdata indication primitive is shown in the
    EXAMPLES section.

  Input/Output Control Calls

    In addition to the services provided by the AT&T Logical Link Interface,
    several functions are provided with the STREAMS I_STR ioctl() call.  These
    functions specify the Ethernet address to be used as the individual
    address on an Ethernet port and enable and disable active Ethernet
    multicast addresses for an Ethernet port.  The individual address may be
    changed only when no SAPs are currently bound.  (Even the device used for
    changing the address may not be bound to a SAP.)  These ioctl() calls use
    the following lli_addr address structure defined in <sys/lli.h>:

    struct lli_addr {
         unchar host[6];
    };

    The address should be filled in network order as shown in one of the
    following examples.

  EXAMPLES

    1.  The following is an example of sending an Ethernet frame by formatting
        a unitdata request primitive and using putmsg().  The code assumes
        that the stream is already bound to SAP 0x800.  The frame to be sent
        contains 100 bytes of data and will be sent to the remote address 08-
        00-36-01-02-03.

        #define UD_REQ_SZ sizeof(struct DL_unitdata_req)
        #define UD_ADR_SZ sizeof(struct lli_ud_addr)

        struct strbuf          ctlbuf;
        struct strbuf          databuf;
        struct DL_unitdata_req ud_req;
        struct lli_ud_addr     ud_adr;
        char                   ctrl_buf[UD_REQ_SZ + UD_ADR_SZ];



  8                                              Intergraph Corporation - 2/94






  et(7)                               CLIX                               et(7)



        char                   data_buf[100];

        /*
         * fill in the DL_unitdata_req and lli_ud_addr structures
         */
        ud_req.PRIM_type = DL_UNITDATA_REQ;
        ud_req.RA_length = UD_ADR_SZ;
        ud_req.RA_offset = UD_REQ_SZ;
        ud_req.SERV_class = DL_NOSRV;
        ud_adr.host[0] = 0x08;
        ud_adr.host[1] = 0x00;
        ud_adr.host[2] = 0x36;
        ud_adr.host[3] = 0x01;
        ud_adr.host[4] = 0x02;
        ud_adr.host[5] = 0x03;
        ud_adr.sap[0] = 0x08;
        ud_adr.sap[1] = 0x00;

        /*
         * copy the DL_unitdata_req and lli_ud_addr structures
         * into the control buffer ctrl_buf and fill in the
         * control and data strbuf structures for the message
         */
        memcpy(ctrl_buf, &ud_req, UD_REQ_SZ);
        memcpy(&ctrl_buf[UD_REQ_SZ], &ud_adr, UD_ADR_SZ);
        ctlbuf.len = UD_REQ_SZ + UD_ADR_SZ;
        ctlbuf.buf = ctrl_buf;
        databuf.len = 100;
        databuf.buf = data_buf;

        /*
         * call putmsg to send the unitdata request primitive
         */
        if (putmsg(fd, &ctlbuf, &databuf, 0) < 0)
                perror("putmsg failed");


    2.  The following is an example of receiving an Ethernet frame with
        getmsg() and parsing the unitdata indication primitive.

        /*
         * the constant MAX_SDU should reflect the SDU_max value
         * returned in an information acknowledgement primitive
         */
        #define MAX_SDU   2048
        #define UD_IND_SZ sizeof(struct DL_unitdata_ind)
        #define UD_ADR_SZ sizeof(struct lli_ud_addr)
        #define ET_ADR_SZ sizeof(struct lli_addr)

        struct strbuf          ctlbuf;
        struct strbuf          databuf;



  2/94 - Intergraph Corporation                                              9






  et(7)                               CLIX                               et(7)



        struct DL_unitdata_ind ud_ind;
        struct lli_ud_addr     ud_adr;
        struct lli_addr        et_addr
        char            ctrl_buf[UD_IND_SZ + UD_ADR_SZ + ET_ADR_SZ];
        char                   data_buf[MAX_SDU];
        int                    flags;

        /*
         * fill in the control and data strbuf structures and
         * call getmsg to get the unitdata indication primitive
         */
        ctlbuf.maxlen = UD_IND_SZ + UD_ADR_SZ + ET_ADR_SZ;
        ctlbuf.len = 0;
        ctlbuf.buf = ctrl_buf;
        databuf.maxlen = MAX_SDU;
        databuf.len = 0;
        databuf.buf = data_buf;
        if (getmsg(fd, &ctlbuf, &databuf, &flags) < 0)
             perror("getmsg failed");
        if (flags)
             printf("unitdata indications use nonpriority messages");
        if (ctlbuf.len < UD_IND_SZ)
             printf("not big enough to be a unitdata indication");
        memcpy(&ud_ind, ctrl_buf, UD_IND_SZ);
        if (ud_ind.PRIM_type != DL_UNITDATA_IND)
             printf("this is not a unitdata indication primitive");
        if (ud_ind.RA_length != ET_ADR_SZ)
             printf("this is not a good remote address length");
        memcpy(&et_adr, &ctrl_buf[ud_ind.RA_offset], ET_ADR_SZ);
        if (ud_ind.LA_length != UD_ADR_SZ)
             printf("this is not a good local address length");
        memcpy(&ud_adr, &ctrl_buf[ud_ind.LA_offset], UD_ADR_SZ);

        /*
         * at this point:
         *
         * -- databuf.len contains the length of the Ethernet
         *    frame data returned in databuf.buf
         * -- et_adr contains the remote (source) address
         *    from the Ethernet header of the received frame
         * -- ud_adr contains the local (destination) address and
         *    the SAP from the Ethernet header of the received frame.
         */


    3.  The following is an example of enabling the multicast address 09-00-
        36-01-02-03.

        struct lli_addr ma;
        struct strioctl sioc;




  10                                             Intergraph Corporation - 2/94






  et(7)                               CLIX                               et(7)



        ma.host[0] = 0x09;
        ma.host[1] = 0x00;
        ma.host[2] = 0x36;
        ma.host[3] = 0x01;
        ma.host[4] = 0x02;
        ma.host[5] = 0x03;

        sioc.ic_cmd = LLI_IOC_ADD_MCAST;
        sioc.ic_timout = 0;
        sioc.ic_len = 6;
        sioc.ic_dp = (char *)(&ma.host[0]);
        ioctl(et0_fd, I_STR, &sioc);


  FILES

    /dev/et
           Special device file for et

    <sys/lihdr.h>
           LLI primitive definitions

    <sys/lli.h>
           et specific definitions

  NOTES

    On CLIX systems, the /etc/incd program is usually responsible for creating
    the network configuration of streams drivers/modules/multiplexors,
    including et.  If the individual address for a given Ethernet port needs
    to be different than the hardware address, /etc/incd can be configured to
    set the address to the desired value.  Manual configuration of the
    individual address or enabling/disabling multicast addresses on a machine
    affects all network applications system-wide and should therefore be
    performed with caution.  It is necessary only in rare circumstances.

  RELATED INFORMATION

    Commands:  incd(8)

    Functions:  open(2), close(2), getmsg(2), ioctl(2), putmsg(2)

    Files:  clone(7), streamio(7), tren(7)











  2/94 - Intergraph Corporation                                             11




Typewritten Software • bear@typewritten.org • Edmonds, WA 98026