Chaosnet (1981)

Published: (June 14, 2026 at 03:14 PM EDT)
64 min read

Source: Hacker News

1 Introduction

Chaosnet is a local network, that is, a system for communication among a group of computers located within one or two kilometers of each other. The name Chaosnet refers to the lack of any centralized control element in this network.

Chaosnet was originally developed in 1975 by the Artificial Intelligence Laboratory of the Massachusetts Institute of Technology as the internal communications medium of the Lisp Machine system [CHINUAL, AIM444]. It has since come to be used to link a variety of machines around the Institute. Chaosnets also exist at several other universities and research laboratories.

The Lisp Machine system is a multi-processor in which each active user is assigned a “personal” computer consisting of a medium-scale processor, a suitable amount of memory, and a swapping disk. Files are stored in a central file-system accessed through Chaosnet. This shared file-system retains the traditional advantages of a time-sharing system, namely inter-user communication, shared programs, and centralized backup and maintenance. At the same time, by giving each active user his own processor, the Lisp Machine system is much more capable than a time-sharing system at executing Lisp programs several million words in size efficiently and with rapid interactive response. Because Chaosnet is taking the place of the file disk in a conventional system, it must be fast (both in response and in throughput), it must be reliable (this is the reason why there is no centralized control), and it must allow connection of several dozen machines. However, it does not need to operate over long distances. Chaosnet is used to access other shared resources in addition to the file system; these include printers, tape drives, and one-of-a-kind specialized processors and I/O devices.

The system goals for Chaosnet were primarily simplicity and high performance. The performance is achieved by starting with a very high speed transmission medium and operating it in a simple, low-overhead fashion, rather than by using unusually clever algorithms. Of course one has to be careful to avoid algorithms which are so simple that they don’t work or waste so much of the transmission medium that performance is impacted. Simplicity was important not only to improve performance, but because Chaosnet connects a diverse set of machines, and hence had to have several implementations all of which require maintenance in proportion to their complexity.

Simplicity of design also aids greatly in maintenance and management of the network itself, which has proven to be a non-trivial task in a network involving a variety of machines and used by a variety of groups, even within the single institution of MIT. It is important to be able to isolate an apparent failure of the whole network to the cable or to a particular host’s hardware or software as rapidly as possible.

The design of Chaosnet was greatly simplified by ignoring problems irrelevant to local networks. Chaosnet contains no special provisions for things such as low-speed links, noisy (very high error-rate) links, multiple paths, and long-distance links with significant transit time. This means that Chaosnet is not particularly suitable for use across the continent or in satellite applications. Chaosnet also makes no attempt to provide unnecessary features such as multiple levels of service or secure communication (other than by end-to-end encryption).

Chaosnet was largely inspired by the pioneering work on local networks at Xerox PARC [ETHERNET].

Chaosnet consists of two parts–the hardware and the software–which, while logically separable, were designed for each other. The hardware provides a carrier-sense multiple-access structure very similar to the PARC Ethernet. Network nodes contend for access to a cable, or ether, over which they may transmit packets addressed to other network nodes. The software defines higher-level protocols in terms of packets. These protocols can be (and are) used with media other than the Chaosnet cable, and with multiple interconnected cables. The software contains ideas borrowed from Ethernet [ETHERNET], TCP [TCP], and Arpanet, with some original ideas and modifications.

2 Hardware Protocol

2.1 The Ether

The transmission medium of Chaosnet is called the ether. Physically it is a coaxial cable, of the semi-rigid 1/2 inch low-loss type used for cable TV, with 75-ohm termination at both ends. At each network node a cable transceiver is attached to the cable. A 10-meter flat cable connects the transceiver to an interface which is attached to a computer’s I/O bus. A network node consists of this transceiver and interface and a computer which executes a certain piece of software called the Network Control Program (NCP), which manages and controls Chaosnet, in addition to whatever application software justifies its existence in the first place.

One network node at a time may seize the ether and transmit a packet, which arrives at all other nodes; each node decides in hardware whether to ignore the packet or to receive it. A single ether must be a linear cable; it may not contain branches nor stubs, and the ends may not be joined into a circle. The maximum length of an ether cable is about 1 kilometer. This is determined by dispersion and by DC attenuation. The maximum number of nodes on a single ether is probably a few dozen. This is determined by degradation of the electrical properties of the cable by the connectors used to attach the transceivers.

The maximum length of an ether could be increased by using repeaters (bidirectional digital amplifiers joining two pieces of cable). In practice this is not done. Instead, the protocol provides for multiple ethers, joined together by nodes called bridges which relay packets from one ether to another. A bridge is typically a pdp11 computer with two or more network interfaces attached to it. A bridge node usually performs other tasks as well, such as interfacing terminals. Bridges attach other network media as well as ethers; some computers connect to the network through their manufacturer’s high speed computer-to-computer interface to a nearby bridge, rather than being interfaced directly to an ether. Asynchronous lines have also been used as Chaosnet media.

The form of information on the ether, the transceiver and interface hardware, and the protocols which control who may seize the ether are described in the following sections.

2.2 Packets

The basic unit of transmission is called a packet. This is a sequence of up to 4032 data bits, plus 48 bits of header information used by the hardware. Packets’ bits are normally grouped into 16-bit words. The division of a transmitted bit stream into packets provides a conveniently-sized unit for resource allocation and error control. The job of the hardware is to deliver a packet from one node to another. Software protocols define the meaning of the data bits in a packet, manage the hardware, compensate for imperfections of the hardware, and provide more useful services than simple transmission of packets from one computer to another.

The hardware header consists of three 16-bit words, called destination, source, and check. The source identifies the node which transmitted this packet onto this ether. This is not necessarily the original source of the message, since it may have originated on a different ether. The destination identifies the node which is intended to receive this packet from this ether. This is not necessarily the final destination of the message; it may be a bridge which should relay the packet to another ether, whence it will eventually reach its final destination. The check word is a cyclic redundancy checksum, generated and checked by hardware, which detects errors in transmission through the ether, entirely-spurious packets created by noise on the cable, and memory errors in the transmitting and receiving packet buffers.

The software protocol is also based on packets, taking 128 of the data bits as a software header. This is described in Packets.

2.3 The Transceiver

Everyone who connects to the ether does so through a transceiver, which is a small box which mounts directly on the cable via a UHF connector and a T-joint. All nodes use identical transceivers (the interface varies depending on what computer it is designed to interface to). The transceiver contains the analog portion of the interface logic, provides ground isolation between the ether cable and the computer, and contains some protective circuitry designed to prevent a malfunctioning program or interface from continuously jamming the ether. (If it were to be redesigned, it ought to contain even more protective circuitry, since there are some possible interface failures that can get past the protection and render the ether unusable.)

The transceiver receives a differential digital signal from the computer interface and impresses it onto the cable as a level of about 8 volts for a 1, or 0 volts (open circuit) for a 0, through a very fast VMOS power FET. When the cable is idle it is held at 0 volts by the terminations. This simple-minded unipolar scheme is adequate for the medium cable lengths and transmission speeds we are using. The transceiver monitors the cable by comparing it against a reference voltage, and returns a differential signal to the interface. In addition, it detects interference (another transceiver transmitting at the same time as this one) and informs the interface.

The transceiver includes indicators (light-emitting diodes) for power OK, transmitted data, received data, and interface attempting to jam the ether. A test button simulates an input of continuous 1’s from the interface, which should light all the lights (dimly) if the transceiver is working. These indicators and the test button are useful for rapidly tracking down network problems. The transceiver requires its own power supply mounted nearby; one power supply can service three transceivers if they are all adjacent. High-voltage isolation between the cable and the computer is provided by optical isolators within the transceiver.

2.4 The Interface

