B

MUX/NPT Routines and Data Structures



B.1    Introduction

This appendix describes the routines and data structures that comprise the MUX/NPT API.



B.2    MUX Routines

This section provides descriptions of the following routines:

muxAddrResFuncAdd( )

muxAddrResFuncDel( )

muxAddrResFuncGet( )

muxAddressForm( )

muxBind( )

muxDevExists( )

muxDevLoad( )

muxDevStart( )

muxDevStop( )

muxDevUnload( )

muxError( )

muxIoctl( )

muxMCastAddrAdd( )

muxMCastAddrDel( )

muxMCastAddrGet( )

muxTkBind( )

muxTkDrvCheck( )

muxTkPollReceive( )

muxTkPollSend( )

muxTkReceive( )

muxTkSend( )

muxTxRestart( )

muxUnbind( )

B.2.1   muxAddrResFuncAdd( )

Use muxAddrResFuncAdd( ) to register an address resolution function for an interface-type/protocol pair. You must call muxAddrResFuncAdd( ) before calling the protocol's protocolAttach( ) routine. If the driver registers itself as an Ethernet driver, you do not need to call muxAddrResFuncAdd( ) because VxWorks automatically assigns arpresolve( ) to registered Ethernet devices.

STATUS muxAddrResFuncAdd 
(
long   ifType,  /* interface type from m2Lib.h, or driver type */
long   protocol,      /* protocol from RFC 1700, or service type */
FUNCPTR addrResFunc    /* the function being added */
)


*      
NOTE: If you are running IP over Ethernet, it is very unlikely that you will want to replace arpresolve( ) with your own implementation.

The prototype for your address resolution function (addrResFunc) must conform to the following:

int xxxResolvRtn 
    (
    FUNCPTR           ipArpCallBackRtn,
    struct mbuf *     pMbuf,
    struct sockaddr * dstIpAddr,
    struct ifnet *    ifp,
    struct rtentry *  rt,
    char *            dstBuff
    )

In addition, your xxxResolvRtn( ) must return one upon success, which indicates that dstIpAddr has been updated with the necessary data-link layer information and that the IP sublayer output function can transmit the packet.

Your xxxResolvRtn( ) must return zero if it cannot resolve the address immediately. In the default arpresolve( ) implementation, resolving the address immediately means arpresolve( ) was able to find the address in its table of results from previous ARP requests. Returning zero indicates that the table did not contain the information but that the packet has been stored and that an ARP request has been queued.

If the ARP request times out, the packet is dropped. If the ARP request completes successfully, processing that event updates the local ARP table and resubmits the packet to the IP sublayer's output function for transmission. This time, the arpresolve( ) call will return one.

What is essential to note here is that arpresolve( ) did not wait for the ARP request to complete before returning. If you replace the default arpresolve( ) function, you must make sure your function returns as soon as possible and that it never blocks. Otherwise, you block the IP sublayer from transmitting other packets out through the interface for which this packet was queued. You must also make sure that your arpresolve( ) function takes responsibility for the packet if it returns zero.

Writing an Address Resolution Function

An address resolution function designed for use with the VxWorks IP sublayer implementation must conform strictly to expectations of that sublayer. The function that you register with muxAddrResFuncAdd( ) must be of the form:

int xxxResolvRtn 
    (
    FUNCPTR           aCallBackRtn,
    struct mbuf *     pMbuf,
    struct sockaddr * dstIpAddr,
    struct ifnet *    ifp,
    struct rtentry *  rt,
    char *            dstBuff
    )

In addition, your xxxResolvRtn( ) must not block, and it must return with a function value of zero or one, where one indicates desIpAddr contains the resolved address and zero indicates that it does not. If your address resolution function returns a zero, it should take responsibility for the packet.

Within your xxxResolvRtn( ), you will likely implement an address resolution table or some equally speedy mechanism that lets you reuse address resolution information discovered previously. If your speedy address resolution mechanism fails, you should queue the work to an address resolution protocol and return zero. As a prototype for your function that queues the work, consider:

int resolveIPaddress 
(
FUNCPTR pCallback, /* a retransmit callback function */
M_BLK_ID pIPPacket, /* the IP packet */
struct sockaddr pIPAddress, /* the IP address */
void * passthru1, /* reserved for internal use */
void * passthru2 /* reserved for internal use */
char * pBuffer, /* pre-allocated, up to 128 bytes */
)

