• No results found

Loop algorithms for LAN data links

Chapter 3 Management

4.8 Loop algorithms for LAN data links

4.8.1 Loop requester

The procedures below define the algorithm for the Loop Requester.

The LAN loopback protocol uses two message codes, “Forward Data” and “Reply”. Forward Data specifies that the message is to be sent onwards to another station. Reply indicates that the message terminates at this station and should be delivered to a Loop Requester. The mes-

sage sent by the requester in effect consists of a Reply, enveloped in a number of Forward Data envelopes. This provides the mechanism needed to do“loop assistance”.

If assisted loopback is desired, the caller will often supply the data link address of the sta-

tion to use as assistant. If no assistant address is supplied, then the Loop Requester attempts tofind an assistant. Stations willing to be assistant listen to the Loopback Assistance multicast address. Tofind an assistant, the requester sends a loop message to that multicast address, and uses the source address from the first received response as the assistant address for the remainder of the operation.

Note that all Loop messages (except for the one used tofind a loop assistant) are sent as sin-

gle attempts. Since the purpose of the Loop directive is to look for network problems, no retries are done during the operation. Otherwise soft errors would be obscured.

PROCEDURE LAN.LoopRequester (op: POINTER TO Operation; buff: POINTER TO Buffer) RAISES {InvalidResponse, DataLinkError, Timeout};

VAR i, j, offset, buflen: INTEGER; addresses: SET OF LANAddress; target: LANAddress;

BEGIN

op^.Version := V4; (* Initially use V4 format *) addresses := op^.Addresses;

FOR i := 1 TO op^.Count DO

IF i = 1

THEN (* For first one we have to select the address *) LAN.FindAssistant (op, buff); (* Select assistant if we need one *) LOOP

IF addresses = { }

THEN (* No target addresses left to try *) IF op^.Version = V4

THEN (* V4 didn’t work, try it with V3 *) op^.Version := V3;

addresses := op^.Addresses;

LAN.FindAssistant (op, buff); (* Find a V3 assistant if we need one *) ELSE RAISE (Timeout) (* Both versions received no response *) END

ELSE

target := « select and remove an address from addresses »;

LAN.BuildLoopMsg (buff, target, op^.AssistanceType, op^.AssistantAddress, op, i, buflen);

TRY

DLI.RequestResponse (op, buff, buff, op^.Version);

op^.Address := target; (*If we get an answer, that’s the address to use *) EXIT (* Leave the address search loop *)

EXCEPT

| Timeout: (* If no answer, keep on trying addresses *) END

4.8.1: Loop requester

69

END

END (* end of target address search loop *)

ELSE (* Not first message *)

LAN.BuildLoopMsg (buff, target, op^.AssistanceType, op^.AssistantAddress, op, i, buflen); DLI.ReqResp (op, buff, buff, op^.Version)

END;

IF buff^.Length # buflen (* If wrong length response *) THEN

RAISE (InvalidResponse, op^.Count – i) END;

offset := DLI.GetInteger (buff, 0); (* Get skip count *)

j := DLI.GetInteger (buff, offset + 2); (* Receipt number of response *)

IF j # i (* If wrong receipt number *)

OR offset + 4 + op^.Length # buflen (* or wrong offset *) THEN

RAISE (InvalidResponse, op^.Count – i) END;

FOR j := 0 to op^.Length – 1 DO

IF buff^.Data[j + offset + 4] # op^.Data (* Check test data *) THEN

RAISE (InvalidResponse, op^.Count – i) END

END END

END LAN.LoopRequester;

The following procedure builds a LAN Loopback message. The message consists of a Reply message (containing the data), preceded by one or more Forward headers. These headers list the addresses on the path the message is to take. For example, if Transmit assistance is being used, the Loopback message destination address is the assistant address; the first Forward header contains the target station address, and the second forward header contains the station address for our circuit.

PROCEDURE LAN.BuildLoopMsg (buff: POINTER TO Buffer; target: LANAddress; help: HelpType; assistant: LANAddress; op: POINTER TO Operation; receipt: INTEGER; VAR buflen: INTEGER); VAR offset: INTEGER;

