Trailing-Edge
-
PDP-10 Archives
-
BB-F493Z-DD_1986
-
10,7/703mon/router.mac
Click 10,7/703mon/router.mac to
see without markup as text/plain
There are 14 other files named router.mac in the archive. Click here to see a list.
;TITLE ROUTER - Routing Layer Service for DECnet-36 V075
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1976, 1986.
;ALL RIGHTS RESERVED.
SUBTTL Loose ends
;Fix events returned to NTMAN (poorly formatted)
;Don't do BUG??? in RTCRTE if endnode
;Improve LSH's at RTR2R4 - Build into RTROAV when entered into cache?
;Highest address in Partial Routing Update Loss
SUBTTL V. Brownell & Anthony J. Rizzolo/Tarl/AJR/HMP 19 FEB 86
SEARCH D36PAR,MACSYM
SALL
ENTRY RTRINI
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1981,1982,1983,1984,1985,1986 by DIGITAL EQUIPMENT CORPORATION,
; MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
;
XP ROUTER,075
IFN FTOPS20,<
SEARCH PROLOG
TTITLE ROUTER,,< - Routing Layer Service for DECnet-36>
>
IFN FTOPS10,<
SEARCH F,S
TITLE ROUTER - Routing Layer Service for DECnet-36
.CPYRT<1981,1986>
>;END OF IFN FTOPS10
D36SYM ;SET UP D36 SPECIFIC PARAMETERS
IFN FTOPS10,<$RELOC>
XRESCD ;RELOC TO HIGHSEG (RSCOD PSECT ON TOPS-20)
SUBTTL Table of Contents
; Table of Contents for ROUTER
;
;
; Section Page
; 1. V. Brownell & Anthony J. Rizzolo/Tarl/AJR/HMP 15 Jan 85 3
; 2. Table of Contents. . . . . . . . . . . . . . . . . . . 4
; 3. Definitions
; 3.1. External References . . . . . . . . . . . . . 5
; 3.2. Accumulators. . . . . . . . . . . . . . . . . 7
; 3.3. Macros. . . . . . . . . . . . . . . . . . . . 8
; 3.4. Packet Route Header . . . . . . . . . . . . . 9
; 3.5. Router Control Message. . . . . . . . . . . . 10
; 3.6. Routing Vectors . . . . . . . . . . . . . . . 11
; 3.7. NI Hello IINFO format . . . . . . . . . . . . 12
; 3.8. Miscellaneous . . . . . . . . . . . . . . . . 13
; 4. Network management tables. . . . . . . . . . . . . . . 14
; 4.1. Executor counters . . . . . . . . . . . . . . 14
; 4.2. Circuit counters. . . . . . . . . . . . . . . 15
; 4.3. Node parameters . . . . . . . . . . . . . . . 16
; 4.4. Executor parameters . . . . . . . . . . . . . 17
; 4.5. Circuit parameters. . . . . . . . . . . . . . 18
; 5. RTRINI - Initialize Router User. . . . . . . . . . . . 19
; 6. RTRON - Turn Router (and DECnet) On. . . . . . . . . . 20
; 7. RTROFF - Turn Router (and DECnet) Off. . . . . . . . . 21
; 8. RTRSEC - Once a second processing for Router . . . . . 22
; 9. RTRJIF - Once a jiffy processing for Router. . . . . . 23
; 10. RTRLCK - Get the RTR interlock . . . . . . . . . . . . 25
; 11. RTRXMT - NSP's entry into Router . . . . . . . . . . . 27
; 12. RTRFWD - Perform Routing of Message. . . . . . . . . . 28
; 13. RTR2RM - Send Message to Remote Node . . . . . . . . . 34
; 14. RTRBEH - Build header for ethernet data messages . . . 37
; 15. R2NODN - Return Output Done to NSP . . . . . . . . . . 38
; 16. R2NRTN - Return Message to NSP . . . . . . . . . . . . 39
; 17. R2NRCV - Pass received Message to NSP. . . . . . . . . 40
; 18. R2KINI - Initialize a Kontroller's Circuit . . . . . . 41
; 19. R2KCLS - Close the data link circuit . . . . . . . . . 42
; 20. CALKON - Call the Kontroller . . . . . . . . . . . . . 43
; 21. CALQOB - Call CALKON for queued output.. . . . . . . . 44
; 22. XMTFAI/CIRFAI - Transmit/Line failed . . . . . . . . . 45
; 23. RTRRCR - Recompute Routing . . . . . . . . . . . . . . 46
; 24. RTRBSV - Build scratch routing vector. . . . . . . . . 47
; 25. RTRBNV - Build the normal vector from scratch vector . 48
; 26. RTRBMV - Maybe vector update when running as an endnode 49
; 27. RTRUPD - Send routing messages if needed . . . . . . . 50
; 28. RTRSNI - Send hello/routing message on the NI. . . . . 57
; 29. CKECTO - Check the cache timer for each node . . . . . 58
; 30. SELDSR - Select a desiginated router . . . . . . . . . 59
; 31. RTRTMR - Routine to perform timer functions. . . . . . 60
; 32. RTRENH - Send Ethernet end-node hello. . . . . . . . . 67
; 33. RTRCHH - Build common part of Ethernet hellos. . . . . 68
; 34. DSRCHK - Check the DSR timer for each circuit. . . . . 69
; 35. Data Link Layer Interface. . . . . . . . . . . . . . . 70
; 35.1. RTRDLE - Entry into Router from DLL . . . . . 70
; 35.2. RTICCB - Create circuit block . . . . . . . . 72
; 35.3. RTILSC - Process line state change. . . . . . 73
; 35.4. RTIOTC - Process Output Complete. . . . . . . 74
; 35.5. RTIINC - Process Input Complete . . . . . . . 75
; 36. RTRSTI - Send routing intitialization message. . . . . 78
; 37. Control Message Processors
; 37.1. RTCINI - Inititialization Messages. . . . . . 80
; 37.2. RTCVER - Verification Messages. . . . . . . . 82
; 37.3. RTCRTE - Routing Messages . . . . . . . . . . 83
; 37.4. RTCTST - Test or Hello Messages . . . . . . . 85
; 37.5. RTCL2M - Level 2 Routing Messages . . . . . . 86
; 37.6. RTCERH - Ethernet Router Hello. . . . . . . . 87
; 37.7. RHMASR - Hello message if Endnode . . . . . . 88
; 37.8. RHMASR - Hello message if Router. . . . . . . 89
; 37.9. RTCNIE - NI Endnode Hello message . . . . . . 91
; 38. RTCILL - Illegal message received. . . . . . . . . . . 92
; 39. RTRBAV - Build adjacency's routing vector from routing update 93
; 40. RTCRME - Routing message error processor . . . . . . . 96
; 41. RTRPNI - Parse a Message Header for NI Hello messages 97
; 42. PSINFO - Parse the info field of Ethernet router hello 98
; 43. RTRRCV - Read version information from message . . . . 99
; 44. RTRHDP - Parse a Input Router Message Header . . . . . 100
; 45. RTRCTD - Check for valid test pattern in Hello/Test message 103
; 46. RTRGNA - Get node address from message header. . . . . 104
; 47. PADSKP - Skip over pad bytes in an Ethernet message header 105
; 48. Network Management
; 48.1. RTRNMX - Entry into Router. . . . . . . . . . 106
; 48.2. Read/Set/Clear a parameter. . . . . . . . . . 107
; 49. Network management
; 49.1. Common routine for parameters . . . . . . . . 108
; 49.2. Setup for loading parameter data. . . . . . . 109
; 50. Network Management
; 50.1. Qualified parameters. . . . . . . . . . . . . 110
; 50.2. READ node/executor state. . . . . . . . . . . 111
; 50.3. Read circuit state. . . . . . . . . . . . . . 112
; 50.4. Set/Clear executor state. . . . . . . . . . . 113
; 50.5. Set/Clear circuit state . . . . . . . . . . . 114
; 50.6. Show counters . . . . . . . . . . . . . . . . 115
; 50.7. Show and zero counters. . . . . . . . . . . . 115
; 50.8. Return list . . . . . . . . . . . . . . . . . 116
; 50.9. Show known/active nodes . . . . . . . . . . . 117
; 50.10. Show adjacent nodes . . . . . . . . . . . . . 118
; 50.11. Show active circuits. . . . . . . . . . . . . 119
; 50.12. Show known circuits . . . . . . . . . . . . . 120
; 50.13. Return list of adjacencies on a circuit . . . 121
; 51. Network Management Event Interface
; 51.1. Router Event Types. . . . . . . . . . . . . . 122
; 51.2. Event Reason Definitions. . . . . . . . . . . 124
; 51.3. RTNEVT - Event Reporter . . . . . . . . . . . 125
; 51.4. Event Parameter Processors. . . . . . . . . . 126
; 51.5. Event Processor Subroutines . . . . . . . . . 129
; 51.6. Miscellaneous Event Processors. . . . . . . . 130
; 52. Miscellaneous Routines
; 52.1. RTRSAO - Set Adjacency off line . . . . . . . 132
; 52.2. RTRZCB - Zap Circuit Block. . . . . . . . . . 133
; 52.3. RTRZAA - Zap all Adjacancies associated with RC 134
; 53. RTRZAB - Zap an adjacency block. . . . . . . . . . . . 135
; 54. Miscellaneous Routines
; 54.1. RTRMAJ - Make an Adjacency Block. . . . . . . 136
; 54.2. RTRMCB - Make a Circuit Block . . . . . . . . 137
; 54.3. RTRGCB - Get Circuit Block Pointer. . . . . . 138
; 54.4. CPYMSG - Copy all MSDs together . . . . . . . 141
; 55. Miscellaneous Routine
; 55.1. RTRGBS - Get maximum blocksize. . . . . . . . 142
; 56. Miscellaneous Routines
; 56.1. RTRCBS - Get useable blocksize. . . . . . . . 143
; 56.2. FREMSG - Toss a Message . . . . . . . . . . . 144
; 56.3. CKSNRM - Normalize Checksum . . . . . . . . . 145
; 57. Local Router Storage . . . . . . . . . . . . . . . . . 146
; 58. End of ROUTER. . . . . . . . . . . . . . . . . . . . . 147
SUBTTL Definitions -- External References
;These are the external references to the D36COM library of routines.
EXT DNGINI ;INITIALIZE FOR INPUT (DGXYBY)
EXT DNPINI ;INITIALIZE FOR OUTPUT (DPXYBY)
EXT DNP1BY ;PUT ONE BYTE IN MESSAGE
EXT DNP2BY ;PUT TWO BYTES IN MESSAGE
EXT DNPHIO ;Put 4 bytes of ethernet address into message
EXT DNPENA ;DEPOSIT 6 BYTES FOR NI ADDRESSES
EXT DNPEBY ;PUT AN EXTENSIBLE BYTE IN MESSAGE
EXT DNPZB ;Write (T1) bytes of zeros into the message
EXT DNG1BY ;GET ONE BYTE FROM MESSAGE
EXT DNG2BY ;GET TWO BYTES FROM MESSAGE
EXT DNGHIO ;Get four bytes of hi-order ethernet address
EXT DNGENA ;GET SIX BYTES FROM MESSAGE
EXT DNGEBY ;GET EXTENSIBLE BYTE FROM MESSAGE
EXT DNGMSG ;GET DECNET-36 MESSAGE BLOCK
EXT DNFMSG ;FREE MESSAGE BLOCK
EXT DNMINI ;RE-USE MESSAGE BLOCK
EXT DNNMSG ;GET NUMBER OF BUFFERS AVAILABLE TO ROUTER
EXT DNLENG ;GET THE MESSAGE LENGTH
EXT DNSLNG ;FIND THE SEGMENT LENGTH
EXT DNGWDS ;GET SOME WORDS
EXT DNGWDZ ;GET SOME ZEROED WORDS
EXT DNFWDS ;FREE SOME WORDS
EXT DNSWDS ;SMEAR SOME WORDS
EXT DNBKBY ;GO BACKWARDS SOME BYTES
EXT DNSKBY ;SKIP SOME BYTES
EXT DNRPOS ;RETURN POSTION IN MESSAGE
EXT DNGPOS ;GO TO POSITION IN MESSAGE
EXT DNGOPS ;GO TO POSITION IN OUTPUT MESSAGE
EXT DNLMSS ;LINK MESSAGE SEGMENT INTO MESSAGE BLOCK
EXT DNCPMS ;COPY MESSAGE BLOCKS
IFN FTRTST,<
EXT UPDTCK ; Better TODCLK
>
EXT DNGTIM ;RETURN CURRENT UPTIME (IN MS)
EXT NTPARM ; Routine to load parameters
EXT NTCTRS ; Routine to load counters
EXT TIMBAS ;Fractions of a second used for time
; computation
;References to DNADLL
EXT DNDDSP ;Entry into DNADLL
EXT DNDINI ;Initialization point for DNADLL
EXT DNDSEC ;DNADLL second routine
;These are external data locations.
EXT DCNSTA ;THE STATE VARIABLE OF DECNET
EXT DCNTSB ;Maximum system buffers
EXT RTRHOM ; Home area
EXT RTRADR ; Our node number
EXT RTRHIO ; High order Ethernet address
EXT RTRLOO ; Low order Ethernet address
EXT RTRBSZ ; Blocksize we advertise
EXT RTRMXN ; Maximum node address we talk to
EXT RTRMX3 ; Maximum number of Phase III nodes
EXT RTRVER ; Version of ROUTER
EXT RTRECO ; ECO level of ROUTER
EXT RTRCUS ; Customer version
EXT RTRXPW ; Our transmit password
EXT IBBLK ;DECnet-36 initialization block
;This is the reference to LLINKS.
EXT NSPRTR ;THE ONE AND ONLY
;We need to know our node name for Phase II NI messages.
EXT SCTA2N ;PERFORM TRANSLATION FROM ADDRESS TO NODE NAME
;These are some default parameters
EXT %RTMXN ;DEFAULT MAXIMUM NODE NUMBER
EXT %RTMXC ;DEFAULT MAXIMUM CIRCUIT COST
EXT %RTMXH ;DEFAULT MAXIMUM HOPS
EXT %RTMX3 ;MAXIMUM NUMBER OF PHASE III NODES
EXT %RTMXV ;MAXIMUM VISITS COUNT
IFN FTOPS10,EXT %RTADR ;DEFAULT LOCAL ADDRESS
EXT %RTRMA ;"ALL ROUTERS" MULTICAST ADDRESS
EXT %RTEMA ;"ALL ENDNODES" MULTICAST ADDRESS
EXT %RTHIO ;HI PART OF THE NI ADDRESS
EXT %RTHOM ;HOME AREA FOR THIS NODE
EXT %RTMXR ;Default maximum number of routers on the NI
EXT %RTBRA ;NUMBER OF BROADCAST ROUTER ADJACENCIES
EXT %RTBEA ;NUMBER OF BROADCAST ENDNODE ADJACENCIES
EXT %RTPRI ;Priority to be the designated router (NI)
EXT %RTTM1 ;LONG TIMER FOR POINT TO POINT
EXT %RTBT1 ;LONG TIMER FOR BROADCAST
EXT %RTTM3 ;DEFAULT HELLO MESSAGE TIMER
EXT %RTTM4 ;DEFAULT NODE LISTENER TIMEOUT VALUE
EXT %RTT3M ;HELLO TIMER MULTIPLIER FOR NON-BROADCAST
EXT %RTB3M ;HELLO TIMER MULTIPLIER FOR BROADCAST CIRCUITS
EXT %RTITM ;TI TIMER
EXT %RTCTO ;Time we can spend in cache without update
EXT %RTCST ;DEFAULT CIRCUIT COST
EXT %RTVER ;ROUTER VERSION NUMBER
EXT %RTECO ;EDIT LEVEL
EXT %RTCUS ;CUSTOMER EDIT LEVEL
;Other external references
EXT NMXEVT ;REPORT AN EVENT TO NMX
EXT NTEIPV ;TELL NETWORK MANAGEMENT THAT BAD VALUE
EXT KONCST ;TABLE OF DEFAULT COSTS PER KONTROLLER TYPE
EXT EVSDRP ;Whether as an endnode we listen to packets
; sent to multicast ID "all routers"
EXT RTN ;NON-SKIP RETURN
EXT RSKP ;SKIP RETURN
IFN FTOPS10,<
EXT BITTBL ;TABLE OF BITS
BITS==BITTBL
>; END IFN FTOPS10
;Interlock management
IFN FTOPS10,<
; EXT RTRLOK ;ROUTER INTERLOCK
; EXT RTRLKO ;INTERLOCK OWNER
EXT .CPCPN ;CURRENT CPU NUMBER
EXT .CPSK0 ;SKIP IF CURRENT CPU IS BOOT CPU
>
SUBTTL Definitions -- Accumulators
;These are some local AC defintions for Router-36.
RC=FREE1 ;RC USUALLY POINTS TO THE CIRCUIT BLOCK
AJ=FREE2 ;AJ USUALLY POINTS TO THE ADJACENCY ENTRY
PURGE FREE1 ;LOSE THIS SYMBOL
PURGE FREE2 ;LOSE THIS ONE TOO
IFN FTOPS10,<
Q1=T5 ;RE-DEFINE THESE AGAIN
Q2=T6 ;TO MATCH TOPS-20
>
SUBTTL Definitions -- Macros
;Event Logging Macro
DEFINE EVENT(TYPE,TEXT,MSGBLK),<
CALL [
IFN FTTRACE,<
ETRACE RTR,<RTR Event: 'TEXT>
>
MOVX T1,TYPE ;;PUT EVENT TYPE IN T1
IFNB <MSGBLK>,MOVE T4,'MSGBLK ;;IF HE GAVE MB POINTER, GIVE IT
IFB <MSGBLK>, SETZ T4, ;;IF NOT, GIVE RTNEVT A ZERO
CALLRET RTNEVT] ;;CALL THE EVENT PROCESSOR AND RETURN
>
REPEAT 0,<
DEFINE EVENT(TYPE,TEXT,MSGBLK),<
CALL RTNEVT
CAI [IFN FTTRACE,<ETRACE RTR,<RTR Event: 'TEXT>>
TYPE
MSGBLK]
>
>
SUBTTL Definitions -- Packet Route Header
;The first byte of the packet route header is defined in the Router
;section of the message block structure. This is purely for convience
;sake. The whole byte is called RMFST and each bit is defined within
;this field.
;The only other field that has to be defined (other than the source and
;destination address) is the FORWARD field which simply consists of the
;VISITS field.
BEGSTR FW ;FORWARD BYTE
FIELDM VST,77 ; VISITS COUNT
ENDSTR
SUBTTL Definitions -- Router Control Message
;The following are field definitions for the Router Control messages.
;Control message all begin with the field CTLFLG, which specifies the type
;of control message.
BEGSTR CM ;CTLFLG
FIELDM TYP,7_1 ; TYPE OF MESSAGE
FIELDM CTL,1
ENDSTR
;These are the various types of router control messages (in CMTYP).
XP RCM.TI,0 ;Router init
XP RCM.TV,1 ;Router verification
XP RCM.TT,2 ;Router hello and test
XP RCM.1R,3 ;Level 1 routing message
XP RCM.2R,4 ;Level 2 routing message
XP RCM.RH,5 ;Ethernet Router hello message
XP RCM.EH,6 ;Ethernet Endnode hello mesaage
;Routing control messages consist of a RTGINFO entry for every node in
;the network, followed by a two byte checksum.
BEGSTR RG ;RTGINFO
FIELDM HOP,37_^D10 ; HOPS
FIELDM CST,1777 ; COST
ENDSTR
;Transport Initialization control messages start with field TIINFO which
;contains the node type and verification required flags.
BEGSTR TI ;TIINFO
FIELDM RSV,36_3 ; RESERVED
FIELDM BLO,1_3 ;BLOCKING REQUESTED
FIELDM VER,1_2 ; VERIFY FLAG
FIELDM NTY,3 ; NODE TYPE
ENDSTR
XP TI.MXL,^D12 ;MAX LENGTH OF ROUTER INIT MSG
;These are the possible types of nodes that can be at the other end
;of a circuit (in FIELD TINTY).
XP ANT.XX,0 ;RESERVED
XP ANT.L2,1 ;LEVEL 2 ROUTER
XP ANT.L1,2 ;LEVEL 1 ROUTER
XP ANT.RT,2 ;ROUTING
XP ANT.NR,3 ;NON-ROUTING
;Router hello message has NO.HEL bytes of the byte HEL.LO.
XP NO.HEL,^D10 ;NUMBER OF TEST BYTES
XP NO.NIH,^D64 ;Number of test bytes in endnode hello
XP HEL.LO,^O252 ;CONSTANT FOR HELLO AND TEST MESSAGES
SUBTTL Definitions -- Routing Vectors
;These are the definitions for each entry in both the scratch and the
;normal routing vectors. The vectors consist of one entry for each
;possible node in the network. Non-existant (un-reachable) nodes are
;set to the maximum node cost and hops.
BEGSTR RN
FIELD FLG,6 ;Flags
BIT RCH ;If set, node is reachable
BIT LCL ;Node is local NSP user
BIT CHG ;Node status was changed
BIT CCH ;Node is in the on-ethernet cache
BIT MBY ;Node maybe reachable (if we are an endnode)
FILLER 15
FIELD HOP,5 ;MIN HOPS
FIELD CST,10 ;MIN COST
ENDSTR
;Define right justified symbols for max-cost and max-hops.
XP RN%CST,MASK.(WID(RNCST),^D35) ;MAX COST
XP RN%HOP,MASK.(WID(RNHOP),^D35) ;MAX HOPS
SUBTTL Definitions -- NI Hello IINFO format
BEGSTR II
FIELDM TYP,3 ;NODE TYPE
FIELDM VRQ,1_2 ;VERIFICATION REQUIRED (0 FOR NI)
FIELDM RJF,1_3 ;REJECT FLAG
FIELDM VFL,1_4 ;VERIFICATION FAILED
FIELDM MTA,1_5 ;NO MULTI-CAST ACCEPTED
FIELDM BRQ,1_6 ;BLOCKING REQUESTED FLAG
FIELDM RSV,1_7 ;RESERVED BIT
ENDSTR
;These are the values in the IITYP field
XP IIT.L2,1 ;LEVEL 2 ROUTER
XP IIT.L1,2 ;LEVEL 1 ROUTER
XP IIT.EN,3 ;ENDNODE
SUBTTL Definitions -- Miscellaneous
SUBTTL Network management tables
SUBTTL Network management tables -- Executor counters
;Generate the executor counter table
XSWAPCD
EXCTAB:
COUNTER(^D900,^D8,<MOVE T1,RTRCAP>,<SETZM RTRCAP>,,<Aged packet loss>)
COUNTER(^D901,^D16,<MOVE T1,RTRCNU>,<SETZM RTRCNU>,,<
Node unreachable packet loss>)
COUNTER(^D902,^D8,<MOVE T1,RTRCNO>,<SETZM RTRCNO>,,<
Node out-of-range packet loss>)
COUNTER(^D903,^D8,<MOVE T1,RTRCOP>,<SETZM RTRCOP>,,<Oversized packet loss>)
COUNTER(^D910,^D8,<MOVE T1,RTRCPF>,<SETZM RTRCPF>,,<Packet format error>)
COUNTER(^D920,^D8,<MOVE T1,RTRCPR>,<SETZM RTRCPR>,,<
Partial routing update loss>)
COUNTER(^D930,^D8,<MOVE T1,RTRCVR>,<SETZM RTRCVR>,,<Verification reject>)
EXCTBL==.-EXCTAB
SUBTTL Network management tables -- Circuit counters
CICTAB: ;Circuit counters maintained by the circuit
COUNTER (^D0,^D16,<CALL [SAVEAC <T2>
LOAD T2,RCSLZ,(RC) ; Time stamp of last zeroed
CALL DNGTIM ; Current time
SUB T1,T2 ; Compute milliseconds
IDIVI T1,TIMBAS ; and return as seconds
RET ]>,<
CALL [CALL DNGTIM
STOR T1,RCSLZ,(RC)
RET ]>,,<Seconds since zeroed>)
COUNTER(^D800,^D32,<LOAD T1,RCCAP,(RC)>,<SETZRO RCCAP,(RC)>,,<
Terminating packets received>)
COUNTER(^D801,^D32,<LOAD T1,RCCDP,(RC)>,<SETZRO RCCDP,(RC)>,,<
Originating packets sent>)
COUNTER(^D802,^D16,<LOAD T1,RCCAL,(RC)>,<SETZRO RCCAL,(RC)>,,<
Terminating congestion loss>)
COUNTER(^D810,^D32,<LOAD T1,RCCTR,(RC)>,<SETZRO RCCTR,(RC)>,,<
Transit packets received>)
COUNTER(^D811,^D32,<LOAD T1,RCCTS,(RC)>,<SETZRO RCCTS,(RC)>,,<
Transit packets sent>)
COUNTER(^D812,^D16,<LOAD T1,RCCTL,(RC)>,<SETZRO RCCTL,(RC)>,,<
Transit congestion loss>)
COUNTER(^D820,^D8,<LOAD T1,RCCCD,(RC)>,<SETZRO RCCCD,(RC)>,,<Circuit down>)
COUNTER(^D821,^D8,<LOAD T1,RCCIF,(RC)>,<SETZRO RCCIF,(RC)>,,<
Initialization failure>)
COUNTER (^D2500,^D16,<LOAD T1,RCBSX,(RC)>,<SETZRO RCBSX,(RC)>,,<
Transmit packets discarded-blocksize exceeded>)
CICTBL==.-CICTAB
SUBTTL Network management tables -- Node parameters
NOSET==PANST ;From BEGSTR in D36PAR
NOCLR==PANCL
BEX==PABEX ;Buffer expected
NDPTAB:
PARAMETER(0,<NOSET!NOCLR>,,,,,<CALL NMXRNS>,,<Node state>)
PARAMETER(^D810,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN AJ
RNMXND
LOAD T2,AJNTY,(AJ)
RNMXOK ]>,<TRN>,<
Adjacency type>)
PARAMETER(^D820,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN P2
RNMXND
LOAD T2,RNCST,(P2)
RNMXOK ]>,<TRN>,<Cost>)
PARAMETER(^D821,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN P2
RNMXND
LOAD T2,RNHOP,(P2)
RNMXOK ]>,<TRN>,<Hops>)
PARAMETER(^D822,<NOSET!NOCLR>,,,,<TRN>,<LOAD T2,RCLID,(RC)>,<TRN>,<Circuit>)
PARAMETER(^D830,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN AJ
RNMXND
MOVE T2,RTRNTY
CAIE T2,RNT.NR
IFSKP.
LOAD T2,NFEID,(P1)
MOVE T1,T2
LSH T1,-^D10
CAME T1,RTRHOM
IFSKP.
TXZ T2,RN%ARE
ADD T2,RTRNRV
TMNN RNCCH,(T2)
IFSKP.
LOAD T2,NFEID,(P1)
RNMXOK
ENDIF.
ENDIF.
ENDIF.
LOAD T2,AJADR,(AJ)
RNMXOK ]>,<TRN>,<
Next node>)
;Note: The following parmameter is used for the NODE JSYS function .NDGNT
; only. Is is NEVER used by NTMAN and is not part of the specified
; DECnet architecture.
PARAMETER(^D2503,<NOSET!NOCLR>,,,,,<CALL NMXRNS>,,<Node state-I DECnet only>)
NDPTBL==.-NDPTAB
SUBTTL Network management tables -- Executor parameters
EXPTAB:
PARAMETER(0,,,,<DS.ON>,<CALL NMXSES>,<CALL NMXRNS>,<CALL NMXSES>,<
Executor state>)
PARAMETER(^D900,<NOSET!NOCLR>,,,,,<CALL [ MOVE T1,RTRVER
STOR T1,VNVER,+T2
MOVE T1,RTRECO
STOR T1,VNECO,+T2
MOVE T1,RTRCUS
STOR T1,VNUCO,+T2
RNMXOK]>,<TRN>,<Routing version>)
PARAMETER(^D901,,,,<RNT.L1>,<TRN>,<MOVE T2,RTRNTY>,<TRN>,<Router type>)
PARAMETER(^D910,,,,<%RTTM1>,<CALL [IMULI T2,TIMBAS
MOVEM T2,RTRTM1
RNMXOK ]>,<
CALL [MOVE T2,RTRTM1
IDIVI T2,TIMBAS
RNMXOK ]>,<
CALL [IMULI T2,TIMBAS
MOVEM T2,RTRTM1
RNMXOK ]>,<Maximum update interval timer>)
PARAMETER(^D912,,,,<%RTBT1>,<CALL [IMULI T2,TIMBAS
MOVEM T2,RTRBT1
RNMXOK ]>,<
CALL [MOVE T2,RTRBT1
IDIVI T2,TIMBAS
RNMXOK ]>,<
CALL [IMULI T2,TIMBAS
MOVEM T2,RTRBT1
RNMXOK ]>,<Max broadcast update int. timer>)
PARAMETER(^D920,<NOSET!NOCLR>,,,,,<MOVE T2,RTRMXN>,,<Maximum address>)
PARAMETER(^D921,,<^D20>,<^D1>,<^D20>,<MOVEM T2,RTRMCN>,<MOVE T2,RTRMCN>,<
MOVEM T2,RTRMCN>,<Maximum number of circuits>)
PARAMETER(^D922,,<^D1022>,<1>,<%RTMXC>,<MOVEM T2,RTRMXC>,<MOVE T2,RTRMXC>,<
MOVEM T2,RTRMXC>,<Maximum circuit cost>)
PARAMETER(^D923,,<^D30>,<1>,<%RTMXH>,<MOVEM T2,RTRMXH>,<MOVE T2,RTRMXH>,<
MOVEM T2,RTRMXH>,<Maximum hops>)
PARAMETER(^D924,,<^D30>,<1>,<%RTMXV>,<MOVEM T2,RTRMXV>,<MOVE T2,RTRMXV>,<
MOVEM T2,RTRMXV>,<Maximum visits>)
PARAMETER(^D926,,<^D1022>,<0>,<%RTBEA>,<MOVEM T2,RTNBEA>,<MOVE T2,RTNBEA>,<
MOVEM T2,RTNBEA>,<Maximum broadcast endnode adjacencies>)
PARAMETER(^D927,,<^D64>,<0>,<%RTBRA>,<MOVEM T2,RTNBRA>,<MOVE T2,RTNBRA>,<
MOVEM T2,RTNBRA>,<Maximum broadcast router adjacencies>)
PARAMETER(^D930,<NOSET!NOCLR>,,,,,<LOAD T2,IBMXB,+IBBLK>,,<Maximum buffers>)
PARAMETER(^D931,<NOSET!NOCLR>,,,,,<MOVE T2,RTRBSZ>,,<Maximum buffer size>)
PARAMETER(^D932,<NOSET!NOCLR>,,,,,<MOVE T2,RTRBSZ>,,<Segment buffer size>)
;See note above
PARAMETER(^D2503,<NOSET!NOCLR>,,,,,<CALL NMXRNS>,,<Node state-I DECnet only>)
EXPTBL==.-EXPTAB
SUBTTL Network management tables -- Circuit parameters
CCPTAB:
PARAMETER(0,,,,<NCK.OF>,<CALL NMXSCS>,<CALL NMXRCS>,<CALL NMXSCS>,<
Circuit state>)
PARAMETER(^D800,<NOSET!NOCLR!BEX>,,,,,<CALL NMXRAL>,,<Adjacent node(s)>)
PARAMETER(^D801,<NOSET!NOCLR>,,,,,<CALL [ LOAD T2,RCDSL,(RC)
HRLZ T2,T2
CALL CVTSTN
RNMXOK]>,,<Desiginated router>)
PARAMETER(^D810,<NOSET!NOCLR>,,,,,<CALL NMXQPS>,,<Block size>)
PARAMETER(^D900,,<^D25>,<1>,<1>,<CALL [ STOR T2,RCCST,(RC)
CALL SETRCX
RNMXOK]>,<
LOAD T2,RCCST,(RC)>,<
CALL [ STOR T2,RCCST,(RC)
CALL SETRCX
RNMXOK]>,<Cost for this circuit>)
PARAMETER(^D901,,<^D255>,<0>,<%RTMXR>,<STOR T2,RCMXR,(RC)>,<
LOAD T2,RCMXR,(RC)>,<
STOR T2,RCMXR,(RC)>,<Maximum routers on this circuit>)
PARAMETER(^D902,,<^D127>,<0>,<0>,<MOVEM T2,RTRPRI>,<MOVE T2,RTRPRI>,<
MOVEM T2,RTRPRI>,<Priority to be designated router>)
PARAMETER(^D906,,<^D8191>,<1>,<%RTTM3>,<CALL [IMULI T2,TIMBAS
STOR T2,RCTM3,(RC)
RNMXOK ]>,<
CALL [LOAD T2,RCTM3,(RC)
IDIVI T2,TIMBAS
RNMXOK ]>,<
CALL [IMULI T2,TIMBAS
STOR T2,RCTM3,(RC)
RNMXOK ]>,<Hello timer>)
PARAMETER(^D907,<NOSET!NOCLR>,,,,,<CALL NMXQPT>,,<
Listen timer>)
CCPTBL==.-CCPTAB
XRESCD
SUBTTL Initialization - Compute Core Requirements
;RTRCCR computes ROUTER's core requirements.
;Call:
; PUSHJ P,RTRCCR
;Returns:
; T1/ Size of ROUTER core
IFN FTOPS10,<
RTRCCR::LOAD T1,IBMXA,+IBBLK ;GET MAXIMUM NODE ADDRESS
ADDI T1,1 ;PLUSE ONE FOR NODE 0
ASH T1,1 ;COMPUTE SIZE OF OUR ROUTING VECTOR
RET ;AND RETURN
>; END IFN FTOPS10
SUBTTL RTRINI - Initialize Router User
;RTRINI - Set up a router user
;
; Call:
; with nothing
;
; Return:
; RET ;ON RESOURCE FAILURE
; RETSKP ;ON SUCCESS
;
; Uses: T1-T3
;
;This routine gets called at system initialization. It sets up the memory
;for the routing vectors and the node type vector. Must be called before
;DECnet is turned on.
INTERN RTRINI
XSWAPCD
RTRINI: TRACE RTR,<Initializing Router>
;Get the Router parameters defined in SETSPD's config file
XMOVEI T2,IBBLK ; Get pointer to initialization block
LOAD T1,IBRTR,(T2) ; Get Router type desired
MOVEM T1,RTRNTY ; Save as our node type
SETZM ENFLG ; Assume routing IV
CAIN T1,RNT.NR ; Are we an endnode today?
SETOM ENFLG ; Yes, then non-routing IV
IFN FTOPS10,<
MOVX T1,ST%END ; Get configuration status endnode flag
SKIPE ENFLG ; Are we running as an endnode today?
IORM T1,CNFST2## ; Yes, set flag
>; END IFN FTOPS10
LOAD T1,IBADR,(T2) ; Get 16 bit node address
MOVEM T1,RTRNAD
TXZ T1,RN%ARE ; Clear the area number
MOVEM T1,RTRADR ; and save the node number
MOVE T1,RTRNAD ; Now get the area number
TXZ T1,RN%NOD ; from the address
LSH T1,-^D10 ; Right justify
MOVEM T1,RTRHOM
LOAD T1,IBBSZ,(T2) ; Get blocksize to use
CAMGE T1,RTRBSZ ; Compare with default (576)
MOVEM T1,RTRBSZ ; If smaller use that, else keep default
LOAD T1,IBMXA,(T2) ; Get the maximum node address
MOVEM T1,RTRMXN
CAMGE T1,RTRMX3 ; Is it less than maximum for Phase III nodes?
MOVEM T1,RTRMX3 ; Yes, use it then
;Here to allocate the "normal" and "scratch" routing vectors.
MOVE T1,RTRMXN ;GET THE MAXIMUM NODE NUMBER
ADDI T1,1 ;Add one for node 0 (nearest area router)
ASH T1,1 ;MAKE IT TWICE AS LONG (HALF FOR REACH VECTOR
; HALF FOR OUTPUT ADJACENCY VECTOR)
IFN FTOPS20,<
CALL DNGWDZ ;GET THAT MANY WORDS
RET ;COULD NOT INITIALIZE
>; END IFN FTOPS20
IFN FTOPS10,<
EXCH T1,DCNVFF## ;GET ADDRESS OF NEXT FREE CORE
ADDM T1,DCNVFF## ;UPDATE PAST ROUTING VECTOR
>; END IFN FTOPS10
MOVEM T1,RTRNRV ;SAVE POINTER TO NORMAL ROUTING VECTOR
MOVE T2,RTRMXN ;GET OUR CURRENT MAXIMUM NODES
ADDI T2,1 ;START THE RTRNOV AT ONE ALSO
MOVEM T2,RTROFS ;SAVE AS OFFSET FROM START OF NRV AND SRV
; NOTE THAT MXN CANNOT GET LARGER!
ADD T1,T2 ;CALCULATE START OF NORMAL OUTPUT VECTOR
MOVEM T1,RTRNOV ;SAVE IT
MOVE T2,RTRNRV ;PREPARE TO CALC END OF SMEAR
ADD T2,RTRMXN ;ADD NUMBER OF ENTRIES TO SPRAY
MOVE T1,RTRNRV ;POINT TO THE HEAD OF THE NORMAL VECTOR
MOVX T3,RNHOP!RNCST ;SMEAR WITH MAXIMUM COST AND HOPS
CALL DNSWDS ;SPRAY THE BLOCK WITH MAXS
MOVE T1,RTRMXN ;GET THE MAXIMUM NODE NUMBER
ADDI T1,1 ;Add one for node 0 (nearest area router)
IDIVI T1,^D36 ;Compute size of routing vector bitmap
SKIPE T2 ;Round up
ADDI T1,1 ;...
CALL DNGWDZ ;Allocate memory for routing vector bitmap
RET ;Return if allocation error
MOVEM T1,RTRNVB ;Save address
;Get and initialize an EC (Event Communication) block
MOVX T1,EV.GEC ;Function code "get EC block"
CALL NMXEVT
RET ; -failed to get memory for block
MOVEM T1,RTRECP ;Save pointer
MOVX T2,^D8 ;ROUTER may queue 8 event blocks on queue
STOR T2,ECMAX,(T1)
IFN FTOPS10,<
CALL D36LIN## ;Initialize DTEs and KDPs
>; End IFN TOPS10
CALL DNDINI ;Initialize DNADLL
RETSKP ;RETURN NICELY
SUBTTL RTRON - Turn Router (and DECnet) On
;RTRON - Turn Router (and DECnet) On
;
; Call:
; With nothing special
;
; Return:
; RET ;ON FAILURE (DECNET IS ALREADY ON, NO
; ;LOCAL NODE NUMBER DEFINED, ETC.)
; RETSKP ;WITH DECNET TURNED ON
;
; Uses: T1-T4
;
;Note that RTRINI must be called to set up the routing vectors for
;Router before DECnet is turned on.
INTERN RTRON
RTRON: SAVEAC <RC,AJ>
MOVE T1,DCNSTA ;Get DECnet state
CAIE T1,DS.ON ;Is it on?
SKIPN T1,RTRADR ;AND DO WE HAVE AN ADDRESS FOR ROUTER?
RET ;NO, CANNOT TURN DECNET ON YET
DPB T1,[POINTR (T2,RN%NOD)] ; Generate our node address in
MOVE T1,RTRHOM ; Ethernet string format
DPB T1,[POINTR (T2,RN%ARE)]
LSHC T1,^D28 ;
DPB T1,[POINT 8,T2,15]
MOVEM T2,RTRLOO ; Low order in string format
MOVE T1,RTRADR
ADD T1,RTRNRV ;FIND THE ENTRY IN THE NORMAL REACH VECTOR
D36OFF ;TURN ON INTERLOCK
SETONE <RNLCL,RNRCH,RNCCH>,(T1) ;LOCAL AND REACHABLE and in cache
SETZRO <RNCST,RNHOP>,(T1) ;ZERO THE HOPS AND COST FOR THIS NODE
MOVE T2,[XCDSEC,,NSPRTR] ;GET NSP'S ENTRY VECTOR
ADD T1,RTROFS ;POINT TO OUTPUT-CIRCUIT VECTOR ENTRY
MOVEM T2,(T1) ;SAVE THE ENTRY VECTOR
D36ON ;TURN OFF INTERLOCK
;And turn DECnet on!
MOVX T1,DS.ON ;GET THE ON STATE
MOVEM T1,DCNSTA ;SET IT
SETZM RTRLMG ;Reset rounting message offset
;Now go through all the circuits, initializing each one.
SKIPN RC,RTRCBQ ;PICK UP FIRST CIRCUIT BLOCK
RETSKP ;NONE THERE, RETURN SUCCESS
RTRON1: CALL R2KINI ;INITIALIZE THIS CIRCUIT
TRN
LOAD RC,RCNXT,(RC) ;Step to next circuit, if any,
JUMPN RC,RTRON1 ; and initialize
RETSKP ;NO MORE, JUST RETURN SUCCESS
SUBTTL RTROFF - Turn Router (and DECnet) Off
;RTROFF - Turn Router (and DECnet) Off
;
; Call:
; With nothing special
;
; Return:
; RETSKP ;ALWAYS
;
; Uses: T1-T4
RTROFF: SAVEAC <RC,AJ>
;Now go through all the circuits, halting each one.
SKIPA RC,RTRCBQ ;GET THE FIRST CIRCUIT BLOCK
RTROF1: LOAD RC,RCNXT,(RC) ;STEP THROUGH TO NEXT ONE
JUMPE RC,RTROF2 ;NONE THERE, RETURN SUCCESS
CALL RTIDWN
CALL R2KCLS
JRST RTROF1 ;
RTROF2: MOVX T1,DS.OFF ;SET THE STATE OF DECNET
MOVEM T1,DCNSTA ; TO "OFF"
RETSKP ;NO MORE, JUST RETURN SUCCESS
SUBTTL RTRSEC - Once a second processing for Router
;RTRSEC - Once a second processing
;
; Call:
; With nothing
;
;Return:
; RET ;ALWAYS
;
; Uses: T1
;
;This is the clock level routine for Router. Once a second this
;routine gets executed. If we are running TOPS-10 SMP, we must make
;sure that this is run on the BOOT CPU. The routine simply calls RTRRCR
;(to recompute the routing) if needed and calls RTRUPD to see if
;routing messages need to be sent out on any or all circuits. Next, we
;call the hello processor to check hello and listener timers for each
;circuit. Finally, it checks the resend queue, and if there are any
;messages on it, it forwards them.
INTERN RTRSEC
XRESCD
RTRSEC: MOVE T1,DCNSTA ;Get DECnet state
CAIE T1,DS.ON ;Is it on?
RET ;NO, NOTHING TO DO
IFN FTOPS10,<
XCT .CPSK0 ;SKIP IF BOOT CPU
RET ;NO, SHOULDN'T BE HERE, BUT JUST RETURN
> ;END IFN FTOPS10
CALL DNDSEC ;Poll DNADLL each second
; SKIPL RTRLOK ;CHECK TO SEE IF ANYONE HAS INTERLOCK
; JRST [SETOM RTRSSV ;COULDN'T GET IT, JUST RETURN
; RET] ; WITH SERVICE NEEDED
; SETZM RTRSSV ;WE HAVE PROVIDED SERVICE
;Note that we did not get the interlock here; we only tested it.
;The interlock is just to keep this clock level code from changing
;the database while any process level code is running. We may
;get interrupted now by interrupt code, but this won't affect us
;as our critical sections are surronded by D36ON/D36OFF.
SAVEAC <P1,P2,MS,RC,AJ,Q1,Q2,MB> ;SAVE SOME NON-SMASHABLE ACS
CALL RTRTMR ;CALL THE TIMER PROCESSOR, WHICH MAY TURN
; ON RTRRCF
SKIPE RTRRCF ;IS THE RECOMPUTE ROUTING FLAG ON?
CALL RTRRCR ; YES, GO RECOMPUTE THE ROUTING
CALL RTRUPD ;Now go through the update process
; SETOM RTRLKO ;CLEAR OWNER OF INTERLOCK
IFN FTRTST,<
SKIPE T1,TSTFLG
CALL RTRTST
SETZM TSTFLG
>
SKIPN ENFLG ;Endnode?
CALL SELDSR ;No, select a designated router
SKIPGE ENFLG ;Endnode?
CALL CKECTO ;Yes, check the cache timer
RET ; AND RETURN
SUBTTL RTRJIF - Once a jiffy processing for Router
;RTRJIF - Once a jiffy processing
;
; Call:
; With nothing
;
; Return:
; RET ;ALWAYS
;
; Uses: T1
;
;This routine's only purpose is to service kontroller requests that
;CALKON queues when the request is for a device on the wrong CPU. Since
;this is a TOPS-10 SMP only problem, it does nothing for TOPS-20.
INTERN RTRJIF
XRENT RTRJIF
IFN FTOPS20,<RET> ;Nothing to do for TOPS20
IFN FTOPS10,<
IFN FTMP,<
; SKIPL RTRLOK ;TEST THE ROUTER INTERLOCK
; RET ;SOMEONE HAS IT, WE'LL TRY AGAIN LATER
SAVEAC <RC,AJ,MB> ;SAVE SOME ACS TO USE
SKIPA RC,RTRCBQ ;START WITH THE FIRST CIRCUIT BLOCK
RTRJI1: LOAD RC,RCNXT,(RC) ;GET PTR TO NEXT CIRCUIT BLOCK
JUMPE RC,RTN ;NO MORE, JUST RETURN
LOAD T1,LIKON,+RC.LID(RC) ;GET THE POINTER TO THE CIRCUIT BLOCK
CAME T1,.CPCPN ;ARE WE RUNNING ON THE CPU FOR THIS CIRCUIT?
JRST RTRJI1 ;NO, CHECK OUT THE NEXT BLOCK
;Check the circuit's resend queue for any requests that we can queue
;for it now that we are running on the correct CPU.
RTRJI2: ;CHECK IF OTHER CPU HAD KONTROLLER TASKS
; QUEUED UP.
JE RCCLS,(RC),RTRJI3 ;IF NO HALT REQUESTED, SKIP THIS CODE
SETZRO RCCLS,(RC) ;CLEAR BIT
MOVEI T1,DF.CLS ;KONTROLLER FUNCTION HALT.
MOVE T2,RC ;POINT TO CIRCUIT BLOCK
CALL CALKON ;AND TRY TO DO IT.
JRST RTIDWN ;IF IT FAILS, DECLARE THE CIRCUIT DEAD.
RTRJI3: JE RCOPN,(RC),RTRJI4 ;IF NO INITIALIZE REQUESTED, SKIP THIS CODE
SETZRO RCOPN,(RC) ;CLEAR BIT
MOVEI T1,DF.OPN ;THE OTHER CPU DID REQUEST THIS.
MOVE T2,RC ;SET UP POINTER TO CIRCUIT BLOCK
CALL CALKON ;INITIALIZE THE LINE
JRST RTIDWN ;AND DECLARE THE CIRCUIT DOWN.
RTRJI4: D36OFF ;TURN OFF INTERRUPTS WHILE PLAYING WITH QUEUES
DEQUE MB,RC.JSQ(RC),MB.NXT,RTRJI6 ;DEQUEUE ANYTHING THAT'S THERE
D36ON ;TURN INTERRUPTS BACK ON
;WE KNOW THAT BY VIRTUE OF GETTING THE MESSAGE
;BLOCK FROM RC.JSQ, RC IS SET UP CORRECTLY.
CALL CALQOB ;SEND THE BLOCK OUT.
JRST RTRJI2 ;SEE IF ANYTHING ELSE ON CIRCUIT'S Q
RTRJI6: D36ON ;TURN THE INTERRUPTS BACK ON
JRST RTRJI1 ; AND CHECK THE NEXT CIRCUIT'S QUEUE
>;End of IFN FTMP
RET
>;End of IFN FTOPS10
SUBTTL RTRLCK - Get the RTR interlock
REPEAT 0,<
;RTRLCK - Grab the RTR interlock
;
; Call:
; With nothing special
;
; Return:
; RET ;ALWAYS WITH INTERLOCK
;
; Uses: Nothing
;
;Note: This interlock routine is only called by RTRXMT. RTRXMT, which
;is NSP's entry point, will never be called by more than one CPU due to
;the NSP interlock. If the NSP interlock changes, we may have to modify
;this assumption. The Router interlock is used to keep Router's clock
;level from modifying the database at clock level (Note that the
;database is only modified at clock level), while someone at process
;level is using it. Route-through happens at interrupt level, so we
;don't have to worry. Our only process level caller is NSP, who always
;has his "global interlock".
RTRLCK: AOSE RTRLOK ;GRAB THE INTERLOCK
RET ;SOMEONE HAS IT (PROBABLY INTERRUPT LEVEL)
; WE DON'T CARE AS LONG AS CLOCK LEVEL
; KNOWS THAT IT CAN'T RUN
APRID RTRLKO ;SET THE OWNER OF THE INTERLOCK
ADJSP P,-1 ;WE'LL CALL THE CALLER
PUSHJ P,@1(P) ; SO WE DON'T NEED HIM ON STACK
TRNA ;NON-SKIP RETURN
AOS -1(P) ;SKIP RETURN
SETOM RTRLKO ;CLEAR THE OWNER OF THE INTERLOCK
SETOM RTRLOK ;GIVE UP THE LOCK
SKIPE RTRSSV ;DID WE GET A REQUEST FOR SERVICE?
CALLRET RTRSEC ;YES, GIVE IT
RET ;OTHERWISE, JUST RETURN
>
IFN FTRTST,<
RTRTST: SAVEAC P1
MOVEI P1,TSTBLK ; Test data block
STOR T1,TRTND,(P1) ; Node to loop with
MOVX T1,^D300 ; Length of data segment
CALL DNGMSG ; Get that many bytes
RET ; Resource failure, tough luck
MOVE MB,T1 ; Set up MB with message block pointer
XMOVEI T1,UD.MSD(MB) ; Initialize the user data segment
CALL DNPINI
LOAD T1,TRTSN ; Get serial number
CALL DNP2BY ; Place serial number in message
MOVX T3,^D298 ; Get the count for loop
RTRTS2: MOVX T1,HEL.LO ; Word that goes in hello messsage
CALL DNP1BY ; Put one in
SOJG T3,RTRTS2 ; and continue till we have enough
MOVE T1,RTRADR
DPB T1,[POINTR (T2,RN%NOD)]
MOVE T1,RTRHOM
DPB T1,[POINTR (T2,RN%ARE)]
STOR T2,MBSRC,(MB)
SETZ T1,
MOVX T2,LD.ETH ; Get the device type for ethernet
STOR T2,LIDEV,+T1 ; Save it
CALL RTRGCB ; Get the circuit block in RC
CALLRET FREMSG
LOAD T1,TRTND,(P1) ; Get number of node to test with
STOR T1,MBDST,(MB) ;
CALL RTRGAJ ; Get the correct adjacency in AJ
CALLRET FREMSG
STOR AJ,RMOAP,(MB) ; Save for RTRFWD
CALL TSTTIM
STOR T1,TRTAF,(P1) ; Save as time at RTRFWD
SETONE RMTST,(MB) ; Indicate this is a test message
SETZ T1, ; No flags
CALLRET RTRXMT ; Try to send it
>
SUBTTL RTRXMT - NSP's entry into Router
;RTRXMT - Routine to forward messages from NSP
;
; Call:
; MB/ Ptr to Message Block
; T1/ RQR flag (RT%RQR)
; ODN flag (RT%ODN)
; TRY flag (RT%TRY)
; Public portion of message block must be filled with destination
; and source nodes and output circuit.
;
; Returns:
; RTN ;ALWAYS
;
;This is the only way which an NSP calls router (except for
;initialization). The ODN flag in T1 specifies whether or not NSP
;really wants message back (see FREMSG). The RQR flag specifies
;whether or not NSP is requesting this message be returned.
INTERN RTRXMT
XRESCD
RTRXMT: MOVE T2,DCNSTA ;Get DECnet state
CAIE T2,DS.ON ;Is it on?
CALLRET FREMSG ;NO, PUNT THE MESSAGE CORRECTLY AND LEAVE
SAVEAC <MB,MS,RC,AJ> ;SAVE A FEW FOR NSP
; CALL RTRLCK ;GET INTERLOCK
MOVX T2,RMRQR ;GET RETURN REQUEST BIT FOR MESSAGE BLK
ANDCAM T2,RM.RQR(MB) ;CLEAR FLAG, ASSUMING NOT INTERESTED
TXNE T1,RT%RQR ;DOES HE WANT IT BACK?
IORM T2,RM.RQR(MB) ;YES, SET BIT IN THE MESSAGE BLK
MOVX T2,RMODN ;GET "NSP WANTS MSG BACK" BIT
ANDCAM T2,RM.ODN(MB) ;CLEAR FLAG, ASSUMING CALLER NOT INTERESTED
TXNE T1,RT%ODN ;DOES HE WANT OUTPUT DONE CALL?
IORM T2,RM.ODN(MB) ;YES, SET FLAG FOR FREMSG AND R2NODN
MOVX T2,RMTRY ;Get "TRYHARD" on NI bit
ANDCAM T2,RM.TRY(MB) ;Assume not requesting us to try hard
TXNE T1,RT%TRY ;Asked to "try hard"?
IORM T2,RM.TRY(MB) ;Yes, set flag to clear destination from cache
SETZRO RMICP,(MB) ;THERE'S NO INPUT CIRCUIT BLOCK POINTER
SETZRO RMIAP,(MB) ; and no input adjacency
SETZRO RMOAP,(MB) ;THERES NO OUTPUT ADJACENCY YET EITHER
SETZRO MBVST,(MB) ;ZERO VISITS COUNT
SETONE RMMB1,(MB) ;BIT THAT MUST BE ONE IN FIRST BYTE
LOAD T1,MBSRC,(MB) ;GET SOURCE NODE ADDRESS
LDB T2,[POINTR (T1,RN%ARE)] ;GET THE AREA NUMBER
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
CAME T2,RTRHOM ;IN OUR AREA
JRST CKLOOP ;NOPE ,THEN FORGET ABOUT IT
ADD T1,RTRNRV ;ADD OFFSET TO NORMAL ROUTING VECTOR
TMNN RNLCL,(T1) ;IS THIS THE LOCAL NODE?
BUG.(CHK,ROUBSN,ROUTER,SOFT,<Bad source node in message from NSP>,,<
Cause: We have received a message from NSP to send. However, the source node
address is not that of the local Router.
Action: Check in LLINKS or SCLINK to see how we got an invalid source node
address.
>,FREMSG)
CKLOOP: LOAD T1,MBCHN,(MB) ;GET CHANNEL NUMBER (circuit id)
JUMPE T1,RTRFWD ;IF NO LOOP BACK CIRCUIT SPECIFIED BY
;SESSION CONTROL, DON'T SET CIRCUIT PTR
CALL RTRGCB ;YES, TRANSLATE INTO A CIRCUIT BLK PTR
BUG.(CHK,ROUILS,ROUTER,SOFT,<Illegal Circuit Specified in NSP msg>,,<
Cause: There was a request to send a message on a particular circuit, however
the circuit has never been intialized by the routing layer.
>,FREMSG)
STOR RC,RMOCP,(MB) ;Store it as output circuit
LOAD AJ,RCAJQ,(RC) ;Get an adjacency pointer
;Note that this grabs the the first adjacency which is the only one for point
; to point, but not necessarily for broadcast
STOR AJ,RMOAP,(MB) ;Save it for forward routine (this is enough
JE RCBCT,(RC),RTRFWD ; unless circuit is broadcast)
CKLOO1: LOAD T1,AJNTY,(AJ) ;Get adjacency type
CAIN T1,ADJ.LN ; If a routing node
IFSKP.
STOR AJ,RMOAP,(MB) ; Save it for forward routine
JRST RTRFWD ; and then forward the message
ENDIF.
LOAD AJ,AJNXT,(AJ) ; Else get next adjacency
JUMPE AJ,FREMSG ; none found then cannot forward the message
JRST CKLOO1 ; check the one we got
SUBTTL RTRFWD - Perform Routing of Message
;RTRFWD - Routine to do routing
;
; Call:
; MB/ Ptr to Message Block
;
; Return:
; RTN ;ALWAYS
;
; Uses T1-T3
;
;This routine takes an input message, checks its Router header and
;routes it to the correct destination using the "normal" routing
;vector. The relavent fields in the public section of the Message
;Block must have been set up.
RTRFWD: XMOVEI T1,RM.MSD(MB) ; Router's private MSD
CALL DNPINI ; Initialize it, as this is where we will
; build the routing layer header
LOAD T1,MBDST,(MB) ; Get the destination address
LDB T2,[POINTR(T1,RN%ARE)] ; Extract the area number
LDB T1,[POINTR(T1,RN%NOD)] ; and the node number from it
CAME T2,RTRHOM ; Is it in our area?
SETZ T1, ; No, select the area router
SKIPL T1 ;LESS THAN 0
CAMLE T1,RTRMXN ;GREATER THAN THE MAX NODE ADDRESS?
JRST RTRFOR ;DEST IS OUT OF RANGE
ADD T1,RTRNRV ; Add in the offset to routing vector
OPSTR <SKIPE>,RMOAP,(MB) ; Have we selected an output adjacency?
IFSKP.
TMNN RNLCL,(T1) ; No, is destination local?
IFSKP.
SETONE MBLCL,(MB) ; Yes, indicate that in message block
JRST RTRFD2 ; and skip ahead
ENDIF.
ENDIF.
SKIPN ENFLG ; Endnode?
IFSKP. ; Yes
MOVE RC,RTRCBQ ; Get pointer to our only circuit
JUMPE RC,RTRFUR ; If no circuit can't do much
LOAD T2,RCSTA,(RC) ; If circuit is not running
CAIE T2,RCS.RN ; cannot forward message
JRST RTRFUR
STOR RC,RMOCP,(MB) ; Save circuit block address
SETONE <RMMZ2,RMMZ3>,(MB) ; Set intra-ethernet and long format hdr
CALL RTRBEH ; Build the ethernet header
JRST RTR2RM ; and try to send message
ELSE.
TMNE RNRCH,(T1) ; Is destination reachable?
IFSKP.
SETONE MBUNR,(MB) ; No, indicate that,
SETZRO RMOAP,(MB) ; clear output adjacency,
JRST RTRPHR ; and skip further checking
ENDIF.
ENDIF.
OPSTR <SKIPE T2,>,RMOAP,(MB) ;Compute an adjacency if we don't have one
IFSKP.
ADD T1,RTROFS ; Index into the output adjacency vector
MOVE T2,(T1) ; Get the output adjacency
STOR T2,RMOAP,(MB) ; and use it as the adjacency to forward to
ENDIF.
LOAD T2,AJSTA,(T2) ; Get state of adjacency
CAIE T2,ADJ.UP ; Is it up?
JRST FREMSG ; No, toss the message
;Now check for over aged packet
RTRFD2: JE RMIAP,(MB),RTRFD3 ; If from our NSP then visit count is zero
LOAD T1,RMFST,(MB) ;GET THE FIRST BYTE OF MESSAGE
OPSTRM <AOS T2,>,MBVST,(MB) ; AND UPDATE AND GET VISITS FIELD
MOVE T3,RTRMXV ;THIS IS THE MAXIMUM VISITS COUNT ALLOWED
TXNE T1,RM%RTS ;IS THIS GOING TO BE COMING BACK?
ASH T3,2 ;YES, GIVE IT TWICE AS MANY HOPS
CAMG T2,T3 ;HAS IT AGED TOO MUCH?
JRST RTRFD3 ;NO, PUT HEADER ON MSG
;Here to report a aged packet loss event.
SETZ T2, ;THIS EVENT HAS NO ENTITY ASSOCIATED WITH IT
SETZ T3, ;Default address to nothing
SKIPE AJ
LOAD T3,AJNAN,(AJ) ;Get address of last router in path
EVENT RE.APL,<Aged packet loss event>,MB
AOS RTRCAP ;INCREMENT THE AGED PACKET COUNTER
CALLRET FREMSG ;FREE THE MESSAGE AND RETURN
;Now decide if destination is point-point or broadcast and build the
;appropriate routing message header.
RTRFD3: TMNE MBLCL,(MB) ;IS THE DESTINATION OUR LOCAL NSP?
JRST RTRPHR ;YES, THEN WE CAN SKIP THE REST OF THIS
IFN FTRTST,<
LOAD T1,MBSRC,(MB) ;Get source address
TMNE RMTST,(MB) ;Is this a test message
JRST [STOR T1,MBDST,(MB) ;Then we want it back
SETZRO MBVST,(MB) ;Reset the visits
JRST .+1]
>
LOAD AJ,RMOAP,(MB) ; OUTPUT ADJACENCY
LOAD RC,AJCBP,(AJ) ; OUTPUT CIRCUIT BLOCK
JN RCBCT,(RC),RTRFNI ; Jump if broadcast circuit?
;Build a short data packet header for packets going out on point-to-point
SETZRO <RMMZ2,RMMZ3>,(MB) ;Short format header - Not intra-NI
LOAD T1,RMFST,(MB) ;GET THE FIRST BYTE OF MESSAGE
CALL DNP1BY ;PUT IT IN MESSAGE HEADER AREA
LOAD T1,MBDST,(MB) ;GET THE DESTINATION NODE ADDRESS
LDB T2,[POINTR(T1,RN%ARE)] ;GET THE AREA
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
SKIPN T2 ;HAVE ONE?
MOVE T2,RTRHOM ;GET OURS THEN
TMNE AJPH4,(AJ) ;Is "next hop" Phase IV?
DPB T2,[POINTR(T1,RN%ARE)] ; Yes, then we need an area
CALL DNP2BY ;PUT DESTINATION NODE ADDRESS INTO MESSAGE
LOAD T1,MBSRC,(MB) ;GET THE SOURCE NODE ADDRESS
LDB T2,[POINTR(T1,RN%ARE)] ;GET THE AREA
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
SKIPN T2 ;Have an area?
MOVE T2,RTRHOM ;NO, USE OURS THEN
TMNE AJPH4,(AJ) ;Is the next hop Phase IV?
IFSKP.
CAME T2,RTRHOM ;No, is this from a foreign area?
CALLRET RTRFUR ;Yes, treat as unreachable because we cannot
; forward a P4 packet to an adjacent P3 node
ELSE.
DPB T2,[POINTR(T1,RN%ARE)] ;Yes, P4 nodes get an area number
ENDIF.
CALL DNP2BY ;PUT SOURCE NODE ADDRESS INTO MESSAGE
LOAD T1,MBVST,(MB) ;GET VISITS BYTE
CALL DNP1BY ;AND PUT THAT IN, TOO
JRST RTRPHR ;DO THE COMMON HEADER STUFF
;Here when the output circuit is an Ethernet
RTRFNI: SETONE RMMZ3,(MB) ;****INDICATES LONG FORMAT TRANSPORT HEADER**
LOAD T2,RMIAP,(MB) ;GET THE INPUT ADJACENCY POINTER
JUMPE T2,RTRFN1 ;MESSAGE IS FROM LOCAL NSP
LOAD T3,AJNTY,(T2) ;GET THE NODE TYPE
LOAD T4,AJNTY,(AJ) ;GET THE NODE TYPE FOR THE OUTPUT ADJACENCY
CAIN T3,ADJ.LN ;IT IS AN ENDNODE?
CAME T3,T4 ;YES, ARE THEY BOTH?
JRST RTRFN2 ;NO, THEN SKIP THIS
;They are both endnodes, see if the input/output circuits are the same NI
LOAD T2,AJCBP,(T2) ;GET THE INPUT CIRCUIT BLOCK POINTER
LOAD T2,RCLID,(T2) ;GET THE LINE ID
LOAD T4,LIDEV,+T2 ;GET THE DEVICE TYPE
CAXE T4,LD.ETH ;IS IT AN ETHERNET?
JRST RTRFN2 ;NO, THEN NO INTRA-ETHERNET
; LOAD T2,LIUNI,+T2 ;UNIT NUMBER
LOAD T3,RCLID,(RC) ;AND THE ONE FOR OUTPUT
; LOAD T3,LIUNI,+T3 ;GET THE UNIT NUMBER
CAME T2,T3 ;ARE THEY THE SAME NI?
TRNA ;NOT NI OR NOT SAME ONE
RTRFN1: SETONE RMMZ2,(MB) ;YES, THEN SET THE INTRA-NI BIT
RTRFN2: CALL RTRBEH ;Now build the Ethernet header
RTRPHR: CALL DNRPOS ;GET CURRENT POSITION IN THE BLOCK
STOR T1,RMMK1,(MB) ;AND SET MARK IN BLOCK
TMNE MBLCL,(MB) ;FOR THE LOCAL NSP?
JRST RTRFLC ;AND FORWARD TO LOCAL NSP
TMNE MBUNR,(MB) ;UNREACHABLE?
JRST RTRFUR ;YES, LOG IT THEN
JN RMOAP,(MB),RTR2RM ;If output adjacency was spec'd, forward it
LOAD T1,MBDST,(MB) ;HAVE A DESTINATION
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
BUG. (CHK,ROUIFS,ROUTER,SOFT,<Router got through the forward routine without picking a route>,,<
Cause: RTRFWD got through its Forward process and either did
not pick up a route or failed to flag a message which was for the
local node or an unreachable message.
Action: Look for corruption in the routing vector.
>,FREMSG)
;Here when destination node is out-of-range.
RTRFOR: TMNE RMRQR,(MB) ;WAS RETURN REQUESTED
JRST RTRFRT ;YES, RETURN IT
LOAD T2,RMICP,(MB) ;GET THE CIRCUIT IT CAME IN ON
SKIPN T2
BUG.(CHK,ROUNSO,ROUTER,SOFT,<NSP sent out of range packet>,,<
Cause: There is a request to forward a packet to a node whose address is
outside the range of our routing vector. Either our NSP has given
a packet we cannot forward or we have received one from the wire.
Action: If the source is local check to see how NSP could give a packet
whose destination node address is greater than RTRMXN. If the
source is remote then there is something wrong with its routing
database or algorithm.
>,FREMSG)
LOAD T2,RCLID,(T2) ;Get device ID
SETZ T3, ;Default address to nothing
SKIPE AJ
LOAD T3,AJNAN,(AJ) ;Get address of last router in path
EVENT RE.NOR,<Node out-of-range packet loss>,MB
AOS RTRCNO ;INCREMENT OUT-OF-RANGE COUNT
CALLRET FREMSG ;RETURN THE MSG BLK
;Here when destination node is unreachable.
RTRFUR: TMNE RMRQR,(MB) ;WAS RETURN REQUESTED?
JRST RTRFRT ;WE HAVE TO RETURN MESSAGE
OPSTR <SKIPN T2,>,RMICP,(MB) ;GET THE CIRCUIT IT CAME IN ON
IFSKP.
LOAD T2,RCLID,(T2) ; and get the circuit ID
SETZ T3, ;Default address to nothing
SKIPE AJ
LOAD T3,AJNAN,(AJ) ;Get address of last router in path
EVENT RE.NUR,<Node unreachable packet loss>,MB
AOS RTRCNU ;INCREMENT EXECUTOR NODE COUNTER
ENDIF.
CALLRET FREMSG ;GIVE THE MESSAGE BACK AND RETURN
;Here to return message to sender due to unreachability.
RTRFRT: ETRACE RTR,<Returning message due to unreachability>
CALL RTRERH ;EAT THE ROUTER HEADER WE PUT ON THE MESSAGE
SETZRO RMRQR,(MB) ;ZERO THE RQR FLAG
SETONE RMRTS,(MB) ;SET THE RETURN TO SENDER FLAG
LOAD T1,MBDST,(MB) ;GET THE DST ADDR
LOAD T2,MBSRC,(MB) ; AND THE SRC ADDR
STOR T2,MBDST,(MB) ;SWITCH THEM
STOR T1,MBSRC,(MB) ; AROUND
TMNN RMICP,(MB) ;THIS MSG COME FROM LOCAL NSP?
JRST [CALL CPYMSG ;YES, MAKE THIS MSG LOOK LIKE AN INPUT
; BY COPYING SEGMENTS TOGETHER
CALLRET FREMSG ;OOPS, COULDN'T GET MSG BLOCK, FORGET IT
EXCH T1,MB ;POINT TO THE NEW MSG IN MB
CALL DNFMSG ;FREE THE OLD MSG
CALLRET R2NRTN] ; AND RETURN THE NEW MSG
CALLRET RTRFWD ;TRY TO FORWARD AGAIN
;Here when the message is for a local NSP.
RTRFLC: LOAD RC,RMICP,(MB) ;SEE WHERE MSG CAME FROM
JUMPE RC,RTRF2C ;IF ICP IS ZERO, MSG IS FROM NSP,
; SO WE HAVE TO COPY DATA
;IF ICP IS NON-ZERO, MSG IS FROM
; OUTSIDE & JUST FALL THROUGH
;We are here when we have to pass an incoming message to NSP.
INCR RCCAP,(RC) ;INCR ARRIVING PACKETS RECEIVED (TO NSP)
RTRF2N: TMNE RMRTS,(MB) ;IS THIS A RETURNED MESSAGE?
CALLRET R2NRFR ;Yes, then give it to NSP
CALLRET R2NRCV ;NO, THIS IS GOOD OLDE RECEIVED DATA
RTRF2C:
;***************************************
TORESCD
DNSNUP(RTRLTR) ;Label for DNSNUP to find local messages
TOXRESCD
;***************************************
CALL RTRERH ;EAT THE ROUTING HEADER
CALL CPYMSG ;COPY THE MSD'S TOGETHER
CALLRET FREMSG ;DON'T CARE IF IT FAILS, THEN FREE IT UP
PUSH P,T1 ;SAVE THE POINTER TO NEW THE MESSAGE
CALL FREMSG ;RETURN THE ORIGINAL TO NSP
POP P,MB ;AND WE CAN DIDDLE WITH OUR NEW COPY
JRST RTRF2N ;NOW PASS THE MESSAGE ON TO NSP
; Get some bytes that we put in the router MSD above. This was to fix problems
; with Event processing, But the local NSP and the Return to sender code does
; not expect these fields to be set up. So we will punt them here.
RTRERH: LOAD T1,MBFMS,(MB) ;GET THE POINTER TO THE FIRST MSD
XMOVEI T2,RM.MSD(MB) ;GET THE ADDRESS OF THE ROUTER MSD
CAME T1,T2 ;SEE IF IT AGREES WITH THE FIRST ONE THERE
RET ;JUST RETURN MUST BE LLINKS RETURN MESSAGE
LOAD T1,MDNXT,+RM.MSD(MB) ;GET THE NEXT MSD POINTER
STOR T1,MBFMS,(MB) ;SAVE AS THE FIRST ONE
RET ;AND RETURN
SUBTTL RTR2RM - Send Message to Remote Node
;RTR2RM - Queue Out Message to Remote through the DLL
;
; Call:
; MB/ Pointer to message block
; RC/ Pointer to circuit block
; AJ/ Pointer to adjacency block if we are a level 1 router
;
; Return:
; RET ;ALWAYS
;
; Uses: P1-P2, T1-T3
RTR2RM: LOAD T1,RCSTA,(RC) ;GET THE CIRCUIT'S STATE
CAIE T1,RCS.RN ;IS IT RUNNING
CAIN T1,RCS.TT ; OR IN TEST?
TRNA ;YES, WE CAN FORWARD THE PACKET
CALLRET FREMSG ;NO, DESTROY THE PACKET
SKIPN ENFLG
IFSKP.
INCR RCCDP,(RC) ; Count data packets
JRST RTR2R1 ; and continue
ENDIF.
JE RMICP,(MB),[INCR RCCDP,(RC) ;IS THE PACKET FROM OUR LOCAL NSP?
JRST RTR2R1] ;YES, INCREMENT COUNT OF NSP PACKETS
; AND SEND MSG WITHOUT WORRYING ABOUT
; SQUARE-ROOT LIMIT
LOAD T1,RMICP,(MB) ;GET THE INPUT CIRCUIT BLOCK
LOAD T1,LIDEV,+RC.LID(T1) ;GET THE LINE ID
LOAD T2,RMIAP,(MB) ;GET THE SOURCE ADJACENCY
LOAD T2,AJNTY,(T2) ;GET THE SOURCE NODE TYPE
CAXN T2,ADJ.LN ;IS IT AN END NODE?
CAXE T1,LD.ETH ;IS THIS THE ETHERNET CHANNEL
JRST RTRCSQ ;HAVE BOTH GOT TO BE ON THE ETHERNET
;Get here when we have a source which is an NI endnode. The SPEC says
;if we get an NI endnode as the source and the destination is not one,
;then we have to check to be sure the hiorder bytes of S-ID are set to
;HIORD. If they are not, we discard the packet. We must do this here
;as opposed to when we receive the packet, as we do not know the
;output adjacency when we have just received it.
LOAD T1,LIDEV,+RC.LID(RC) ;GET THE DEVICE TYPE
LOAD T2,AJNTY,(AJ) ;GET THE NODE TYPE
CAXN T1,LD.ETH ;IS THIS ON AN ETHERNET TOO?
CAXE T2,ADJ.LN ; AND IS THE DESTINATION AN END NODE?
TRNA ;NOT ON AN NI OR NOT AN END NODE
JRST RTRCSQ ;THEN SKIP THIS
LOAD T1,MBSR1,(MB) ;GET THE FIRST 4 BYTES OF SOURCE ADDRESS
CAME T1,RTRHIO ;IS THIS THE HIORDER?
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
LOAD T1,MBDS1,(MB) ; Now check the first 4 bytes of the
CAME T1,RTRHIO ; destination address
JSP T1,RTEMFE
;We now check the "square-root" limit criterion, to see if the message
;should be discarded. We check this by comparing the number of message
;blocks queued out on this circuit with the number of message blocks that
;the memory manager has guaranteed router divided by the square-root
;of the number of circuits (We simplify things by just using the number
;of circuits divided by two, which is close enough for a small number of
;circuits).
RTRCSQ: INCR RCCTR,(RC) ;NO, INCREMENT THE TRANSIT PACKETS RECEIVED
CALL DNNMSG ;GET NUMBER OF MESSAGE BLOCKS AVAILABLE
MOVE T2,RTRNLN ;FIND THE NUMBER OF CIRCUITS IN USE
ASH T2,-1 ;DIVIDE BY TWO
IDIV T1,T2 ;DIVIDE TO FIND THE QUEUE THRESHOLD
OPSTR <CAMLE T1,>,RCCMQ,(RC) ;COMPARE WITH NUMBER OF MSG BLKS QUEUED
JRST RTR2R1 ;WE DON'T HAVE TO FLUSH IT
;Here to discard a message that has exceeded the "square-root" limit.
TRACE RTR,<Congestion Loss on output>
INCR RCCTL,(RC) ;INCREMENT THE CONGESTION LOSS COUNTER
CALLRET FREMSG ;FREE THE MESSAGE AND RETURN
;All packets to be sent come through here.
RTR2R1:
;Now we have to diddle with the MSD pointers slightly to convince
;the DLL not to get the router header from the input MSD.
XMOVEI T1,RM.MSD(MB) ;POINT TO THE ROUTER MSD
STOR T1,MBFMS,(MB) ;STORE IN FIRST MSD SLOT
MOVE T1,MB
CALL DNLENG ; Get length of message
OPSTR <SUB T1,>,MDBYT,+RM.MSD(MB) ; Don't count Router's header
SKIPN ENFLG ; Endnode?
IFSKP.
LOAD T2,RCRBS,(RC) ; Check against our receive block size
ELSE.
LOAD T2,AJBSZ,(AJ) ; else check against adjacencies
ENDIF.
CAMG T1,T2 ; Too many bytes for
IFSKP. ; destination's buffer?
INCR RCBSX,(RC) ; Yes, count the times this happens
CALLRET FREMSG ; and toss the message
ENDIF.
JE RMICP,(MB),RTR2R4 ;DID IT COME FROM A REMOTE NODE?
INCR RCCTS,(RC) ;IT DID, INCREMENT TRANSIT COUNT
LOAD T1,MDPTR,+IN.MSD(MB) ;ALSO GET THE DYNAMIC BYTE POINTER
STOR T1,MDAUX,+IN.MSD(MB) ; AND STORE IT IN THE ORIGNAL BYTE POINTER
; SO THE DLL DOESN'T USE THE OLD ROUTER
; HEADER, WHICH WE JUST STRIPED AWAY
;Now set up the arguments for the data link and give it the packet
RTR2R4: INCR RCCMQ,(RC) ;INCREMENT NUMBER OF MESSAGES QUEUED
MOVX T1,DF.XMT ;Function is transmit
SKIPN ENFLG ; Endnode?
IFSKP.
;Clear cache if try-hard
LOAD T2,MBDST,(MB) ; Yes, get the destination address
MOVE T3,T2 ; In case we need it later
TXZ T2,RN%ARE ; Clear the area number field
ADD T2,RTRNRV ; Add reach vector offset
TMNN RMTRY,(MB) ; "Try hard" flag set?
IFSKP.
SETZRO RNCCH,(T2) ; Yes, clear the in-cache flag
ENDIF.
;Now we must determine the next hop address. The following rules apply:
; If destination is in cache then nexthop = destination
; else
; If designated router .ne. 0 then nexthop = desiginated router
; else
; nexthop = destination
LOAD T4,RCDSL,(RC) ; No, get address of designated router
TMNN RNCCH,(T2) ; Is cache flag set?
JUMPN T4,RTR2R5 ; Not in cache, use DSR if we have one
CAME T3,RTRNAD ; Is this destined for us?
IFSKP. ; Yes, must be loop node from NML
SKIPE T4 ; Do we have a DSR?
JRST RTR2R5 ; Yes, send it there
ENDIF. ; No, send it to ourselves (this will fail)
SETZ T4, ; Start clean
LSHC T3,-^D8 ; Convert from 0,,N1,N2 to N2,N1,,0
LSH T3,2
LSH T4,-^D18 ; Shift back to last character in string
IOR T4,T3 ; Put it in T4 with the next to last char.
ELSE.
LOAD T4,AJNAL,(AJ) ; Address of next hop (Ethernet only)
ENDIF.
RTR2R5: HRLZ T4,T4 ; Position address correctly
MOVE T2,RC ; Send on this circuit
MOVE T3,MB ; this message
CALL CALKON ; Call the data link layer (DNADLL)
CALLRET XMTFAI ; The transmit failed - Restart data link
RET ;GIVE A GOOD RETURN TO CALLER
SUBTTL RTRBEH - Build header for ethernet data messages
RTRBEH: LOAD T1,RMFST,(MB) ;GET THE FIRST BYTE
CALL DNP1BY ;PUT IT INTO THE MESSAGE
SETZ T1, ;CLEAR OUT SOME RESERVED FIELDS
CALL DNP2BY ;D-AREA, D-SUBAREA
MOVE T1,RTRHIO ;Get HIORD
CALL DNPHIO ;Place in message
LOAD T1,MBDST,(MB) ; and the 16 bit node address NSP gave us
CALL DNP2BY
SETZ T1, ;ZERO SOME MORE FIELDS
CALL DNP2BY ;S-AREA, S-SUBAREA
MOVE T1,RTRHIO ;Get HIORD
CALL DNPHIO
LOAD T1,MBSRC,(MB) ; and the 16 bit source address
CALL DNP2BY
SETZ T1, ;SOME MORE RESERVEDS
CALL DNP1BY ;NEXT LEVEL 2 ROUTER
LOAD T1,MBVST,(MB) ;Get visits count
CALL DNP1BY
SETZ T1, ;NEXT 2 FIELDS ARE RESERVED, JUST WRITE ZERO'S
; LOAD T1,MBSCL,(MB) ;GET THE SERVICE CLASS
CALL DNP1BY ;INTO THE MESSAGE
; LOAD T1,MBPRO,(MB) ;GET THE PROTOCAL TYPE
CALL DNP1BY ;INTO THE MESSAGE
RET
SUBTTL R2NODN - Return Output Done to NSP
;R2NODN - Give Output Done to NSP
;
; Call:
; MB/ Pointer to Message Block
;The relevant fields must be set up in the public portion of the message
;block (i.e., source and destination node addresses, etc.)
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
R2NODN: MOVX T3,NV.ODN ;GET THE OUTPUT DONE ENTRY TYPE
MOVE T4,MB ;SET UP MB FOR NSP
LOAD T1,MBSRC,(MB) ;IT'S GOING BACK TO SOURCE
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
CALLRET R2NCL1 ;CALL NSP
SUBTTL R2NRTN - Return Message to NSP
;R2NRTN - Return Message to NSP
;
; Call:
; MB/ Pointer to Message Block
;Fields must be set up correctly in the Public portion of the message
;block.
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
R2NRTN: SKIPA T3,[NV.RTS] ;Returned by local router to local NSP
R2NRFR: MOVX T3,NV.RFR ;Returned by remote router to local NSP
CALLRET R2NCAL ;MERGE WITH THE OTHER CODE
SUBTTL R2NRCV - Pass received Message to NSP
;R2NRCV - Pass received message to router user (ususally NSP)
;
; Call:
; MB/ Pointer to Message Block
;Fields must be set up correctly in the public portion of the message
;block.
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
;R2NCAL, which is the actual routine which calls a router user (also called
;an NSP), will check the message block for the destination address and use
;this to find look up the correct entry vector in the normal routing vector.
;RTRNOV contains the entry vector for NSP when the node entry for RTRNRV
;says it is a local node (RNLCL is on).
R2NRCV: LOAD T2,MBSRC,(MB) ;GET THE SOURCE OF THIS MESSAGE
LDB T1,[POINTR(T2,RN%ARE)] ;GET THE AREA NUMBER
CAME T1,RTRHOM ;OUR AREA?
JUMPN T1,R2NRC1 ;JUMP IF FROM ANOTHER AREA
LDB T1,[POINTR(T2,RN%NOD)] ;GET THE NODE NUMBER
SKIPLE T1 ;RANGE CHECK THE ADDRESS
CAMLE T1,RTRMXN ; FOR REASONABLENESS
SKIPA ;OUT OF RANGE
JRST R2NRC1 ;ALL OK, CONTINUE
EVENT RE.NOR,<Node out-of-range packet loss>,MB
AOS RTRCNO ;INCREMENT OUT-OF-RANGE COUNT
CALLRET FREMSG ;RETURN THE MESSAGE BLOCK
R2NRC1: MOVX T3,NV.RCV ;GIVE RECEIVED MESSAGE ENTRY TYPE
R2NCAL: SKIPN T4,MB ;HE WANTS THE MESSAGE BLOCK PTR IN T4
BUG.(CHK,ROUXNZ,ROUTER,SOFT,<R2NCAL called with MB=0>,,<
Cause: Somehow MB was trashed in the forward process. It is unlikely
to get this far if RTRFWD rececived a bad MB.
Action: Look for faulty code in the forward process
>,RTN)
LOAD T1,MBDST,(MB) ;GET THE DESTINATION OF THIS MESSAGE
LDB T2,[POINTR(T1,RN%ARE)] ;GET THE AREA IN T2
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
SKIPE T2 ;Do we have an area?
CAMN T2,RTRHOM ;Yes, is it ours?
SKIPA ;Ours or don't have one
JRST R2NCLE ;Not ours, THEN LET SOMEONE ELSE WORRY ABOUT IT
R2NCL1: ADD T1,RTRNRV ;GET NODE'S ENTRY IN "NORMAL" VECTOR
JN RNLCL,(T1),R2NCL2 ;IF IT IS A LOCAL NODE, RETURN MESSAGE
TMNE RMODN,(MB) ;NOT LOCAL, CHECK FLAGS FOR CONSISTENCY
BUG.(CHK,ROUNLN,ROUTER,SOFT,<Trying to return msg to non-local NSP>,,<
Cause: We have decided to return a message to the local NSP but the local
NSP was not the originator.
>,R2NCLE)
R2NCLE: SETZRO RMODN,(MB) ;MAKE FREMSG TOSS THE MSG NOW
CALLRET FREMSG ;RETURN MSG BLK TO FREE POOL
R2NCL2: ADD T1,RTROFS ;GET THE VECTORED ENTRY POINT POINTER
MOVE T1,(T1) ;GET THE CORRECT ENTRY
CALLRET (T1) ;CALL WHATEVER IS ABOVE US
SUBTTL R2KINI - Initialize a Kontroller's Circuit
;R2KINI - Initialize a DLL circuit
;
; Call:
; RC/ Pointer to Circuit Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T2
R2KINI: LOAD T1,RCSTA,(RC) ;GET THE CIRCUIT STATE
CAIE T1,RCS.OF ;We must be in OFF or
CAIN T1,RCS.RJ ; rejected state
TRNA
RET ;NO, THEN SKIP THIS
MOVX T1,DF.OPN ; Function is open
MOVE T2,RC ; Circuit block
LOAD T3,RCLID,(RC) ; Get the line ID for sanity check
CALL CALKON ; Try to open the port
IFSKP.
JE RCBCT,(RC),R2KIN1 ; Point-to-point doesn't send NI hellos
CAIE T1,LS.ON ; Is line running?
IFSKP.
MOVX T1,RCS.RN ; Yes, then put circuit into the run state
SETONE RCSHM,(RC) ; Send a hello message to start things off
ELSE.
MOVX T1,RCS.WT ; No, say "waiting" then
ENDIF.
STOR T1,RCSTA,(RC) ; Set the state
SETZRO RCTIN,(RC) ; Clear timer
RETSKP
ELSE.
CALL DNGTIM ; Get the current time
ADD T1,RTRCRT ; Wait before re-attempting the open
STOR T1,RCTIN,(RC)
RET ; and indicate failure
ENDIF.
R2KIN1: MOVX T1,RCS.WT ; Advance to the wait state
STOR T1,RCSTA,(RC)
MOVX T1,ADJ.IN ;SAY THE ADJACENCY IS INITIALIZING
OPSTR <SKIPE AJ,>,RCAJQ,(RC) ;Get the adjacency
STOR T1,AJSTA,(AJ) ;STORE IT IN THE ADJACENCY BLOCK
IFN FTOPS20,<
LOAD T1,LIDEV,+RC.LID(RC) ; Get the device type
CAIE T1,LD.DTE ; If DTE then give it a TOPS20
IFSKP.
MOVX T1,RE.LDL ; specific event. This is so the
LOAD T2,RCLID,(RC) ; Data Link Watcher will wiggle
MOVX T3,RS.LSL ; the DTE again.
SETZ T4,
CALL RTNEVH ; Give a hidden event to NML
ENDIF.
> ;End IFN FTOPS20
RETSKP ;GIVE GOOD RETURN ABOVE
SUBTTL R2KCLS - Close the data link circuit
;R2KCLS - Close a DLL circuit
;
; Call:
; RC/ Pointer to Circuit Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T2
;
;We have to set the state of the circuit to off state.
R2KCLS: MOVX T1,RCS.OF ;We are in "OFF" state
STOR T1,RCSTA,(RC) ;Store this state
MOVX T1,DF.CLS ;Function is close
MOVE T2,RC ;Circuit block
CALL CALKON ;Tell the DLL we are shutting down
TRN
RET
SUBTTL CALKON - Call the Kontroller
;CALKON - Call the DLL level "kontroller"
;
; Call:
; T1/ Kontroller Function Code
; T2/ Pointer to circuit block
; T3/ Argument (Usually Pointer to Message Block)
; T4/ Next hop for the NI
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
;This routine will call the correct Kontroller on the correct circuit
;given the line id. The kontroller is called with T1 containing the
;function to perform, T2 containing the hardware line address and T3
;with function specific data. If the device is on the wrong CPU (only
;DTEs on TOPS-10 SMP), CALKON will queue the request to be serviced
;at once-a-jiffy service on the correct CPU.
CALKON: SAVEAC <RC,P1> ;SAVE A COUPLE ACS
MOVE RC,T2 ;SET UP THE CIRCUIT BLOCK POINTER
IFN FTMP,<
PUSH P,T4 ;SAVE T4
LOAD T4,LIDEV,+RC.LID(RC) ;GET THE DEVICE TYPE
CAIE T4,LD.DTE ;IS IT CPU-DEPENDANT?
JRST CALKO5 ;NOT CPU DEPENDANT, GO AHEAD AND DO IT.
LOAD T4,LIKON,+RC.LID(RC) ;GET THE CPU NUMBER OF THE CIRCUIT
CAMN T4,.CPCPN ;ARE WE ON THAT CPU NOW?
JRST CALKO5 ;YES
CAIN T1,DF.XMT ;QUEUED OUTPUT?
JRST CALKO4 ;YES, QUEUE UP THE MESSAGE BLOCK.
CAIE T1,DF.OPN ;IS THIS AN INITIALIZE FUNCTION?
JRST CALKO1 ;NO, TRY FOR SOMETHING ELSE
SETONE RCOPN,(RC) ;FLAG INITIALIZE TO BE DONE AT JIFFY LEVEL.
POP P,T4 ;RESTORE T4
MOVEI T1,LS.OFF ;PRETEND LINE STATE IS OFF
RETSKP ;SAY WE DID IT.
CALKO1: CAIE T1,DF.CLS ;IS THIS A HALT KONTROLLER FUNCTION?
BUG.(CHK,ROUIKF,ROUTER,SOFT,<Illegal Kontroller function>,,<
Cause: CALKON was called with an illegal function code. The only allowed
values are DF.XMT, DF.OPN, and DF.CLS.
>,RTN)
SETONE RCCLS,(RC) ;FLAG HALT TO BE DONE AT JIFFY LEVEL.
POP P,T4 ;RESTORE T4
RETSKP ;SAY WE DID IT
CALKO4: D36OFF ;NO, WE'LL HAVE TO QUEUE THE MESSAGE
ENDQUE T3,RC.JSQ(RC),MB.NXT,T1 ;QUEUE THE MESSAGE
D36ON ;TURN INTERRUPTS BACK ON
POP P,T4 ;RESTORE T4
RETSKP ; AND RETURN TO SENDER
CALKO5: POP P,T4 ;RESTORE T4
>;End of IFN FTMP
LOAD T2,RCDLB,(RC) ;GET THE KONTROLLER'S BLOCK ADDRESS
LOAD P1,LIDEV,+RC.LID(RC) ;GET THE DEVICE TYPE
;************************
TORESCD
DNSNUP(RTROTR) ;LABEL FOR DNSNUP TO FIND OUTPUT MESSAGES
TOXRESCD
;EXPECTS (T3) = MESSAGE BLOCK
;************************
CALLRET DNDDSP ;DISPATCH TO DNADLL AND RETURN +1 OR +2
SUBTTL CALQOB - Call CALKON for queued output.
;CALQOB - Send a message to the DLL "kontroller"
;
; Call:
; RC/ Pointer to the circuit block
; MB/ Pointer to message block
; T4/ Next hop address (if any)
; Return:
; +1, Always. If the output fails, it calls XMTFAI which returns
; the message in MB and closes the port, setting a time at
; which to reopen it.
;
;This routine is a jacket around CALKON to make the code sending messages
;simpler and easier to read.
CALQOB: INCR RCCMQ,(RC) ;INCREMENT NUMBER OF MESSAGES QUEUED
MOVX T1,DF.XMT ;SET UP FUNCTION CODE
MOVE T2,RC ;COPY POINTER TO CIRCUIT BLOCK
MOVE T3,MB ;COPY POINTER TO MESSAGE BLOCK
CALL CALKON ;CALL THE KONTROLLER
CALLRET XMTFAI ;OUTPUT FAILED
RET ;RETURN SUCCESS
SUBTTL XMTFAI/CIRFAI - Transmit/Line failed
;Call:
; RC/ Circuit block
; MB/ Message that couldn't be transmitted
XMTFAI: SETZRO RMDRM,(MB) ; Don't try to resend this
MOVE T3,MB ; SET UP MESSAGE BLOCK POINTER FOR RTIOTC
CALL RTIOTC ; FREE UP THE MESSAGE BLOCK
CIRFAI: CALL RTIDWN ; SAY THE LINE IS NOW DOWN
CALL R2KCLS ; Close the port
MOVX T1,RCS.RJ ; Set state to rejected
STOR T1,RCSTA,(RC)
CALL DNGTIM ; and try to reopen it soon
STOR T1,RCTIN,(RC) ;
RET
SUBTTL RTRRCR - Recompute Routing
;RTRRCR - Routine to Recompute Routing Vector
;
; Call:
; RTRNRV is expected to contain a ptr to the current "normal"
;routing vector, while RTRNVB points to the routing vector bitmap.
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
; AC Usage:
; AJ/ Pointer to the adjacency block
; RC/ Ptr to circuit block
; T4/ Index into scratch routing vector
; T3/ Index into normal routing vector
;
;This routine is called whenever it is thought that the topology of
;the network may have changed. RTRNRV is the normal routing vector
;which is used by the forwarding routine, while RTRNVB is a bitmap
;of which nodes need to be recomputed.
RTRRCR: SKIPN RTRCBQ ;Any circuits yet?
RET ;If not, just return
TRACE RTR,<Recomputing network topology>
STKVAR <MSGLEN>
SKIPN ENFLG ; Endnode?
IFSKP.
SKIPE EVSDRP ; If we are not eavesdropping then nothing to
CALL RTRBMV ; update. Update "maybe" vector
ELSE.
SETZM RTRRCF ; Clear the "recompute-routing" flag
CALL RTRBNV ; Build normal routing vector
ENDIF.
SKIPN T1,AJOFLQ ; Any adjacencies to free?
RET ; No
RTRRC2: LOAD P1,AJNXT,(T1) ; Get next adjacency on queue if any
CALL DNFWDS ; Return the memory
MOVE T1,P1 ; Get possible next adjacency to free
JUMPN T1,RTRRC2 ; If another tryto free it
SETZM AJOFLQ ; The queue is now empty
RET ; And now we are done
SUBTTL RTRBNV - Build normal routing vector
;Here to recompute the normal routing vector. We also
;look for local users in the "normal" routing vector as we go
;through. With local users, RTRNOV has the address of the vector entry
;to that "NSP", therefore it is left alone.
RTRBNV: STKVAR <NVBAOJ,NVBENT,UPDCNT>
SETZM UPDCNT ;Initialize update count
IFN FTOPS20,<
STKVAR <TCIFLG>
SETZM TCIFLG ;Initialize topology change count
>; END IFN FTOPS20
MOVE T1,RTRMXN ;Get maximum node address
ADDI T1,1 ;Adjust for node 0
IDIVI T1,^D36 ;Compute size of routing vector bitmap
SKIPE T2 ;Round up
ADDI T1,1 ;...
MOVNS T1 ;Create an AOBJN pointer to bitmap
HRLZS T1 ;...
RTRBN1: MOVEM T1,NVBAOJ ;Save routing vector bitmap AOBJN pointer
HRRZ T2,T1 ;Get current routing vector bitmap offset
ADD T2,RTRNVB ;Add address of routing vector bitmap
SETZ T1, ;Get a zero for entry
EXCH T1,(T2) ;Clear entry and get current value
MOVEM T1,NVBENT ;Save current entry
RTRBN2: MOVE T1,NVBENT ;Get current entry value
JUMPE T1,RTRBN8 ;Jump if current entry zero
JFFO T1,.+1 ;Find next bit set within entry
MOVE T1,BITS(T2) ;Clear bit just found in saved entry value
ANDCAM T1,NVBENT ;...
HRRZ P2,NVBAOJ ;Compute node number of node to recompute
IMULI P2,^D36 ;...
ADD P2,T2 ;...
CAMLE P2,RTRMXN ;Range check computed node number
BUG.(CHK,ROUBMC,ROUTER,SOFT,<Normal routing vector bitmap corrupted>,,,RTRBN9)
MOVE P1,RTRNRV ;Get address of normal routing vector
ADD P1,P2 ;Offset to node being recomputed
MOVE T4,(P1) ;Get current routing information
TXNE T4,RNLCL ;Is this the local node?
JRST RTRBN2 ;Yes, skip over this node
;Continued on next page
;Continued from previous page
MOVX Q1,RNHOP!RNCST ;Start off with maximum cost and hops
SETZ Q2, ;And no known adjacency pointer
SKIPN RC,RTRCBQ ;Get address of first circuit block
JRST RTRBN7 ;None there?
RTRBN3: LOAD AJ,RCAJQ,(RC) ;Get address of first adjacency block
JUMPE AJ,RTRBN6 ;None there, ignore this circuit
RTRBN4: LOAD T1,AJSTA,(AJ) ;Get current state of adjacency
CAXE T1,ADJ.UP ;Is it up?
JRST RTRBN5 ;No, skip this adjacency
LOAD T1,AJNAN,(AJ) ;Get node address of adjacent node
JUMPE T1,RTRBN5 ;Skip this adjacency if no node address
CAME T1,P2 ;Recomputing this node's information?
IFSKP.
SETZ T4, ;Yes, get dummy routing information
ELSE.
LOAD P1,AJRTV,(AJ) ;Get address of adjacency's routing vector
JUMPE P1,RTRBN5 ;No routing information if an endnode
ADD P1,P2 ;Offset to node being recomputed
MOVE T4,(P1) ;Get current routing information
ENDIF.
LOAD T1,RNCST,+T4 ;Compute cost to subject node
OPSTR <ADD T1,>,RCCST,(RC) ;...
LOAD T2,RNHOP,+T4 ;Compute hops to subject node
ADDI T2,1 ;...
CAMG T1,RTRMXC ;Cost and hops within range?
CAMLE T2,RTRMXH ;...
JRST RTRBN5 ;No, skip this adjacency
LOAD T3,RNCST,+Q1 ;Get best cost so far
CAMLE T1,T3 ;Is cost via this adjacency the same or better?
JRST RTRBN5 ;No, skip this adjacency
CAMN T1,T3 ;Is this adjacency the same cost?
JUMPN Q2,[LOAD T3,AJNAN,(AJ) ;Yes, get node address of adjacent node
LOAD T4,AJNAN,(Q2) ;And address of best (so far) adjacency
CAMG T3,T4 ;Is new adjacency node address greater?
JRST RTRBN5 ;No, ignore this adjacency
JRST .+1] ;Yes, use this adjacency
STOR T1,RNCST,+Q1 ;Update best cost and hops values
STOR T2,RNHOP,+Q1 ;...
TXO Q1,RNRCH ;Mark node as reachable
MOVE Q2,AJ ;Remember chosen adjacency for this node
RTRBN5: LOAD AJ,AJNXT,(AJ) ;Step to next adjacency
JUMPN AJ,RTRBN4 ;Loop back for all adjacencies
RTRBN6: LOAD RC,RCNXT,(RC) ;Step to next circuit
JUMPN RC,RTRBN3 ;Loop back for all adjacencies
;Continued on next page
;Continued from previous page
RTRBN7: MOVE P1,RTRNRV ;Get address of normal routing vector
ADD P1,P2 ;Offset to node being recomputed
MOVE T4,(P1) ;Get current routing information
LDB T1,[POINTR (Q1,RNCST!RNHOP)] ;Get cost and hops values
LDB T2,[POINTR (T4,RNCST!RNHOP)] ;...
MOVE T3,P1 ;Get address of current entry
ADD T3,RTROFS ;Offset to output adjacency vector
MOVE T3,(T3) ;Get current output adjacency
CAMN T1,T2 ;Any change in cost or hops?
CAME T3,Q2 ;Or output adjacency?
IFNSK.
TXO Q1,RNCHG ;Yes, set change flag
AOS UPDCNT ;Increment update count
SUB T1,T2 ;Update routing vector checksum
ADDM T1,RTRCKS ;...
XOR T4,Q1 ;Did reachability change?
TXNN T4,RNRCH ;...
IFSKP.
IFN FTOPS20,<
AOS TCIFLG ;Increment topology change count
>; END IFN FTOPS20
TXNE Q1,RNRCH ;Is node now reachable?
TDZA T3,T3 ;Yes, get reachable flag and skip
MOVEI T3,1 ;No, get unreachable flag
MOVE T2,P2 ;Get node number
MOVE T1,RTRHOM ;Generate full node address
DPB T1,[POINTR (T2,RN%ARE)] ;...
EVENT RE.NRC,<Node reachability change>
ENDIF.
MOVE T1,P1 ;Get address of current entry
ADD T1,RTROFS ;Offset to output adjacency vector
MOVEM Q2,(T1) ;Store updated routing information
MOVEM Q1,(P1) ;...
ENDIF.
JRST RTRBN2 ;Loop back for entire bitmap entry
RTRBN8: MOVE T1,NVBAOJ ;Get AOBJN pointer to bitmap vector
AOBJN T1,RTRBN1 ;Loop back to inspect entire bitmap
RTRBN9: SKIPN UPDCNT ;Any changes in routing vector?
RET ;No, return
IFN FTOPS20,<
SKIPE TCIFLG ;Topology change?
CALLX (MSEC1,NTCIN) ;Yes, signal topology change interrupt
>; END IFN FTOPS20
SKIPN RC,RTRCBQ ;Get address of first circuit block
RET ;None? Give up now
RTRBN0: SETONE RCSRM,(RC) ;Set send routing message flag
LOAD RC,RCNXT,(RC) ;Get address of next circuit block
JUMPN RC,RTRBN0 ;Loop back to set SRM for all circuits
RET ;And then return
SUBTTL RTRBMV - Maybe vector update when running as an endnode
RTRBMV: CALL DNGTIM ; Get current milliseconds
CAMG T1,BMVTIM ; and see if time for another update
RET ; of the maybe vector.
ADD T1,BMVIVL ; Compute time of next update
MOVEM T1,BMVTIM
SKIPN RC,RTRCBQ ; Do we have a circuit
RET
OPSTR <SKIPE AJ,>,RCAJQ,(RC) ; Get the only adjacency
IFSKP.
MOVE T1,RTRNRV ; Address of vector
MOVE T2,RTRMXN ; Number of slots in vector
AOJ T2, ; including node 0
DO.
SETZRO RNMBY,(T1) ; Clear the "maybe bit"
SOJLE T2,RTN ; Exit when all elements done
AOJ T1, ; Point to next element
LOOP. ; Loop back
ENDDO.
ENDIF.
LOAD P2,AJRTV,(AJ) ; Get pointer to routing vector
JUMPE P2,RTN ; Just in case
ADDI P2,1 ; Start with node 1
SKIPN P1,RTRNRV ; Get reach vector
RET
LOAD T1,RCCST,(RC) ; Get the cost on the Ethernet
STOR T1,RNCST,(P1) ; and save it in element 0 of the vector
MOVEI T1,1 ; and dummy up the hops
STOR T1,RNHOP,(P1)
ADDI P1,1 ; Step to node 1
MOVE Q1,RTRMXN ; Get the maximum number of nodes
RTRBM1: SETZRO RNMBY,(P1) ; Assume not reachable
LOAD T2,RNCST,(P2) ; Get the cost
OPSTR <ADD T2,>,RCCST,(RC) ; Add the circuit cost
LOAD T1,RNHOP,(P2) ; Get the number of hops
AOS T1 ; Adjust it by us
CAMGE T2,RTRMXC ; Is the cost within the max?
CAML T1,RTRMXH ; How about the hops?
JRST RTRBM2 ; No, then do the next node
SETONE RNMBY,(P1) ; Yes, assume reachable
RTRBM2: AOJ P1, ; Do the next one
AOJ P2, ; on both of them
SOJGE Q1,RTRBM1 ; Loop for the next node
SETZM RTRRCF ; Clear the "recompute-routing" flag
RET
SUBTTL RTRUPD - Send routing messages if needed
;RTRUPD - Routine to perform the update process (send routing messages)
;
; Call:
; RTRNRV must contain the ptr to the normal routing vector
; RTRCBQ must contain a ptr to the first circuit block
;
; Return:
; RET ;Always
;
; Uses: T1-T4
;Loop through all the circuit blocks and see if the long timer (T2) has
;expired. If it has we send a routing message, if it hasn't check
;the send routing message flag and if set, send the routing message if
;the short timer has expired. The routing message is built from the
;"normal" routing vector. After the routing message has been queued,
;the circuit block "last routing message sent" timer is updated, and
;the "send routing message" flag is cleared.
RTRUPD: SKIPGE ENFLG ;If an endnode
RET ; then don't send a routing message
TRVAR <COUNTPOS,NODCNT,TOTALNF>
STKVAR <EMPTY,MAXNODE,MAXSEG,OVFLG>
SKIPA RC,RTRCBQ ;GET THE BEGINNING OF THE CIRCUIT QUEUE
UPDLOP: LOAD RC,RCNXT,(RC) ;GET THE POINTER TO THE NEXT ONE
;Careful if this call is moved (JRST RTRCHK)
JUMPE RC,RTRCHK ;IF DONE THEN GO CHECK THE ROUTING VECTOR
LOAD T1,RCSTA,(RC) ;GET THE STATE OF THIS CIRCUIT
CAIE T1,RCS.TT ;IS THE STATE IN TEST
CAIN T1,RCS.RN ; OR OK STATE
TRNA ;YES, SEND ROUTING MESSAGE
JRST UPDLOP ;NO, LOOK AT NEXT CIRCUIT
SETZM TOTALNF ;CLEAR OUT TOTAL NODE FLAG
SETZM EMPTY ;Clear flag saying data in message
OPSTR <SKIPN T2,>,RCTLR,(RC) ;Have we ever sent an update?
JRST RTRSRB ;No, send one now
CALL DNGTIM ;GET THE CURRENT TIME IN T1
SUB T1,T2 ; Compute the elapsed time since last update
MOVE T2,RTRTM1 ; Get the long timer for point to point
TMNE RCBCT,(RC) ; Broadcast circuit?
MOVE T2,RTRBT1 ; Yes, use the broadcast timer
CAML T1,T2 ; Has the update timer (T1) expired?
JRST RTRSRB ; Yes, send all nodes now
TMNN RCSRM,(RC) ; Forced update?
JRST UPDLOP ; No, look at next circuit
TRNA
RTRSRB: SETOM TOTALNF ; Indicate we need to send complete topology
LOAD T1,RCBSZ,(RC) ;GET THE CIRCUIT BLOCK SIZE
SKIPN T1 ;HAVE ONE TO USE?
BUG.(CHK,ROUBSZ,ROUTER,SOFT,<Router circuit block size was zero on a running circuit>,,<
Cause: The blocksize for a circuit is defaulted to RTRBSZ and updated which
information from nodes on the circuit to determine a new minimum
blocksize for the circuit. Somehow this ended up as zero.
>,UPDLOP)
LOAD AJ,RCAJQ,(RC) ; No, then get pointer to only adjacency for
; point-point or any for broadcast
JUMPE AJ,UPDLOP ; No adjacencies, give up...
JN RCBCT,(RC),RTRSX1 ; If broadcast don't check adjacency state
LOAD T1,AJSTA,(AJ) ; Get state of adjacency
CAIE T1,ADJ.UP ; Is it "up"
JRST UPDLOP ; No, try next circuit
RTRSX1: MOVE P1,RTRNRV ;POINT TO NORMAL ROUTING VECTOR
SETZ P2, ;CLEAR OUT CHECKSUM
LOAD T1,AJNTY,(AJ) ;GET THE NODE TYPE IN T1
CAIE T1,ADJ.3F ;IS IT A PHASE III ROUTER?
JRST SP4RM ;NO, THEN CHECK FOR PHASE IV
MOVE T1,RTRMX3 ;GET THE MAXIMUM NUMBER OF PHASE III NODES
MOVEM T1,NODCNT ;SAVE AS THE COUNT OF NODES
LSH T1,1 ;TWO BYTES PER NODE
ADDI T1,2 ;ADD IN SPACE FOR CHECKSUM
CALL DNGMSG ;GET THE MESSAGE BLOCK
JRST UPDLOP ;COULDN'T, THEN TRY NEXT CIRCUIT
MOVE MB,T1 ;GET THE MESSAGE BLOCK POINTER
XMOVEI T1,UD.MSD(MB) ;GET POINTER TO USER DATA MSD
CALL DNPINI ;INITIALIZE THE MSD AND HEADER
SP3LOP: AOS P1 ;PHASE III STARTS WITH NODE 1
LDB T1,[POINTR((P1),<RNHOP!RNCST>)] ;GET THE HOP!COST
ADD P2,T1 ;SUM THE CHECKSUM
CALL DNP2BY ;PLACE BYTES IN ROUTING MESSAGE
SOSLE NODCNT ;DO IT FOR ALL THE NODES but not zero
JRST SP3LOP ;Continue until last node done
MOVE T1,P2 ;Checksum in T1
CALL RTRSNS ;SEND THE SEGMENT OUT
TRN ;ON ERROR TRY NEXT CIRCUIT
JRST UPDLOP ;AND DO THE NEXT ONE
; Here to handle a Phase IV message, but first we have to check for
; Phase III small nodes. If it is one then we exit and do the next circuit
; T1 was set up with the node type from the adjacency vector above.
SP4RM: JN RCBCT,(RC),SP4RM1 ;If broadcast don't check adjacency type
CAIE T1,ADJ.3S ;PHASE III SMALL NODE
CAIN T1,ADJ.LN ;OR PHASE IV END NODE
JRST UPDLOP ;Yes, then no routing update need be sent
SP4RM1: ADD P1,RTRLMG ;Add in offset so we don't start with the same
; node in the vector each time
MOVE T1,RTRMXN ;GET THE MAXIMUM NUMBER OF NODES
MOVEM T1,MAXNODE ;SAVE AS MAXIMUM TO SEND
SP4RM3: MOVEI P2,1 ;THE CHECKSUM STARTS AT 1 FOR PHASE IV
LOAD T1,RCBSZ,(RC) ;GET THE NUMBER OF BYTES FOR MESSAGE BLOCK
CALL DNGMSG ;GET THE MESSAGE BLOCK
JRST UPDLOP ;COULDN'T, THEN TRY NEXT CIRCUIT
MOVE MB,T1 ;GET THE MESSAGE BLOCK POINTER
XMOVEI T1,UD.MSD(MB) ;GET POINTER TO USER DATA MSD
CALL DNPINI ;INITIALIZE THE MSD AND HEADER
LOAD T1,RCBSZ,(RC) ;Number of bytes we can fit into one message
SUBI T1,6 ;Minus the header length and checksum
LSH T1,-1 ;Divide by two since all parts of a segment
MOVEM T1,MAXSEG ; are two bytes in width
SP4RM4: SETZM NODCNT ;CLEAR OUT THE NODE COUNT FOR THIS SEGMENT
SETZM OVFLG ;CLEAR THE OVERFLOW FLAG NOW
SKIPE TOTALNF ;ARE WE TO INCLUDE ALL NODES?
JRST SP4RM6 ;YES, THEN START WITH THIS ONE
; Here we loop until we get a node which has the CHANGE bit set in the routing
; vector.
SP4RM5: LOAD T1,RNCHG,(P1) ;GET THE CHANGE BIT
JUMPN T1,SP4RM6 ;When set start with this node
AOS P1 ;INCREMENT THE COUNT
MOVE T1,P1 ;GET THE NODE NUMBER
SUB T1,RTRNRV ;FROM THE INDEX INTO ROUTING TABLE
CAMLE T1,RTRMXN ;HAVE WE REACHED THE END OF THE VECTOR?
MOVE P1,RTRNRV ;YES, THEN RESET TO THE BEGINNING
SOSL MAXNODE ;DECREMENT COUNT OF NODES LEFT TO LOOK AT
JRST SP4RM5 ;LOOP UNTIL WE FIND ONE WITH CHANGE SET
JRST SP4RM9 ;WE HAVE LOOKED AT ALL NODES
;Here to begin a new segment of the routing message
SP4RM6: MOVE T1,MAXSEG ;Get number of 2-byte fields left in buffer
CAIGE T1,3 ;Is there enough room for a one node segemnt?
JRST SP4RM8 ;No, then send current message and start anew
CALL DNRPOS ;READ THE CURRENT POSITION
MOVEM T1,COUNTPOS ;SAVE THE POSITION FOR COUNT
SETZ T1, ;GET A ZERO
CALL DNP2BY ;PUT THE COUNT IN
MOVE T1,P1 ;GET THE NODE NUMBER INDES
SUB T1,RTRNRV ;MAKE IT A NODE NUMBER
ADD P2,T1 ;ADD INTO THE CHECKSUM
CALL DNP2BY ;PUT THE 2 BYTES INTO THE MESSAGE
SOS MAXSEG ;Start-ID = 2 bytes
SOS MAXSEG ; and count = 2 bytes
SP4RM7: LDB T1,[POINTR((P1),<RNHOP!RNCST>)] ;Get COST/HOPS for this entry
ADD P2,T1 ;ADD TO CHECKSUM
AOS NODCNT ;INCREMENT THE COUNT OF NODES IN THIS SEGMENT
SETOM EMPTY ;Flag to indicate data in message
CALL DNP2BY ;Put COST/HOPS into the message
AOS P1 ;DO THE NEXT ONE
MOVE T1,P1 ;GET THE NODE NUMBER
SUB T1,RTRNRV ;FROM THE INDEX INTO ROUTING TABLE
CAMG T1,RTRMXN ;HAVE WE REACHED THE MAXIMUM YET?
IFSKP.
SETOM OVFLG ;SET THE OVERFLOW FLAG SO WE END THE SEGMENT
MOVE P1,RTRNRV ; and reset to the beginning of the vector
ENDIF.
SOSG MAXNODE ;DECREMENT TOTAL NODE COUNT
JRST SP4RM9 ; JUMP IF DONE
SOSG MAXSEG ; Two COST/HOP bytes and see if more room
JRST SP4RM8 ; NO, THEN SEND IT AND LOOP BACK
SKIPE OVFLG ;OVERFLOW SET?
IFSKP. ; No
LOAD T1,RNCHG,(P1) ;GET THE CHANGE BIT FOR NEXT NODE
SKIPN TOTALNF ;IS THE TOTAL NODE FLAG SET?
SKIPE T1 ; or do we have a change bit set?
JRST SP4RM7 ; Yes, go do the next entry
ENDIF.
CALL CLSSEG ; Close the current segment
JRST SP4RM4 ; and possibly start a new one
SP4RM8: CALL CLSSEG ; Close out the current segment
MOVE T1,P2 ; Checksum to T1
CALL RTRSNS ;SEND THE SEGMENT OUT
JRST UPDLOP ;ERROR, THEN GO TO THE NEXT CIRCUIT (MB freed)
JRST SP4RM3 ;SUCCESS, START A NEW MESSAGE
;Here when all nodes in the normal vector have been looked at
;See if we found any and if so send the routing message.
SP4RM9: SKIPE EMPTY ; Any data in message?
IFSKP. ; No
CALL FREMSG ; Return the message block
JRST UPDLOP ; and step to next circuit
ENDIF.
SKIPE NODCNT ; Yes, do we have any nodes in this segment?
CALL CLSSEG ; Yes, close off the segment
MOVE T1,P2 ; Checksum must be in T1
CALL RTRSNS ;SEND THE SEGMENT OUT
JRST UPDLOP ;ERROR, THEN GO TO THE NEXT CIRCUIT
MOVE T1,RTRBSZ ;Get the block size
IDIVI T1,5 ; and use it to compute
ADD T1,RTRLMG ; a new starting point
CAML T1,RTRMXN ;HAVE WE GONE TOO FAR?
SETZ T1, ; Start over again
MOVEM T1,RTRLMG ;MAKE THIS NEW START
JRST UPDLOP ; Now advance to the next circuit
ENDSV.
;Here because we have reached the end of a segment. That was determined
;by the absence of a CHANGE flag in the vector for some node, or the end of a
;message, or the end of the reach vector has been reached. We will now
;close the segment.
CLSSEG: CALL DNRPOS ;GET OUR CURRENT POSITION
EXCH T1,COUNTPOS ;Get the previously reverved spot for the count
CALL DNGOPS ;GO TO THAT POSITION
MOVE T1,NODCNT ;GET THE NUMBER OF NODES FOR THIS SEGMENT
ADD P2,T1 ;ADD THE COUNT TO THE CHECKSUM
CALL DNP2BY ;PLACE IT INTO THE MESSAGE
MOVE T1,COUNTPOS ;GET THE END OF THE MESSAGE BACK
CALL DNGOPS ;AND GO THERE
RET
;Here to checksum the routing vector to see if it may be corrupted
RTRCHK: SOSLE CHKCNT ;TIME TO CHECK ROUTING VECTOR CHECKSUM?
RET ;NO, RETURN
MOVE T1,CHKVAL ;YES, RESET CHECKSUM COUNTER
MOVEM T1,CHKCNT ;...
MOVE T3,RTRMXN ;GET THE MAXIMUM NUMBER OF NODES
MOVE P1,RTRNRV ;GET THE POINTER TO THE NORMAL ROUTING VECTOR
SETZ P2, ;CLEAR OUT REG FOR CHECKSUM
RTRCK1: SETZRO RNCHG,(P1) ;CLEAR OUT CHANGE FLAG
LDB T1,[POINTR((P1),<RNHOP!RNCST>)] ;GET THE HOPS!COST
ADD P2,T1 ;ADD INTO MESSAGE
AOJ P1, ;ADD IN THE NEXT ONE
SOJGE T3,RTRCK1 ;LOOP FOR THEM ALL
CAME P2,RTRCKS ;IS IT THE SAME AS THE OLD CHECKSUM?
SKIPN RTRCKS ; AND DID WE HAVE ONE?
TRNA ;IT'S OK
BUG.(CHK,ROUBCD,ROUTER,SOFT,<Bad Checksum detected when building routing msg>,,<
Cause: Somehow our internal reachability vector has been damaged since the
last rebuilding.
>)
MOVEM P2,RTRCKS ;STORE THE CHECKSUM
RET ;RETURN TO CALLER
;
; All Outgoing Routing Messages Both Phase III And Phase IV
; pass through this routine. It expects the unnormalized checksum
; in P2.
RTRSNS: MOVE T1,P2 ;GET COPY OF CHECKSUM
CALL CKSNRM ;NORMALIZE THE CHECKSUM
CALL DNP2BY ; AND WRITE IT IN MESSAGE
;Now we must make up the router header
XMOVEI T1,RM.MSD(MB) ;GET POINTER TO ROUTER'S MSD
CALL DNPINI ;SET UP TO WRITE HEADER
SETZ T1, ;BUILD FIRST BYTE IN T1
MOVX T2,RCM.1R ;TYPE = ROUTING MESSAGE
STOR T2,CMTYP,+T1 ;PLACE IT IN CORRECT FIELD
SETONE CMCTL,+T1 ;INDICATE IT IS A CONTROL MESSAGE
CALL DNP1BY ;PLACE THE BYTE
MOVE T1,RTRADR ;GET OUR ADDRESS
MOVE T3,RTRHOM ; and our area
TMNE AJPH4,(AJ) ; If Phase IV include the area number
DPB T3,[POINTR(T1,RN%ARE)]
CALL DNP2BY ;PUT ADDRESS IN MESSAGE
SETZ T1, ;ZERO FOR A RESERVED PHASE IV BYTE
TMNE AJPH4,(AJ) ; If Phase IV include a reserved byte
CALL DNP1BY
XMOVEI T1,UD.MSD(MB) ;POINT TO USER DATA MSD
XMOVEI T2,RM.MSD(MB) ;MAKE RTR MSD POINT TO USER DATA MSD
SETZ T3, ;DON'T CHANGE BYTE POINTERS
CALL DNLMSS ;LINK IN THE MESSAGE SEGMENT
TRACE RTR,<Sending routing message>
JE RCBCT,(RC),RTRSN2 ;If not broadcast send packet now
DMOVE T1,RTRALR ;Sending to "all-routers"
CALL RTRSNI ;Broadcast set it up differently
TRNA
RTRSN2: CALL CALQOB ;OUTPUT THE MESSAGE BLOCK
TRN
SETZRO RCSRM,(RC) ;INDICATE WE HAVE SENT ROUTING MESSAGE
CALL DNGTIM ;Get current time
SKIPE TOTALNF ;Was this a complete update?
STOR T1,RCTLR,(RC) ;Yes, remember the time we sent it
RETSKP ;GIVE GOOD RETURN
ENDTV.
SUBTTL RTRSNI - Send hello/routing message on the NI
;Call:
; T1/ Destination address high order
; T2/ Destination address low order
RTRSNI: STOR T1,MBDS1,(MB) ; Save address of destination (High-order)
STOR T2,MBDST,(MB) ; Low order address
SETZ T4, ; No next hop for broadcast messages
CALL CALQOB ;
RET ;AND CONTINUE ON
SUBTTL CKECTO - Check the cache timer for each node
CKECTO: SOSLE CCHTIM ; Time to check cache flags?
RET ; No
MOVE T4,RTRMXN ; Count of slots in vector
MOVE T3,RTRNRV ; Point to the reach vector which contains
; the cache flag
CKECT1: JE RNCCH,(T3),CKECT2 ; If cache flag is set check cache timeout
MOVE T2,T3 ; Copy current vector address
ADD T2,RTROFS ; Add offset to timer value
CALL DNGTIM ; Get current time
CAMG T1,(T2) ; Is current time past time out value
IFSKP.
SETZRO RNCCH,(T3) ; Yes, clear the in-cache flag
ENDIF.
CKECT2: AOJ T3, ; Step to next node
SOJGE T4,CKECT1 ; More to do?
MOVE T1,RTRADR ; Get local address
ADD T1,RTRNRV ; and index into reach vector slot
SETONE RNCCH,(T1) ; and set the in-cache flag
MOVEI T1,^D120 ; Two minutes before we check again
MOVEM T1,CCHTIM
RET
SUBTTL SELDSR - Select a desiginated router
SELDSR: SKIPA RC,RTRCBQ ; Loop through all circuit blocks
SELDS1: LOAD RC,RCNXT,(RC)
JUMPE RC,RTN ; If done, just return
TMNN RCBCT,(RC) ; We only compute a desiginated router for
JRST SELDS1 ; for broadcast circuits
SETZRO RCPRI,(RC) ; Start at lowest priority
SETZ P1,
OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Get pointer to first adjacency
SELDS2: LOAD AJ,AJNXT,(AJ) ; Step to next
SKIPN AJ
IFSKP.
LOAD T1,AJSTA,(AJ) ; Get state of adjacency
CAIE T1,ADJ.IN ; If state is not initializing
CAIN T1,ADJ.UP ; or up, don't consider it
TRNA
JRST SELDS2
LOAD T1,AJPRI,(AJ) ; Get the adjacency's priority
LOAD T3,AJNAH,(AJ) ; Get the address
LOAD T4,AJNAL,(AJ)
ELSE.
MOVE T1,RTRPRI ; No more adjacencies, check ourselves
MOVE T3,RTRHIO ; Get our address in string format
HLRZ T4,RTRLOO
ENDIF.
CAIGE T1,(P1) ; Is it greater/equal than what we have so far?
JRST SELDS3 ; No, step to next
CAIE T1,(P1) ; Was it the same?
IFSKP.
LOAD T2,RCDSL,(RC) ; Get current designated router's address
CAMG T4,T2 ; Is new one higher?
JRST SELDS3 ; No, keep the one we have
ENDIF.
MOVE P1,T1 ; Save this as the highest
DMOVE Q1,T3 ; and save address
SELDS3: JUMPN AJ,SELDS2 ; Check next adjacency or ultimately ourselves
STOR P1,RCPRI,(RC) ; Save new priority
OPSTR <CAMN Q2,>,RCDSL,(RC) ; Has the designated router changed?
RET ; No, then done
STOR Q2,RCDSL,(RC) ; Save the designated routers address
HRLZ Q2,Q2 ; Reposition low order
CAME Q2,RTRLOO ; Are we the designated router?
IFSKP.
MOVEI T2,^D5 ; Seconds to wait
STOR T2,RCDRT,(RC) ; before we assume DSR role
ELSE.
SETZRO RCDRT,(RC) ; No longer waiting to assume DSR role
SETZRO RCDSR,(RC) ; We are not the DSR
ENDIF.
STOR Q1,RCDSH,(RC) ; Save high order of address
JRST SELDS1 ; and check next circuit
SUBTTL RTRTMR - Routine to perform timer functions
;RTRTMR - Hello, Listener and other timer processes
;
; Call:
; RTRCBQ must point to the first circuit block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
;This code implements the Update Process, the Node Talker Process, and the
;Node Listener Process.
;First we do the Node Listener Process. This consists of ensuring that we
;have heard from all adjacencies within time T3 * T3MULT (or BCT3MULT). (T3
;is the adjacencies hello timer). Ie: current_time - AJTLR < AJNHT. If the
;previous expression is not true, then if the circuit is a:
; point to point - set off-line
; broadcast (Ethernet) - the adjacency is destroyed.
RTRTMR: SAVEAC <P1>
SKIPA RC,RTRCBQ ;GET THE FIRST CIRCUIT BLOCK
RTRTR1: LOAD RC,RCNXT,(RC) ;GET NEXT CIRCUIT BLOCK
JUMPE RC,RTRSHM ;Send hellos if necessary
LOAD P1,RCSTA,(RC) ;Get state of circuit
CAILE P1,RCS.RJ ;Is state off or rejected?
JRST RTRTR2 ;No, check TI state
LOAD T2,RCTIN,(RC) ;Is the timer running?
JUMPE T2,RTRTR2 ;No, look no further (maybe to TR3)
CALL DNGTIM ;Get the current time in T1
CAMGE T1,T2 ;Has time elapsed?
IFSKP. ;Yes
CALL R2KINI ;Try to reopen circuit
TRN
JRST RTRTR3 ; and move to next circuit
ENDIF.
RTRTR2: CAIE P1,RCS.TI ;IS LINK IN TI WAIT?
CAIN P1,RCS.TV ;IS IT IN TV WAIT?
TRNA ;YES, CHECK OUT TI TIMER
JRST RTRTR3 ;NO, CHECK OUT OTHER TIMERS
CALL DNGTIM ;GET THE CURRENT TIME
OPSTR <SUB T1,>,RCTIN,(RC) ;SUBTRACT WHEN WE GOT THE LINE UP
CAMGE T1,RTRITM ;HAS TIME EXPIRED?
JRST RTRTR3 ;NO, JUST CONTINUE ON
;Here when the time allowed for the response to the RI we sent has expired.
ETRACE RTR,<Initialization timer expired and is restarting the circuit>
MOVX T1,RS.VRT ;EVENT REASON: VERIFICATION RECEIVE TIMEOUT
CALL RTEINL ;REPORT INITIALIZATION FAILURE EVENT
CALL CIRFAI ;Close the portal and set reopen time
; SETOM RTRRCF ;RECOMPUTE ROUTING LATER
JRST RTRTR1 ; AND TRY THE NEXT CIRCUIT
;Now check the hello and listener timers.
RTRTR3: CAIE P1,RCS.TT ; Is circuit in test state
CAIN P1,RCS.RN ; or is it running?
TRNA ;YES, OK TO DO THINGS
JRST RTRTR1 ;NO, CHECK OUT THE NEXT CIRCUIT
RTRCHT: OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Get pointer to first adjacency
RTRCH1: LOAD AJ,AJNXT,(AJ) ;Get next adjacency
JUMPE AJ,[CALL RTRTLK ;Check the hello timer
CALL DSRCHK ; and the desiginated router timer
JRST RTRTR1] ;Now, step to next circuit
LOAD T1,AJSTA,(AJ) ;Get the state of the adjacency
CAIE T1,ADJ.UP ;Is it up?
JRST RTRCH1 ;No, then don't check further
CALL DNGTIM ;GET THE CURRENT TIME
OPSTR <SUB T1,>,AJTLR,(AJ) ;SUBTRACT THE TIME LAST MESSAGE WAS RECEIVED
OPSTR <CAMGE T1,>,AJNHT,(AJ) ;DID THE LISTENER TIMER EXPIRE?
JRST RTRCH1 ; No, check the next adjacency
;Here when the listener timer has been exceeded. The adjacency is declared
;down. On point to point circuits, the circuit gets recycled.
LOAD T3,AJNAN,(AJ) ;Get the node address
INCR RCAJD,(RC) ;Count adjacency down events
LOAD T2,RCLID,(RC) ;Get the device ID
EVENT RE.AJD,<Adjacency down-listen timer expired>,
CALL SETRCA ;Yes, set recompute routing flags
JN RCBCT,(RC),RTRCH3 ;No circuit down if broadcast
ETRACE RTR,<Node listener timed out and is rejecting circuit>
MOVX T1,RS.ALT ;EVENT REASON: ADJACENT NODE LISTENER TIMEOUT
CALL RTELDL ;REPORT CIRCUIT DOWN - CIRCUIT FAULT EVENT
CALL CIRFAI ;Close the port and set reopen time
JRST RTRCH1 ; Check next adjacency
RTRCH3: SKIPN ENFLG ; Endnode?
IFSKP.
MOVX T1,ADJ.UN ; Set adjacency state to unused
STOR T1,AJSTA,(AJ)
SETZRO RCDSL,(RC) ; Clear DR address
ELSE.
MOVE T1,AJ ;The adjacency to zap
MOVE T2,RC ; and the circuit block it belongs to
CALL RTRZAB ;Flush the adjacency block
ENDIF.
JRST RTRCH1 ; down and check next
;This code implements the Node Talker Process. Loop through all circuits,
;sending hello messages on any circuits that need them. For point to
;point circuits, a hello message is sent when no other traffic has been sent
;within T3 (the hello timer period for this circuit).
;Ie: current_time - RCTLS >= RCTM3. For broadcast circuits, a hello message
;is sent when when T3 seconds have elapsed since the last hello message
;(current_time - RCTLH >= RCTM3).
RTRTLK: CALL DNGTIM ;Get the time again
LOAD T3,RCTLS,(RC) ;Assume point to point for a moment
TMNE RCBCT,(RC) ;Broadcast circuit?
LOAD T3,RCTLH,(RC) ; Yes, then compare against last hello time
SUB T1,T3 ;Compute amount of elapsed time
MOVX T2,RCSHM ;Get the send hello message flag
OPSTR <CAML T1,>,RCTM3,(RC) ;Have we been quiet for too long??
IORM T2,$RCSHM(RC) ; Yes, set send Hello message flag
RET
; Here to send hello messages to all circuits that have RCSHM set
RTRSHM: SKIPA RC,RTRCBQ ;Point to first circuit block
RTRSH1: LOAD RC,RCNXT,(RC) ;Get next circuit block
JUMPE RC,RTN ;And return when done...
TMNN RCSHM,(RC) ;Do we need to send a hello message?
JRST RTRSH1 ; Nope, try again
;We have just found a circuit that needs a hello message, determine what type
;of circuit it is, send the appropriate message.
JN RCBCT,(RC),RTREHM ; Broadcst circuit?
MOVX T1,NO.HEL+1 ;LENGTH OF DATA SEGMENT
CALL DNGMSG ;GET THAT MANY BYTES
JRST RTRSH1 ;RESOURCE FAILURE, TRY NEXT CIRCUIT
MOVE MB,T1 ;SET UP MB WITH MESSAGE BLOCK POINTER
XMOVEI T1,UD.MSD(MB) ;INITIALIZE THE USER DATA SEGMENT
CALL DNPINI ;DO IT
MOVX T1,NO.HEL ;GET THE NUMBER OF HELLOS IN MESSAGE
CALL DNP1BY ;PLACE THE IMAGE COUNT IN THE MESSAGE
MOVX T3,NO.HEL ;GET THE COUNT FOR LOOP
RTRSH2: MOVX T1,HEL.LO ;WORD THAT GOES IN HELLO MESSSAGE
CALL DNP1BY ;PUT ONE IN
SOJG T3,RTRSH2 ; AND DO ANOTHER ONE IF NEEDED
;Make up the router header.
XMOVEI T1,RM.MSD(MB) ;POINT TO THE ROUTER PORTION OF MESSAGE
CALL DNPINI ;INITIALIZE IT
SETZ T1, ;BUILD THE BYTE IN T1
MOVX T2,RCM.TT ;TYPE OF CONTROL MESSAGE IS TEST MESSAGE
STOR T2,CMTYP,+T1 ;PUT IN BYTE
SETONE CMCTL,+T1 ;SAY IT'S A CONTROL MESSAGE
CALL DNP1BY ;PUT IN THE CTLFLG BYTE
MOVE T1,RTRADR ;GET OUR LOCAL ADDRESS
MOVE T3,RTRHOM ;GET MY AREA
LOAD AJ,RCAJQ,(RC) ;Get the adjacency on this circuit
TMNE AJPH4,(AJ) ;Phase IV node?
DPB T3,[POINTR(T1,RN%ARE)] ; AREA IF PHASE IV
CALL DNP2BY ;PUT THE SOURCE ADDRESS IN MESSAGE
XMOVEI T1,UD.MSD(MB) ;LINK THE USER DATA
XMOVEI T2,RM.MSD(MB) ; TO THE ROUTER HEADER
SETZ T3, ;DON'T CHANGE ANY POINTERS
CALL DNLMSS ;LINK THEM
TRACE RTR,<Sending hello message>
CALL CALQOB ;QUEUE THE MESSAGE BLOCK
SETZRO RCSHM,(RC) ;Indicate that we sent the hello
JRST RTRSH1 ; AND DO IT ALL AGAIN FOR THE NEXT CIRCUIT
;Here to send a hello message on a broadcast style circuit
RTREHM: CALL DNGTIM ;Get the current time
OPSTR <SUB T1,>,RCTLH,(RC) ;Compute time since the last hello
CAMG T1,RTRTM2 ;Has enough time elapsed?
JRST RTRSH1 ; Nope, come back later
SKIPGE ENFLG ; Endnode?
JRST RTRENH ; Yes, send endnode hello
MOVE T1,RTNBRA ;Maximum number of Router BRA's
ADDI T1,1 ; plus one for the reserved
IMULI T1,7 ;Each one takes seven bytes
OPSTR <CAMLE T1,>,RCBSZ,(RC) ;Will this exceed the minimum block size?
JRST RTREH6 ;Yes, then don't do it
CALL DNGMSG ;Get space for message
JRST RTRSH1 ;Can't, try next circuit block
MOVE MB,T1 ;Set message pointer
XMOVEI T1,UD.MSD(MB) ;Initialize user data segment
CALL DNPINI
;
; Now for the 18 bytes of header
;
SETZ T1, ;Start clean
MOVX T2,RCM.RH ;Control message type is Router hello
STOR T2,CMTYP,+T1
SETONE CMCTL,+T1 ;Say type is control
CALL DNP1BY ;Write byte into message
CALL RTRCHH ;Build common Hello header
MOVX T1,IIT.L1 ;We are a level 1 router
CALL DNP1BY ;Write IINFO
LOAD T1,RCRBS,(RC) ; and the blocksize we advertise
CALL DNP2BY
MOVE T1,RTRPRI ;Get our priority to be designated router
CALL DNP1BY
SETZ T1,
CALL DNP1BY ;Reserved byte (area)
LOAD T1,RCTM3,(RC) ;Hello timer
IDIVI T1,^D1000 ;Convert it to seconds
CALL DNP2BY
SETZ T1,
CALL DNP1BY ;Reserved (MPD)
;
; Set up E-LIST (List of Ethernet nodes we have heard from recently)
;
CALL DNRPOS ;Get current position in the message
STOR T1,RMMK1,(MB) ; and set mark in block
SETZ T1, ;Reserve a byte for the count
CALL DNP1BY
MOVEI T1,^D7 ;Write 7 reserved bytes
CALL DNPZB
CALL DNRPOS ;Get current position in the block
STOR T1,RMMK2,(MB) ; and set mark in block
CALL DNP1BY ;
MOVEI P1,^D8 ;Keep track of number written so far
OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Pointer to adjacencies on this circuit
RTREH3: LOAD AJ,AJNXT,(AJ) ;Step to next adjacency
JUMPE AJ,RTREH4 ;No more try next circuit
LOAD T2,AJNTY,(AJ) ;Get adjacency's node type
CAIE T2,ADJ.L2 ;Phase IV level 2 router
CAIN T2,ADJ.L1 ; or plain routing node?
TRNA
JRST RTREH3 ;Not a router, don't include it
LOAD T2,AJSTA,(AJ) ;Get state of this adjacency
SKIPN T2 ;Valid state?
BUG.(CHK,ROUAWS,ROUTER,SOFT,<Adjacency block in queue when state is unused>,,<
Cause: An adjacency block has been left in the queue of active adjacencies
but its state is unused.
>,RTREH3)
LOAD T1,AJNAH,(AJ) ;Hi-order NI address
LOAD T2,AJNAL,(AJ) ; and the low-order
HRLZ T2,T2 ;Put into string format
CALL DNPENA ;Put ID into message
LOAD T1,AJPRI,(AJ) ;Get adjacency's priority
TRZ T1,200 ;Set state to unknown
LOAD T2,AJSTA,(AJ) ;Get the state of the adjacency
CAIN T2,ADJ.UP ;Is it up?
TRO T1,200 ; Yes, then say "known 2-way"
CALL DNP1BY ;Write into message
ADDI P1,7 ;Account for the 7 bytes just written
JRST RTREH3 ;Check next adjacency
; Here when done with inserting routing adjacencies we know about. Update
; counts in the message.
RTREH4: CALL DNRPOS ;Get position at end of message
OPSTR <EXCH T1,>,RMMK1,(MB) ;Save EOM count, get pos of 1st counter
CALL DNGOPS ;Repostion to count
MOVE T1,P1 ;Get count
CALL DNP1BY ;Write it
SUBI P1,^D8 ;Subtract reserved name and count
LOAD T1,RMMK2,(MB) ;Bytes to second count
CALL DNGOPS ;Reposition
MOVE T1,P1 ;Get second adjusted count
CALL DNP1BY ;Write it
LOAD T1,RMMK1,(MB) ;Get pointer to end of message
CALL DNGOPS ;Point to the true end of the message
LOAD T1,RCDSL,(RC) ;Get designated router on this circuit
HLRZ T2,RTRLOO ;Get our address in string format
CAIE T1,(T2) ;Is it us?
IFSKP.
SETONE RMDRM,(MB) ;Yes, set flag so we resend to "all-endnodes"
ENDIF.
TRACE RTR,<Sending Ethernet router hello message>
DMOVE T1,RTRALR ;Send to "ALL-ROUTERS"
CALL RTRSNI ;Queue this message
;Send one to all-endnodes
RTREH6: SETZRO RCSHM,(RC) ;We have sent the Hello
CALL DNGTIM ;Time stamp
STOR T1,RCTLH,(RC) ; Bamm!
JRST RTRSH1 ; and onto the next circuit
SUBTTL RTRENH - Send Ethernet end-node hello
RTRENH: CALL DNGTIM ;Get the current time
OPSTR <SUB T1,>,RCTLH,(RC) ;Compute time since the last hello
CAMG T1,RTRTM2 ;Has enough time elapsed?
JRST RTRSH1 ; Nope, come back later
MOVEI T1,<NO.NIH+^D32> ;Number of bytes for hello message
CALL DNGMSG ;Get space for message
JRST RTRSH1 ;Can't, try next circuit block
MOVE MB,T1 ;Set message pointer
XMOVEI T1,UD.MSD(MB) ;Initialize user data segment
CALL DNPINI
;
; Now for the 18 bytes of header
;
SETZ T1, ;Start clean
MOVX T2,RCM.EH ;Control message type is Endnode hello
STOR T2,CMTYP,+T1
SETONE CMCTL,+T1 ;Say type is control
CALL DNP1BY ;Write byte into message
CALL RTRCHH ;Build common Hello header
MOVX T1,IIT.EN ;We are an ethernet endnode
CALL DNP1BY ;Write IINFO
LOAD T1,RCRBS,(RC) ;Get the blocksize we will advertise
CALL DNP2BY
SETZ T1,
CALL DNP1BY ;Reserved byte (area)
MOVEI T1,^D8 ;Write 8 bytes of zeros for the seed
CALL DNPZB
LOAD T1,RCDSH,(RC) ;Address of the designated router
LOAD T2,RCDSL,(RC) ; we believe exists
LSH T2,^D18 ;Position as a string
CALL DNPENA
LOAD T1,RCTM3,(RC) ;Hello timer
IDIVI T1,^D1000 ;Convert it to seconds
CALL DNP2BY
SETZ T1,
CALL DNP1BY ;Reserved
MOVX T1,NO.NIH ;Send NO.NIH bytes of test message
CALL DNP1BY ;Place the image count in the message
MOVX T3,NO.NIH ;Get the count for loop
RTREN2: MOVX T1,HEL.LO ;Word that goes in hello messsage
CALL DNP1BY ;Put one in
SOJG T3,RTREN2 ; and do another one if needed
TRACE RTR,<Sending Ethernet endnode hello message>
DMOVE T1,RTRALR ;Send to "all-routers"
CALL RTRSNI ;Queue this message
SETZRO RCSHM,(RC) ;We have sent the Hello
CALL DNGTIM ;Time stamp
STOR T1,RCTLH,(RC) ; Bamm!
JRST RTRSH1 ; and onto the next circuit
SUBTTL RTRCHH - Build common part of Ethernet hellos
RTRCHH:
MOVE T1,RTRVER ;Version number of ROUTER
CALL DNP1BY ;Stuff it
SETZ T1, ;ECO # and User ECO # are 0
CALL DNP2BY ;Stuff them
MOVE T1,RTRHIO ;High order
MOVE T2,RTRLOO ; and low order
CALL DNPENA ;Write the address into the message
RET
SUBTTL DSRCHK - Check the DSR timer for each circuit
DSRCHK: TMNN RCBCT,(RC) ;If not broadcast, we don't care
RET
LOAD T1,RCDRT,(RC) ;Is "wait to be DSR" timer running
JUMPE T1,RTN ;If not just exit
SOJG T1,DSRCK1 ;Count down the timer
SETONE RCDSR,(RC) ; and if it expires set the DSR flag
DSRCK1: STOR T1,RCDRT,(RC) ;Save the new value
RET
SUBTTL Data Link Layer Interface
SUBTTL Data Link Layer Interface -- RTRDLE - Entry into Router from DLL
; Call:
; T1/ Function Code
; T2/ Router Circuit Block Address (except if DI.CCB)
; T3/ Data (ususally pointer to message block)
; T4/ Additional data
;
; Return:
; RET ;Always
;
; Uses: T1-T4
;
;We simply check the arguments, set up some arguments for the routines
;which handle the functions and dispatch to those routines.
;
;Note that we decide what to do if DECnet is not running at each
;individual interrupt handler. For example if DECnet is turned off
;between the buffer request and the input done, we could have problems.
;We do not accept and new buffer requests or protocol ups once DECnet
;has been turned off.
INTERN RTRDLE
XRESCD
RTRDLE:
IFN FTPARANOIA,<
CAXL T1,DI.ODN ;RANGE CHECK THE
CAXLE T1,DI.ICB ; FUNCTION CODE
BUG.(CHK,ROUIFD,ROUTER,SOFT,<Illegal function code from the DLL>,,<
Cause: The module DNADLL and ROUTER get their function code from the D36PAR.
They must have been compiled from different UNVs.
Action: Compile from the same D36PAR.UNV
>,RTN)
> ;END IFN FTPARANOIA
SAVEAC <MB,MS,RC,AJ,P1,P2,Q1,Q2> ;SAVE SOME AC'S
STKVAR <DSPWRD> ; Place to save word from dispatch table
MOVE RC,T2 ;GET THE ROUTER CIRCUIT BLOCK
MOVE P1,RTRDTB-1(T1) ;GET BITS AND DISPATCH FOR THIS FUNCTION.
HRRM T1,DSPWRD ; Save function in case can't dispatch
HLLM P1,DSPWRD ; Save function flags
RTRDS2: TXZN P1,RD.CMB ;SHOULD I CHECK FOR A VALID MB?
JRST RTRDS4 ;NO, THIS FUNCTION DOESN'T HAVE AN MB.
SKIPN MB,T3 ;COPY THE MB
RTRDS3: BUG.(CHK,ROUBMB,ROUTER,SOFT,<Bad message block pointer>,,<
Cause: DNADLL has called RTRDLE with a function requiring a message
block, and the pointer supplied (in T3) is either 0 or out of
range.
Action: Determine why DNADLL gave a bogus pointer since he
originally should have obtained it from us.
>,RTRDS9)
IFN FTPARANOIA,<
CALL DNCHMB## ;ASK D36COM TO CHECK THIS POINTER FOR US
JRST RTRDS9 ;BAD POINTER, FORGET THIS REQUEST.
> ;END IFN FTPARANOIA
RTRDS4: TXZN P1,RD.CKS ;SHOULD WE CHECK DECNET/CIRCUIT STATE?
JRST RTRDS6 ;DON'T WORRY ABOUT STATE
MOVE T1,DCNSTA ;Get DECnet state
CAIE T1,DS.ON ;Is it on?
JRST RTRDS7 ;NO, RETURN NOW.
LOAD T2,RCSTA,(RC) ;GET THE CIRCUIT STATE
CAXE T2,RCS.OF ;If state is off
CAXN T2,RCS.RJ ; or rejected
TRNA
RTRDS6: CALLRET (P1) ;NO, CALL APPROPRIATE ROUTINE AND RETURN
RTRDS7: MOVE P1,DSPWRD ; Recover dispatch flags
TXNE P1,RD.CMB ; Does this function have an MB?
CALL FREMSG ; Yes, dispose of it properly, MB = message
TLZ P1,-1 ; Remove flags
CAIE P1,DI.ODN ; If output done then...
JRST RTRDS9
DECR RCCMQ,(RC) ; message no longer queued to the DLL
RTRDS9: SETZ T1, ;MAKE SURE THAT THE REQUESTOR UNDERSTANDS
RET ; THAT THE REQUEST FAILED
RD.CRC==1B0 ;CHECK RC. MAKE SURE IT IS NON-ZERO, AND IF
; FTPARANOIA, RANGE CHECK AND FIND ON RTRCBQ
RD.CMB==1B1 ;CHECK MB. MAKE SURE IT IS NON-ZERO, AND IF
; FTPARANOIA, CALL DNCHFB TO ENSURE IT IS GOOD.
RD.CKS==1B2 ;CHECK STATES BEFORE CALLING. IF EITHER DECNET
; OR LINE STATE IS OFF, SIMPLY ZERO T1 AND
; RETURN.
RTRDTB: RD.CRC+RD.CKS+RD.CMB+RTIOTC ;OUTPUT DONE
RD.CRC+RD.CKS+RD.CMB+RTIINC ;INPUT COMPLETE
RD.CKS+RD.CRC+RTILSC ;LINE STATE CHANGE
RTICCB ;CREATE CIRCUIT
SUBTTL Data Link Layer Interface -- RTICCB - Create circuit block
;RTICCB - Create a circuit block
;
; Call:
; T2/ Data Link Block address
; T3/ Line-ID
; T4/ Blocksize to advertise for this circuit
;
; We can not get here if the circuit state is OFF
;
; Return:
; RET ;Always, returns with T1 containing circuit
; ; block address or zero if it couldn't
; ; allocate a new one
;
; Uses: T1-T4
;
RTICCB: DMOVE P1,T2 ; Save DLB and line ID
MOVE Q1,T4 ; and blocksize
MOVE T1,P2 ; Get the LINE-ID
SKIPN ENFLG ; Endnode?
IFSKP. ; Yes
LOAD T2,LIDEV,+T1 ; Then get the device type on this line
CAIE T2,LD.ETH ; Is it an ethernet?
JRST RTRCCE ; No, then don't initialize with it
ENDIF.
CALL RTRMCB ; Make up the circuit block
JRST RTRCCE ; and return if can't allocate memory
MOVE RC,T1 ; Circuit block pointer we got.
STOR P1,RCDLB,(RC) ; Save data link block address for later calls
STOR Q1,RCRBS,(RC) ; and maximum blocksize we can advertise
ENDQUE RC,RTRCBQ,RC.NXT,T1 ; Add circuit block to queue
JN RCBCT,(RC),RTRCC1 ; If broadcast don't make adjacency block
JN RCAJQ,(RC),RTRCC1 ; If we have an adjacency block don't make one
SETO T1, ; Flag to indicate we expect routing adjacency
CALL RTRMAJ ; Make up the adjacency block
JRST RTRCCE ; Error return
RTRCC1: MOVE T1,RC ; Return circuit block address as callback ID
RET
RTRCCE: SETZ T1, ; Indicate failure
RET
SUBTTL Data Link Layer Interface -- RTILSC - Process line state change
; RTILSC - "Line state change" interrupt from the DLL
;
; Call:
; T2/ Circuit block address
; T3/ New Line State
;
; Return:
; RET ;ALWAYS
;
; Uses:
RTILSC: TRACE RTR,<Received line state change from DLL>
CAIE T3,LS.OFF ; Is new state off?
JRST RTION ; No, must be on
RTIDWN: MOVX T1,RS.LSL ;EVENT REASON: CIRCUIT SYNCHRONIZATION LOST
;*** Was it ever up ?? No event if not
CALL RTELDL ;REPORT CIRCUIT DOWN - CIRCUIT FAULT EVENT
CALL SETRCC ;SET RECOMPUTE ROUTING FLAGS
CALL RTRZCB ;CLEAN OUT THE CIRCUIT BLOCK
CALL RTRSAO ;SET ANY REMAINING ADJACENCIES TO UNUSED
LOAD T1,RCSTA,(RC) ;Get current state
MOVX T2,RCS.FA ; Failed state code
CAIG T1,RCS.RJ ; If off/rejected, don't change state
IFSKP.
STOR T2,RCSTA,(RC) ;STORE AS CURRENT STATE FOR THIS CIRCUIT
TMNN RCBCT,(RC) ;If broadcast, then close portal
IFSKP.
CALL R2KCLS ;Close it
CALL DNGTIM ;Get current uptime
ADDI T1,^D1000 ;Wait a second
STOR T1,RCTIN,(RC) ; to reopen the portal
ENDIF.
ENDIF.
RET
RTION: LOAD T2,RCSTA,(RC) ;GET CIRCUIT STATE
CAIN T2,RCS.RN ; Are we already on?
RET ; Yes, ignore notification
CAIE T2,RCS.WT ;MAKE SURE WE'RE IN WAITING STATE
CAIN T2,RCS.FA ; or failed
TRNA
JRST [ETRACE RTR,<Line state to ON rcv'd in wrong state>
CALLRET CIRFAI] ;TRY TO REINITIALIZE THE CIRCUIT
LOAD T2,RCLID,(RC) ;Get the line-id for the event
EVENT RE.LUP,<Circuit up> ;Generate the event
TMNN RCBCT,(RC) ; Is this a broadcast circuit?
IFSKP.
MOVX T1,RCS.RN ; The circuit state is run
STOR T1,RCSTA,(RC) ;
SETONE RCSHM,(RC) ; Send a hello message to start things off
ELSE.
MOVX T1,RCS.TI ;NEW STATE = TRANSPORT INITIALIZATION WAIT
STOR T1,RCSTA,(RC) ;STORE THE NEW CIRCUIT STATE
CALL RTRSTI
ENDIF.
RET
SUBTTL Data Link Layer Interface -- RTIOTC - Process Output Complete
;RTIOTC - Routine to process output complete interrupt
;
; Call:
; RC/ Circuit block address
; T3/ Message block address
; T4/ Status
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T3
RTIOTC: TRACE RTR,<Output Complete>
MOVE MB,T3 ;GET THE MESSAGE BLOCK ADDRESS
MOVE T1,MB ;ARG FOR DNLENG
CALL DNLENG ;FIGURE OUT THE LENGTH OF THE MESSAGE
DECR RCCMQ,(RC) ;DECREMENT MESSAGES QUEUED COUNT
CALL DNGTIM ;Get the current time
STOR T1,RCTLS,(RC) ;Update time last sent. It is ok to do this on
; ethernets for "all-routers & "all-endnodes"
; since they use TLH for the "talker" process.
TMNN RMDRM,(MB) ;Should this be resent to "all-endnodes"?
IFSKP.
SETZRO RMDRM,(MB) ;Yes, but resend it only once
DMOVE T1,RTRAEN ;Set "all-endnodes" address
CALLRET RTRSNI
ENDIF.
TMNN RMICP,(MB) ;Is this from the local node?
IFSKP.
INCR RCCTS,(RC) ;No, increment the transit count
IFN FTRTST,<
MOVEI P1,TSTBLK
CALL TSTTIM
STOR T1,TRTOC,(P1)
LOAD T2,TRTAF,(P1)
SUB T1,T2
STOR T1,TRTFD,(P1)
>
CALLRET FREMSG ; and discard the packet
ENDIF.
INCR RCCLC,(RC) ;OTHERWISE, INCREMENT THE LOCAL COUNT
CALLRET FREMSG ;GIVE PACKET TO BACK TO NSP, OR FREE IT
SUBTTL Data Link Layer Interface -- RTIINC - Process Input Complete
;RTIINC - Process input complete interrupt
;
; Call:
; RC/ Circuit block pointer
; T3/ Pointer to message block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T3
RTIINC: TRACE RTR,<Input Complete>
MOVE MB,T3 ;GET POINTER TO MESSAGE BLOCK
STOR RC,RMICP,(MB) ;STORE THE INPUT CIRCUIT ADDRESS
;****************************************
TORESCD
DNSNUP(RTRITR) ;Label for DNSNUP to find input messages
TOXRESCD
;****************************************
LOAD AJ,RCAJQ,(RC) ;Get first adjacency in queue
JE RCBCT,(RC),RTRIN4 ;If point-to-point be satisfied with it
LOAD T1,MBSRC,(MB) ;Yes, get address of sender
CALL RTRGAJ ;Look for adjacency with this address...
CALLRET FREMSG ; Not in our area, dump the message
RTRIN4: STOR AJ,RMIAP,(MB) ; and store it for the forwarding routine
SETZRO RMOAP,(MB) ;SO WE DON'T CONFUSE OURSELVES
SETZRO RMOCP,(MB)
MOVE T1,MB ;COPY POINTER TO MESSAGE BLOCK
CALL DNLENG ;SIZE OF THIS MESSAGE
SKIPGE ENFLG ;Endnode?
IFSKP.
CALL DNGTIM ; NO, GET THE CURRENT TIME
SKIPE AJ ; Skip if this adjacency is not initialized
STOR T1,AJTLR,(AJ) ;STORE TIME WE LAST HEARD FOR NEIGHBOR
ENDIF.
CALL RTRHDP ;PARSE THE HEADER
JSP T1,RTEMFE ;REPORT THE MESSAGE FORMAT ERROR EVENT
JE RMCTL,(MB),RTIIN1 ;IF IT'S A DATA MESSAGE, PROCESS IT
;We have a control message here, find the type and dispatch
LOAD T1,RCSTA,(RC) ;GET THE CIRCUIT'S STATE
LOAD T2,RMCTY,(MB) ;GET THE CONTROL MESSAGE TYPE
CALL @RTIIND(T2) ; AND DISPATCH ON THAT TYPE
RET ;RETURN TO SENDER
RTIIND: IFIW <RTCINI&777777> ;ROUTER INITIALIZATION (0)
IFIW <RTCVER&777777> ;ROUTER VERIFICATION (1)
IFIW <RTCTST&777777> ;ROUTER TEST MESSAGE (2)
IFIW <RTCRTE&777777> ;ROUTER ROUTING MESSAGE (3)
IFIW <RTCL2M&777777> ;ROUTER LEVEL 2 ROUTING MESSAGE (4)
IFIW <RTCERH&777777> ;NI ROUTER HELLO MESSAGE (5)
IFIW <RTCNIE&777777> ;NI ENDNODE HELLO MESSAGE (6)
IFIW <RTCILL&777777> ;Illegal message type
;Here with a data message.
RTIIN1:
IFN FTRTST,<
LOAD T1,MBSRC,(MB) ; Get source node
LOAD T2,MBDST,(MB) ; and destination
CAMN T1,T2 ; The same?
JRST [SETONE RMTST,(MB) ; Yes, assume this is a test message
MOVEI P1,TSTBLK ; Get address of test data block
LOAD T1,TRTND,(P1) ; Get the loop node address
STOR T1,MBDST,(MB) ; Save that as the destination
CALL TSTTIM ; Get the uptime in ms.
STOR T1,TRTIC,(P1) ; Save it as time received here
LOAD T2,TRTAF,(P1) ;
SUB T1,T2 ; Compute elapsed time
STOR T1,TRTTA,(P1) ; Save for interested parties
CALL TSTTIM ; Get time again
STOR T1,TRTAF,(P1) ; and save it as time at RTRFWD
JRST .+1]
>
TMNE MBEBF,(MB) ;IS THIS MESSAGE IN AN EMERGENCY BUFFER?
JRST RTIINF ;YES, HANDLE IT DIFFERENTLY
RTIIN2: LOAD T1,RCSTA,(RC) ;GET THE STATE OF THE CIRCUIT
CAIE T1,RCS.TT ;SEE IF THIS IS A GOOD STATE TO BE IN
CAIN T1,RCS.RN ; FOR RECIEVING DATA
TRNA ;WE SEEM TO BE OK
JRST [ETRACE RTR,<Circuit in wrong state for forwarding>
CALLRET FREMSG]
CALLRET RTRFWD ;FORWARD THE MESSAGE
;Here to discard an arriving packet due to congestion.
RTIINF: OPSTR <SKIPGE T2,>,MBDST,(MB) ;GET THE DESTINATION
CALLRET RTRFOR ;DESTINATION IS OUT-OF-RANGE
LDB T2,[POINTR(T2,RN%NOD)] ;GET THE NODE NUMBER
CAMLE T2,RTRMXN ;RANGE CHECK IT
CALLRET RTRFOR ;DESTINATION IS OUT-OF-RANGE
ADD T2,RTRNRV ;GET THE NODE'S ROUTING VECTOR ENTRY
TMNE RNLCL,(T2) ;IF IT WAS SUPPOSED TO COME TO US
IFSKP.
INCR RCCAL,(RC) ;REPORT IT AS ARRIVED CONGESTION LOSS
ELSE.
INCR RCCTL,(RC) ; else increment the transit congestion loss
ENDIF.
CALLRET FREMSG ;FREE MSG BLK & RETURN
SUBTTL RTRSTI - Send routing intitialization message
RTRSTI: MOVX T1,TI.MXL ;MAX LENGTH OF A TI MESSAGE
CALL DNGMSG ; USER MESSAGE AREA
CALLRET CIRFAI ;CAN'T DO IT, Close the port and try again
MOVE MB,T1 ;MAKE MB POINT TO MESSAGE
XMOVEI T1,UD.MSD(MB) ;POINT TO THE USER-DATA MSD
CALL DNPINI ;INITIALIZE MS & THE MSD
SETZ T1, ;MAKE UP FIRST BYTE IN T1/ 0
SETONE CMCTL,+T1 ;TURN ON THE CONTROL MESSAGE BIT
IFN RCM.TI,<
MOVX T2,RCM.TI ;TYPE IS ROUTER INIT
STOR T2,CMTYP,+T1 ;AND STORE THAT IN THE TYPE FIELD
>
CALL DNP1BY ;WRITE THE FIRST BYTE
LOAD AJ,RCAJQ,(RC) ;GET THE ADJACENCY
JUMPE AJ,CIRFAI ;If we don't have one reinitialize
MOVE T1,RTRADR ;GET OUR ADDRESS
MOVE T2,RTRHOM ;GET MY AREA
LOAD T3,RCLID,(RC) ;GET CIRCUIT IDENTIFIER
LOAD T3,LIDEV,+T3 ;GET LINE TYPE
LOAD T4,AJVER,(AJ) ;GET ADJACENCY VERSION
CAIE T3,LD.DTE ;IF A DTE CIRCUIT
CAIN T4,1 ;OR A PHASE III NODE
SKIPA ;THEN DON'T INCLUDE AREA NUMBER
DPB T2,[POINTR(T1,RN%ARE)]
CALL DNP2BY ;STORE THE NODE ADDRESS
;Build TIINFO.
SETZ T1, ;START BUILDING TIINFO FIELD
MOVEI T2,ANT.RT ; Assume we are a routing node
MOVEI T3,RNT.L1 ; See what type of node we are this time
CAME T3,RTRNTY ; Are we a routing node?
MOVEI T2,ANT.NR ; No, then say we are non-routing
STOR T2,TINTY,+T1 ;STORE THE NODE TYPE
SKIPE RTRVRQ ;IS VERIFICATION REQUIRED?
TXO T1,TIVER ;YES, TELL HIM ABOUT IT
CALL DNP1BY ;PUT THE BYTE IN
;Give a blocksize.
LOAD T1,RCRBS,(RC) ;GET THE BLOCKSIZE
CALL DNP2BY ;TWO BYTES WORTH
;Fill in version, etc.
LOAD T3,AJVER,(AJ) ;GET THE ADJACENCY ROUTING VERSION
CAMN T3,RTRVER ;IS IT THE SAME AS OURS?
JRST FILVER ;YES, THEN FILL IN THE VERSION NUMBER
ADDI T3,1 ;SEE IF ITS ONE MINUS OURS
CAMN T3,RTRVER ;IS IT?
JRST [LOAD T3,AJVER,(AJ) ;THEN USE HIS VERSION NUMBER
JRST FILVR1] ;STORE IN THE MESSAGE
FILVER: MOVE T3,RTRVER ;VERSION OF RTR
FILVR1: MOVE T1,T3 ;GET VERSION TO SEND IN INIT
CALL DNP1BY ;PUT IT IN MESSAGE
LOAD T1,AJECO,(AJ) ;GET THE ECO LEVEL
CALL DNP1BY ;PUT IT IN, ALSO
MOVE T1,RTRCUS ;CUSTOMER ARGUMENT NUMBER
CALL DNP1BY ;AND STORE THAT ALSO
;Now for the HELLO timer
LOAD T1,RCTM3,(RC) ;GET TIMER VALUE FOR THIS CIRCUIT
IDIVI T1,^D1000 ;SEND TIMER AS SECONDS
CAIL T3,2 ;ONLY OUTPUT IF PHASE IV OR GREATER
CALL DNP2BY ;TWO BYTES WORTH
;Now fill in one reserved byte
SETZ T1, ;USE A ZERO
CALL DNP1BY ;PUT IN THE BYTE
;Here we give the message to the DLL to send.
TRACE RTR,<Sending Router Init message>
CALL CALQOB ;OUTPUT THE MESSAGE
CALL DNGTIM ;GET THE CURRENT TIME
STOR T1,RCTIN,(RC) ;RECORD THE TIME THAT WE SENT THE TI
RET
SUBTTL Control Message Processors -- RTCINI - Inititialization Messages
;RTCINI - Process Incoming Router Init Message
;
; Call:
; T1/ Circuit State
; RC/ Ptr to Circuit Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
RTCINI: TRACE RTR,<Processing Router Init message>
CAIE T1,RCS.TI ;ARE WE IN RTR INIT WAIT STATE?
JRST [ETRACE RTR,<RTR Init message rcvd in wrong state>
MOVX T1,RS.UPT ;EVENT REASON: UNEXPECTED PACKET LOSS
CALLRET RTELDS] ;REPORT THE CIRCUIT DOWN - SOFTWARE FAULT EVENT
LOAD T1,MBSRC,(MB) ;GET THE SOURCE NODE
LDB T2,[POINTR(T1,RN%ARE)] ;GET THE AREA NUMBER
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
SKIPN T2 ; If Phase III...
MOVE T2,RTRHOM ; then default the area
CAME T2,RTRHOM ;MY AREA?
JRST RTCNHA ;NO, THEN DON'T DO IT
RTCI9N: CAIL T1,1 ;CHECK NODE ADDRESS
CAMLE T1,RTRMXN ; FOR REASONABLENESS
RTCNHA: JRST [MOVX T1,RS.ANO ;REASON: ADJACENT NODE ADDRESS OUT OF RANGE
CALLRET RTEINO] ;REPORT THE INITIALIZATION FAILURE EVENT
STOR T1,AJNAN,(AJ) ;Store the node's number
STOR T2,AJNAA,(AJ) ; and node's area
MOVX T1,ADJ.UP ;SAY THE ADJACENCY IS NOW UP
STOR T1,AJSTA,(AJ)
MOVE T1,MB ;POINT TO INPUT MESSAGE
CALL DNLENG ;CALCULATE THE LENGTH
CAIL T1,^D6 ;IS IT THE CORRECT LENGTH FOR RTR INIT MSGS?
CALL DNG1BY ;GET THE INITINFO FIELD
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR
; TXNE T1,TIRSV ;IS THE RESERVED FIELD ZERO?
; JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
MOVX T2,AJVRQ ;GET THE VERFIFY AND REQUIRED BIT
ANDCAM T2,AJ.VRQ(AJ) ;ASSUME THAT VERIFICATION ISN'T REQUIRED
TXNE T1,TIVER ;IS IT REALLY REQUIRED?
IORM T2,AJ.VRQ(AJ) ;YES, SET IT
MOVX T2,AJBLO ;GET THE BLOCKING REQUESTED BIT
ANDCAM T2,AJ.VRQ(AJ) ;ASSUME THAT BLOCKING WAS NOT REQUESTED
TXNE T1,TIBLO ;BLOCKING REQUESTED?
IORM T2,AJ.VRQ(AJ) ;YES, THEN SET IT
LOAD T2,TINTY,+T1 ;GET NODE TYPE FROM BYTE
STOR T2,AJNTY,(AJ) ;STORE THE NODE TYPE IN CIRCUIT BLOCK
;Get the blocksize
CALL DNG2BY ;GET TWO BYTE BLOCKSIZE
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
CAMGE T1,RTRBSZ ;IS THE BLOCKSIZE REASONABLE
JRST [MOVX T1,RS.ABS ;EVENT REASON: Adjacency block size too small
CALLRET RTEINO] ;REPORT THE INITIALIZATION FAILURE EVENT
STOR T1,RCBSZ,(RC) ;Save for use when building routing updates
STOR T1,AJBSZ,(AJ) ; and here for network management
;Next comes the Version number, ECO number and Customer args.
CALL DNG1BY ;GET THE VERSION NUMBER
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
STOR T1,AJVER,(AJ) ;STORE IT IN CIRCUIT BLOCK
CAIE T1,1 ;IS THE ADJACENCY PHASE III OR IV?
IFSKP.
LOAD T2,AJNTY,(AJ) ;(III) GET THE NODE TYPE FROM ABOVE (TIINFO)
SETO T1, ;Use T1 to hold node type for adjacency block
CAIN T2,ANT.RT ;IS IT A ROUTING NODE?
MOVX T1,ADJ.3F ;YUP, MUST BE A PHASE III FULL NODE
CAIN T2,ANT.NR ;IS IT A NON-ROUTING NODE?
MOVX T1,ADJ.3S ;YES, WELL ITS A PHASE III SMALL NODE
SKIPGE T1 ;DID WE GET ONE?
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
STOR T1,AJNTY,(AJ) ;SAVE IT
SETZRO AJPH4,(AJ) ;Note that this node is not a PH4 node
ELSE.
LOAD T2,AJNTY,(AJ) ; (IV) GET THE NODE TYPE FROM ABOVE (TIINFO)
SETO T1, ;Use -1 as a flag
CAXN T2,ANT.L1 ;IS IT A LEVEL 1 ROUTER
MOVX T1,ADJ.L1 ;SAY SO
CAXN T2,ANT.L2 ;LEVEL 2
MOVX T1,ADJ.L2 ;SAY SO
CAXN T2,ANT.NR ;NON-ROUTING
MOVX T1,ADJ.LN ;SAY SO
SKIPGE T1 ;HAVE ONE?
JSP T1,RTEMFE ;NO, THEN WE HAVE AN ERROR
STOR T1,AJNTY,(AJ) ;SAVE IT
SETONE AJPH4,(AJ) ;Indicate we have a Phase IV node
ENDIF.
RTCIN0: CALL DNG1BY ;GET THE ECO NUMBER
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
STOR T1,AJECO,(AJ) ;STORE IT
CALL DNG1BY ;ALSO THE CUSTOMER ARGUMENT
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
STOR T1,AJCUS,(AJ) ;STORE IT ALSO
; Get the hello timer from the router init message, there is one
TMNN AJPH4,(AJ) ;Phase IV node?
JRST RTCIN1 ;NO, THEN HELLO TIMER IS NOT THERE
CALL DNG2BY ;GET THE HELLO TIMER NOW
JSP T1,RTEMFE ;MESSAGE FORMAT ERROR+++
IMULI T1,%RTT3M*^D1000 ;Hello timer multiplier and convert to ms.
STOR T1,AJNHT,(AJ) ;SAVE AS NEIGHBOR'S HELLO TIMER
;Now we have read the whole message, next send a verification if necessary.
RTCIN1: CALL DNG1BY ;Now get the reserved field
JSP T1,RTEMFE ;None, bum message
SKIPE T1 ;It must be zero
JSP T1,RTEMFE ;We can't understand non-zero
TMNE AJVRQ,(AJ) ;DOES HE WANT VERIFICATION?
IFSKP. ; No, he doesn't
SETZRO RCTIN,(RC) ;ZERO THE TIME WE SENT TI TIMER
CALL FREMSG ; FREE MESSAGE
ELSE.
MOVE T1,MB ;PASS PTR TO MSG BLK TO DNMINI
LDB T2,[POINT 8,RTRXPW,7];GET COUNT OF PASSWORD BYTES
AOJ T2, ; + COUNT BYTE AS LENGTH OF DATA SPACE
CALL DNMINI ;FIX UP THE MSG BLK
RET ;PROPOGATE ERROR RETURN
XMOVEI T1,RM.MSD(MB) ;GET ADDR OF ROUTER MSD
CALL DNPINI ;GET READY TO STICK BYTES IN MESSAGE
SETZ T1, ;BUILD FIRST BYTE IN T1
MOVX T2,RCM.TV ;TYPE = ROUTER VERIFICATION
STOR T2,CMTYP,+T1 ;FILL IN FIELD IN AC
SETONE CMCTL,+T1 ;TV MESSAGE IS A CONTROL MESSAGE
CALL DNP1BY ;STORE IN MESSAGE
MOVE T1,RTRADR ;GET OUR (ROUTER'S) ADDRESS
MOVE T3,RTRHOM ;GET MY AREA
TMNE AJPH4,(AJ) ;Phase IV node?
DPB T3,[POINTR(T1,RN%ARE)] ; AREA IF PHASE IV
CALL DNP2BY ;STORE THAT
;Put a password at the end of the verification msg
MOVE T3,[POINT 8,RTRXPW];POINT TO PASSWORD STRING
ILDB T2,T3 ;GET COUNT OF BYTES IN PASSWORD
SKIPA T1,T2 ;COPY COUNT AS DATA BYTE
RTCIN2: ILDB T1,T3 ;GET NEXT DATA BYTE
CALL DNP1BY ;TELL MSG ABOUT IT
SOJGE T2,RTCIN2 ;CONTINUE TILL DONE
TRACE RTR,<Sending Router Verification message>
CALL CALQOB ;OUTPUT THE MESSAGE
CALL DNGTIM ;GET CURRENT TIME
STOR T1,RCTIN,(RC) ;REGISTER THE TIME THAT WE SENT THE TV
ENDIF.
; MOVX T1,RCS.TV ;ASSUME THAT WE REQUIRE VERIFICATION
; SKIPN RTRVRQ ;DO WE REQUIRE VERIFICATION?
MOVX T1,RCS.RN ;NO, WE'RE NOW IN RUN STATE
STOR T1,RCSTA,(RC) ;INDICATE THAT IN THE CIRCUIT BLOCK
MOVX T1,ADJ.UP ;SAY THE ADJACENCY IS UP NOW
STOR T1,AJSTA,(AJ) ; AND RUNNING
MOVN T1,RTRTM1 ;SET TIMER TO FORCE SENDING ROUTING MESSAGE
STOR T1,RCTLR,(RC) ;...
LOAD T2,RCLID,(RC) ;Get the device ID
LOAD T3,AJADR,(AJ) ;Address needed for the event
EVENT RE.AUP,<Adjacency up>
LOAD T1,AJNAN,(AJ) ;Get node number
CALL SETRCF ;Set recompute routing flags
MOVN T1,RTRTM1 ;Reset the time of last routing
STOR T1,RCTLR,(RC) ; message
LOAD T1,AJVER,(AJ) ; Get adjacent node's version
CAIN T1,1 ; Phase III node?
CALLRET RTRSTI ; Yes, send TI response and return
RET ; AND RETURN
SUBTTL Control Message Processors -- RTCVER - Verification Messages
;RTCVER - Routine to handle verification messages
;
; Call:
; T1/ Circuit State
; RC/ Pointer to Circuit Block
; MB/ Pointer to Message Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
RTCVER: TRACE RTR,<Processing Router Verification message>
CAIE T1,RCS.TV ;ARE WE WAITING FOR A VERIFICATION
JRST [ETRACE RTR,<RTR Verification message rcvd in wrong state>
MOVX T1,RS.UPT ;EVENT REASON: UNEXPECTED PACKET type
CALLRET RTELDS] ;REPORT CIRCUIT DOWN - SOFTWARE ERROR EVENT
CALL DNG1BY ;GET FIRST BYTE (IMAGE COUNT)
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
MOVE P1,T1 ;PRESERVE IT FOR A WHILE
MOVE T1,MB ;POINT TO MESSAGE
CALL DNLENG ;CALCULATE LENGTH
CAMLE P1,T1 ;DOES IT LOOK LIKE A REASONABLE LENGTH?
CALLRET RTEVRJ ;++VERIFICATION REJECT
MOVX T1,RCS.RN ;IF WE GOT THIS FAR,
STOR T1,RCSTA,(RC) ; WE DESERVE TO BE IN A GOOD STATE
CALLRET FREMSG ;TOSS MESSAGE AND RETURN
SUBTTL Control Message Processors -- RTCRTE - Routing Messages
;RTCRTE - Routine to handle incoming routing message
;
; Call:
; T1/ State of circuit
; AJ/ Pointer to adjacency block
; RC/ Pointer to circuit block
; MB/ Pointer to message block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
RTCRTE: TRACE RTR,<Processing Routing message>
CAIE T1,RCS.TT ;CHECK OUR STATE FOR EITHER TEST OR
CAIN T1,RCS.RN ; OK ST