This function would supply the address resolution protocol with the information needed to perform the address resolution as well as the packet destined for that address. If the address resolution succeeds, the function would add that information to its table (or equivalent), and then use pCallback to submit the packet (with its original parameters) to the IP layer output function for transmission. This time, your xxxResolvRtn( ) replacement function should be able to return with the address resolution information.

B.2.2   muxAddrResFuncDel( )

Use muxAddrResFuncDel( ) to undo the assignment of an address resolution function to an interface-type/protocol pair.

STATUS muxAddrResFuncDel 
(
long   ifType,  /* media interface type from m2Lib.h */
long   protocol,      /* protocol type, for instance from RFC 1700 */
)

The muxAddrResFuncDel( ) function returns OK, or ERROR if the request fails.

B.2.3   muxAddrResFuncGet( )

Use muxAddrResFuncGet( ) to retrieve a pointer to the address resolution function registered to the specified interface-type/protocol pair.

FUNCPTR muxAddrResFuncGet 
(
long ifType, /* interface type from m2Lib.h, or driver type*/
long protocol /* protocol from RFC 1700, or service type */
)

This function returns a pointer to the address resolution function, or NULL if no function is registered for the service.

B.2.4   muxAddressForm( )

Use muxAddressForm( ) to form a frame with a link-layer address. A network service needs this function when working with ENDs, which are frame-oriented, but not with NPT drivers, which are packet oriented.

When given the source and destination addressing information (through pSrcAddr and pDstAddr), this function returns an mBlk that points to an assembled link-level header, and prepends this header to the mBlk chain pointed to by pMblk. Note that the pDstAddr.mBlkHdr.reserved field should be set to the network protocol type.

M_BLK_ID muxAddressForm 
(
void *  pCookie,  /* the cookie returned by muxBind() */
M_BLK_ID pMblk,    /* pointer to the packet being reformed */
M_BLK_ID pSrcAddr, /* pointer to the mBlk with the source address */
M_BLK_ID pDstAddr, /* pointer to the mBlk with the dest address */
)

This function returns the head of an mBlk chain containing the data from pMblk with a prepended link-level header, or NULL if the attempt fails.

B.2.5   muxBind( )

You can use muxBind( ) to bind a network service to an END. However, it is often better to use muxTkBind( ), which works with both ENDs and NPT drivers.

void * muxBind 
(
char *  pName, /* interface name, for example, ln, ei,... */
int unit, /* unit number */
BOOL (* stackENDRcvRtn)(void *, long, M_BLK_ID, LL_HDR_INFO *, void *),
STATUS (* stackENDShutdownRtn)(void *, void *),
STATUS (* stackENDRestartRtn)(void *, void *),
void (* stackENDErrorRtn)(END_OBJ *, END_ERR *, void *),
long type, /* protocol type, from RFC1700 or user-defined */
char * pProtoName, /* string name for protocol */
void * pSpare /* identifies the binding instance */
)

Note that the stack*Rtn functions in the parameter list are defined differently than in muxTkBind( ).

The muxBind( ) function returns a cookie identifying the network driver to which the MUX has bound the service. The service should keep track of this cookie for use with other MUX functions.

B.2.6   muxDevExists( )

Use muxDevExists( ) to test whether a given device has already been loaded into the network stack. As input, it expects the name and unit number of the device to be tested.

BOOL muxDevExists 
(
char * pName, /* string containing a device name (ln, ei, ...)*/
int unit /* unit number */
)

This function returns TRUE if the device has already been loaded into the network stack, or FALSE otherwise.

B.2.7   muxDevLoad( )

Use muxDevLoad( ) to load a network driver into the MUX. Internally, muxDevLoad( ) calls the driver's endLoad( ) or nptLoad( ). After the device is loaded, you must call muxDevStart( ) to start the device.

The pInitString argument passes directly into the endLoad( ) or nptLoad( ) function. Likewise, the pBSP argument is passed along to the driver, which may or may not use it. This argument can be used to pass in tables of BSP-specific functions that the driver can use.

void * muxDevLoad 
(
int unit, /* unit number of device */
END_OBJ * (* endLoad)(char *, void *), /* driver's load function */
char * pInitString, /* init string for driver */
BOOL loaning, /* unused */
void * pBSP /* BSP-specific */
)