The interface is typically a wire-wrap board containing about 120 TTL logic chips, which plugs into the I/O bus of a computer and connects it to the ether (through a transceiver.) The interface implements the hardware protocols described in the next section, buffers incoming and outgoing packets, generates and checks checksums, and interrupts the host computer when a packet is to be read out of the receive packet buffer or stored into the transmit packet buffer. These packet buffers shield the host computer from the high speed of data transmission on the cable. Instead of having to produce bits at a high rate, the host can produce them at a lower rate, collect them into a packet, and then tell the interface to transmit the packet in a single burst of high-speed transmission.

Interfaces currently exist for Lisp machines, for DEC LSI-11 micro-computers, and for the DEC Unibus [UNIBUS], which allows Chaosnet to be attached to pdp11’s, VAX’s, and the peripheral processors of most pdp10’s. Programming documentation for this compatible family of interfaces appears later in this paper.

Interfaces for other computers are likely to exist in the future. The existing interface design does not make any unusual special demands of its host computer and should be easily adaptable to other architectures.

2.5 Hardware Protocols

The purpose of these protocols is to deliver packets intact from one node to another node on the same ether, with fairly high probability of success, and to guarantee to give an error indication or lose the packet entirely if it is not delivered intact. An additional purpose is to provide high performance and not to bog down when subjected to a heavy load.

Bits are represented on the ether using a technique which is called Upright Biphase NRZI. Each bit cell, which is approximately 250 nanoseconds long, begins with a transition in state, from high to low or from low to high. This transition marks the beginning of a bit cell and provides self-clocking. 3/4 of the way through the bit cell, the state of the cable is sampled; high represents a 1 and low represents a 0. If the bit being represented is the same as the previous bit, there will be one transition at the beginning of the bit cell and a second in the middle of the bit cell. If the bit being represented is the opposite of the previous bit, there will be no transition in the middle of the bit cell since the clock transition will have set the cable to the desired state. The AC frequency of the signal on the cable varies between 1/2 the bit rate and the full bit rate. The information bit-rate is 4 million bits per second.

The self-clocking feature allows for slight variations in transmission and cable propagation speed. However, since the 3/4 of a bit cell delay is a fixed delay, only modest variations in speed can be tolerated. A crystal clock is used as the source of the transmit timing in the interface.

Since there is always at least one state-transition per bit cell, the states where the ether remains high or low for an appreciable time are available for non-data uses. If the ether remains low for more than about two bit cells, it is considered to be not-busy. This condition marks the end of a packet and allows someone else to transmit. Note that if no transceivers are active, the terminations will hold the ether low.

If the ether remains high for about two bit cells, this is an “abort signal”. Abort signals are used for two purposes. If the transceiver detects a collision (two nodes trying to transmit at the same time), each transmitting interface ceases to transmit and sends an abort signal (four bit cells long), which tells all receivers to ignore the aborted packet and ensures that the other transmitter also aborts. Thus when a collision occurs, the ether is cleared as soon as possible to help prevent long tie-ups under conditions of heavy load. The other use for the abort signal is in hardware flow-control. When a receiving interface determines that an incoming packet is addressed to it, but its receive buffer already contains a packet, it sends an abort signal which causes the transmitter to stop. This serves the dual purpose of immediately informing the transmitter that its message did not get through, and preventing the ether from being tied up while a long packet is transmitted which the receiver cannot receive.

Packets are transmitted over the ether in reverse bit-order, for hardware convenience. The three header words, which to the software appear to be at the end of the packet, are transmitted first, in the order check, source, destination. The data words, in reverse order, follow. Words are transmitted least-significant bit first. Of course, the software need not be aware of this reversal; packets arrive at the destination in the same form as they were created by the source. At the end of the packet, an extra zero bit is appended to bring the ether to the low state so that an extra spurious clock-transition will not be generated when it goes idle. This bit is stripped off by the interface and is never seen by software.

The check word is used for error detection, as described above. The source word is made available to the software, which ignores it in most cases, and also serves to synchronize the clocks in the collision-avoidance mechanism which is described below. The destination word is compared by each receiver against its own address. If they match, or if the destination is zero, or if the software selects the “match any destination” mode, the packet is placed in the receive packet buffer and the host computer is interrupted. The zero destination feature is used for “broadcast” messages. Note that a receiver whose packet buffer is full will only generate an abort signal if the packet was specifically addressed to it.

2.6 Ether Contention

Chaosnet has no centralized control element; when a network node has a message to transmit, its interface seizes the ether and transmits a packet. The time when it seizes the ether is determined only by state inside that particular interface and by the local state of the cable at the point where that interface’s transceiver is attached.

If two interfaces should decide to seize the ether and transmit at the same time, their transmissions will interfere and no useful information will be transmitted. This is called a collision. Collisions are the principal limitation on the bandwidth of a heavily-loaded ether-type network, and should be avoided. (However, neither PARC’s network nor MIT’s network has yet been operated with a heavy enough load to make collisions really significant.)

Chaosnet uses a novel collision avoidance technique. First of all, an interface will never initiate transmission unless the ether is seen to be not busy, i.e. it has been in the low state for some time. This ensures that collisions can only occur near the beginning of a packet. Once transmission of a packet has gotten well started, the ether is effectively “seized” (all interfaces realize that it is busy) and transmission will continue successfully through to the end of the packet. The amount of ether transmission time wasted by a collided packet is therefore limited to the round-trip cable propagation delay. This technique is called carrier sense.

Secondly, the hardware uses a time-division technique to attempt to prevent two interfaces from initiating transmission at the same time. This technique should prevent essentially all collisions while imposing only a modest delay in the initiation of transmission. It is designed so that it works better as the load on the ether increases; the wasted time between packets and the relative rate of collisions both decrease.

The basic idea is that each interface is assigned a time-slot, or turn, according to its address. It may only initiate transmission during its turn. The turns are spaced far enough apart that if one interface initiates transmission, every other interface will perceive that the ether is busy by the time its own turn arrives, and will not initiate an interfering transmission. Each interface contains a time-slot counter which counts while the ether is not busy, keeping track of whose turn it is. Each packet synchronizes the counters in all of the interfaces by setting them from the source address of that packet; at the time the packet was transmitted, it must have been the turn of the interface that transmitted it.

Another way to think of this is to make an analogy with ring networks. One can imagine a virtual token which passes down the cable until it gets to the end, then jumps to the beginning of the cable and repeats. An interface may only initiate transmission at the instant the token passes by it. When an interface transmits, the token stops moving and remains at that interface until the end of the packet, whereupon it continues down the cable, passing every other interface, giving them each a chance to transmit before letting the first interface transmit a second packet.

The token is not represented by any physical transmission on the cable. That would constitute a form of centralized control, and would lead to reliability problems if the token was lost or duplicated. Instead, every interface contains a time-slot counter which keeps track of where the token is thought to be. Every time a packet is transmitted these counters are brought up-to-date. The token cannot be lost because a counter by its nature eventually returns to all previous states. It does not matter if the token is duplicated (i.e. the counters lose synchronization) occasionally, since this will only cause collisions, which we know how to detect and deal with, and since the first successful transmission will resynchronize all counters. The basic mechanism of the ether network with contention and collisions is known to work, and the collision-avoidance scheme is an added-on optimization which improves performance without changing the basic mechanism.

