-- 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..