This function returns a cookie that can be passed to muxDevStart( ), or NULL, if the device could not be loaded, in which case errno is set to S_muxLib_LOAD_FAILED.

B.2.8   muxDevStart( )

Use muxDevStart( ) to start a device after you have successfully loaded the device using muxDevLoad( ). Internally, muxDevStart( ) activates the network interfaces for a device by calling the drivers endStart( ) routine.

STATUS muxDevStart 
(
void * pCookie  /* the cookie returned from muxDevLoad() */
)

The muxDevStart( ) function returns OK, on success; ERROR, if the driver's endStart( ) routine fails; or ENETDOWN, if pCookie does not represent a valid device.

B.2.9   muxDevStop( )

Use muxDevStop( ) to stop the specified driver. Internally, muxDevStop( ) calls the endStop( ) or nptStop( ) routine registered for the driver.

STATUS muxDevStop 
(
void * pCookie /* the cookie returned from muxDevLoad() */
)

The muxDevStart( ) function returns OK, on success; ERROR, if the endStop( ) or nptStop( ) routine registered for the driver fails; or ENETDOWN, if pCookie does not represent a valid device.

B.2.10   muxDevUnload( )

Use muxDevUnload( ) to unload a device from the MUX. Unloading a device closes any network connections made through the device.

To notify protocols that the device is unloading, muxDevUnload( ) calls the stackShutdownRtn( ) function for each protocol bound to the device (internally, the stackShutdownRtn( ) should call muxUnbind( ) to detach from the device).

To free device-internal resources, muxDevUnload( ) calls the endUnload( ) or nptUnload( ) function that the device registered with the MUX.

STATUS muxDevUnload 
(
char * pName, /* the name of the device, for example, ln or ei */
int unit /* the unit number */
)

This function returns OK, on success; or ERROR, if the device could not be found, or the error returned from the device's endUnload( ) or nptUnload( ) function if that function fails.

B.2.11   muxError( )

Drivers use muxError( ) to report an error to a network service that is bound to it through the MUX. You can find predefined errors in end.h. This function is passed two arguments: the END object that identifies the device that is issuing the error and a pointer to an END_ERR structure (see B.3.2 END_ERR, p.287).

void muxError 
(
void *     pEnd,    /* END object pointer returned by end/nptLoad() */
END_ERR * pError /* error structure */
}

B.2.12   muxIoctl( )

Use muxIoctl( ) to access the ioctl services that network interfaces have registered with the MUX. Typical uses of muxIoctl( ) include starting, stopping, or resetting a network interface, or adding or configuring MAC and network addresses.

STATUS muxIoctl 
(
void * pCookie, /* returned by muxTkBind() */
int cmd, /* ioctl command */
caddr_t data /* data needed to carry out the command */
)

This function returns OK if successful; ERROR, if the device was unable to successfully complete the command; or ENETDOWN, if the cookie did not represent a valid device.

B.2.13   muxMCastAddrAdd( )

Use muxMCastAddrAdd( ) to add an address to the table of multicast addresses maintained for a device. It expects two arguments: a cookie that was returned when muxTkBind( ) was used to bind to the device, and a string containing the address to be added.

STATUS muxMCastAddrAdd 
(
void * pCookie, /* returned by muxTkBind() */
char * pAddress /* address to add to the table */
)

This function returns OK, if successful; ERROR, if the device was unable to successfully add the address (if this is because the device does not support multicasting, errno will be set to ENOTSUP ); or ENETDOWN, if the cookie does not represent a valid device.

B.2.14   muxMCastAddrDel( )

Use muxMCastAddrDel( ) to remove an address from the table of multicast addresses maintained for a device. It expects two arguments: a cookie that was returned when muxTkBind( ) was used to bind to the device, and a string containing the address to be removed.

STATUS muxMCastAddrDel 
(
void * pCookie, /* returned by muxTkBind() */
char * pAddress /* address to delete from the table */
)

This function returns OK , if successful; ERROR, if the device was unable to successfully remove the address (if this is because the device does not support multicasting, errno will be set to ENOTSUP, if this is because the address was not found in the table, errno will be set to EINVAL); ENETDOWN, if the cookie does not represent a valid device.

B.2.15   muxMCastAddrGet( )

