perm filename PUPGAT.MAC[S,NET]1 blob sn#634033 filedate 1981-12-11 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	<PUP>PUPGAT.MAC14     2-SEP-79 16:00:23    EDIT BY TAFT
C00004 00003	GATSRV SNDINF RECINF
C00007 00004	RECIN1 RECIN2 RECIN3 RECIN4 RECIN5
C00011 00005	GATCHK GATCH1 GATCH2 GATCH4 GATCH6 GATCH9
C00015 00006	BLDGIP BLDGI1 BLDGI2 STNXRT STNXR1 STNXR2 GATENT
C00018 00007	GATINI GATIN1 GATIN2 GATIN3 GATIN4 GATIN6
C00023 ENDMK
C⊗;
;<PUP>PUPGAT.MAC;14     2-SEP-79 16:00:23    EDIT BY TAFT
;<PUP>PUPGAT.MAC;13    27-APR-77 12:34:35    EDIT BY TAFT
;<PUP>PUPGAT.MAC;12    18-MAR-77 17:08:43    EDIT BY TAFT
; SEARCH PSVDEF
;<PUP>PUPGAT.MAC;11    30-JAN-77 16:24:34    EDIT BY TAFT
; Do not advertise as being a gateway if ENTFLG is off
;<PUP>PUPGAT.MAC;10    29-OCT-76 14:36:16    EDIT BY TAFT
; Unconditionally update Tenex's RT upon first call to GATCHK
;<PUP>PUPGAT.MAC;9    25-OCT-76 21:30:46    EDIT BY TAFT
; Randomize broadcast interval to avoid getting in sync with
; other gateways.
;<PUP>PUPGAT.MAC;8    20-OCT-76 13:27:31    EDIT BY TAFT
; Remove directly connected net restriction for gateway info
;GATSRV SNDINF RECINF

; Copyright 1979 by Xerox Corporation

	TITLE PUPGAT -- GATEWAY INFORMATION SERVER FOR PUPSRV
	SUBTTL E. A. Taft / October, 1976

	SEARCH PUPDEF,PSVDEF,STENEX
	USEVAR TOPVAR,TOPPVR	; This is part of the top fork




; Gateway Information server (socket 2)

GATSRV::CAIN A,200		; Type = "Are you a gateway"?
	 JRST SNDINF		; Yes, send info response
	CAIN A,201		; Type = "I am a gateway"?
	 JRST RECINF		; Yes, absorb info into our RT
	TLNE F,(DEBUGF)
	 ELOG <Illegal Pup Type %1O from %2P>
	POPJ P,

; Send response to "Are you a gateway" packet
SNDINF:	TLNE F,(GATEWF)		; Is this host a gateway?
	TLNN F,(GATINF)		; Has initialization finished?
	 POPJ P,		; No, just ignore request
	PUSHJ P,GATENT		; Yes, is ENTFLG set?
	 POPJ P,		; No, ignore
	PUSHJ P,SWPPRT##	; Yes, swap source and destination
	PUSHJ P,BLDGIP		; Build gateway info packet
	MOVEI A,201		; Reply Pup Type
	PUSHJ P,SNDPUP##	; Send it off
	 POPJ P,		; Failed
	TLNE F,(DEBUGF)		; Log reply only if debugging
	 LOG <Gateway info for %1P>
	POPJ P,

; Process "I am a gateway" packet and update local routing table
RECINF:	LDB A,PPUPSS		; Get source socket
	LDB B,PPUPSN		; Ignore info from non-directly-
	CAMLE B,MAXNET		;  connected nets
	 TDZA B,B
	 HRRZ B,RTADR-1(B)
	SKIPE B
	CAIE A,2		; Make sure from right guy
	 JRST [	ELOG <Gateway Info Pup from suspect source %2P>
		POPJ P,]
	LDB A,PPUPSN		; Ignore packets from myself
	HRRZ A,RTADR-1(A)
	LDB B,PPUPSH
	CAIN B,(A)
	 POPJ P,
	PUSHJ P,SAVE2##		; Get some more ac's
	MOVEI D,PBCONT(PB)	; Init byte ptr into packet
	HRLI D,(POINT 8)
	LDB C,PUPLEN		; Get pup length
	SUBI C,MNPLEN		; Compute number of content bytes
	ASH C,-2		; Compute number of info blocks
	JUMPLE C,CPOPJ##	; Forget it if none
	HRRZS 0(P)		; Note no RT changes made yet
