-- File: ChecksumsImpl.mesa - last edit:
-- AOF 13-Aug-87 16:42:23
-- Copyright (C) 1984, 1986, 1987 by Xerox Corporation. All rights reserved.
DIRECTORY
Checksums USING [ComputeChecksum],
Environment USING [bytesPerWord],
Inline USING [BITAND, BITNOT, BITROTATE],
Mopcodes USING [zADD, zACD, zDUP, zINC, zJNEB, zLIN1, zLI0],
NSBuffer USING [Body],
NSTypes USING [base, BufferBody, TransportControl];
ChecksumsImpl: PROGRAM
IMPORTS Checksums, Inline
EXPORTS Checksums
SHARES NSTypes =
BEGIN
RawWords: TYPE = LONG POINTER TO RawWord;
RawWord: TYPE = RECORD[SEQUENCE COMPUTED WORD OF WORD];
bpw: NATURAL = Environment.bytesPerWord;
transportControlOffset: CARDINAL =
LOOPHOLE[@NSTypes.base.pktLength, CARDINAL] +
SIZE[CARDINAL --pktLength field--];
-- These procedures sets the checksum field of the NS Packet.
SetChecksum: PUBLIC PROC[b: NSBuffer.Body] =
BEGIN
b.checksum ← Checksums.ComputeChecksum[
0, (b.pktLength + bpw - 1) / bpw - 1, @b.pktLength];
END;
-- These procedures checks the checksum field of the NS Packet,
-- and returns TRUE or FALSE. The buffer is always a system buffer
TestChecksum: PUBLIC PROC[b: NSBuffer.Body]
RETURNS [BOOLEAN] =
BEGIN
cs: CARDINAL; --local used so we can look at cs with debugger
IF b.checksum = 177777B THEN RETURN[TRUE];
cs ← Checksums.ComputeChecksum[
0, (b.pktLength + bpw - 1) / bpw - 1, @b.pktLength];
RETURN[b.checksum = cs];
END;
SlowlyComputeChecksum: PUBLIC PROC[
cs: CARDINAL, nWords: CARDINAL, p: LONG POINTER] RETURNS [CARDINAL] =
BEGIN
t: CARDINAL;
THROUGH [0..nWords) DO
IF cs > (t ← cs + p↑) THEN cs ← t + 1 ELSE cs ← t;
IF cs >= 100000B THEN cs ← cs*2 + 1 ELSE cs ← cs*2;
p ← p + 1;
ENDLOOP;
IF cs = 177777B THEN cs ← 0;
RETURN[cs];
END;
-- This procedure updates the checksum field of the NS Packet
-- after it increments the nsTransportControl.
IncrNSTransportControlAndUpdateChecksum: PUBLIC PROC[b: NSBuffer.Body] =
BEGIN
resisdual: INTEGER;
newVal, oldVal: WORD;
raw: RawWords = LOOPHOLE[b];
oldVal ← raw[transportControlOffset]; --save the old value before mods
b.transportControl.hopCount ← SUCC[b.transportControl.hopCount]; --modify
IF b.checksum = 177777B THEN RETURN;
newVal ← raw[transportControlOffset]; --capture the new value
resisdual ← Inline.BITAND[
(b.pktLength + bpw - 1) / bpw - transportControlOffset, 17B];
b.checksum ← OnesAdd[
b.checksum, Inline.BITROTATE[OnesSub[newVal, oldVal], resisdual]];
END; -- UpdateChecksum
OnesAdd: PROC[a, b: WORD] RETURNS [CARDINAL] = MACHINE CODE
BEGIN
-- c ← a + b; IF c < a THEN c ← c + 1; IF c=177777B THEN c ← 0;
Mopcodes.zLI0;
Mopcodes.zACD;
Mopcodes.zADD;
Mopcodes.zDUP;
Mopcodes.zLIN1;
Mopcodes.zJNEB, 3;
Mopcodes.zINC;
END;
OnesSub: PROC[a, b: WORD] RETURNS [CARDINAL] = INLINE
{RETURN[OnesAdd[a, Inline.BITNOT[b]]]};
END. -- ChecksumsImpl
LOG
17-May-84 10:21:03 AOF Post Klamath
18-Aug-86 15:48:41 AOF Trying to get back bytes for 14.0 BufferMgr
13-Aug-87 13:25:58 AOF Computing increment checksums correctly