Use muxMCastAddrGet( ) to retrieve the list of multicast addresses that have been registered for a driver. It expects two arguments: a cookie that was returned when muxTkBind( ) was used to bind to the device, and a pointer to a pre-allocated MULTI_TABLE structure into which the table contents will be written during this function call (see B.3.8 MULTI_TABLE, p.294).

int muxMCastAddrGet 
(
void * pCookie, /* returned by muxTkBind() */
MULTI_TABLE * pTable /* structure that will hold retrieved table */
)

This function returns OK, if successful; ERROR, if the device was unable to successfully supply the list; or ENETDOWN, if the cookie does not represent a valid device.

B.2.16   muxTkBind( )

Use muxTkBind( ) to bind a network service to a network interface. Before the network service can send and receive packets from the network, it must bind to one or more network drivers through which the packets will be sent and received. To specify these network drivers and bind to them, use the function muxTkBind( ).

In the call to muxTkBind( ) you must provide the following information:

  • the network driver to bind to (name and unit number)

  • a network service type, based on RFC 1700 or user-defined

  • optional data structures used to exchange information with the driver (typically used when a network service is designed to work with a particular network driver)

  • a set of callback routines used by the MUX (see Table B-1)

  • a key or private data structure which will be passed back when these callbacks are invoked to identify the bound interface

These callback functions are listed in Table B-1 and are described at greater length in 11.3.1 Service Functions Registered Using muxTkBind( ), p.231.

Table B-1 :   Network Service Callback Functions   


Callback Function
Description

stackRcvRtn( )
Receive data from the MUX.
stackErrorRtn( )
Receive an error notification from the MUX.
stackShutdownRtn( )
Shut down the network service.
stackRestartRtn( )
Restart a suspended network service.

Two additional arguments (pNetSvcInfo and pNetDrvInfo) allow the sublayer to exchange additional information with the network driver, depending on requirements specific to the particular service or driver. The Wind River IP network protocol, for instance, expects a driver to pass up certain information, although it does not pass anything back down. These additional arguments may be especially helpful to those network services and network driver types that are naturally "tightly coupled."

As part of the bind phase, the network service typically retrieve the address resolution and mapping functions for each network interface that is being bound to, storing them in a private data structure allocated by the service.

The muxTkBind( ) function returns a cookie that uniquely represents the binding instance and is used to identify that binding instance in subsequent calls. A return value of NULL indicates that the bind failed.

The muxTkBind( ) function is defined as:

void * muxTkBind 
(
char * pName, /* interface name, for example: ln, ei */
int unit, /* unit number */
BOOL (* stackRcvRtn)(void *, long, M_BLK_ID, void *),
STATUS (* stackShutdownRtn)(void *),
STATUS (* stackRestartRtn)(void *),
void (* stackErrorRtn)(void *, END_ERR *),
long type, /* from RFC1700 or user-defined */
char * pProtoName, /* string name of service */
void * pNetCallBackId, /* returned to svc sublayer during recv */
void * pNetSvcInfo, /* ref to netSrvInfo structure */
void * pNetDrvInfo /* ref to netDrvInfo structure */
)

This function returns a cookie that uniquely represents the binding instance, or NULL if the bind fails.

B.2.17   muxTkDrvCheck( )

A network service sublayer uses muxTkDrvCheck( ) to determine whether a particular driver is an NPT driver.


*      
NOTE: Internally, muxTkDrvCheck( ) uses an EIOCGNPT ioctl to ask the driver whether its is an NPT. An NPT returns a zero in response to an EIOCGNPT ioctl.

int muxTkDrvCheck 
(
char * pDevName /* the name of the device being checked */
)

This routine returns 1 if that device is an NPT driver, 0 (zero) otherwise, and ERROR (-1) if the specified device could not be found.

B.2.18   muxTkPollReceive( )

A network service sublayer uses muxTkPollReceive( ) to poll a device for incoming data. If no data is available at the time of the call, muxTkPollReceive( ) returns EAGAIN. The pSpare argument points to any optional spare data provided by an NPT driver. In the case of an END, pSpare will always be NULL or point to NULL.

STATUS muxTkPollReceive 
(
void * pCookie, /* returned by muxTkBind() */
M_BLK_ID pNBuff, /* a vector of buffers passed to us */
void * pSpare /* a reference to spare data is returned here */
)

