{Begin SubSec Support for Other Level One Protocols}
{Title Support for Other Level One Protocols}
{Text
Raw packets other than of type PUP or NS can also be sent and received.  This section describes facilities to support such protocols.  Many of these functions have a {lisp \} in their names to designate that they are system internal, not to be dealt with as casually as user-level functions.

{FnDef {Name \ALLOCATE.ETHERPACKET} {Args}
{Text
Returns an {lisp ETHERPACKET} datum.  Enough of the packet is cleared so that if the packet represents a {lisp PUP} or {lisp NS} packet, that its header is all zeros; no guarantee is made about the remainder of the packet. 
}}

{FnDef {Name \RELEASE.ETHERPACKET} {Args EPKT}
{Text
Returns {arg EPKT} to the pool of free packets.  This operation is dangerous if the caller actually is still holding on to {arg EPKT}, e.g., in some queue, since this packet could be returned to someone else (via {fn \ALLOCATE.ETHERPACKET}) and suffer the resulting contention.

From a logical standpoint, programs need never call {fn \RELEASE.ETHERPACKET}, since the packets are eventually garbage-collected after all pointers to them drop.  However, since the packets are so large, normal garbage collections tend not to occur frequently enough.  Thus, for best performance, a well-disciplined program should explicitly release packets when it knows it is finished with them.
}}

A locally-connected network for the transmission and receipt of Ether packets is specified by a {it network descriptor block}, an object of type {lisp NDB}.  There is one {lisp NDB} for each directly-connected network; ordinarily there is only one.  The {lisp NDB} contains information specific to the network, e.g., its {lisp PUP} and {lisp NS} network numbers, and information about how to send and receive packets on it.

{vardef {Name \LOCALNDBS}
{Text
The first {lisp NDB} connected to this machine, or {lisp NIL} if there is no network.  Any other {lisp NDB}s are linked to this first one via the {lisp NDBNEXT} field of the {lisp NDB}.
}}


In order to transmit an Ether packet, a program must specify the packet's type and its immediate destination.  The type is a 16-bit integer identifying the packet's protocol.  There are preassigned types for {lisp PUP} and {lisp NS}.  The destination is a host address on the local network, in whatever form the local network uses for addressing; it is not necessarily related to the logical ultimate destination of the packet.  Determining the immediate destination of a packet is the task of {it routing}.  The functions {fn SENDPUP} and {fn SENDXIP} take care of this for the {lisp PUP} and {lisp NS} protocols, routing a packet directly to its destination if that host is on the local network, or routing it to a gateway if the host is on some other network accessible via the gateway.  Of course, a gateway must know about the type (protocol) of a packet in order to be able to forward it.

{FnDef {Name ENCAPSULATE.ETHERPACKET} {Args NDB PACKET PDH NBYTES ETYPE}
{Text
Encapsulates {arg PACKET} for transmission on network {arg NDB}.  {arg PDH} is the physical destination host (e.g., an 8-bit pup host number or a 48-bit NS host number); {arg NBYTES} is the length of the packet in bytes; {arg ETYPE} is the packet's encapsulation type (an integer).
}}

{FnDef {Name TRANSMIT.ETHERPACKET} {Args NDB PACKET}
{Text
Transmits {arg PACKET}, which must already have been encapsulated, on network {arg NDB}.  Disposition of the packet after transmission is complete is determined by the value of {arg PACKET}'s {lisp EPREQUEUE} field.
}}



In order to receive Ether packets of type other than {lisp PUP} or {lisp NS}, the programmer must specify what to do with incoming packets.  Lisp maintains a set of {it packet filters}, functions whose job it is to appropriately dispose of incoming packets of the kind they want.  When a packet arrives, the Ethernet driver calls each filter function in turn until it finds one that accepts the packet.  The filter function is called with two arguments: ({arg PACKET} {arg TYPE}), where {arg PACKET} is the actual packet, and {arg TYPE} is its Ethernet encapsulation type (a number).  If a filter function accepts the packet, it should do what it wants to with it, and return {lisp T}; else it should return {lisp NIL}, allowing other packet filters to see the packet.

Since the filter function is run at interrupt level, it should keep its computation to a minimum.  For example, if there is a lot to be done with the packet, the filter function can place it on a queue and notify another process of its arrival.

The system already supplies packet filters for packets of type {lisp PUP} and {lisp NS}; these filters enqueue the incoming packet on the input queue of the socket to which the packet is addressed, after checking that the packet is well-formed and indeed addressed to an existing socket on this machine.

Incoming packets have their {lisp EPNETWORK} field filled in with the {lisp NDB} of the network on which the packet arrived.


{FnDef {Name \ADD.PACKET.FILTER} {Args FILTER}
{Text
Adds function {arg FILTER} to the list of packet filters if it is not already there.  
}}

{FnDef {Name \DEL.PACKET.FILTER} {Args FILTER}
{Text
Removes {arg FILTER} from the list of packet filters.
}}


{FnDef {Name \CHECKSUM} {Args BASE NWORDS INITSUM}
{Text
Computes the one's complement add and cycle checksum for the {arg NWORDS} words starting at address {arg BASE}.  If {arg INITSUM} is supplied, it is treated as the accumulated checksum for some set of words preceding {arg BASE}; normally {arg INITSUM} is omitted (and thus treated as zero).
}}


{FnDef {Name PRINTPACKET} {Args PACKET CALLER FILE PRE.NOTE DOFILTER}
{Text
Prints {arg PACKET} by invoking a function appropriate to {arg PACKET}'s type.  See {fn PRINTPUP} for the intended meaning of the other arguments.  In order for {fn PRINTPACKET} to work on a non-standard packet, there must be information on the list {var \PACKET.PRINTERS}.
}}

{VarDef {Name \PACKET.PRINTERS}
{Text
An association list mapping packet type into the name of a function for printing that type of packet.
}}

}{End SubSec Support for Other Level One Protocols}

{Begin SubSec The SYSQUEUE mechanism}
{Title The SYSQUEUE mechanism}
{Text
The {lisp SYSQUEUE} facility provides a low-level queueing facility.  The functions described herein are all system internal: they can cause much confusion if misused.

A {lisp SYSQUEUE} is a datum containing a pointer to the first element of the queue and a pointer to the last; each item in the queue points to the next via a pointer field located at offset 0 in the item (its {lisp QLINK} field in the {lisp QABLEITEM} record).  A {lisp SYSQUEUE} can be created by calling {lisp (NCREATE 'SYSQUEUE)}.

{FnDef {Name \ENQUEUE} {Args Q ITEM}
{Text
Enqueues {arg ITEM} on {arg Q}, i.e., links it to the tail of the queue, updating {arg Q}'s tail pointer appropriately.
}}

{FnDef {Name \DEQUEUE} {Args Q}
{Text
Removes the first item from {arg Q} and returns it, or returns {lisp NIL} if {arg Q} is empty.
}}

{FnDef {Name \UNQUEUE} {Args Q ITEM NOERRORFLG}
{Text
Removes the {arg ITEM} from {arg Q}, wherever it is located in the queue, and returns it.  If {arg ITEM} is not in {arg Q}, causes an error, unless {arg NOERRORFLG} is true, in which case it returns {lisp NIL}.
}}


{FnDef {Name \QUEUELENGTH} {Args Q}
{Text
Returns the number of elements in {arg Q}.
}}

{FnDef {Name \ONQUEUE} {Args ITEM Q}
{Text
True if {arg ITEM} is an element of {arg Q}.
}}



}{End SubSec The SYSQUEUE mechanism}