;RECIN1 RECIN2 RECIN3 RECIN4 RECIN5

; GATSRV (CONT'D)

; Loop here for each info block.
; Update my RT entry for the net given in the block if:
; (1) my RT entry says the net is inaccessible, or
; (2) the info block's hop count +1 is less than my hop count, or
; (3) the Pup source is the gateway thru which we already route, or
; (4) my entry has timed out (not updated in RTTINT seconds).
RECIN1:	ILDB P1,D		; Get net number
	IBP D			; Flush gateway net number
	IBP D			; Flush gateway host number
	ILDB P2,D		; Hop count
	ADDI P2,1		; My hops = his hops +1
	CAIL P1,1		; Make sure net number in range
	CAMLE P1,MAXNET
	 JRST RECIN5		; Not in range, ignore
	HRRZ A,RTADR-1(P1)	; Check local host adr on net
	JUMPN A,RECIN5		; Ignore if directly connected
	SKIPL RTADR-1(P1)	; Net previously inaccessible?
	CAMGE P2,RTHOPS-1(P1)	; Fewer hops on new route?
	 JRST RECIN3		; One of those, set new entry
	LDB A,[POINT 8,RTADR-1(P1),9]  ; Get gateway net in my RT
	LDB B,PPUPSN		; Source net of gateway info Pup
	CAIE A,(B)		; Same?
	 JRST RECIN2		; No, continue
	LDB A,[POINT 8,RTADR-1(P1),17]  ; Get gateway host in my RT
	LDB B,PPUPSH		; Source host of gateway info Pup
	CAIN A,(B)		; Same?
	 JRST [	CAME P2,RTHOPS-1(P1)  ; Yes, same hop count too?
		 JRST RECIN3	; No, do the update
		TIME		; Yes, just reset the timer and
		ADDI A,RTTINT*↑D1000  ; avoid the update expense
		MOVEM A,RTTIME-1(P1)
		JRST RECIN5]
RECIN2:	TIME			; Get now
	CAMGE A,RTTIME-1(P1)	; Has entry timed out?
	 JRST RECIN5		; No, ignore gateway info block

; Replace existing entry with new info block
RECIN3:	CAILE P2,MAXHOP		; Hop count too large?
	 JRST [	MOVSI A,(1B0)	; Yes, declare net inaccessible
		MOVEM A,RTADR-1(P1)
		HRLOI A,377777	; Set timer to infinity
		JRST RECIN4]
	LDB A,PPUPSN		; Gateway net ← Pup source net
	LDB B,PPUPSH		; Gateway host ← Pup source host
	LSH A,8
	IORI A,(B)
	HRLZM A,RTADR-1(P1)	; Zero out rest of entry
	TIME			; Reset timer
	ADDI A,RTTINT*↑D1000
RECIN4:	MOVEM A,RTTIME-1(P1)
	MOVEM P2,RTHOPS-1(P1)	; Set hop count
	TLNE F,(GATINF)		; Initialization complete?
	 HRROS 0(P)		; Yes, remember to update Tenex
RECIN5:	SOJG C,RECIN1		; Repeat for all info blocks
	SKIPGE 0(P)		; Did anything change?
	 PUSHJ P,STNXRT		; Yes, set Tenex RT
	POPJ P,			; Done
;GATCHK GATCH1 GATCH2 GATCH4 GATCH6 GATCH9

; Check routing table and broadcast gateway info packet
; Returns +1
; Clobbers A-D, PB, SV

GATCHK::PUSHJ P,RANDOM##	; Compute time of next call randomly in
	MULI B,<GATINT*↑D1000>/4  ;  range .75*GATINT to 1.25*GATINT
	ADDI B,GATINT*↑D1000
	MOVEM B,GATTIM
	TIME
	ADDM A,GATTIM
	MOVEI SV,SV.GAT		; Set service table index
	TLON F,(GATINF)		; Say initialization is complete
	 PUSHJ P,STNXRT		; First time, update Tenex's RT

; Flush routing table entries that have not been updated
; in the past (2*RTTINT) seconds
	HLLZ C,PUPROU##		; Init AOBJN pointer
	HRRZS 0(P)		; No RT changes made yet
	SUBI A,RTTINT*↑D1000	; RT timer cutoff = 2*RTTINT

GATCH1:	CAMGE A,RTTIME(C)	; Has entry timed out?
	 JRST GATCH2		; No
	MOVSI B,(1B0)		; Yes, declare net inaccessible
	MOVEM B,RTADR(C)
	HRLOI B,377777		; Reset timer to infinity
	MOVEM B,RTTIME(C)
	MOVEI B,MAXHOP+1	; Make route look very poor
	MOVEM B,RTHOPS(C)
	HRROS 0(P)		; Remember that RT has changed
GATCH2:	AOBJN C,GATCH1		; Repeat for all entries in RT

	SKIPGE 0(P)		; Did anything change?
	 PUSHJ P,STNXRT		; Yes, set Tenex RT

; If this host is a gateway, broadcast gateway info packets
; on all directly connected networks
	TLNE F,(GATEWF)		; Are we a gateway?
	TLNN F,(ENABLF)		; In control of system sockets?
	 JRST GATCH9		; No, done
	PUSHJ P,GATENT		; Is ENTFLG set?
	 JRST GATCH9		; No, don't send gateway info
	PUSHJ P,SAVE1##		; Yes, get another ac
	MOVEI PB,SRVPKT##	; Set pointer to PB
	PUSHJ P,BLDGIP		; Build gateway info packet
	HLLZ P1,PUPROU##	; Init AOBJN pointer

GATCH4:	MOVE B,RTADR(P1)	; Get RT entry for net
	TRNE B,-1		; Directly connected?
	TLNN B,(1B1)		; Able to be broadcast upon?
	 JRST GATCH6		; No, bypass
	MOVEI A,1(P1)		; Yes, get net number
	SETZB B,C		; Let Tenex default host and socket
	PUSHJ P,STSPRT##	; Set source port in Pup
	MOVEI C,2		; Dest socket = gateway info
	PUSHJ P,STDPRT##	; Set destination port in Pup
	SETZM PBHEAD+1(PB)	; Zero Pup ID just for kicks
	MOVEI A,201		; Pup type = "I'm a gateway"
	PUSHJ P,SNDPUP##	; Send the Pup
	 CAI			; Failed, forget it
GATCH6:	AOBJN P1,GATCH4		; Repeat for all nets
GATCH9:	SETO SV,		; No service now in progress
	POPJ P,
;BLDGIP BLDGI1 BLDGI2 STNXRT STNXR1 STNXR2 GATENT

; Build gateway info packet
;	PB/ Pointer to packet buffer
; Returns +1:  Contents and length have been setup
; Clobbers A-C

BLDGIP:	HLLZ C,PUPROU##		; Init AOBJN ptr to routing table
	MOVEI A,PBCONT(PB)	; Init byte ptr into packet
	HRLI A,(POINT 8)
BLDGI1:	SKIPGE RTADR(C)		; Check for accessible network
	 JRST BLDGI2		; Not accessible, ignore
	MOVEI B,1(C)		; Ok, compute network number
	IDPB B,A		; Store in packet
	HLRZ B,RTADR(C)		; Get net/host for routing
	ROT B,-8		; Right-justify net
	IDPB B,A		; Append it
	ROT B,8			; Right-justify host
	IDPB B,A		; Append it
	MOVE B,RTHOPS(C)	; Get hop count
	IDPB B,A		; Append it
BLDGI2:	AOBJN C,BLDGI1		; Repeat for all networks
	PUSHJ P,ENDPUP##	; Finish up, set size
	POPJ P,


; Set Tenex's routing table to be equal to mine
; Returns +1
; Clobbers A-D

STNXRT:	TLNN F,(ENABLF)		; Am I enabled?
	 POPJ P,		; No, forget it
	PUSHJ P,SAVE1##		; Save another ac
IFN TENEX,<
	HLLZ P1,PUPROU##	; Init AOBJN ptr to routing table
STNXR1:	MOVE D,RTADR(P1)	; Get my RT entry for net
	TRNE D,-1		; Are we directly connected?
	 JRST STNXR2		; Yes, skip it
	MOVE A,[SIXBIT /PUPROU/]  ; Function name
	MOVEI B,1(P1)		; Net number
	SETO C,			; Mask of bits to change
	OPRFN			; Set the entry in Tenex
	 PUSHJ P,SCREWUP##
STNXR2:	AOBJN P1,STNXR1		; Repeat for all nets
>;IFN TENEX,<
IFN WAITS,<
	PUSHJ P,ROUCLR##	; Clear old our private routing table
	HLLZ A,PUPROU##
	HRRI A,1
	SKIPL B,RTADR-1(A)	; Is this host accessible?
	  PUSHJ P,ROUADD##	; Yes, hash in routing table
	AOBJN A,.-2		; Repeat for each network
	PUSHJ P,ROUSET##
	 ELOG <Failed to set routing table>
>;IFN WAITS
	POPJ P,


; Check whether ENTFLG is on
; Returns +1:  Off
;	+2:  On
; Clobbers A

GATENT:	HRRZ A,ENTFLG##
	GETAB
	 PUSHJ P,SCREWUP##
	JUMPN A,SKPRET##
	POPJ P,
;GATINI GATIN1 GATIN2 GATIN3 GATIN4 GATIN6

; Initialize gateway information server
; Returns +1
; Clobbers A-D, PB, SV

GATINI::MOVEI SV,SV.GAT		; Set service table index
	HLRE A,PUPROU##		; Get negative length of Tenex RT
	MOVNS A			; Make positive
	CAILE A,NNETS		; Make sure in range
	 JRST [	TYPE <Insufficient routing table space (NNETS)>
		HALTF]
	MOVEM A,MAXNET		; Store for my use
	HRRZ A,PUPPAR##		; Get word 2 of pup parameter table
	HRLI A,2
	GETAB
	 PUSHJ P,SCREWUP##
	TLNE A,(1B0)		; Is this host a gateway?
	 TLO F,(GATEWF)		; Yes, set flag
	TIME			; Get now
	ADDI A,↑D10000		; Call GATCHK 10 seconds from now
	MOVEM A,GATTIM

; Initialize local routing table
	MOVE A,PUPROU##		; Get descriptor for Tenex RT
	MOVEI B,RTADR		; Where to put it
	PUSHJ P,REDGTB##	; Read into my space

	TIME			; Get now
	ADDI A,RTTINT*↑D1000	; When to time out RT entry
	HLLZ C,PUPROU##		; Init AOBJN pointer
GATIN1:	SETZM RTHOPS(C)		; Assume directly connected
	HRLOI B,377777		; Set timeout to infinity
	MOVEM B,RTTIME(C)
	SKIPGE B,RTADR(C)	; Network accessible?
	 JRST GATIN2		; No, go set hops to maximum
	TRNE B,-1		; Yes, directly connected?
	 JRST GATIN3		; Yes, done
	MOVEM A,RTTIME(C)	; Indirectly connected, set timer
GATIN2:	MOVEI B,MAXHOP+1	; Make routing look very poor
	MOVEM B,RTHOPS(C)
GATIN3:	AOBJN C,GATIN1		; Repeat for all nets

; Broadcast gateway info requests on all directly connected nets
	PUSHJ P,SAVE1##		; Get another ac
	MOVEI PB,SRVPKT##	; Set pointer to PB
	MOVEI A,MNPLEN		; Minimum-length Pup
	DPB A,PUPLEN
	HLLZ P1,PUPROU##	; Init AOBJN pointer

GATIN4:	MOVE B,RTADR(P1)	; Get RT entry for net
	TRNE B,-1		; Directly connected?
	TLNN B,(1B1)		; Able to be broadcast upon?
	 JRST GATIN6		; No, bypass
	MOVEI A,1(P1)		; Yes, get net number
	SETZB B,C		; Let Tenex default host and socket
	PUSHJ P,STSPRT##	; Set source port in Pup
	MOVEI C,2		; Dest socket = gateway info
	PUSHJ P,STDPRT##	; Set destination port in Pup
	SETZM PBHEAD+1(PB)	; Zero Pup ID just for kicks
	MOVEI A,200		; Pup type = "Are you a gateway"
	PUSHJ P,SNDPUP##	; Send the Pup
	 CAI			; Failed, forget it
GATIN6:	AOBJN P1,GATIN4		; Repeat for all nets
	SETO SV,		; No service now in progress
	POPJ P,


; Storage for this module

GS MAXNET		; Highest allowable net number
GS GATTIM		; Time for next call to GATCHK

; Routing table stuff, indexed by (net number -1)
GS RTADR,NNETS		; Routing table (same format as Tenex's)
GS RTHOPS,NNETS		; Hop count table
GS RTTIME,NNETS		; When to time out routing table entry


	END