This function returns OK on success; EAGAIN if no packet is available; ENETDOWN, if the cookie passed in does not represent a loaded device; or an error value specific to the end/nptpollReceive( ) routine registered for the particular driver.

B.2.19   muxTkPollSend( )

Use muxTkPollSend( )is to transmit packets when a driver is in polled-mode. This is the polled-mode equivalent to the interrupt-mode muxTkSend( ). When using muxTkPollSend( ), the driver does not need to call muxAddressForm( ) to complete the packet, nor does it need to prepend an mBlk of type MF_IFADDR containing the destination address. Like muxTkSend( ), this function expects as arguments a cookie identifying the device and a pointer to the mBlk chain containing the data.

STATUS muxTkPollSend 
(
void * pCookie, /* returned by muxTkBind()*/
M_BLK_ID pNBuff, /* data to be sent */
char * dstMacAddr, /* destination MAC address */
USHORT netType, /* network service that is calling us */
void * pSpareData /* spare data passed to driver on each send */
)

This function returns OK, on success; ENETDOWN, if the cookie passed in does not represent a valid device; or an error value specific to the end/nptpollSend( ) routine of the driver being used.

B.2.20   muxTkReceive( )

A driver uses muxTkReceive( ) to pass validated packets up to the MUX.1

The muxTkReceive( ) function forwards the data to the network service sublayer by calling the stackRcvRtn( ) registered for that sublayer.

Arguments to the function call include:

  • a reference to the END object returned by the endLoad( ) or nptLoad( ) function

  • an mBlk or mBlk chain that contains the received frame

  • the offset value into the frame where the data field (the network service layer header) begins

  • the network service type of the service for which the packet is destined2

  • a flag (wrongDstAddr) which should be set to TRUE if the packet being received is not addressed to this device/service interface (which might happen if the driver is in MUX_PROTO_PROMISC mode)

  • a reference to any optional data or information that a network service may expect to accompany the packet

The MUX strips off the frame header before forwarding the packet to the network service, unless the network service is registered as MUX_PROTO_SNARF or MUX_PROTO_PROMISC, in which case it will receive the complete frame.

The function is defined as:

STATUS muxTkReceive 
(
END_OBJ * pEnd,          /* returned by nptLoad() */
M_BLK_ID pMblk,         /* the buffer being received */
long netSvcOffset,  /* offset to network datagram in the packet */
long netSvcType,    /* network service type */
BOOL wrongDstAddr, /* not addressed to this interface */
void * pSpareData     /* out-of-band data */
)

This function returns OK, on success; ERROR, if the cookie is invalid; or FALSE, if no services are bound to the referenced driver.

B.2.21   muxTkSend( )

A network service sublayer uses muxTkSend( ) to transmit packet.

STATUS muxTkSend 
(
void * pCookie, /* returned by muxTkBind()*/
M_BLK_ID pNBuff, /* data to be sent */
char * dstMacAddr, /* destination MAC address */
USHORT netType, /* network service that is calling us */
void * pSpareData /* spare data passed on each send */
)

To send a packet, the caller must supply:

  • the cookie obtained from bind that identifies the bound interface

  • a pointer to the buffer chain (mBlk chain) containing the packet

  • the physical layer address to which the packet is being sent

  • the type of network service that is sending the packet

The data to be sent should be formed into an mBlk chain (if it is not already in this form). If the sublayer has a registered address resolution function for the service/device interface, it should call this function to determine the destination physical-layer address.

The network service may send fully formed physical layer frames to the device. For an END, this is the required and default behavior, but when sending to a device that uses an NPT driver this requires that you set the M_L2HDR flag in the mBlk header.

The muxTkSend( ) routine may return an error indicating that the driver is out of resources for transmitting the packet. You can use this error to establish a flow control mechanism if desired. The sublayer typically waits to send any more packets until the MUX calls the stackRestartRtn( ) callback function.

This function returns OK, if successful; END_ERR_BLOCK, if the send( ) routine of the driver is temporarily unable to complete the send due to insufficient resources or some other problem; ERROR, if the send( ) routine of the driver fails; or ENETDOWN, if the cookie does not represent a valid device.

B.2.22   muxTxRestart( )