BEGIN

DLI.PutInteger (buff, 0, 0); (* Initial skip count = 0 *) IF help IN {Transmit, Full} (* If first hop is to assistant *) THEN

buff^.Destination := assistant; (* Set first hop destination address *) LAN.Forward (buff, 2, target); (* First Forward header points to target *) offset := 10

ELSE (* Receive assistance or no assistance, first hop to target *) buff^.Destination := target;

offset := 2 END;

IF help IN {Receive, Full} (* If assistant used on the way back *) THEN

LAN.Forward (buff, offset, assistant); offset := offset + 8

END;

LAN.Forward (buff, offset, op^.CircPtr^.DataLinkAddress);

(* Last forward header points back to us *) offset := offset + 8;

DLI.PutInteger (buff, offset, Reply); (* Put in Reply header *) DLI.PutInteger (buff, offset + 2, receipt);

FOR j := 0 to op^.Length – 1 DO

buff^.Data[j + offset + 4] := op^.Data (* Load the test data pattern into the buffer *) END;

buflen := op^.Length + offset + 4; (* total loop message length *) buff^.Length := buflen

END LAN.BuildLoopMsg;

PROCEDURE LAN.Forward (buff: POINTER TO Buffer; offset: INTEGER; address; LANAddress); BEGIN

DLI.PutInteger (buff, offset, ForwardData); DLI.PutAddress (buff, offset + 2, address) END LAN.Forward;

PROCEDURE LAN.FindAssistant (op: POINTER TO Operation; buff: POINTER TO Buffer); VAR assistants: SET OF LANAddress;

BEGIN

IF op^.AssistanceType # None (* Need to select an assistant? *) THEN

assistants := op^.AssistantAddresses; (* Initialize the list of addresses to try *) LOOP

IF assistants = { }

THEN (* No assistant addresses left to try *) IF op^.Version = V4

THEN (* V4 didn’t work, try it with V3

op^.Version := V3;

assistants := op^.AssistantAddresses

ELSE RAISE (Timeout) (* Both versions received no response *) END

ELSE

target := « select and remove an address from assistants »; LAN.BuildLoopMsg (buff, target, None, NullAddress, op, –1); TRY

DLI.Transact (op, buff, buff); (* Do a “direct” loop to the selected address *) op^.AssistantAddress := buff^.Source; (* Whoever responds is the assistant *) EXIT (* Leave the assistant search loop *)

EXCEPT

| Timeout: (* If no answer, keep on trying addresses *) END END END END END LAN.FindAssistant;

4.8.2 Loop server

There is always one Loop Server active for each LAN circuit. It keeps a receive pending at all times. When a message comes in (which will have function code ForwardData), the message is modified appropriately and sent onwards. Invalid messages are quietly ignored.

Note that the Loop Server is required to support the full range of valid message sizes for each data link.

PROCEDURE LAN.LoopServer (circ: POINTER TO Circuit); VAR op: POINTER TO Operation;

buff: POINTER TO Buffer; offset: INTEGER;

4.9: XID and TEST algorithms

71

nexthop: LANAddress; BEGIN

NEW (op); (* Get an Operation record *)

op^.CircPtr := circ; op^.Op := LoopServer; LOOP

op^.Address := NullAddress; (* We’ll listen to any remote station address *) op^.Version := Unknown; (* Accept any version *)

DLI.Receive (op, buff, Infinite); (* Wait for a message, however long it takes *) offset := DLI.GetInteger (buff, 0); (* Get the offset value from message *)

IF buff^.Length % offset+10 (* Must have our header plus next guy’s msgtype *) THEN

nexthop := GetAddress (buff, offset+2); (* Get address to send to *) IF nexthop[0] = 0 (* Must not be a multicast address *) THEN

buff^.Destination := nexthop; (* Forwarding address is our destination *) DLI.PutInteger (buff, 0, offset+8); (* Update Offset in message buffer *) DLI.Send (op, buff, op^.Version)

END END;

DLI.ReceiveDone (buff) (* Done using the receive buffer *)

END (* Repeat that forever *)

END LAN.LoopServer;