There is a finite propagation delay time between interfaces, and this time is not small compared with the bit-rate of Chaosnet, nor when compared with the desirable length of a time slot. This time consists of the delay in the cable, about 5 nanoseconds per meter, and the delay through the two transceivers, about 220 nanoseconds. This propagation delay means that the time-slot counters in two different interfaces cannot be exactly synchronized, and that when interface A initiates transmission interface B will not instantaneously see that the ether is busy. Special relativity tells us that in fact the concept “exactly synchronized” is meaningless. Since the two time-slot counters are not in the same place, the only way we can compare them is to send a message from one to the other, through the ether, containing the reading of the counter. But this message takes non-zero time to get there, so the counter-reading it contains is wrong by the time it is compared against the other counter! We in fact do send messages containing counter readings; the source address in a packet equals the reading of the time-slot counter in the interface that sent it–at the time it was sent. Since the network nodes are not in relative motion, we can measure the distance between them and use that information to improve their synchronization.

What we are trying to do is to prevent collisions. This means that if interface A starts transmitting a packet in its turn, then by the time interface B thinks that its own turn has arrived, it must perceive the ether as busy. We will assign addresses (and hence time slots) and set the length of a time slot in such a way that this will happen. Suppose the maximum delay through the ether between A and B is t. This would be the delay for one of them sending a packet to the other; the delay between A’s receipt of a third party’s packet and B’s receipt of that packet is less, especially if the third party is between A and B on the cable. Then the maximum perceived difference between a clock at A and a clock at B is 2t; if a message is sent from B to A synchronizing the clocks, and then a message is sent from A to B containing A’s clock reading, at B this clock reading will be slow by 2t.

When a packet transmitted by A arrives at B, B’s clock may read as much as 2t earlier or later than A’s turn, depending on the transmission direction of the last synchronizing message. In order to guarantee that B’s turn has not yet happened, the time between any of A’s turns and any of B’s turns must always be at least 2t, twice the maximum propagation delay through the ether between A and B. This is the important idea! We cause this to be true by assigning addresses starting at one end of the cable; each node’s address is the previous node’s address plus twice the propagation delay between them, divided by the length of a turn. It is easy to see that if this is done for all adjacent pairs, the condition will automatically be true for non-adjacent pairs as well. When we get to the end of the cable, we must assign a number of empty slots equal to twice the propagation delay of the full length of cable, to provide the necessary separation between the turns of the two nodes at the ends of the cable.

The virtual token travels through the network at a substantially slower speed than a real signal such as a packet; in the fastest case, when nodes are very far apart, it travels at just half the speed of a real signal. Since a Chaosnet ether has the geometry of a line, as compared to the ring net’s circle, the virtual token is also slowed down by the need to return from the end of the cable to the beginning. This slower speed of the token is the price one pays for the increased robustness of Chaosnet as compared with a ring network. In a real system, we slow the token down even more to provide a margin of safety. The speed of the network is not significantly affected by the slow token, since the interval between packet transmissions by a single node is much longer than the round-trip time of the token. Indeed, if the network is being used primarily for file transfer, and hence the packets are large, the transmission time alone for a typical packet is several times the round-trip time of the token. A typical value for the token’s round-trip time is 64 microseconds.

In spite of all this, sometimes collisions will occur anyway. If the cable has been idle for a long time, the various clocks will have lost synchronization. If a source address is corrupted by a transmission error, any interface that sees that source address will set its clock to an incorrect value. Sometimes a packet will collide with random noise rather than another legitimate packet. In addition, the transmitter does not distinguish receiver-busy aborts from real collisions.

When a collision does occur, we recover from it (in software) by retransmitting the packet again a couple of times, hoping that we will be lucky enough not to have another collision, or that the receiver will soon clear its packet buffer. This retransmission is done by the software, not the hardware, since the hardware destroys the packet in its packet buffer in the process of transmitting it. But if collisions continue to occur, we give up and let somebody else have the ether. The packet is lost. A higher level of protocol will soon realize that it has been lost and retransmit it. We assume that there is enough randomness in the higher-level software that the two nodes which originally collided will not collide again on the retransmission by deciding to retransmit at precisely the same instant.

3 Software Protocol–World View

The purpose of the basic software protocol of Chaosnet is to allow high-speed communication among processes on different machines, with no undetected transmission errors. The speed for file transfers in real-life circumstances was to be comparable with an inexpensive magnetic tape drive (30000 characters per second, or about 10 times the speed of the Arpanet). We actually get about double this in some favorable cases. To achieve this speed it was important to design out bottlenecks such as are found in the Arpanet, for instance the control-link which is shared between multiple connections and the need to acknowledge each message before the next message can be sent. The protocol must be simple, for the sake of reliability and to allow its use by modest computer systems. A full Chaosnet Network Control Program is just about half the size of an Arpanet NCP on the same machine, and the protocol allows low-performance implementations to omit some features. A minimal implementation exists for a single-chip microcomputer.

3.1 Connections

The principal service provided by Chaosnet is a connection between two user processes. This is a full-duplex reliable packet-transmission channel. The network undertakes never to garble, lose, duplicate, or resequence the packets; in the event of a serious error it may break the connection off entirely, informing both user processes. User programs may either deal in terms of packets, or ignore packet boundaries and treat the connection as two uni-directional streams of 8-bit or 16-bit bytes.

On top of the connection facility “user” programs build other facilities, such as file access, interactive terminal connections, and data in other byte sizes, such as 36 bits. The meaning of the packets or bytes transmitted through a connection is defined by the particular higher-level protocol in use.

In addition to reliable communication, the protocol provides flow control, includes a way by which prospective communicants may get in touch with each other (called contacting or rendezvous), and provides various network maintenance and housekeeping facilities. These are discussed later.

3.3 Addresses and Indices

Each node (or host) on the network is identified by an address, which is a 16-bit number. These addresses are used in the routing of packets. There is a table (the system hosts table, SYSBIN;HOSTS2, in the case of ITS) which relates symbolic host names to numeric host addresses.

An address consists of two fields. The most-significant 8 bits identify a subnet, and the least-significant 8 bits identify a host within that subnet. Both fields must be non-zero. A subnet corresponds to a single transmission path. Some subnets are physical Chaosnet cables (ethers), while others are other media, for instance an interface between a pdp10 and a pdp11. The significance of subnets will become clear when routing is discussed (see Routing).

When a host is connected to an ether, the host’s hardware address on that ether is the same as its software address, including the subnet field.

A connection is specified by the names of its two ends. Such a name consists of a 16-bit host address and a 16-bit connection index, which is assigned by that host, as the name of the entity inside the host which owns the connection. The only requirements placed by the protocol on indices are that they be non-zero and that they be unique within a particular host; that is, a host may not assign the same index number to two different connections unless enough time has elapsed between the closing of the first connection and the opening of the second connection that confusion between the two is unlikely.

Typically the least-significant n bits of an index are used as a subscript into the operating system’s tables, and the most-significant 16-n bits are incremented each time a table slot is reused, to provide uniqueness. The number of uniquizing bits must be sufficiently large, compared to the rate at which connection-table slots are reused, that if two connections have the same index, a packet from the old connection cannot sit around in the network (e.g. in buffers inside hosts or bridges) long enough to be seen as belonging to the new connection.

It is important to note that packets are not sent between hosts (physical computers). They are sent between user processes; more exactly, between channels attached to user processes. Each channel has a 32-bit identification, which is divided into subnet, host, index, and uniquization fields. From the point of a view of a user process using the network, the Network Control Program section of his host’s operating system is part of the network, and the multiplexing and demultiplexing it performs is no different from the routing performed by other parts of the network. It makes no difference whether two communicating processes run in the same host or in different hosts.

Certain control packets, however, are sent between hosts rather than users. This is visible to users when opening a connection; a contact name is only valid with respect to a particular host. This is a compromise in the design of Chaosnet, which was made so that an operational system could be built without first solving the research and engineering problems associated with making a diverse set of hosts into a uniform, one-level name space.

3.4 Packet Numbers