A network interface driver uses muxTxRestart( ) to tell a network service that it may resume sending data. That network service is presumed to have paused itself in response to an error returned from a muxTkSend( ) call. A driver can use muxTxRestart( ) to implement flow control.

void muxTxRestart 
(
END_OBJ * pEnd  /* returned by endLoad() or nptLoad() */
)

B.2.23   muxUnbind( )

A network service uses muxUnbind( ) to disconnect from a device. As input, muxUnbind( ) expects a cookie that identifies the device, the driver type that was passed during the bind, and a pointer to the stack*RcvRtn( ) registered at bind-time.

STATUS muxUnbind 
(
void * pCookie, /* returned from muxTkBind() */
long type, /* the device type passed in at bind-time */
FUNCPTR stackRcvRtn /* pointer to the service receive routine */
)

This function returns OK, if the device is successfully unbound; or ERROR otherwise (if errno is set to EINVAL, the device was not bound to the service when this function was called).



B.3    Data Structures

This section provides descriptions for the following structures:

  • DEV_OBJ
  • END_ERR
  • END_OBJ
  • END_QUERY
  • LL_HDR_INFO
  • M2_INTERFACETBL
  • mBlk
  • MULTI_TABLE
  • NET_FUNCS

B.3.1   DEV_OBJ

The MUX uses the DEV_OBJ structure to store the name and control structure of your device. The private control structure, held in the pDevice member of this structure, stores information such as memory pool addresses and other essential data. The DEV_OBJ structure is defined in end.h as:

typedef struct dev_obj 
{
char name[END_NAME_MAX];        /* device name */
int unit;        /* for multiple units */
char description[END_DESC_MAX];  /* text description */
void * pDevice;        /* device control structure */
} DEV_OBJ;
name

unit

description

pDevice

B.3.2   END_ERR

The END_ERR structure is defined as:

typedef struct end_err 
{
INT32 errCode; /* Error code */
char * pMesg; /* NULL-terminated error message */
void * pSpare; /* Pointer to user-defined data */
} END_ERR;

The errCode member of the END_ERR structure is 32 bits long. The lower 16 bits are reserved for system error messages, while the upper 16 bits may be used for custom error messages. Table B-2 lists currently defined error codes:

Table B-2 :   END_ERR Error Codes


Error Code
Description

END_ERR_INFO
This error is informational only.
END_ERR_WARN
A non-fatal error has occurred.
END_ERR_RESET
An error occurred that forced the device to reset itself, but the device has recovered.
END_ERR_FLAGS
The driver has changed the flags member of the END_OBJ structure.
END_ERR_DOWN
A fatal error occurred that forced the device to go down. The device can no longer send or receive packets.
END_ERR_UP
The device was down but has now come up and may again send and receive packets.

B.3.3   END_OBJ

END_OBJ is the head of the structural interface between the MUX and a network interface driver. The driver allocates this structure and initializes some of its elements within its endLoad( ) or nptLoad( ) function. The structure is defined in target/h/end.h and is diagramed in Figure B-1.

Figure B-1 :   The END_OBJ Structure and Related Structures

The MUX manages some of the elements in this structure, but the driver is responsible for setting and managing others:

node

devObject

receiveRtn

STATUS receiveRtn 
(
void *   pCookie, /* The cookie passed in to endLoad() */
M_BLK_ID pMblk    /* The packet, as an mblk chain */
)
outputFilter

pOutputFilterSpare

attached

txSem

flags

IFF_ALLMULTI
This device receives all multicast packets.

IFF_BROADCAST
The broadcast address is valid.

IFF_DEBUG
Debugging is on.

IFF_LINK0
A per link layer defined bit.

IFF_LINK1
A per link layer defined bit.

IFF_LINK2
A per link layer defined bit.

IFF_LOOPBACK
This is a loopback net.

IFF_MULTICAST
The device supports multicast.

IFF_NOARP
There is no address resolution protocol.

IFF_NOTRAILERS
The device must avoid using trailers.

IFF_OACTIVE
Transmission in progress.

IFF_POINTOPOINT
The interface is a point-to-point link.

IFF_PROMISC
This device receives all packets.

IFF_RUNNING
The device has successfully allocated needed resources.

IFF_SIMPLEX
The device cannot hear its own transmissions.

IFF_UP
The interface driver is up.


