-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved.
-- PhoneAdoptionPup.mesa, HGM, 26-Oct-85 23:21:47
-- From PhoneAdoptionImpl.mesa - (last edited by LSK 28-Jun-85 14:56:18)
DIRECTORY
Buffer USING [Buffer, Type],
CommFlags USING [doDebug, driverStats],
CommHeap USING [zone],
CommUtil USING [GetEthernetHostNumber],
Driver USING [Network],
Environment USING [bytesPerWord],
ForwarderDefs USING [DoErrorPup],
PhoneAdoption USING [AdoptForNS],
PhoneCreate USING [],
PhoneNet USING [Initialize],
PhoneNetInternal USING [
DataPacketReceived, PacketType, PhoneNetEncap, State, Version1,
phoneEncapsulationOffsetVer1, phoneEncapsulationBytesVer1,
dataOffsetWords,
dataEncapsulationBytes, FindLine,
RegisterCongestionProc, CongestionProc],
Protocol1 USING [
AddFamilyMember, Family,
MatrixRecord, DecapsulatorProc, EncapsulatorProc],
PupDefs USING [PupPackageMake],
PupTypes USING [],
PupRouterDefs USING [ContextObject],
RS232C USING [ChannelHandle, CommParamObject, Create],
RS232CEnvironment USING [],
System USING [NetworkNumber, nullNetworkNumber];
PhoneAdoptionPup: MONITOR
IMPORTS
CommHeap, CommUtil, ForwarderDefs, PhoneAdoption, PhoneNet,
PhoneNetInternal, Protocol1, PupDefs, RS232C
EXPORTS Buffer, PhoneCreate =
BEGIN
Network: PUBLIC TYPE = Driver.Network;
CreateSimplePhoneNet: PUBLIC PROC [lineNumber: CARDINAL, pupNet: CARDINAL, nsNet: System.NetworkNumber] = {
parms: RS232C.CommParamObject ← [full, bitSynchronous, bps9600, directConn[]];
chan: RS232C.ChannelHandle ← RS232C.Create[lineNumber, @parms, preemptAlways, preemptNever];
PhoneNet.Initialize [
lineNumber: lineNumber,
channel: chan,
commParams: @parms,
negotiationMode: active,
hardwareStatsAvailable: TRUE,
clientData: 0,
ourEntityClass: internetworkRouter];
PhoneAdoption.AdoptForNS [lineNumber, FALSE, System.nullNetworkNumber];
AdoptForPup[lineNumber, pupNet ];
};
AdoptForPup: PROC [lineNumber: CARDINAL, pupNetNumber: CARDINAL] =
BEGIN
pupHostNumber: CARDINAL ← CommUtil.GetEthernetHostNumber[];
driver: Driver.Network ← @PhoneNetInternal.FindLine[lineNumber].state.phoneNetObject;
family: Protocol1.Family ← PupDefs.PupPackageMake[];
matrix: Protocol1.MatrixRecord ← [ --AddFamilyMember copies fields
family: family, context: ,
encapsulator: EncapsulatePupPhonenet,
decapsulator: DecapsulatePupPhonenet];
matrix.context ← CommHeap.zone.NEW[PupRouterDefs.ContextObject ← [
protocol: NIL, network: driver,
pupNetNumber: pupNetNumber, pupHostNumber: pupHostNumber]];
Protocol1.AddFamilyMember[driver, @matrix];
PhoneNetInternal.RegisterCongestionProc[pup, CongestionProc];
matrix.family.stateChanged[driver, matrix.context, add]; -- Bug somewhere ##########
END;
--**************** Encapsulation and decapsulation **************
DecapsulatePupPhonenet: Protocol1.DecapsulatorProc =
--PROCEDURE [b: Buffer.Buffer] RETURNS [type: Buffer.Type]
BEGIN
network: Driver.Network = b.network;
state: PhoneNetInternal.State = network.stats;
PhoneNetInternal.DataPacketReceived[state];
IF state.protocolVersion = old THEN RETURN[TypeOfBufferVer1[state, b]];
-- version is # old
SELECT b.encapsulation.spare1 FROM
PhoneNetInternal.dataOffsetWords =>
BEGIN
OPEN pe: LOOPHOLE[b.encapsulation, data PhoneNetInternal.PhoneNetEncap];
RETURN[TypeOfBufferInternal[state, b, pe.data.pktType,
PhoneNetInternal.dataEncapsulationBytes]];
END;
ENDCASE => {IF CommFlags.doDebug THEN ERROR ELSE RETURN[vagrant]};
END;
EncapsulatePupPhonenet: Protocol1.EncapsulatorProc =
BEGIN
network: Driver.Network = b.network;
state: PhoneNetInternal.State = network.stats;
encapsulationLengthBytes: CARDINAL;
IF state.state # data THEN
BEGIN
IF CommFlags.driverStats THEN StatIncr[@state.statsRec[notInDataState]];
b.status ← circuitNotReady;
RETURN;
END;
b.status ← pending;
SELECT TRUE FROM
state.protocolVersion = old =>
BEGIN
OPEN pe: LOOPHOLE[b.encapsulation, ver1 PhoneNetInternal.PhoneNetEncap];
pe.ver1 ← [
offset: PhoneNetInternal.phoneEncapsulationOffsetVer1,
framing0: 0, framing1: 0, framing2: 0, framing3: 0,
recognition: 0, --for auto-recog
pnType: pupPhonePacket, pnSrcID: state.myHostNumber];
encapsulationLengthBytes ← PhoneNetInternal.phoneEncapsulationBytesVer1;
END;
state.protocolVersion = version3 =>
BEGIN
OPEN pe: LOOPHOLE[b.encapsulation, data PhoneNetInternal.PhoneNetEncap];
pe.data ← [
offset: PhoneNetInternal.dataOffsetWords,
spare1: 0, spare2: 0, spare3: 0, spare4: 0,
spare5: 0, pktType: pup, LTA: FALSE, reserved: 0];
encapsulationLengthBytes ← PhoneNetInternal.dataEncapsulationBytes;
END;
ENDCASE => IF CommFlags.doDebug THEN ERROR ELSE NULL;
b.driver.length ←
(b.pup.pupLength + 1 + encapsulationLengthBytes) / Environment.bytesPerWord;
--note that length is in words. Since software checksum is on words,
--it expects the driver to pad.
END; --EncapsulatePupPhonenet
minBytesPerPup: CARDINAL = 22;
TypeOfBufferInternal: PROCEDURE[
state: PhoneNetInternal.State, b: Buffer.Buffer,
pktType: PhoneNetInternal.PacketType,
encapsulationWidthBytes: CARDINAL]
RETURNS[type: Buffer.Type] =
BEGIN
bytes: CARDINAL ← (Environment.bytesPerWord * b.driver.length);
IF bytes < encapsulationWidthBytes THEN GOTO Rejected;
-- control packets can be very short (e.g. null control packets)
bytes ← bytes - encapsulationWidthBytes;
SELECT pktType FROM
pup =>
BEGIN
IF (b.pup.pupLength > bytes) OR
(b.pup.pupLength < minBytesPerPup) THEN GOTO Rejected;
IF CommFlags.driverStats THEN StatIncr[@state.statsRec[pupReceived]];
type ← pup;
END;
ENDCASE => type ← vagrant;
EXITS Rejected =>
BEGIN
IF CommFlags.driverStats THEN
StatIncr[@state.statsRec[pktsRejectedBadLength]];
type ← orphan; --this is a BAD packet
END;
END; --TypeOfBufferInternal
TypeOfBufferVer1: PROCEDURE [state: PhoneNetInternal.State, b: Buffer.Buffer]
RETURNS[type: Buffer.Type] =
--determine buffer type
BEGIN
bytes: CARDINAL ← (Environment.bytesPerWord * b.driver.length);
IF bytes < PhoneNetInternal.phoneEncapsulationBytesVer1 THEN GOTO Rejected;
bytes ← bytes - PhoneNetInternal.phoneEncapsulationBytesVer1;
SELECT LOOPHOLE[b.encapsulation, PhoneNetInternal.Version1].pnType FROM
pupPhonePacket =>
BEGIN
IF (b.pup.pupLength > bytes) OR
(b.pup.pupLength < minBytesPerPup) THEN GOTO Rejected;
IF CommFlags.driverStats THEN StatIncr[@state.statsRec[pupReceived]];
type ← pup;
END;
ENDCASE => type ← vagrant;
EXITS Rejected =>
BEGIN
IF CommFlags.driverStats THEN
StatIncr[@state.statsRec[pktsRejectedBadLength]];
type ← orphan;
END;
END; --TypeOfBufferVer1
-- ****** CONGESTION PROCESSING ****
CongestionProc: PhoneNetInternal.CongestionProc =
-- PROCEDURE [b: Buffer.Buffer, type: TypeOfCongestion];
-- RETURNS [tryAgain: BOOLEAN ← FALSE];
BEGIN
SELECT type FROM
warning => ForwarderDefs.DoErrorPup[b, gatewayResourceLimitsPupErrorCode, "Warning: Output queue getting full"];
discarded => ForwarderDefs.DoErrorPup[b, gatewayResourceLimitsPupErrorCode, "Fatal: Output queue is full"];
ENDCASE => ERROR;
END;
StatIncr: PROCEDURE [counter: LONG POINTER TO LONG CARDINAL] = INLINE
{counter↑ ← (counter↑ + 1) MOD (LAST[LONG CARDINAL] - 1)};
END..