There are two kinds of packets, controlled and uncontrolled. Controlled packets are subject to error-control and flow-control protocols, described below (see Flow and Error Control), which guarantee that each controlled packet is delivered to its destination exactly once, that the controlled packets belonging to a single connection are delivered in the same order they were sent, and that a slow receiver is not overwhelmed with packets from a fast sender. Uncontrolled packets are simply transmitted; they will usually but not always arrive at their destination exactly once. The protocol for using them must take this into account.

Each controlled packet is identified by an unsigned 16-bit packet number. Successive packets are identified by sequential numbers, with wrap-around from all 1’s to all 0’s. When a connection is first opened, each end numbers its first controlled packet (RFC or OPN) however it likes, and that sets the numbering for all following packets.

Packet numbers should be compared modulo 65536 (2 to the 16th), to ensure correct handling of wrap-around cases. On a pdp11, use the instructions

CMP A,B BMI A_is_less

Do not use the BLT or BLO instruction. On a pdp10, use the instructions

SUB A,B TRNE A,100000 JRST A_is_less

Do not use the CAMGE instruction. On a Lisp machine, use the code

(IF (BIT-TEST #o100000 (- A B)) )

Do not use the LESSP (or can be.INSRT’ed into a Midas program to define symbols for the format of a packet, the packet opcodes, and the states of a connection. The symbol prefixes are %COfor opcodes,%CSfor states,$CPKfor packet-format byte-pointers, and%CP` for packet-format values.

The file SYSENG;NETWRK > can be .INSRT’ed into a Midas program to provide a library of subroutines for opening connections, listening for requests for connection, analyzing network errors and printing useful messages to the user, and accessing the host-name table (SYSBIN;HOSTS2). All system programs that use the Chaosnet do so with the aid of these subroutines. NETWRK supports both Chaosnet and Arpanet. Documentation is provided in comments at the beginning of the file.

9 The TOPS-20/TENEX Implementation

A Chaosnet connection is represented by a JFN obtained from the CHA: device. The standard I/O operations can be performed on such a JFN, in which case the system will open a Chaosnet stream connection and transfer 8-bit bytes in both directions. When a Chaosnet connection is used in this way, it is compatible with the rest of the TOPS-20 file and I/O system.

Alternatively, special operations can be used to send and receive packets and do other Chaosnet-specific operations on a Chaosnet JFN. These are described below.

For more information, see [CPR].

9.1 Opening Connections

A (potential) Chaosnet connection is represented by a JFN. When the JFN is opened, an actual Chaosnet connection is created. The GTJFN syntax is as follows:

The device name is CHA:. The filename is the symbolic name or octal number of the host at the other end of the connection, or a null string if it is desired to listen for an incoming Request For Connection rather than initiating a connection. The extension (filetype) is normally the contact name; some special cases are described below. Use of * names and JFN stepping is not permitted. The directory, generation (version) number, and semicolon attributes are ignored if present.

When the JFN is opened (with OPENF), normally the system will wait for the connection to open up; a user connection (nonblank filename) will wait for a response to be returned to its RFC, and a server connection (blank filename) will wait for an RFC to come in to its contact name. If an RFC is refused or the foreign host is not up, OPENF will return an error. If data mode 6 or 7 is used with OPENF, it will return immediately, without waiting for the connection to open. This is useful if you want to open several Chaosnet connections simultaneously, or if you want to determine the reason for failure if the connection does not open; if the normal data mode 0 OPENF fails, the operating system will not let you read the CLS packet nor do the .MOERR operation (described below).

There are a number of special cases in the GTJFN syntax. If the extension is a null string, then the contact name is specified by OPENF rather than by GTJFN; AC3 contains the number of characters in the contact name in the left half, and the address of the contact name in the right half. In listening mode (the filename is a null string), then if the extension is also null, this JFN will listen to any RFC that is not otherwise serviced. Privileges are required and only one job at a time can do this. This mechanism is used by a system server process. If the filename is null and the extension is a hyphen, the JFN is put in a special mode for simple transactions; packet-level I/O may be used to transmit any number of RFCs and receive any response packets (ANS, FWD, LOS, or CLS).

When a JFN is closed with CLOSF, if it has an open connection the end-of-data protocol is used (an EOF packet is transmitted and its acknowledgement is awaited), and then a CLS packet is transmitted. (This is not completely implemented yet; currently no EOF is sent, and .MOEOF (see below) must be used.) If the JFN is in the RFC-Received state, the RFC is refused by sending a CLS.

9.2 Stream Input and Output

The normal I/O JSYSes (BIN, BOUT, SIN, SOUT) work on Chaosnet JFNs. When the connection was created by listening, doing I/O to it automatically accepts it first (sending an OPN). The input and output data are transmitted as 8-bit bytes in standard data packets (opcode 200). On input, if an EOF packet is encountered the standard end-of-file action occurs. If a CLS or LOS is encountered, or the connection is in a bad state, an error is signalled. The message from the CLS or LOS may be picked up with .MOERR (see below).

On TOPS-20, but not Tenex, the SIBE, SOBE, DIBE, DOBE, SINR, and SOUTR JSYSes may be used. The latter two treat each packet as a separate record.

The OPENF byte size may be either 7 or 8. With a byte size of 8, the raw Chaosnet data bytes are transmitted. With a byte size of 7, the system converts between the ASCII code it uses normally and the Lisp Machine character set, which is standard on Chaosnet. (This is not yet implemented; currently a byte size of 7 will be accepted but will behave the same as 8.)

9.3 Packet Input and Output

It is possible to do packet-level input and output and to deal directly with the details of the Chaosnet protocol by using the special operations described in the following section. Note that stream I/O and packet I/O should not be mixed in the same connection, unless you know exactly what you are doing, since you can get your data out of order.

9.4 Special Operations

GDSTS returns device-dependent status. AC2 returns the state of the connection, and AC3 returns the number of packet slots available in the output window in the left half, and the number of available input packets in the right half. The symbolic names for the connection states are as follows:

.CSCLS The connection is closed (or was never opened).

.CSLSN The connection is listening for an RFC.

.CSRFC An RFC has been received by a listening connection.

.CSRFS An RFC has been sent.

.CSOPN The connection is open.

.CSLOS The connection has been broken by a LOS packet.

.CSINC The connection has been broken by Incomplete Transmission (no response from the other end for a long time).

.CSPRF This is the “permanent RFC” state which is entered by GTJFN with a null filename and an extension of just a hyphen.

MTOPR performs a variety of special operations, with the JFN in AC1, one of the following function codes in AC2, and an argument and/or return value in AC3.

.MOPKS Send a packet. AC3 contains the address of the first word of the packet. An error return is taken if the connection is in a bad state for the kind of packet being transmitted. This will wait for space to be available in the window.

.MOPKR Receive a packet. AC3 contains the address of a 126-word buffer in which the packet is to be stored. This will wait until an input packet arrives.

.MOOPN Accept a Request for Connection. Error if the connection is not in the RFC-received state.

.MOSND Force out any buffered stream output.

.MOEOF Force out any buffered stream output, then send an EOF packet.

.MONOP Force out any buffered stream output, then wait for it to be transmitted and acknowledged. (This is not a “no op”, but .MONOP is the system standard name for this operation.)

.MOERR Returns the error message from a received CLS or LOS packet. An error is signalled if no error message is available. AC3 is a string pointer to where to put the error message; it is updated to point at the terminating null character which makes the message an ASCIZ string.

.MOACN Assigns PSI (interrupt) channels. The left half of AC3 is the channel number for output interrupts, and the right half is the channel number for input and state-change interrupts. Specifying -1 as a channel number disables interrupts. Output interrupts are signalled when the window is full and then an acknowledgement is received which makes some space so that more packets may be output. Input interrupts are signalled when the state changes, and when there are no input packets available and then a packet is received.

.MOSWS Sets the receive window size from AC3.

.MORWS Returns the receive window size in the left half of AC3 and the transmit window size in the right half.

.MOAWS Returns the available space in the transmit window in AC3.

.MOUAC Returns the number of unacknowledged output packets in AC3.

.MOFHS Returns the foreign host number in AC3.

.MOSIZ Returns the maximum packet size in bytes in AC3. This can be smaller than the Chaosnet standard (488) on machines encumbered with an RSX20F front end.

.MOSRT Sets the RFC timeout period in milliseconds from AC3. The maximum is 262 seconds.

9.5 Utility Programs

There are two Chaosnet utility programs, both named CHASTA. One prints one line for each connection that exists, giving its state, number of input and output packets, who it is connected to, etc. The other prints the STATUS protocol information for every host on the network, including the host name, when it was last up, and its packet throughput and error counts. This information is maintained by a system daemon process.

9.6 Server Programs

When an RFC is received for contact-name, if no process is listening for contact-name and the file SYSTEM:CHAOS.contact-name (or DSK:CHAOS.contact-name on Tenex) exists, the server program contained in that file is run. The server program should open CHA:.contact-name. This is implemented by the CHARFC program which runs as a daemon job and opens CHA:., the magic name which gets a copy of all unclaimed RFCs. Normally the server program is run in a freshly-created job, and may log in if it wishes, but if the file is marked as ephemeral (the “;E” attribute), it is run in a subfork of the CHARFC job. Ephemeral servers should be used for protocols that don’t involve a long-term connection.

The TELNET and SUPDUP servers attach their Chaosnet connection directly to an NVT, just as the corresponding Arpanet servers do.

When the system starts up, the file SYSTEM:HOSTS2.BIN (or DSK:HOSTS2.BIN on Tenex) is read in and used to initialize the host name table inside the system used by GTJFN. This is the ITS/TOPS-20/WAITS standard multi-network host table.

10 The Lisp Machine Implementation

Lisp Machine Chaosnet support consists of a set of Lisp functions and data-structure definitions in the chaos: package. There are three important data structures. A conn represents a connection. A pkt represents a packet. A stream is a standard I/O stream which transmits to and receives from a connection. The details of these data structures are described later.

There are two processes which belong to the Chaosnet NCP. The receiver process looks at packets as they arrive from the network. Control packets are processed immediately. Data packets are put on the input packet queue of the connection to which they are directed. The background process wakes up periodically to do retransmission, probing, and certain “background tasks” such as starting up a server when an RFC arrives and processing “connection interrupts” (described below).

10.1 Opening and Closing Connections

10.1.1 User-Side

Function: chaos:connect host contact-name &optional window-size timeout Opens a stream connection, and returns a conn if it succeeds or a string giving the reason for failure. host may be a number or the name of a known host. contact-name is a string containing the contact name and any additional arguments to go in the RFC packet. If window-size is not specified it defaults to 13. If timeout is not specified it defaults to 600 (ten seconds).

Function: chaos:simple host contact-name &optional timeout Taking arguments similar to those of chaos:connect, this performs the user side of a simple-transaction. The returned value is either an ANS packet or a string containing a failure message. The ANS packet should be disposed of (using chaos:return-pkt, see below) when you are done with it.

Function: chaos:remove-conn conn Makes conn null and void. It becomes inactive, all its buffered packets are freed, and the corresponding Chaosnet connection (if any) goes away.

Function: chaos:close conn &optional reason Closes and removes the connection. If it is open, a CLS packet is sent containing the string reason. Don’t use this to reject RFC’s; use chaos:reject for that.

Function: chaos:open-foreign-connection host index &optional pkt-allocation distinguished-port Creates a conn which may be used to transmit and receive foreign protocols encapsulated in UNC packets. host and index are the destination address for packets sent with chaos:send-unc-pkt. pkt-allocation is the “window size”, i.e. the maximum number of input packets which may be buffered. It defaults to 10. If distinguished-port is supplied, the local index is set to it. This is necessary for protocols which define the meanings of particular index numbers.

10.1.2 Server-Side

Function: chaos:listen contact-name &optional window-size wait-for-rfc Waits for an RFC for the specified contact name to arrive, then returns a conn which will be in the RFC Received state. If window-size is not specified it defaults to 13. If wait-for-rfc is specified as nil (it defaults to t) then the conn will be returned immediately without waiting for an RFC to arrive.

Variable: chaos:server-alist Contains an entry for each server which always exists. When an RFC arrives for one of these servers, the specified form is evaluated in the background process; typically it creates a process which will then do a chaos:listen. Use the add-initialization function to add entries to this list.

Function: chaos:accept conn conn must be in the RFC Received state. An OPN packet will be transmitted and conn will enter the Open state. If the RFC packet has not already been read with chaos:get-next-pkt, it is discarded. You should read it before accepting if it contains arguments in addition to the contact name.

Function: chaos:reject conn reason conn must be in the RFC Received state. A CLS packet containing the string reason will be sent and conn will be removed.

Function: chaos:answer-string conn string conn must be in the RFC Received state. An ANS packet containing the string string will be sent and conn will be removed.

Function: chaos:answer conn pkt conn must be in the RFC Received state. pkt is transmitted as an ANS packet and conn is removed. Use this function when the answer is some binary data rather than a text string.

Function: chaos:fast-answer-string contact-name string If a pending RFC exists to contact-name, an ANS containing string is sent in response to it and t is returned. Otherwise nil is returned. This function involves the minimum possible overhead. No conn is created.

10.2 Connection States

Function: chaos:state conn Returns the current state of the connection, as one of the following symbols:

chaos:inactive-state A conn which does not correspond to any Chaosnet connection.

chaos:open-state An open connection.

chaos:rfc-sent-state An RFC has been transmitted and no response has yet been received.

chaos:answered-state An ANS has been received.

chaos:cls-received-state A CLS has been received.

chaos:los-received-state A LOS has been received.

chaos:host-down-state The connection is in the Incomplete Transmission state; communications with the foreign host have broken down.

chaos:listening-state A LSN has been “transmitted” and the connection is awaiting an RFC.

chaos:rfc-received-state An RFC has been received while listening and has not yet been responded to.

chaos:foreign-state The connection is being used with a foreign protocol encapsulated in UNC packets.

Function: chaos:wait conn state timeout &optional whostate Waits until the state of conn is not the symbol state, or until timeout 60ths of a second have elapsed. If the timeout occurs, nil is returned; otherwise t is returned. whostate is the process state to put in the who-line; it defaults to "net wait".

10.3 Stream Input and Output

Function: chaos:stream conn Creates a bidirectional stream which accesses conn, which should be open as a stream connection, as 8-bit bytes. In addition to the usual I/O operations, the following special operations are supported:

:force-output Any buffered output is transmitted. Normally output is accumulated until a full packet’s worth of bytes are available, so that maximum-size packets are transmitted.

:finish Waits until either all packets have been sent and acknowledged, or the connection ceases to be open. If successful, returns t; if the connection goes into a bad state, returns nil.

:eof Forces out any buffered output, sends an EOF packet, and does a :finish.

:clear-eof Allows you to read past an EOF packet on input. Each :tyi will return nil or signal the specified eof error until a :clear-eof is done.

:close Send a CLS packet and remove the connection.

10.4 Packet Input and Output

Input and output on a Chaosnet connection can be done at the whole-packet level, using the functions in this section. A packet is represented by a pkt data structure. Allocation of pkts is controlled by the system; each pkt that it gives you must be given back. There are functions to convert between pkts and strings. A pkt is an art-16b array containing the packet header and data; the chaos:first-data-word-in-pkt’th element of the array is the first 16-bit data word. The leader of a pkt contains a number of fields used by the system.

Function: chaos:pkt-opcode pkt Accessor for the opcode field of pkt’s header. For each standard opcode a symbol exists in the chaos: package, consisting of the standard 3-letter code and a suffix of “-op”, chaos:rfc-op for example. The value of the symbol is the numeric opcode.

Function: chaos:pkt-nbytes pkt Accessor for the number-of-data-bytes field of pkt’s header.

Function: chaos:pkt-string pkt An indirect array which is the data field of pkt as a string of 8-bit bytes. The length of this string is equal to (chaos:pkt-nbytes pkt).

Function: chaos:set-pkt-string pkt &rest strings Copies the strings into the data field of pkt, concatenating them, and sets (chaos:pkt-nbytes pkt) accordingly.

Function: chaos:get-pkt Allocates a pkt for use by the user.

Function: chaos:return-pkt pkt Deallocates a pkt.

Function: chaos:send-pkt conn pkt &optional (opcode chaos:dat-op) Transmits pkt on conn. pkt should have been allocated with chaos:get-pkt and then had its data field and n-bytes filled in. opcode must be a data opcode (200 or more) or EOF. An error is signalled, with condition chaos:not-open-state, if conn is not open.

Function: chaos:send-string conn &rest strings Sends a data packet containing the concatenation of strings as its data.

Function: chaos:send-unc-pkt conn pkt &optional pkt-number ack-number Transmits pkt, an UNC packet, on conn. The opcode, packet number, and acknowledge number fields in the packet header are filled in (the latter two only if the optional arguments are supplied).

Function: chaos:may-transmit conn A predicate which returns t if there is any space in the window.

Function: chaos:finish conn &optional (whostate "Net Finish") Waits until either all packets have been sent and acknowledged, or the connection ceases to be open. If successful, returns t; if the connection goes into a bad state, returns nil. whostate is the process state to display in the who-line while waiting.

Function: chaos:get-next-pkt conn &optional (no-hang-p nil) Returns the next input packet from conn. When you are done with the packet you must give it back to the system with chaos:return-pkt. This can return an RFC, CLS, or ANS packet, in addition to data, UNC, or EOF. If no-hang-p is t, nil will be returned if there are no packets available or the connection is in a bad state. Otherwise an error will be signalled if the connection is in a bad state, with condition name chaos:host-down, chaos:los-received-state, or chaos:read-on-closed-connection. If no packets are available and no-hang-p is nil, chaos:get-next-pkt will wait for packets to come in or the state to change. The process state in the who-line is “NETI”.

Function: chaos:data-available conn A predicate which returns t if there any input packets available from conn.

10.5 Connection Interrupts

Function: chaos:interrupt-function conn This attribute of a conn is a function to be called in the background process when certain events occur on this connection. Normally this is nil, which means not to call any function, but you can use setf to store a function here. Since the function is called in the Chaosnet background process, it should not do any operations that might have to wait for the network, since that could permanently hang the background process.

The function’s first argument is one of the following symbols, giving the reason for the “interrupt”. The function’s second argument is conn. Additional arguments may be present depending on the reason. The possible reasons are:

:input A packet has arrived for the connection when it had no input packets queued. It is now possible to do chaos:get-next-pkt without having to wait. There are no additional arguments.

:output An acknowledgement has arrived for the connection and made space in the window when formerly it was full. Additional output packets may now be transmitted with chaos:send-pkt without having to wait. There are no additional arguments.

:change-of-state The state of the connection has changed. The third argument to the function is the symbol for the new state.

Function: chaos:read-pkts conn Some interrupt functions will want to look at the queued input packets of a connection when they get a :input interrupt. chaos:read-pkts returns the first packet available for reading. Successive packets can be found by following chaos:pkt-link.

Function: chaos:pkt-link pkt Lists of packets in the NCP are threaded together by storing each packet in the chaos:pkt-link of its predecessor. The list is terminated with nil.

10.6 Information and Control

Function: chaos:host-data &optional host host may be a number or a known host name, and defaults to the local host. Two values are returned. The first value is the host name and the second is the host number. If the host is a number not in the table, it is asked its name using the STATUS protocol; if no response is received the name "Unknown" is returned.

Function: hostat &rest hosts Interrogates the specified hosts, or all known hosts if none are specified, with the STATUS protocol and prints the results in columns as a table.

Function: chaos:print-conn conn &optional (short t) Prints everything the system knows about the connection. If short is nil it also prints everything the system knows about each queued input and output packet on the connection.

Function: chaos:print-pkt pkt &optional (short nil) Prints everything the system knows about the packet, except its data field. If short is t, only the first line of the information is printed.

Function: chaos:print-all-pkts pkt &optional (short t) Calls chaos:print-pkt on pkt and all packets on the threaded list emanating from it.

Function: chaos:status Prints the hardware status.

Function: chaos:reset Resets the hardware and software and turns off the network.

Function: chaos:assure-enabled Turns on the network if it is not already on. It is normally always on unless you call one of these functions.

Function: chaos:enable Resets the hardware and turns on the network.

Function: chaos:disable Resets the hardware and turns off the network.

11 The VAX/VMS Implementation

This describes the interface to Chaosnet through the routines in the “CHAOS.B32” BLISS-32 subroutine package. Definitions of standard values are in “NCPDEFS.R32”. Though it is possible to interface to the NCP at the VMS I/O level, it is not recommended practice. All references to Chaosnet in this text are with respect to the subroutine package, and not VMS QIO’s.

A Chaosnet connection is represented by a one longword “channel number”, which has no direct relationship to a VMS channel number. However, for every Chaosnet channel currently allocated, there is an associated VMS channel maintained by the subroutine package.

All of the routines described below are declared “global”.

11.1 Opening and Closing

Function: parse_host (host, ret-host-num) Parses the string pointed to by host (which points to a standard VMS string descriptor), and stores the resulting host number in the word pointed to by ret-host-num. Returns a status code.

Function: chaos_rfc (ret-chan, host, contact-name, wait-time) Opens a new Chaosnet channel and sends an RFC. ret-chan is a longword to receive the channel number. host is a string acceptable to parse_host. contact-name is a pointer to a string descriptor. wait-time is either zero, which means to wait indefinitely for a response to the RFC, or a pointer to a quadword block acceptable to the $SETIMR system service. A status code is returned, which will be SS$_TIMEOUT if the routine times out.

Function: chaos_lsn (ret-chan, contact-name, wait-time) Like chaos_rfc, but “sends” a LSN instead of an RFC. No host is specified.

Function: chaos_accept (chan, window, rfc-arg, ret-rfc-arg-size) Accepts an incoming RFC. The connection must be in RFC-received state. window is the window size. rfc-arg is an optional string descriptor which receives the argument to the RFC. ret-rfc-arg-size is also optional, and gets the argument’s length.

Function: chaos_ans (chan, data, wait-time) Sends an ANS packet to the Chaosnet channel. data points to a string descriptor, wait-time is ignored. A status code is returned, and if an error occurs, the channel is deassigned.

Function: chaos_close (chan, reason) Closes the connection, and deassigns the channel. reason is a pointer to a string descriptor of a string to be included in the CLS packet.

Function: chaos_assign (ret-chan) Assigns a Chaosnet channel, and stores it in the longword pointed to by ret-chan. This routine allocates a VMS channel. A status code is returned.

Function: chaos_deassign (chan) Given a Chaosnet channel previously assigned by chaos_assign, deassigns it and the associated VMS channel.

11.2 Stream Input and Output

Function: chaos_in_char (chan, ret-char, timeout) Returns the next character from the channel in the longword pointed to by ret-char. Waits until a character is available or until timeout, whichever comes first. A status code is returned.

Function: chaos_out_char (chan, char) Outputs one character. Characters are buffered until a packet fills up or until the output is forced out by chaos_force_out. A status code is returned.

Function: chaos_sout (chan, string) Like repeated calls to chaos_out_char: sends string from string descriptor pointed to by string.

Function: chaos_force_out (chan) If doing serial output, and a partial packet is buffered, force it to be sent.

Function: chaos_finish (chan) Does a chaos_force_out, then waits for all packets to be acknowledged by the foreign end.

Function: chaos_eof (chan) Sends an EOF packet after forcing out any buffered output.

11.3 Packet Input and Output

Function: allocate_pkt (size, chan, ret-pkt) Allocates a packet suitable for chaos_in_pkt and chaos_out_pkt. The packet can hold up to size bytes of data; the number of bytes field in the packet’s header is filled in from size. ret-pkt points to a longword to receive a pointer to the packet. A status code is returned.

Function: deallocate_pkt (pkt) Returns a previously allocated packet to the free pool. A packet may be reused, since the I/O routines do not deallocate them, as long as the I/O is being done synchronously. Returns a status code.

Function: chaos_out_pkt (chan, pkt, efn, astadr, astprm) Outputs pkt to chan, waiting if there is no window room available. efn is the event channel to use for waiting. astadr and astprm are as for VMS system services: an AST address and parameter, respectively, that get signalled when the packet is read by the NCP. chaos_out_pkt returns as soon as there is space in the window, without waiting for the NCP to finish transmitting the packet.

Function: chaos_in_pkt (chan, efn, pkt, astadr, astprm) Reads the next input packet, whatever opcode it may be, from the connection, waiting indefinitely if there are no input packets. efn is the event channel to wait on, and astadr and astprm are for an AST to be delivered when the read completes. chaos_in_pkt does not return until the read completes. A status code is returned.

11.4 Checking the State

Function: chaos_xmit_room (chan, wait) Returns SS$_NORMAL if there is room left in the transmit window. Returns an error if the connection went into a bad state. If wait is true, and there is no room left, then chaos_xmit_room waits until room is available. If there is no room left and wait is false, it returns SS$_EXQUOTA.

Function: chaos_state (chan) Updates the state of the Chaosnet channel via a request to the NCP. Returns a status code. To check the state of the connection, first call this routine then look at chan_state in the channel block described below.

Function: chaos_wait (chan, old-state, timeout) Waits until the channel goes out of the specified state or until timeout occurs. Timeout is either zero (no timeout) or a pointer to a quadword block acceptable to $SETIMR. A status code is returned.

Function: chaos_wait_til (chan, state, timeout) Waits until the channel goes into the specified state or until timeout occurs. Timeout is either zero (no timeout) or a pointer to a quadword block acceptable to $SETIMR. A status code is returned.

The channel number is used as an index into the global blockvector channel, defined in the “CHAOS.B32” file. Since BLISS-32 does not allow the field definitions to be global, they should be copied into any program that needs to look inside the channel blockvector. The most useful fields are

chan_state One of the state codes defined below.

chan_sta_txw The window size in the transmit direction.

chan_sta_rxw The window size in the receive direction.

chan_sta_txwa The number of packet slots available in the transmit window.

chan_sta_rxav The number of input packets available.

The states are as follows:

conn_st_closed (0) Connection closed by a CLS packet.

conn_st_rfcrcv (1) RFC received by listening connection.

conn_st_rfcsnt (2) RFC sent, no response yet.

conn_st_open (3) Connection open.

conn_st_los (4) Connection broken by a LOS packet.

conn_st_incom (5) Incomplete transmission (no response from foreign host).

conn_st_new (6) Connection newly allocated.

conn_st_lsn (7) Listening for an incoming RFC.

conn_st_full (%O'400') This bit is set when the transmit window is full. Usually, the remainder of the state will be conn_st_open.

12 The Unix Implementation

Chaosnet support on UNIX is implemented as a device driver in the operating system and a set of user and server programs. The code will run on pdp11 systems running Version 7 UNIX and on VAX systems running the current Berkeley UNIX. The pdp11 version probably requires a processor with separate instruction and data spaces (pdp11/44, /45, or /70); it has not been tried on other processors.

The NCP is implemented entirely in the kernel as a device driver, and is thus accessed from user programs using the normal input/output system calls. Packets received from the network are processed at interrupt level (this may be changed to AST’s in the near future). All other processing is done in system calls issued by user processes.

12.2 Special Files for Creating Connections

There are several special files in the file system that provide ways of creating and accessing connections (these names are defined in ):

CHRFCDEV Opening this file creates a connection to a remote host. The host address should follow the file name as an additional pathname component containing ascii digits representing the Chaosnet address in decimal (soon to be octal). The rest of the pathname after the host address is taken as the contact name that will be sent in the RFC packet. Thus to open a TELNET connection to the host at address 234 use:

#include #include char pathbuf[100]; int fd; sprintf(pathbuf, “%s/%d/%s”, CHRFCDEV, 234, CHAOS_TELNET); fd = open(pathbuf, 2);

To send a message to User at host address 567 use:

sprintf(pathbuf, “%s/%d/%s %s”, CHRFCDEV, 567, CHAOS_SEND, User); fd = open(pathbuf, 1);

Opening CHRFCDEV returns when the response to the RFC is received from the remote host, or a fixed timeout, whichever happens first. Other timeouts may be implemented by the user program, using the alarm system call. ANS packets are acceptable responses. The data in the ANS packet will be readable, and will be followed by end-of-file as with a full connection or a normal file.

CHRFCADEV This device provides the same functions as CHRFCDEV except that it returns immediately after transmission of the RFC packet with the connection in the CSRFCSENT state. This allows the user program to have access to the contents of packets refusing the connection (CLS, LOS). See the CHIOCSWAIT and CHIOCPREAD ioctl’s below.

CHLISTDEV Opening this file creates a connection in the Listening state with the contact name given as the pathname component following the device name. Thus to listen for a TELNET connection use:

sprintf(pathbuf, “%s/%s”, CHLISTDEV, CHAOS_TELNET); fd = open(pathbuf, 2);

Use the CHIOCSWAIT ioctl to wait for a RFC to arrive, and CHIOCREJECT, CHIOCACCEPT, or CHIOCANSWER to respond.

CHURFCDEV This file, the “unmatched RFC server” device, when opened and read will return the contents of RFC packets that have no listener. Read calls on this connection just return RFC data. If another read on this file is done before the RFC is matched, it is discarded. This file may only be opened by one user at a time. Normally this file is opened by the system unmatched-RFC server process.

12.3 Stream Mode Connections

The default mode when a Chaosnet device is opened is stream mode. This mode makes the connection behave like a UNIX file, with the exception that seek system calls are disallowed and read calls will return whatever data is available if there is any. (Rather than returning the full number of bytes requested.) Thus standard I/O library routines can easily be used to read and write on these connections. A normal UNIX end of file indication will be returned on receiving an EOF packet, and will continue to be returned until either the connection is closed or more data arrives on the connection. If the connection is closed before an EOF packet is received (via a CLS or LOS packet arriving or a connection timeout occurring), an error will be returned after all data and EOF packets have been read.

If the file was opened for writing (open mode 1 or 2), then an EOF packet will be sent and its acknowledgement awaited when the file is closed (unless the connection was already closed).

In stream mode all non-data packets are discarded and data packet opcodes are all treated the same. Ioctl’s can be used to read non-data packets (RFC, CLS, LOS etc.) and perform other network specific functions.

The contents of ANS and UNC packets are read as data in the stream, just as if they had been data packets.

12.4 Record Mode Connections

This mode, set on a connection by issuing

ioctl(fd, CHIOCSMODE, CHRECORD);

gives the user program access to packet opcodes and packet boundaries, without any further awareness of network data structures. Read calls from the connection return all the data in a single packet, with the first byte of the data being the opcode in the packet. The count returned is, as normal, the count of bytes transfered, including the opcode. Opcodes are defined in .

RFC, ANS, CLS, LOS, EOF, UNC, FWD, and data packets will be returned to the user. The buffer given must be large enough to fit the entire packet including the opcode byte, or an error is returned.

Write calls must include the desired opcode as the first byte of data and also reflect this byte in the byte count. The data to be written must not exceed the maximum packet size.

If a record mode connection is closed in the OPEN state a CLS packet will automatically be sent. The CHIOCREJECT ioctl should be used to send a CLS packet containing a specific reason.

12.5 TTY Mode Connections

TTY mode (via CHTTY) connections allow the connection to act exactly as a UNIX tty, allowing, for example, remote login service with no extra process for the NVT. Unfortunately, none of the remote protocols (TELNET, SUPDUP) can work over a transparent connection that just acts like a terminal.
This mode is currently unused.

12.6 Foreign Protocol Mode

Used for a connection to transmit and receive foreign protocols encapsulated in UNC packets. (unimplemented)

12.7 IOCTL System Call Commands

The following ioctl codes can be used on Chaosnet connections.

CHIOCSMODE Set the connection mode. Argument is CHSTREAM, CHRECORD, CHTTY, or CHFOREIGN.

CHIOCSWAIT Wait until the connection state changes from the given state (in the third argument). Typically used for listeners waiting for a RFC:

ioctl(fd, CHIOCSWAIT, CSLISTEN);

or for a user end waiting for a respone to a RFC:

ioctl(fd, CHIOCSWAIT, CSRFCSENT);

CHIOCFLUSH In stream mode, send out any data waiting for a full packet. This is done every 1/2 second at clock level anyway.

CHIOCOWAIT Wait for all transmitted data (after doing a CHIOCFLUSH) to be acknowledged by the other end of the connection. If the argument is non-zero, an EOF packet is sent first, and then it must be acknowledged also.

CHIOCGSTAT Get the status of the connection. The argument is the address where the status structure (struct chst in ) will be returned. This is frequently used to ascertain the state of the connection after a CHIOCSWAIT call, or to find out the Chaosnet address of the other end.

CHIOCANSWER When a connection is in the CSRFCRCVD state, this causes data writes on the connection to be sent using an ANS packet. In stream mode, the packet is filled incrementally. In record mode the first packet sent is made into an ANS. In every case only one packet is sent and the connection is made closed.

CHIOCACCEPT When a connection is in the CSRFCRCVD state, this causes an OPEN packet to be sent and the connection opened.

CHIOCREJECT When the connection is in either the CSRFCRCVD or CSOPEN state this causes a CLS packet to be sent, closing the connection. The argument is the address of a null-terminated string which is copied into the close packet.

CHIOCPREAD Read a packet from the received packet queue. Used in stream mode to read control packets that are otherwise ignored. Typically used to read RFC or CLS packets.

CHIOCRSKIP Skip over the unmatched RFC at the head of the unmatched RFC queue and mark it to only be matched against a listen, not queued as an unmatched RFC. This is used by the unmatched RFC server to ignore RFC’s it knows someone else might want.

FIONREAD A normal UNIX ioctl, this returns an integer at the address specified by the argument, containing the number of byes available to be read.

12.8 Signals

All read, write, open, close, and ioctl’s are interruptable except when waiting for buffer allocation. Read and write calls are automatically restarted (on VAX UNIX). All others currently return EINTR errors.

12.9 Software Installation

Global header files are placed in a “chaos” subdirectory of the system header file directory (usually /usr/include) so that #include works.

The kernel code is found in two subdirectories of the kernel source directory, parallel to sys, dev, and conf:

chncp This directory contains the parts of the NCP which do not depend on the operating system. It also contains the actual Chaosnet interface drivers - which do have some operating-system-dependent code. These drivers interface only to the Chaosnet code (except interrupt vectors) and thus are not usable as UNIX device drivers (this may change).

chunix This directory contains the top level device driver interface from the system call level (through cdevsw) to the NCP and some system dependent utilities (buffer allocation etc.)

The NCP needs two entries in the character device switch and one other small change in conf.c.

In the UNIX kernel proper several small changes are required:

nami.c A small (2 line) change is required to nami to allow Chaosnet special files to have additional pathname components after the one that matches the special file in the file system.

clock.c A call to the Chaosnet clock process routine must be placed in the clock routine called every clock tick (this should be done with timeouts but isn’t).

fio.c Several bugs in closef which never were encountered by other drivers need fixing.

All these changes are conditioned on #ifdef CHAOS. In the normal (Berkeley) VAX configuration scheme, normal entries made in the configuration file suffice to cause all the right files to be included in the system if the line

pseudo-device chaos

is specified and the CHAOS option is included in the “options” line. The “files” file gets a few more lines.

For pdp11 UNIX, since the configuration system is much more primitive, some handwork is usually required to make the kernel correctly.

All user program sources can be put in /usr/src/cmd/chaos, /usr/local/src/cmd/chaos, /usr/src/local/cmd/chaos. The make file contains variables for destinations of all programs. The default destination for user programs is /usr/local. Server programs are placed in /usr/local/lib/chaos. The unmatched RFC server (“chserver”) is placed in /etc and should be started in the /etc/rc file at boot time. It may be killed and restarted at any time.

References

The following documents are of some related interest. AIM is an AI Memo of the MIT Artificial Intelligence Laboratory. RFC is a Request for Comments of the Arpanet Network Working Group. IEN is an Internet Experiment Note of the Arpanet Network Working Group.

[AIM444] A. Bawden, R. Greenblatt, et al., Lisp Machine Progress Report, AIM-444.

[CHINUAL] D. Weinreb, D. Moon, Lisp Machine Manual, MIT AI Lab.

[CPR] C. Ryland, TOPS-20 Chaosnet Manual, unpublished.

[ETHERNET] R. Metcalfe, D. Boggs, Ethernet: Distributed Packet Switching for Local Computer Networks, CACM Vol. 19, No. 7, July 1976, p. 395.

[FILE] Documented online on the file AI:LMDOC;CHFILE >.

[FINGER] K. Harrenstien, Name/Finger, RFC-742.

[RFC733] D. Crocker et al., Standard for the Format of Arpa Network Text Messages, RFC-733.

[SUPDUP] M. Crispin, Supdup Protocol, RFC-747, RFC-734.

[TCP] DOD Standard Transmission Control Protocol, IEN-129.

[TELNET] Telnet Protocol Specification, RFC-542.

[TIME] K. Harrenstien, Time Server, RFC-738.

[UDP] J. Postel, User Datagram Protocol, IEN-88.

[UNIBUS] PDP11 Peripherals Handbook, Digital Equipment Corporation.

Packet Opcode Index

Index EntrySection

A ANS (5): Answer to a simple transaction

B BRD (16): Broadcast

C CLS (3): Close connection

D DAT (200-277): 8-bit Data DAT (300-377): 16-bit Data

E EOF (14): End of File

F FWD (4): Forward a request for connection

L LOS (11): Lossage LSN (12): Listen

M MNT (13): Maintenance

O OPN (2): Open connection

R RFC (1): Request for connection RUT (10): Routing Information

S SNS (6): Sense status STS (7): Status

U UNC (15): Uncontrolled Data

0 views
Back to Blog

Related posts

Read more »

Rome Fell and Nobody Noticed

When I first began learning about the Roman Empire in middle school, I was most interested in what everyone else seems to be interested in — the time of Caesar...