*      
WARNING: If the driver changes the state of the flags element (for example, marking itself as "down" by setting the IFF_DOWN flag), the driver should export this change by calling muxError( ) with the errCode member of the END_ERR structure set to END_ERR_FLAGS.

pFuncTable

mib2Tbl

multiList

nMulti

protocols

snarfCount

pNetPool

B.3.4   END_QUERY

This structure is designed specifically for use within the EIOCQUERY ioctl command.

typedef struct 
{
int query;         /* the query */
int queryLen;       /* length of expected/returned data */
char queryData[4]; /* 4 byte minimum; 120 byte maximum */
} END_QUERY;

B.3.5   LL_HDR_INFO

The MUX uses the LL_HDR_INFO structure to keep track of link-level header information associated with packets passed from an END to the MUX and from there up to a protocol. An LL_HDR_INFO structure is passed as an argument to an END's stack receive routine.

The LL_HDR_INFO structure is defined as:

typedef struct llHdrInfo 
{
int destAddrOffset; /* destination address offset into mBlk */
int destSize; /* size of destination address */
int srcAddrOffset; /* source address offset into mBlk */
int srcSize; /* size of source address */
int ctrlAddrOffset; /* control info offset into mBlk */
int ctrlSize; /* size of control info */
int pktType; /* type of the packet */
int dataOffset; /* offset into mBlk where data starts */
} LL_HDR_INFO;

B.3.6   M2_INTERFACETBL and M2-ID

The M2_INTERFACETBL is still part of the END_OBJ structure for the purpose of backwards-compatibility, but a new structure, the M2_ID structure, has been added that encompasses and enhances the M2_INTERFACETBL structure.

The M2_ID structure referenced in the END_OBJ includes the elements that were found in the M2_INTERFACETBL structure, and extends this with additional elements from RFC 2233 (see Figure B-2).

Figure B-2 :   The M2_ID Structure and Related Structures

B.3.7   mBlk

Use mBlk structures as a vehicle for passing packets between the driver and protocol layers. The mBlk structure is defined in netBufLib.h as:

typedef struct mBlk 
{
M_BLK_HDR mBlkHdr; /* block header, pointer to mHdr structure */
M_PKT_HDR mBlkPktHdr; /* packet header, pointer to pktHdr structure */
CL_BLK * pClBlk; /* pointer to cluster block */
} M_BLK;

The elements of an mBlk structure are:

mBlkHdr

mBlkPktHdr

pClBlk

Setting appropriate values for the members of an mBlk structure and the structures referenced by an mBlk structure is most easily accomplished by calling the appropriate netBufLib routines for the creation of an mBlk/clBlk/cluster construct.

B.3.8   MULTI_TABLE

The MULTI_TABLE structure is defined as follows:

typedef struct multi_table 
{
long    len;      /* length of table, in bytes */
char * pTable; /* pointer to entries */
} MULTI_TABLE;

B.3.9   NET_FUNCS

The MUX uses this structure to reference the functions implemented for a driver. The NET_FUNCS structure is defined as:

typedef struct net_funcs 
{
STATUS    (* start)(void *);
STATUS    (* stop)(void *);
STATUS    (* unload)(void *);
int       (* ioctl)(void *, int, caddr_t);
STATUS    (* send)(void *, M_BLK_ID);
STATUS    (* mCastAddrAdd)(void *, char*);
STATUS    (* mCastAddrDel)(void *, char*);
STATUS    (* mCastAddrGet)(void *, MULTI_TABLE*);
STATUS    (* pollSend)(void *, M_BLK_ID);
STATUS    (* pollRcv)(void *, M_BLK_ID);
M_BLK_ID  (* formAddress)(M_BLK_ID, M_BLK_ID, M_BLK_ID, BOOL );
STATUS    (* packetDataGet)(M_BLK_ID, LL_HDR_INFO *);
STATUS    (* addrGet)(M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID, M_BLK_ID);
int       (* endBind)(void *, void *, void *, long );
} NET_FUNCS;

The driver functions referred to in this structure are described in greater detail elsewhere (see NPT Driver Entry Points Exported to the MUX, p.209 and END Entry Points Exported to the MUX, p.195).


1:  This function is registered by the MUX as the receiveRtn in the END_OBJ data structure for the device. The driver should make a call to this reference rather than calling muxTkReceive( ) directly.

2:  Typically, this value can be found in the header of the received frame.