Trailing-Edge
-
PDP-10 Archives
-
BB-BT99T-BB_1990
-
10,7/mon/router.mac
There are 25 other files named router.mac in the archive. Click here to see a list.
;TITLE ROUTER - Routing Layer Service for DECnet-36 V110
;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,1988,1990.
;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 17-APR-90
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,110
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,1990>
>;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 %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,,^D65535*TIMBAS,,<%RTTM1>,<MOVEM T2,RTRTM1>,<MOVE T2,RTRTM1>,<MOVEM T2,RTRTM1>,<Maximum update interval timer>)
PARAMETER(^D912,,^D65535*TIMBAS,,<%RTBT1>,<MOVEM T2,RTRBT1>,<MOVE T2,RTRBT1>,<MOVEM T2,RTRBT1>,<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*TIMBAS>,<1*TIMBAS>,<%RTTM3>,<STOR T2,RCTM3,(RC)>,<LOAD T2,RCTM3,(RC)>,<STOR T2,RCTM3,(RC)>,<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 CALQMB ;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 RMICP,(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,AJADR,(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,AJADR,(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,AJADR,(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 T3,MBDST,(MB) ; Yes, get the destination address
TMNN RMTRY,(MB) ; "Try hard" flag set?
IFSKP.
LOAD T2,RN%ARE,+T3 ; Yes, get area number of node
CAME T2,RTRHOM ; Our area?
IFSKP.
MOVE T2,T3 ; Get node address
TXZ T2,RN%ARE ; Clear the area number field
ADD T2,RTRNRV ; Add reach vector offset
SETZRO RNCCH,(T2) ; Clear the in-cache flag
ENDIF.
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) ; Get address of designated router
LOAD T2,RN%ARE,+T3 ; Get area number of node
CAME T2,RTRHOM ; Our area?
JRST RTR2R3 ; No, node not in cache, continue
MOVE T2,T3 ; Get node address
TXZ T2,RN%ARE ; Clear the area number field
ADD T2,RTRNRV ; Add reach vector offset
TMNN RNCCH,(T2) ; Is cache flag set?
RTR2R3: 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.
;
;CALQMB is a special entry for message blocks that were queued to MB.NXT
;for a circuit on some other CPU.
CALQOB: INCR RCCMQ,(RC) ;INCREMENT NUMBER OF MESSAGES QUEUED
CALQMB: 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.
SOSGE 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.(INF,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,AJADR,(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
TMNN RCDSR,(RC) ;Are we the designated router?
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: LOAD T1,LIDEV,+RC.LID(RC) ; Get circuit/line type
CAIE T1,LD.DDP ; Is it a DDP?
JRST RTRCC2 ; No, treat normally
CALL R2KINI ; Yes, default DDPs to STATE ON
JFCL ; Ho hum
RTRCC2: 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...
SETZ AJ, ;Not in our area, no adjacency block
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
CALL RTELDS ;REPORT THE CIRCUIT DOWN - SOFTWARE FAULT EVENT
CALLRET CIRFAI] ;HIT THE LINE WITH A BIGGER SLEDGEHAMMER
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 STATE
TRNA ;WE SEEM ALRIGHT
JRST [ETRACE RTR,<Routing message rcvd in wrong state>
MOVX T1,RS.UPT ;EVENT REASON: UNEXPECTED PACKET RECEIVED
CALLRET RTELDS] ;REPORT CIRCUIT DOWN - SOFTWARE FAULT EVENT
SKIPN ENFLG ; Endnode?
IFSKP.
CALL DNG1BY ; Get reserved byte
CALLRET FREMSG ; Forget any error
LOAD T1,MBSRC,(MB) ; Get the source address
LDB T2,[POINTR (T1,RN%ARE)] ; Get the area number
LDB T3,[POINTR(T1,RN%NOD)] ; Get the node number
LOAD T4,RCAJQ,(RC)
LOAD T4,AJNAN,(T4) ; Get DSR low order address
CAIE T3,(T4) ; Same as the sender of message?
JRST FREMSG ; No, then don't bother processing
SKIPN T2 ; Phase IV area number there?
CALLRET FREMSG
CAME T2,RTRHOM ; Is packet from our area
CALLRET FREMSG
LOAD AJ,RCAJQ,(RC) ; Get our only adjacency
JUMPE AJ,FREMSG
ELSE.
JUMPE AJ,FREMSG ; If no adjacency, toss message
CALL CK2WAY ;Do we have a known two-way adjacency?
CALLRET FREMSG ;No, can't accept this message
TMNN AJPH4,(AJ) ; Phase 4 node?
IFSKP.
LOAD T1,AJNTY,(AJ) ;Get type
CAXE T1,ADJ.LN ;Is it non-routing?
IFSKP.
LOAD T1,AJNAN,(AJ) ;Get address and give a buginf
BUG.(INF,ROURFN,ROUTER,SOFT,<Routing message received from non-routing node>,<<T1,Address>>,<
Cause: We have received a routing message from a node we believe to be an
endnode so we will have no vector to store it in.
count.
Action: Check the address of the node and then see if it thinks it is a
routing/non-routing node.
>,FREMSG)
ENDIF.
CALL DNG1BY ; Get expected reserved byte
JSP T1,RTEMFE ;++Message format error
ENDIF.
LOAD T1,MBSRC,(MB) ;GET THE SOURCE ADDRESS
LDB T2,[POINTR (T1,RN%ARE)] ;GET THE AREA NUMBER
LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
SKIPN T2 ;Phase IV area number there?
MOVE T2,RTRHOM ;No, then supply a default
OPSTR <CAMN T1,>,AJNAN,(AJ) ;Is that the number we expected?
CAME T2,RTRHOM ;Is packet from our area
JRST [MOVX T1,RS.ANA ;EVENT REASON: ADJACENT NODE ADDRESS CHANGE
CALLRET RTEADO] ;REPORT ADJACENCY DOWN - OPERATOR FAULT EVENT
ENDIF.
MOVE T1,MB ;POINT TO INPUT MESSAGE
CALL DNLENG ;GET ITS LENGTH
TXNE T1,1B35 ;SEE IF IT'S AN EVEN LENGTH
CALLRET RTCRME ;++MESSAGE FORMAT ERROR EVENT
SUBI T1,2 ;GET COUNT WITHOUT CHECKSUM
ASH T1,-1 ;MAKE IT ENTRY COUNT
; EXACTLY THE LENGTH THAT WE ARE EXPECTING
MOVE P2,T1 ;GET COPY OF ENTRY COUNT
CALL DNRPOS ;READ THE POSTION IN MESSAGE
STOR T1,RMMK2,(MB) ;STORE THE ROUTING MESSAGE POSITION
;RTCRTE - Continued from previous page
;Here to read the message, while summing the checksum.
SETZ P1, ;A PLACE FOR THE CHECKSUM
TMNE AJPH4,(AJ) ;Phase 4 node?
AOJ P1, ;YES, THEN START WITH 1
RTCRT2: CALL DNG2BY ;GET A BYTE OF THE ROUTING MESSAGE
CALLRET RTCRME ;++MESSAGE FORMAT ERROR EVENT
ADD P1,T1 ;SUM THE CHECKSUM
SOJG P2,RTCRT2 ;SKIM THROUGH IT
;Get the checksum in the message and verify it.
CALL DNG2BY ;GET THE CHECKSUM FROM THE MESSAGE
JRST [MOVX T1,RS.RUC ;EVENT ERROR: CHECKSUM ERROR DETECTED
CALLRET RTELDS] ;REPORT THE CIRCUIT DOWN - SOFTWARE ERROR EVENT
EXCH T1,P1 ;EXCHANGE THE CHECKSUMS
CALL CKSNRM ;NORMALIZE THE ONE WE FIGURED OUT
CAME T1,P1 ;BETTER BE THE SAME
CALLRET RTCRME ;++MESSAGE FORMAT ERROR EVENT
;*** Bugchk here??? ***** if no RTV
CALLRET RTRBAV ; Build routing data into adjacency's vector
SUBTTL Control Message Processors -- RTCTST - Test or Hello Messages
;RTCTST - Routine to handle the hello and test messages
;
; Call:
; T1/ State of Circuit
; RC/ Pointer to Circuit Block
; MB/ Pointer to Message Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
;Router Hello and Test messages consist of a image count followed by that
;count of bytes filled with some constant (HEL.LO).
RTCTST: TRACE RTR,<Processing test or hello message>
CAIE T1,RCS.TT ;ARE WE IN TEST OR
CAIN T1,RCS.RN ; OK MODE?
TRNA ;YES
JRST [ETRACE RTR,<Test or Hello message rcvd in wrong state>
MOVX T1,RS.UPT ;REASON: UNEXPECTED PACKET RECEIVED
CALLRET RTELDS] ;REPORT CIRCUIT DOWN - CIRCUIT FAULT EVENT
LOAD T1,MBSRC,(MB) ;GET THE SOURCE ADDRESS
LDB T2,[POINTR (T1,RN%ARE)] ;GET THE AREA NUMBER
JUMPE T2,RTCTS1 ; Phase III nodes don't supply area numbers
CAME T2,RTRHOM
CALLRET FREMSG ;NOT FROM OUR AREA, PUNT IT THEN
RTCTS1: LDB T1,[POINTR(T1,RN%NOD)] ;GET THE NODE NUMBER
OPSTR <CAMN T1,>,AJNAN,(AJ) ;IS IT WHAT WE EXPECTED?
IFSKP.
MOVX T1,RS.ANA ;REASON: ADJACENT NODE ADDRESS CHANGED
CALL RTEADO ;REPORT ADJACENCY DOWN - OPERATOR FAULT EVENT
CALLRET CIRFAI ;Close the circuit and restart it
ENDIF.
CALL RTRCTD ;Check the test bytes
TRN
RET
SUBTTL Control Message Processors -- RTCL2M - Level 2 Routing Messages
RTCL2M:
CALLRET FREMSG ;Free message and return since we can not be
;a level 2 router
SUBTTL Control Message Processors -- RTCERH - Ethernet Router Hello
RTCERH: STKVAR <<RSID,2>> ;STORAGE FOR CURRENT RS LIST ID
TRACE RTR,<Processing Ethernet Router Hello message>
CAIE T1,RCS.TT ;ARE WE IN TEST OR
CAIN T1,RCS.RN ; OK MODE?
TRNA ;YES
JRST [ETRACE RTR,<Test or Hello message rcvd in wrong state>
MOVX T1,RS.UPT ;REASON: UNEXPECTED PACKET RECEIVED
CALLRET RTELDS] ;REPORT CIRCUIT DOWN - CIRCUIT FAULT EVENT
SKIPN ENFLG ; Endnode?
CALLRET RHMASR ; No
CALLRET RHMASE
SUBTTL Control Message Processors -- RHMASR - Hello message if Endnode
;Process a hello message from a routing node if we are an endnode
RHMASE: LOAD T1,MBSRC,(MB) ; Get the source node
LDB T1,[POINTR(T1,RN%ARE)] ; Get the area number
CAME T1,RTRHOM ; My area?
JRST FREMSG ; No, ignore it
LOAD AJ,RCAJQ,(RC) ; Get our only adjacency - maybe
CAME T4,RTRAEN ; Sent to multicast "all endnodes"?
JRST FREMSG ; No, don't want it
CALL RTRRCV ; Yes, read and check version
JSP T1,RTEMFE ; Bad version **EVENT??**
CALL DNGENA ; The the 6 byte address of transmitting node
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
CAME T1,RTRHIO ; HIORD?
JSP T1,RTEMFE ; No, we don't want it
HLRZ P1,T2 ; Repostion address and save it
STOR T1,RCDSH,(RC) ; Save this address as the designated router
LOAD T3,RCDSL,(RC) ; Current designated router address
SKIPE AJ ; Do we have an adjacency?
IFSKP.
SETO T1, ; No, make a "routing" adjacency block
CALL RTRMAJ ; so we can eavesdrop on routing messages
CALLRET FREMSG
MOVE AJ,T1
INCR RCNRO,(RC) ; Count a router adjacency on this circuit
AOS RTRBRA ; and this node
ELSE.
SKIPN T3 ; Yes, do we have a DR?
IFSKP.
CAME T3,P1 ; Yes, is it the same as address just received?
IFSKP.
CALL DNGTIM ; Get the current time
STOR T1,AJTLR,(AJ) ; Store time we last heard from DR
CALLRET FREMSG ; and nothing more to do
ELSE.
CALL SETRCA ; Set to recompute routing
LOAD T2,RCLID,(RC) ; No, get device ID
LOAD T3,AJADR,(AJ) ; Node's address
EVENT RE.AJD,<Adjacency down> ;Signal address change as
CALL RTRSAO ; adjacency off-line. Set the adjacency offline
ENDIF. ; and reuse the adjacency
ENDIF.
ENDIF.
STOR P1,RCDSL,(RC) ; Save address of designated router
CALL PSINFO ; Get information in the IINFO field
JSP T1,RTEMFE
CALL DNGTIM ; Get the current time
STOR T1,AJTLR,(AJ) ; Time last heard from designated router
MOVX T1,ADJ.UP ; Set the adjacency state to up
STOR T1,AJSTA,(AJ)
LOAD T2,RCLID,(RC) ; Get device ID
LOAD T3,MBSRC,(MB) ; Get address of sender
STOR T3,AJNAN,(AJ)
LDB T1,[POINTR(T3,RN%ARE)] ;Get the area number
STOR T1,AJNAA,(AJ)
STOR P1,AJNAL,(AJ) ; Save low order address in string format
CALL DNG2BY ; Get the block size
JSP T1,RTEMFE ; None, bad message
STOR T1,AJBSZ,(AJ) ; Save the block size requested
CALL DNG2BY ; Skip priority and area
JSP T1,RTEMFE ; None, bad message
CALL DNG2BY ; Get the Hello Timer
JSP T1,RTEMFE ; None, bad message
IMULI T1,%RTB3M*^D1000 ; Calculate the Listen Timer
STOR T1,AJNHT,(AJ) ;
LOAD T2,RCLID,(RC) ; No, get device ID
LOAD T3,AJADR,(AJ) ; Node's address
EVENT RE.AUP,<Adjacency up>
CALLRET FREMSG
SUBTTL Control Message Processors -- RHMASR - Hello message if Router
;Process a hello message from a routing node if we are a routing node
RHMASR: SETO T1, ;Flag to indicate that this is a router hello
CALL RTRPNI ;PARSE OFF THE COMMON HEADER
CALLRET FREMSG ;ERROR
CALL DNG1BY ;GET THE ROUTER PRIORITY
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR
STOR T1,AJPRI,(AJ) ;SAVE IT
CALL DNG1BY ;GET THE ROUTER AREA
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
STOR T1,AJARE,(AJ) ;SAVE IT
CALL DNG2BY ;GET THE HELLO TIMER IN SECONDS
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
IMULI T1,%RTB3M*^D1000 ;Broadcast multiplier & convert to milliseconds
STOR T1,AJNHT,(AJ) ;SAVE THE HELLO TIMER
CALL DNGTIM ;Get the current time
STOR T1,AJTLR,(AJ) ;Save it for timeout processing
CALL DNG1BY ;GET THE RESERVED BYTE
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
STOR T1,AJMPD,(AJ) ;SAVE MPD
CALL DNG1BY ;GET THE COUNT OF NI-LIST NODES
JSP T1,RTEMFE ;RETURN IF NONE
CAIL T1,8 ;IS IT .GE. TO 8
CAILE T1,^D244 ; .AND. .LE. 244?
JSP T1,RTEMFE ; NO TO EITHER
MOVE P1,T1 ;SAVE THE COUNT
CALL DNGENA ;GET THE FIRST 6 BYTES
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
SKIPN T1 ; Must be zero
SKIPE T2 ; Just feeling paranoid
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
CALL DNG1BY ; Which is really 7 bytes
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
SKIPE T1 ; Should be zero
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
SUBI P1,7 ;WE REMOVED 7 BYTES
CALL DNG1BY ;GET THE COUNT FOR THE SECOND LIST
JSP T1,RTEMFE ; ++Message Format Error++
CAIE P1,1(T1) ;DO THE COUNTS TALLY?
JSP T1,RTEMFE ; NOPE, INNER COUNT SHOULD BE .LT. OUTER
JUMPE T1,RHMNSD ;IF ADJACENCY LIST IS 0, Node is shutting down
IDIVI T1,7 ;DIVIDE BY SIZE OF ENTRIES
SKIPE T2 ;An even multiple of seven
JSP T1,RTEMFE ; NO
MOVE P1,T1 ;SAVE THE COUNT
CAILE T1,^D236 ;NUMBER MAKE SENSE
BUG.(INF,ROURCE,ROUTER,SOFT,<Bad NI Router list message format>,,<
Cause: We have received a router hello message with more than 256 known
2-way adjacencies.
>,FREMSG)
; RHMASR continued
; Now peruse the ROUTER/STATE list looking for ourselves. If we find ourself
; this means that the other node knows about us.
STKVAR <SELF>
SETZM SELF ;Initialize to zero
RHMAR1: CALL DNGENA ; Get the six bytes of node id
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
CAME T1,RTRHIO ;IS IT HIORD (HIGH PART OF NODE ADDRESS)
JRST RHMAR3 ;NOPE, THEN SKIP IT
MOVE T3,RTRLOO ;GET MY ADDRESS
CAME T2,T3 ;IS IT ME?
JRST RHMAR3 ;NOPE, THEN SKIP IT
SETOM SELF ;We have seen ourselves!
LOAD T1,AJSTA,(AJ) ;Yes, get the adjacency state
CAXN T1,ADJ.UP ;Is it up?
JRST RHMAR3 ;Yes, then don't generate adjacency up event
MOVX T1,ADJ.UP ;Set the state to "up"
STOR T1,AJSTA,(AJ) ; in the adjacency block
SETONE RCSRM,(RC) ;Send a routing update on this circuit
LOAD T2,RCLID,(RC) ;Get device ID
LOAD T3,AJADR,(AJ) ;Get node address for the event
EVENT RE.AUP,<Adjacency up> ; and send the event
LOAD T1,AJNAN,(AJ) ;Get node number
CALL SETRCF ;Set recompute routing flags
MOVN T1,RTRBT1 ;Reset the time of last routing
STOR T1,RCTLR,(RC) ; message
RHMAR3: CALL DNG1BY ;GET PRISTATE
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
SOJG P1,RHMAR1 ;AND GET THE NEXT ONE
SKIPE SELF ;Did we find ourselves?
CALLRET FREMSG ;Yes, !!Success!!
MOVX T1,ADJ.IN ;No, then set adjacency state to initializing
TRNA
RHMNSD: MOVX T1,ADJ.UN ;Set state to unused
LOAD T2,AJSTA,(AJ) ;Get the state of the adjacency
CAXE T2,ADJ.UP ;Was it up?
CALLRET FREMSG ;No, then done
STOR T1,AJSTA,(AJ) ;Save new state
MOVE P1,T1 ;Save for later check
INCR RCAJD,(RC) ;Count adjacency down events
LOAD T2,RCLID,(RC) ;Get the device ID
LOAD T3,AJADR,(AJ) ;Get the node address
EVENT RE.ADO,<Adjacency down-operator initiated>,
CALL SETRCA ;Set recompute routing flags
CAIE P1,ADJ.UN ;Is new state unused?
CALLRET FREMSG ;No, then done
MOVE T1,AJ
MOVE T2,RC
CALL RTRZAB ;Yes, release the adjacency
CALLRET FREMSG
SUBTTL Control Message Processors -- RTCNIE - NI Endnode Hello message
RTCNIE: TRACE RTR,<Processing NI Endnode hello and test message>
SKIPGE ENFLG ;Endnode?
CALLRET FREMSG ; Yes, don't process this
CAIE T1,RCS.TT ;Are we in test or
CAIN T1,RCS.RN ; run mode?
TRNA ;Yes
JRST [ETRACE RTR,<Test or Hello message received in wrong state>
MOVX T1,RS.UPT ;REASON: UNEXPECTED PACKET RECEIVED
CALLRET RTELDS] ;REPORT CIRCUIT DOWN - CIRCUIT FAULT EVENT
SETZ T1, ;Flag to say this is an endnode hello
CALL RTRPNI ;Parse off common header and set up AJ if
CALLRET FREMSG ; we have not exceeded maximum adjacencies
CALL DNG1BY ;Get the area (reserved)
JSP T1,RTEMFE ;Bad packet if not there
MOVEI T1,^D14 ;Skip over the next 14 bytes which include
CALL DNSKBY ; the seed (8 bytes) & the neighbors system ID
JSP T1,RTEMFE ; ++Bad packet++
CALL DNG2BY ;Hello timer in seconds
JSP T1,RTEMFE
IMULI T1,%RTB3M*^D1000 ;Broadcast multiplier & convert to milliseconds
STOR T1,AJNHT,(AJ) ;Save the hello timer
CALL DNG1BY ;MPD (reserved)
JSP T1,RTEMFE
CALL RTRCTD ;Now, check the test data
RET ;Bad test data
CALL DNGTIM ;Time stamp this
STOR T1,AJTLR,(AJ) ; as time last heard from adjacency
LOAD T1,AJSTA,(AJ) ;Get adjacency state
CAIN T1,ADJ.UP ;If it was up then done
RET
MOVX T1,ADJ.UP ;Set the adjacency state to up
STOR T1,AJSTA,(AJ)
LOAD T2,RCLID,(RC) ;Get device ID
LOAD T3,AJADR,(AJ) ;Needed for the event
EVENT RE.AUP,<Adjacency up>
LOAD T1,AJNAN,(AJ) ;Get node number
CALLRET SETRCF ;Set recompute routing flags and return
SUBTTL RTCILL - Illegal message received
RTCILL: MOVE T1,MB ; Setup for DNFMSG
BUG.(CHK,ROUBMT,ROUTER,SOFT,<Bad message type received from the DLL>,,<
Cause: The DLL received a bad message from another node or incorrectly copied
a message into the message block.
>,DNFMSG)
SUBTTL RTRBAV - Build adjacency's routing vector from routing update
RTRBAV: STKVAR <MSGLEN,VECMAX>
SETZM HIADDR ;Initialize highest address in case of P.R.U.L.
MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
CALL DNGINI ;GET UP TO GET BYTES
LOAD T1,RMMK2,(MB) ;GET THE ROUTING DATA'S POSITION
CALL DNGPOS ; AND GO TO IT
MOVE T1,MB ;POINT TO MESSAGE BLOCK AGAIN
CALL DNLENG ;GET THE LENGTH OF THE MESSAGE
SUBI T1,2 ;ACCOUNT FOR CHECKSUM
ASH T1,-1 ;MAKE IT AN ENTRY (NODE) COUNT
MOVEM T1,MSGLEN ;SAVE THE LENGTH OF THE WHOLE MESSAGE
TMNN AJPH4,(AJ) ;Phase IV node?
JRST RTRBA4 ;NO, THEN USE THIS LENGTH
RTRBA3: CALL DNG2BY ;YES, THEN GET THE COUNT OF ENTRIES
BUG. (CHK,ROUUOC,ROUTER,SOFT,<Unable to obtain count of nodes in Phase IV message>,,<
Cause: We have received what we think is a routing message that DNLENG said
has more bytes than we have read and when we try to read another two
DNG2BY says the count is exhausted.
>,RTRBA9)
MOVE P2,T1 ;SAVE THE COUNT
CALL DNG2BY ;Get two bytes of starting node ID
CALLRET RTCRME ;Message format error
CAILE T1,RTRMXN ;Is starting node address larger than we handle
BUG. (CHK,ROUATL,ROUTER,SOFT,<A routing message contains a start ID greater than we can handle>,,<
Cause: An adjacent node has sent a routing message with the start ID
that would cause indexing into the per adjacency vector past
the end of the vector.
>,RTRBA9)
MOVNI T2,2 ;Account for the bytes we just read
ADDM T2,MSGLEN ; 4 bytes = 2 entries
LOAD P1,AJRTV,(AJ) ;GET THE ADJACENCY ROUTING VECTOR POINTER
SKIPE P1 ;HAVE A WORKING COPY?
LOAD P1,AJRVC,(AJ) ;USE HIDDEN VALUE
STOR P1,AJRTV,(AJ) ;UPDATE JUST IN CASE ...
JUMPE P1,[
BUG. (CHK,ROUNAV,ROUTER,SOFT,<An adjacency has no routing vector>,<<AJ,Adjacency block>>,<
Cause: A routing vector is built for each routing adjacency when the adjacency
block is created. Either we didn't build one or we cleared the pointer
to it.
>,RTRBA9)]
MOVE T3,P1 ;Compute the last address in the
ADD T3,RTRMXN ; per adjacency vector that we can
MOVEM T3,VECMAX ; use
ADD P1,T1 ;ADD IN THE STARTING NODE NUMBER
JRST RTRBA5 ;SKIP PHASE III CODE
RTRBA4: MOVE P2,MSGLEN ;GET THE MESSAGE LENGTH BACK
LOAD P1,AJRTV,(AJ) ;GET THE ADJACENCY ROUTING VECTOR POINTER
MOVE T3,P1 ;Compute the last address in the
ADD T3,RTRMXN ; per adjacency vector that we can use
MOVEM T3,VECMAX
AOJ P1, ; Increment it to node 1
RTRBA5: MOVE T1,P2 ; Number of nodes in message or segment
TMNE AJPH4,(AJ) ; Phase IV node?
SOS T1 ; Yes, account for node 0, the area router
SKIPGE T1 ; Negative count of entries is not good
; CAMLE T1,RTRMXN ; More than we care to know about?
BUG.(CHK,ROURML,ROUTER,SOFT,<Stored routing message format error in RTRBAV>,<<T1,COUNT>>,<
Cause: We have received a P3 routing message with a negative count of nodes
in it or no checksum or a P4 routing message with a negative segment
count.
Data: Count - Count or checksum
>,RTRBA9)
;RTRBAV - Continued from last page
;At this point P2 contains the number of entries in the routing message for
;Phase III messages or the number of entries in the segment for Phase IV.
RTRBA6: CALL DNG2BY ;GET THE BYTE FOR A NODE
BUG.(CHK,ROUUER,ROUTER,SOFT,<Unexpected end of routing message>,,<
Cause: The number of bytes in the routing message did not correspond
to the length expected. This may be caused by reading too many
bytes out of the message without decrementing the count of bytes
read or caused by an improper routing message.
>,RTRBA9)
CAMG P1,VECMAX ; Have we stepped past the end of the vector?
IFSKP. ; A CAMG because vector size is RTRMXN+1
CAMLE P1,HIADDR ; Is this the highest address so far?
MOVEM P1,HIADDR ; Yes, save new high and use as a flag in-
; dicating address higher than our maximum
ELSE. ; address
LOAD T4,RGCST,+T1 ; GET THE COST FROM THE BYTE
LOAD T3,RGHOP,+T1 ; GET THE HOP COUNT
LOAD T1,RNCST,(P1) ; Get previous cost
CAIN T4,(T1) ; Different?
IFSKP.
MOVE T1,P1 ; Compute current node number
OPSTR <SUB T1,>,AJRTV,(AJ) ; ...
CALL SETRCF ; Set recompute routing flags
ENDIF.
STOR T4,RNCST,(P1) ; Save both as new cost/hops
STOR T3,RNHOP,(P1) ;
ENDIF.
AOJ P1, ; INCREMENT THE POINTER
SOS MSGLEN ; DECREMENT THE COUNT OF ENTRIES
SOJG P2,RTRBA6 ; AND LOOP UNTIL FINISHED WITH THEM ALL
RTRBA8: SKIPLE MSGLEN ; HAVE ANY MORE SEGMENTS TO THIS MESSAGE?
JRST RTRBA3 ; YES, THEN GET THEIR INFO
RTRBA9: SKIPN HIADDR ; Any overflows?
IFSKP.
OPSTR <MOVN T1,>,AJRTV,(AJ) ; Get start of vector
ADDM T1,HIADDR ; Compute highest address for the event
CALL RTCRTF ; Yes, EVENT - Partial routing update loss
ENDIF.
CALLRET FREMSG ; Return message block
;Here to report the partial routing update loss.
RTCRTF: SKIPGE ENFLG ; Non-routing?
RET ; Yes, then no event
LOAD T2,RCLID,(RC) ; Get the entity ID
LOAD T3,AJADR,(AJ) ; Get address of sender
EVENT RE.PRL,<Partial routing update loss event>,MB
AOS RTRCPR ; Increment the counter
RET
SUBTTL RTCRME - Routing message error processor
RTCRME: SKIPGE ENFLG ; Non-routing
JRST FREMSG ; Yes, just dispose of message
JSP T1,RTEMFE ; No, generate an event
SUBTTL RTRPNI - Parse a Message Header for NI Hello messages
;RTRPNI - Parse Router Header on Incoming Message
;
; Call:
; RC/ Pointer to circuit block
; MB/ Pointer to Input message
;
; Return:
; RET ;IF BAD HEADER
; RETSKP ;ON SUCCESS
;
; Uses: T1-T2,AJ
;
; This routine parses off the common header from the NI Endnode hello message
;and the NI Router hello message and stores the correct information in the
;adjacency block.
RTRPNI: SAVEAC P1
STKVAR <HELTYP,LOSADR> ;Hello type flag and string format node address
MOVEM T1,HELTYP ;Save hello type
CALL RTRRCV ;Read and check the version of the Router
RET
CALL DNGENA ;GET THE 6 BYTE SYSTEM ID IN T1 AND T2
RET
CAME T1,RTRHIO ;Do we have HIORD?
RET ; No
STOR T1,MBSR1,(MB) ;Save the source high order
HLRZM T2,LOSADR ;We will need this later
CALL CVTSTN ; (T2) Convert string address to 16 bit address
STOR T1,MBSRC,(MB) ; Stuff it into the MB
HRRZ T2,T1 ; Get the node address in a scratch AC
TXZ T2,RN%ARE ; and get only the number
CAMLE T2,RTRMXN ; Within our allowed maximum?
RET ; No, don't make an adjacency
CALL RTRGAJ ; Find the adjacency associated w/this node
RET ; Not in my area, drop the message
JUMPN AJ,RTRPN3 ; Jump if an adjacency exists
SKIPN HELTYP ; Router hello?
JRST RTRPN1 ; No, then assume endnode
MOVE P1,RTRBRA ; Number of router adjacencies that are up
CAMLE P1,RTNBRA ; Have we exceeded the maximum?
JRST RTRPN4 ; yes, allow no more
LOAD T1,RCNRO,(RC) ; Get number of Routers on this circuit
OPSTR <CAML T1,>,RCMXR,(RC) ; see if maximum exceeded
JRST RTRPN4 ; Yes, don't allow it
SETO T1, ; Flag to indicate routing adjacency
CALL RTRMAJ ; Make an adjacency
RET ; Can't, must be out of memory
MOVE AJ,T1 ; Get adjacency address
ADDI P1,1 ; Account for it
MOVEM P1,RTRBRA ; Save new count of routers
INCR RCNRO,(RC)
JRST RTRPN2 ; Rejoin common code
RTRPN1: MOVE P1,RTRBEA ; Number of endnode adjacencies that are up
CAMLE P1,RTNBEA ; Have we exceeded the maximum?
JRST RTRPN4 ; Yes, allow no more
SETZ T1, ; Flag to indicate endnode adjacency
CALL RTRMAJ ; Make an adjacency block
RET ; Error return
MOVE AJ,T1 ; Get adjacency address
ADDI P1,1 ; Increment number of endnode adjacencies
MOVEM P1,RTRBEA ; Save new count
RTRPN2: LOAD T1,MBSR1,(MB) ; Get the high order address
STOR T1,AJNAH,(AJ) ; Put it into the AJ block
MOVE T1,LOSADR ; Get the low order string address
STOR T1,AJNAL,(AJ) ; and save address in string format
LOAD T1,MBSRC,(MB) ; Get the low order node address
STOR T1,AJNAN,(AJ) ; Stuff it
LDB T1,[POINTR(T1,RN%ARE)] ; Get the area number
STOR T1,AJNAA,(AJ) ; Save that too
RTRPN3: LOAD T1,AJCBP,(AJ) ; Get the circuit block pointer
CAME T1,RC ; Same as one it came in on
RET ; Error return
CALL PSINFO ; Save infomation in the IINFO field
RET
CALL DNG2BY ;GET THE BLOCK SIZE
RET
CAMGE T1,RTRBSZ ;Is it at least as large as ours?
;*** Should we do more?
RET
LOAD T2,AJNTY,(AJ) ;Get the adjacency type
CAIN T2,ADJ.LN ;Is it an endnode?
IFSKP. ;No, check the blocksize
LOAD T2,RCBSZ,(RC) ;Get block size currently used on this circuit
;*** What if little guy goes away?
CAIGE T1,(T2) ;Is the new one smaller
STOR T1,RCBSZ,(RC) ;Yes, then use it
ENDIF.
STOR T1,AJBSZ,(AJ) ;SAVE THE BLOCK SIZE REQUESTED
RETSKP ;RETURN SUCCESS TO CALLER
RTRPN4: MOVE T3,T2 ; Get adjacency's address
LOAD T2,RCLID,(RC) ; Get the entity ID
EVENT RE.ARJ,<Adjacency rejected>
RET ; Yes, then don't make an adjacency
ENDSV.
SUBTTL PSINFO - Parse the info field of Ethernet router hello
;Call:
; AJ/ Adjacency block
;
;Return:
; RET ;On error in info field of message
; RETSKP ;Info parsed and entered into the
; ; adjacency block
PSINFO: CALL DNG1BY ; Get the IINFO field
RET
LOAD T2,IITYP,+T1 ; Get routing type
SETO T3, ; Put a funny value in receiving AC
CAXN T2,IIT.L1 ; Is it a level one router?
MOVX T3,ADJ.L1 ; Yes
CAXN T2,IIT.L2 ; Is it a level 2 router?
MOVX T3,ADJ.L2 ; Yes
CAXN T2,IIT.EN ; Is it an endnode?
MOVX T3,ADJ.LN ; Yes
JUMPL T3,RTN ; Strange value
STOR T3,AJNTY,(AJ) ; Tell the Adjacency about it
SETONE AJPH4,(AJ) ; and set the Phase IV flag
LOAD T2,IIVRQ,+T1 ;GET THE VERICATION REQUIRED FLAG
STOR T2,AJVRQ,(AJ) ;STOR IT IN THE ADJACENCY BLOCK
LOAD T2,IIRJF,+T1 ;GET THE REJECT FLAG
STOR T2,AJRJF,(AJ) ;SAVE IT
LOAD T2,IIMTA,+T1 ;GET THE NO MULTICAST TRAFFIC ACCEPTED FLAG
STOR T2,AJMTA,(AJ) ;SAVE IT
LOAD T2,IIBRQ,+T1 ;GET THE BLOCKING REQUESTED FLAG
STOR T2,AJBLO,(AJ) ;SAVE IT
RETSKP
SUBTTL RTRRCV - Read version information from message
RTRRCV: CALL DNG1BY ;GET THE VERSION NUMBER
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
CAME T1,RTRVER ;IS IT THE CORRECT VERSION?
RET ;NO, THEN JUST RETURN
CALL DNG2BY ;GET THE ECO AND USER ECO
JSP T1,RTEMFE ; ++MESSAGE FORMAT ERROR++
RETSKP
SUBTTL RTRHDP - Parse a Input Router Message Header
;RTRHDP - Parse Router Header on Incoming Message
;
; This routine will skip over leading padding, and parse the first control byte
; of the routing packet. For Short Data Packets, and Long Data Packets, this
; routine will also completely parse their headers.
;
; Call:
; MB/ Pointer to Input message
;
; Return:
; RET ;IF BAD HEADER
; RETSKP ;ON SUCCESS
;
; Uses: T1-T2
;
;Note that DNGINI is called here and should not be recalled afterwards
;for the Router MSD.
RTRHDP: MOVE T1,MB ;POINT TO THE MESSAGE BLOCK
CALL DNGINI ;SET UP FOR CALLS TO DNGxBY
CALL DNRPOS ;GET OUR POSITION
STOR T1,RMMK1,(MB) ;STORE IT FOR EVENT PROCESSING
CALL DNG1BY ;Try to read message flags
RET ;RAN OUT, GIVE ERROR RETURN
TXZN T1,RM%MZ1 ;IS THE PAD FLAG SET?
IFSKP.
CALL PADSKP ;Skip over any pad bytes (NI) and return with
RET ; first byte of message. Error if PADSKP fails
ENDIF.
STOR T1,RMFST,(MB) ;Store message flags for later use
TXNN T1,RM%CTL ;Is this a control packet?
JRST RTRHD1 ; No, go parse a data packet
;Here with a control message. Check the type and return.
TXNE T1,^-<CMTYP!CMCTL> ;MAKE SURE THE RESERVED BITS ARE ZERO
RET ;NOPE, GIVE BAD RETURN
LOAD T2,CMTYP,+T1 ;GET THE CONTROL MESSAGE TYPE
STOR T2,RMCTY,(MB) ;STORE THAT IN MESSAGE BLOCK
CAIL T2,RCM.RH ;Is this an ethernet only message?
RETSKP ;Yes, then don't look for source node addr
CALL DNG2BY ;Get the node address of the sender
RET ;If none, then error
STOR T1,MBSRC,(MB) ;Save in MB's public section
RETSKP ;RETURN TO SENDER WITH GOOD RETURN
;Here with a data packet. Parse it w/regards to Ethernet vs. point to point
RTRHD1: JN RCBCT,(RC),RTRHNI ;If NI, handle differently
TXNE T1,RM%EVL ;IS THE EVOLUTION BIT SET?
JRST RTRHD2 ;YES, IT HAS A PHASE II ROUTING HEADER
;Check all the fields in the packet route header and store pertinent fields
;in the message block.
TXNN T1,RM%MB1 ;IF LOW TWO ORDER BYTES ARE 00, THIS
; MESSAGE IS A PHASE II WITHOUT A ROUTING
; HEADER
JRST RTRHD2 ;IT IS, RETURN, INDICATING PHASE II MESSAGE
TXNE T1,RM%MZ1!RM%MZ2!RM%MZ3 ;MAKE SURE THESE FIELDS ARE ZERO
RET ;THEY'RE NOT, GIVE ERROR RETURN
TXNE T1,RM%RQR ;IS RQR ON?
TXNN T1,RM%RTS ; AND RTS
TRNA ;NO, OK
RET ;YES, THAT'S A PROBLEM
;Now parse the source, destination and visits fields of packet route header.
CALL RTRGNA ;GET THE DESTINATION ADDRESS
RET ;OUT OF BYTES, GIVE BAD RETURN
STOR T1,MBDST,(MB) ;STORE IT
CALL RTRGNA ;GET THE SOURCE ADDRESS
RET ;RAN OUT, GIVE BAD RETURN
STOR T1,MBSRC,(MB) ;STORE THAT, TOO
CALL DNG1BY ;GET THE "FORWARD" BYTE
RET ;RAN OUT, GIVE BAD RETURN
TXNE T1,^-FWVST ;MAKE SURE IT'S NOT TOO BIG
RET ;IT'S TOO BIG
STOR T1,MBVST,(MB) ;STORE IT IN THE MESSAGE BLOCK
RETSKP ;LOOKS GOOD, RETURN
;Here we have a Phase II message. Set the Phase II flag in the message
;block and return.
RTRHD2: SETONE RMPH2,(MB) ;SAY THIS IS A PHASE II MESSAGE
RETSKP ; AND GIVE GOOD RETURN
;Parse an Ethernet style (Long Data Packet) header
RTRHNI: CALL DNG1BY ;GET D-AREA
RET ;NOTHING
CALL DNG1BY ;GET D-SUBAREA
RET ;ERROR IF NOTHING
CALL DNGHIO ;Ethenet hi-order address
RET ;RETURN IF NOTHING THERE
STOR T1,MBDS1,(MB) ;SAVE FIRST PART OF DESTINATION
CALL DNG2BY ; get low order node address
RET
STOR T1,MBDST,(MB) ;AND NORMAL DECNET-NODE STUFF
CALL DNG1BY ;GET THE S-AREA
RET ;ERROR
CALL DNG1BY ;GET THE S-SUBAREA
RET ;ERROR
CALL DNGHIO ;GET THE SOURCE ID
RET ; Error
STOR T1,MBSR1,(MB) ;SAVE THE SOURCE
CALL DNG2BY ; Get low order of node address
RET
STOR T1,MBSRC,(MB) ; and save that
SKIPN ENFLG ; Endnode?
IFSKP.
LOAD T2,MBDST,(MB)
CAME T2,RTRNAD ; Destined for us?
RET ; No, then bad message - We don't do routing
TMNN RMMZ2,(MB) ; Intra-NI flag set?
IFSKP. ; Yes, see if we should enter it into cache
LDB T2,[POINTR(T1,RN%ARE)] ; Get the area number
TXZ T1,RN%ARE ; and only the node number
CAME T2,RTRHOM ; In our home area?
IFSKP. ; Find our slot in vector
CAMLE T1,RTRMXN ; Higher than our maximum address?
RET ; Yes, drop it
EXCH T1,T2
ADD T2,RTRNRV ; Offset into vector
SETONE RNCCH,(T2) ; Set the on-ethernet cache bit
ADD T2,RTROFS ; Step to cache timer vector(same as OA vector)
CALL DNGTIM ; Get current time
ADD T1,RTRCTO ; Add the in-cache time
MOVEM T1,(T2) ; Save the time when cache bit is flushed
ENDIF.
ENDIF.
ENDIF.
CALL DNG1BY ;GET THE NEXT LEVEL 2 ROUTER
RET ;NOT THERE
CALL DNG1BY ;GET THE VISIT COUNT
RET ;NOT THERE
TXNE T1,^-FWVST ;MAKE SURE IT'S NOT TOO BIG
RET ;IT'S TOO BIG
STOR T1,MBVST,(MB) ;STORE IT IN THE MESSAGE BLOCK
CALL DNG1BY ;GET THE SERVICE CLASS
RET ;ERROR IF NOT THERE
CALL DNG1BY ;GET THE PROTOCAL TYPE
RET ;ERROR IF NOT THERE
RETSKP ;GIVE GOOD RETURN
SUBTTL RTRCTD - Check for valid test pattern in Hello/Test message
RTRCTD: SAVEAC <P1>
CALL DNG1BY ;GET THE IMAGE COUNT OF TEST MESSAGE
JSP T1,RTEMFE ;++MESSAGE FORMAT ERROR EVENT
CAILE T1,^D128 ;IS THE LENGTH WITHIN REASON
BUG.(INF,ROUBTF,ROUTER,SOFT,<Bad Test message format>,,<
Cause: We received a hello message from a P3 node or a P4 endnode
that contained too many bytes of test data.
>,FREMSG)
;Check to see if the test data is ok.
MOVE P1,T1 ;PRESERVE IT SORT OF
SOJGE P1,[CALL DNG1BY ;GET A BYTE OF THE TEST
JRST [MOVX T1,RS.ALI ;REASON: INVALID TEST DATA
CALLRET RTELDS] ;REPORT THE CIRCUIT DOWN EVENT
CAIE T1,HEL.LO ;IS IT EQUAL TO THE MAGIC NUMBER
BUG.(INF,ROUBTM,ROUTER,SOFT,<Bad Hello or Test message>,,<
Cause: We have received bad test data in a hello message.
>,FREMSG)
JRST .] ;LOOK AT ALL THE BYTES
CALL FREMSG ;FREE THE MESSAGE AND RETURN
RETSKP
SUBTTL RTRGNA - Get node address from message header
RTRGNA: CALL DNG2BY ;Read expected node address
RET ;Pass on the error
LDB T2,[POINTR (T1,RN%ARE)] ;Get the area number if any
JUMPN T2,RSKP ;We got one use it
MOVE T2,RTRHOM ;None given use our home area
DPB T2,[POINTR (T1,RN%ARE)] ;Put ours into the node address
JRST RSKP ; and return a success
SUBTTL PADSKP - Skip over pad bytes in an Ethernet message header
;Call:
; T1/ First byte in input MSD
;Return:
; T1/ First byte in message header (having skipped over any pad bytes)
PADSKP: SAVEAC <P1>
SOSGE P1,T1 ;Account for this byte
RET ;Pad with count of zero
PADSK1: CALL DNG1BY ;Get one more byte (Lastly the control byte)
RET
SOJGE P1,PADSK1 ;Loop for all the pads
TXNE T1,RM%MZ1 ;Did we get a second pad flag?
RET ; Yes, that is illegal
RETSKP ;Successful
IFN FTOPS10,< SUBTTL Network Management Interface -- RTNLID - Give the line id
;RTNLID - Give the line id for a given node
;
;Call
; T1/ Node address
;Return
; RET ;node unreachable
; RETSKP ;T1 contains line-id
RTNLID::LOAD T2,RN%ARE,T1 ;GET AREA PORTION
SKIPE T2 ;HOME AREA?
CAMN T2,RTRHOM ;...
SKIPA ;YES, KEEP GOING
SETZ T1, ;NO, USE AREA ROUTER
ANDI T1,RN%NOD ;KEEP ONLY THE NODE PORTION
CAMLE T1,RTRMXN ;OUT OF RANGE?
BUG.(CHK,ROUNMR,ROUTER,SOFT,<NMX out of range>,,<
Cause: This BUG is not documented yet.
>,RTN)
RTNLI1: ADD T1,RTRNRV ;ADD IN THE VECTOR ADDRESS
TMNE RNLCL,(T1) ;IS NODE LOCAL?
JRST [SETZ T1, ;CLEAR OUT THE REGISTER FOR LOCAL NODES
RETSKP] ;AND GIVE GOOD RETURN
TMNN RNRCH,(T1) ;IS NODE REACHABLE?
RET ;NOPE, TELL CALLER.
ADD T1,RTROFS ;NOW POINT TO OUTPUT ADJACENCY VECTOR
MOVE T1,(T1) ;GET THE OUTPUT CIRCUIT POINTER
LOAD T1,AJCBP,(T1) ;NOW THE OUTPUT CIRCUIT POINTER
LOAD T1,RCLID,(T1) ;GET LINE ID FROM CIRCUIT BLOCK
RETSKP ;SUCCESS.
RTNRCH::POINTR(RN.RCH(T2),RNRCH)
RTNLCL::POINTR(RN.LCL(T2),RNLCL)
RTNCST::POINTR(RN.CST(T2),RNCST)
RTNHOP::POINTR(RN.HOP(T2),RNHOP)
>; END IFN FTOPS10
SUBTTL Network Management -- RTRNMX - Entry into Router
;RTRNMX - Entry point for network management functions
;
;Call
; T1/ Function code
; T2/ NM block address
;Return
; RET ; Error - Reason in T1
; RETSKP ; Request complete
INTERN RTRNMX
XSWAPCD
RTRNMX:
IFN FTPARANOIA,<
CAIL T1,NF.SET ; Range check the function code
CAILE T1,NF.RET ;
BUG.(CHK,RTRIFN,ROUTER,SOFT,<Illegal function code from NTMAN>,,<
Cause: The function code supplied by NTMAN is out of range of functions
supported by Router.
Action: Find routine in NTMAN supplying illegal function code and correct it.
>,[RNMXER (NF.MPE)])
>
SAVEAC <P1,P2,RC,AJ>
MOVE T1,NMXDSP(T1) ; Routine to do processing
CALLRET (T1) ; Go to it
NMXDSP:
IFIW!<NMXSET&777777> ; Set Parameter
IFIW!<NMXCLR&777777> ; Clear Parameter
IFIW!<NMXRED&777777> ; Read Parameter
IFIW!<NMXSHC&777777> ; Show Counters
IFIW!<NMXSZC&777777> ; Show and Zero Counters
IFIW!<NMXRET&777777> ; Return list of Entity Ids
NMXILL: RNMXER (NF.FNS) ; Function not supported
XRESCD
SUBTTL Network Management -- Read/Set/Clear a parameter
;NMXRED - called to read a network management parameter
;Call: T2/ address of NM block
; CALL NMXRED
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
XSWAPCD
NMXRED: MOVX T3,NF.RED ;Load function code
CALLRET NMXPCM ;Join common code
XRESCD
;NMXSET - called to set a network management parameter
;Call: T2/ address of NM block
; CALL NMXSET
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
XSWAPCD
NMXSET: MOVX T3,NF.SET ;Load function code
CALLRET NMXPCM ;Call common code
XRESCD
;NMXCLR - called to clear a network management parameter
;Call: T2/ address of NM block
; CALL NMXCLR
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
XSWAPCD
NMXCLR: MOVX T3,NF.SET ;Load function code
CALLRET NMXPCM ;Call common code
XRESCD
SUBTTL Network management -- Common routine for parameters
;NMXPCM - Performs common processing for parameter read, set, and clear
;Call:
; T2/ address of NM block
; T3/ Function (read,set,clear)
; CALL NMXPCM
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
XSWAPCD
NMXPCM: MOVE P1,T2 ;Move NF pointer to where it should be
LOAD T1,NFETY,(P1) ;Get the entity type
CAIE T1,.NTNOD ;Is request for a node entity?
IFSKP.
LOAD P2,NFEID,(P1) ;Yes, get node address
LDB T2,[POINTR (P2,RN%ARE)] ;Get the area number
TXZ P2,RN%ARE ;Clear the area number
CAME T2,RTRHOM ;Is it same as ours?
SETZ P2, ;No, select the area router
ADD P2,RTRNRV ;Add in the vector address
TMNN RNLCL,(P2) ;Is it local?
IFSKP.
XMOVEI T1,EXPTAB ;Yes, use executor parameter table
MOVEI T2,EXPTBL ; and its length
ELSE.
MOVE T2,RTRNTY ;Get routing type for later checking
LOAD T1,NFPRM,(P1) ;Get requested parameter
CAIE T1,0 ;Is it state? <0 = hack for now>
IFSKP.
CAMN P2,RTRNRV ;Have we selected the area router?
RNMXND ;Yes, then we have no data to return
CAIN T2,RNT.NR ; or if we are an endnode there is no
RNMXND ; no state information
ELSE. ;Not state
CAIE T2,RNT.NR ;Are we an endnode?
IFSKP.
CALL ENPARM ; Yes, set up parameter pointers
RET
ELSE.
CALL RNPARM ; Set up parameter pointers
RET
ENDIF.
ENDIF.
XMOVEI T1,NDPTAB ;Node parameter table
MOVEI T2,NDPTBL
ENDIF.
ELSE.
CAIE T1,.NTCKT ;No, maybe circuit
IFSKP.
LOAD T1,NFEID,(P1) ;Get circuit identifier
CALL RTRGCB ;Get the circuit block (RC)=circuit block
RNMXER (NF.URC)
XMOVEI T1,CCPTAB ;Address of circuit parameter table
MOVEI T2,CCPTBL ; and its length
ELSE.
RNMXER (NF.FNS) ;We don't do any others
ENDIF.
ENDIF.
;Call NTPARM to do the real work
CALLRET NTPARM ; and call common function to do work
SUBTTL Network management -- Setup for loading parameter data
;Here for all parameters except state. State needs only to have P2 setup
ENPARM: MOVE RC,RTRCBQ ; Get only circuit and
LOAD AJ,RCAJQ,(RC) ; possibly our desiginated router
LOAD T1,NFPRM,(P1) ; Get requested parameter
CAIN T1,^D810 ; Is requested parameter routing type?
SETZ AJ, ; Yes, don't supply it
CAIE T1,^D2503 ; or NODE JSYS reachability?
MOVE P2,RTRNRV ; Use kludged up cost/hops in vector(0)
RETSKP
RNPARM: TMNN RNRCH,(P2) ;Is it reachable?
RNMXND ;No, then no data
SETZ AJ, ;Start with no adjacency
CAMN P2,RTRNRV ;Have we selected the area router?
IFSKP.
SKIPA RC,RTRCBQ ;No, a local area node, see if adjacent
DO.
LOAD RC,RCNXT,(RC) ;Get next circuit for RTRGAJ
JUMPE RC,ENDLP.
LOAD T1,NFEID,(P1) ;Get the node's address
CALL RTRGAJ ;See if an adjacency exists
RNMXER (NF.OPF) ;Not in our area, an error
JUMPE AJ,TOP. ;Didn't find one, try next circuit
ENDDO.
ENDIF.
MOVE T1,P2 ;No, get the address we selected
ADD T1,RTROFS ;Now point to output adjacency vector
MOVE T1,(T1) ;Get the output adjacency pointer
SKIPE AJ ;Did we find an adjacency?
IFSKP.
LOAD T2,NFPRM,(P1) ;No, then get parameter requested
CAIE T2,^D810 ;Is it routing type?
MOVE AJ,T1 ;No, then load AJ with output adjacency
ENDIF.
LOAD RC,AJCBP,(T1) ;Now the output circuit pointer
RETSKP
SUBTTL Network Management -- Qualified parameters
;Call:
; RC/ circuit block
; P1/ NMX function block
;
; CALL NMXQPS
; CALL NMXQPT
; RET T1/ Error code if error, 0 if no data, .GT. 0 if success
; T2/ Datum
;
;Context: Jsys
NMXQPS: SKIPA T1,[-1] ; Adjacent node block size
NMXQPT: SETZ T1, ; Adjacent node hello timer
STKVAR <FUNC>
MOVEM T1,FUNC ; Save parameter requested
TMNN NFQUF,(P1) ; Do we have a qualifier?
RNMXER (NF.MPE) ; It is required
LOAD T1,NFQUA,(P1) ; Get qualifier - a node address
CALL RTRGAJ ; Look for the adjacency
RNMXER (NF.MPE) ; Not in this area!
JUMPE AJ,[RNMXND] ; Not reachable
LOAD T2,AJNHT,(AJ) ; Get hello timer datum
IDIVI T2,TIMBAS ; Convert to seconds
SKIPE FUNC ; Is that what was requested?
LOAD T2,AJBSZ,(AJ) ; No, then get the block size
RNMXOK ; and return success
ENDSV.
SUBTTL Network Management -- READ node/executor state
;Call:
; P2/ Reachability vector pointer
;
; CALL NMXRNS
; RET T1/ contains error code if error else unchanged
; T2/ contains state
;
;Context: Jsys
NMXRNS: TMNN RNLCL,(P2) ; Yes, for the local node?
IFSKP.
MOVE T2,DCNSTA ; Get DECnet state
ELSE.
MOVX T2,RM.UNR ; Assume unreachable
SKIPN ENFLG ; Endnode?
IFSKP.
TMNE <RNMBY,RNCCH>,(P2) ; Maybe reachable?
MOVX T2,RM.REA ; Yes
ELSE.
TMNE RNRCH,(P2) ; Is it reachable?
MOVX T2,RM.REA ; Yes, say so
ENDIF.
ENDIF.
RNMXOK
SUBTTL Network Management -- Read circuit state
;Call: T1/ Default success flag
; RC/ Circuit block
; CALL NMXRCS
; RET T1/contains error code if error else unchanged
;
;Use: Only T1,T2 (must preserve all others)
;Context: Jsys
NMXRCS: LOAD T2,RCSTA,(RC) ; Get circuit state
MOVE T2,[RNS.OF ; Off is off
RNS.ST ; Rejected is starting
RNS.ST ; Failed is starting
RNS.ST ; Wait is starting
RNS.ST ; Init wait is starting
RNS.ST ; Verification wait is also
RNS.ST ; I guess testing is too
RNS.ON](T2) ; and running is on
RNMXOK
SUBTTL Network Management -- Set/Clear executor state
;Call: T1/ Default success flag
; T2/ New value
; P2/ Reachability vector
; CALL NMXSES
; RET T1/contains error code if error else unchanged
;
;Use: Only T1,T2
;Context: Jsys
NMXSES: TMNN RNLCL,(P2) ; Is this for the executor
RNMXER (NF.PNA) ; No, can't do it then
MOVE T1,DCNSTA ; Get DECnet state
CAIE T1,(T2) ; State changing?
RNMXOK ; No, just a NOP
SKIPE T2 ; Is new state off?
IFSKP. ; Yes
CALL RTROFF ; Then turn off DECnet
ELSE.
CALL RTRON ; else turn it on
ENDIF.
RNMXOK ; Indicate success
SUBTTL Network Management -- Set/Clear circuit state
;Call: T1/ Default success flag
; T2/ New value
; RC/ Circuit block
; CALL NMXSCS
; RET T1/contains error code if error else unchanged
;
;Use: Only T1,T2 (must preserve all others)
;Context: Jsys
NMXSCS: LOAD T1,RCSTA,(RC) ; Get current state
CAIE T2,NCK.OF ; Is new state off?
IFSKP.
CAIN T1,RCS.OF ; Is current state off?
RNMXOK ; Yes, just a NOP
CALL SETRCC ; Set recompute routing flags
CALL RTRZCB ; Clean out the circuit block
CALL RTRSAO ; Set any remaining adjacencies to unused
CALL R2KCLS ; Shut the circuit down
ELSE.
CAIE T1,RCS.OF ; Current state off?
IFSKP.
CALL R2KINI ; Attempt to start circuit
IFNSK.
SETZRO RCTIN,(RC) ; Clear restart timer
RNMXER (NF.OPF) ; Failed!
ENDIF.
ENDIF.
ENDIF.
RNMXOK ; Indicate success
SUBTTL Network Management -- Show counters
SUBTTL Network Management -- Show and zero counters
;NMXSHC - called to show counters
;Call: T2/ address of NF block
; CALL NMXSHC
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
;NMXSZC - called to show and zero counters
;Call: T2/ address of NF block
; CALL NMXSZC
; +1 on error with code in T1
; +2 on success
;
;Context: Jsys
XSWAPCD
NMXSHC: SKIPA T3,[NF.COU] ;Load function code and skip
NMXSZC: MOVX T3,NF.SZC ;Load function code
STKVAR <FUNC>
MOVEM T3,FUNC
MOVE P1,T2 ;Move NF pointer to where it should be
LOAD T1,NFETY,(P1) ;Get the entity type
CAIE T1,.NTNOD ;Is request for a node entity?
IFSKP.
LOAD T1,NFEID,(P1) ;Get the entity ID
CAME T1,RTRNAD ;Is it us?
RNMXND ;No, then nothing to return
XMOVEI T1,EXCTAB ;Address of executor counter table
MOVEI T2,EXCTBL ; and its length
ELSE.
CAIE T1,.NTCKT ;No, maybe circuit
IFSKP.
LOAD T1,NFEID,(P1) ;Get circuit identifier
CALL RTRGCB ;Get the circuit block
RNMXER (NF.URC)
XMOVEI T1,CICTAB ;Address of circuit counter table
MOVEI T2,CICTBL ; and its length
ELSE.
RNMXER (NF.FNS) ;We don't do any others
ENDIF.
ENDIF.
;Call NTCTRS to do the real work
MOVE T3,FUNC ;Get function to do
CALLRET NTCTRS ;Read the counters and return
ENDSV.
SUBTTL Network Management -- Return list
;NMXRET - Return list of entities
;Call T2/ Address of NM block
NMXRET: MOVE P1,T2 ; Save address of NM block
TMNN NFBFF,(P1) ; Buffer present?
RNMXER (NF.MPE) ; Must have one for this stuff
LOAD T1,NFBLN,(P1) ; Get the buffer length
SKIPG T1
RNMXER (NF.MPE) ; NTMAN/NML screwed up
LOADE T2,NFSEL,(P1) ; Get the selector type
CAXL T2,.NTSGN ; Range check the selection criteria
CAXLE T2,.NTKNO ; If not between SIGNIFICANT & KNOW
RNMXER (NF.MPE) ; we don't do it
LOAD T1,NFETY,(P1) ; Get entity type
CAIE T1,.NTNOD ; Is this a node entity request?
IFSKP.
CALLRET <-.NTSGN>+@[
IFIW <NMXILS&777777> ; SIGNIFICANT nodes not supported
IFIW <NMXSAN&777777> ; ADJACENT nodes
IFIW <NMXILS&777777> ; LOOP Nodes
IFIW <NMXSAX&777777> ; ACTIVE Nodes
IFIW <NMXSKN&777777>](T2) ; KNOWN Nodes
ELSE.
CAIE T1,.NTCKT ; Is the entity circuit?
IFSKP.
CALLRET <-.NTSGN>+@[
IFIW <NMXILS&777777> ; SIGNIFICANT nodes not supported
IFIW <NMXILS&777777> ; ADJACENT circuits
IFIW <NMXILS&777777> ; LOOP circuits
IFIW <NMXSAC&777777> ; ACTIVE circuits
IFIW <NMXSKC&777777>](T2) ; KNOWN circuits
ELSE.
RNMXER (NF.FNS) ; We don't do any others
ENDIF.
ENDIF.
NMXILS: RNMXER (NF.MPE) ; Error on NTMAN's part
SUBTTL Network Management -- Show known/active nodes
;Call: P1/ NF block
; P2/ Scratch
NMXSAX: TDZA T1,T1 ; "Active nodes"
NMXSKN: MOVEI T1,1 ; "Known nodes"
STKVAR <FUNC>
MOVEM T1,FUNC
LOAD T4,NFBUF,(P1) ; Get the buffer address
LOAD T1,NFBLN,(P1) ; Get length of buffer
CAMGE T1,RTRMXN ; Is it big enough?
RNMXER (NF.MPE) ; NTMAN got it wrong
SKIPE FUNC
AOS T4 ; Starting at node 1 position for "known"
MOVE T3,RTRNRV ; Address of reach vector
AOS T3 ; Start at node 1
MOVEI T1,1 ; Start loop at 1 (this will be node number)
MOVE T2,RTRHOM ; Get the local area number
LSH T2,^D10 ; Position to area field
SETZ P2, ; Count is zero
DO.
TMNN RNRCH,(T3) ; Is this node reachable?
IFSKP.
MOVEM T1,(T4) ; Put address into buffer
IORM T2,(T4) ; Set the area number
AOJ P2, ; Count it
AOJ T4, ; Advance buffer pointer
ELSE.
SKIPE FUNC
AOJ T4, ; Advance pointer if "known"
ENDIF.
AOJ T1, ; Advance node number
AOJ T3, ; Step to next node in vector
CAMG T1,RTRMXN ; Have we reached the top of the vector?
LOOP. ; No, loop until done
STOR P2,NFBLN,(P1) ; Save count for NTMAN
RETSKP ; Yes, return success
ENDDO.
ENDSV.
SUBTTL Network Management -- Show adjacent nodes
;Call: P1/ NF block
NMXSAN: SAVEAC <Q1,Q2> ; We need more than the temps
SETZ P2, ; Count starts at 0
LOAD T2,NFBLN,(P1) ; Get length of buffer
LOAD T4,NFBUF,(P1) ; Get buffer address
ADD T2,T4 ; Compute end of buffer
SKIPA Q1,RTRCBQ ; Point to first circuit
NMXSN1: LOAD Q1,RCNXT,(Q1) ; Get next circuit
JUMPE Q1,NMXSN4 ; Finished, return success
LOAD T1,RCSTA,(Q1) ; Get circuit state
CAIN T1,RCS.OF ; Is state "off"?
JRST NMXSN1 ; Yes, step to next circuit
LOAD Q2,RCAJQ,(Q1) ; Get first in queue of adjacencies
NMXSN2: JUMPE Q2,NMXSN1 ; None, try next circuit
LOAD T1,AJSTA,(Q2) ; Get adjacency state
CAIE T1,ADJ.UP ; Is it up?
JRST NMXSN3 ; No, skip it then
CAML T4,T2 ; Check to be sure we don't run off end
RNMXER (NF.MPE) ; NTMAN error if not enough room
LOAD T1,AJADR,(Q2) ; Get node address
MOVEM T1,(T4) ; Save into buffer
AOJ T4, ; Advance buffer
AOJ P2,
NMXSN3: LOAD Q2,AJNXT,(Q2) ; Step to next adjacency
JRST NMXSN2 ; Try next
NMXSN4: STOR P2,NFBLN,(P1) ; Save count
SKIPN T1,P2
RET
RETSKP
SUBTTL Network Management -- Show active circuits
;Call: P1/ NF block
NMXSAC: LOAD T2,NFBLN,(P1) ; Get length of buffer
LOAD T4,NFBUF,(P1) ; Get buffer address
ADD T2,T4 ; Compute end of buffer
SETZ P2, ; Intialize count
SKIPA T3,RTRCBQ ; Point to first circuit
NMXSA1: LOAD T3,RCNXT,(T3) ; Get next circuit
JUMPE T3,NMXSA2 ; Finished, return success
LOAD T1,RCSTA,(T3) ; Get circuit state
CAIN T1,RCS.OF ; Is state "off"?
JRST NMXSA1 ; Yes, step to next circuit
CAML T4,T2 ; Check to be sure we don't run off end
RNMXER (NF.MPE) ; NTMAN error if not enough room
LOAD T1,RCLID,(T3) ; Get circuit ID
MOVEM T1,(T4) ; Save into buffer
AOS P2
AOJA T4,NMXSA1 ; Advance buffer and try another
NMXSA2: STOR P2,NFBLN,(P1) ; Save count
SKIPN T1,P2
RET
RETSKP
SUBTTL Network Management -- Show known circuits
;Call: P1/ NF block
NMXSKC: LOAD T2,NFBLN,(P1) ; Get length of buffer
LOAD T4,NFBUF,(P1) ; Get buffer address
ADD T2,T4 ; Compute end of buffer
SETZ P2,
SKIPA T3,RTRCBQ ; Point to first circuit
NMXSK1: LOAD T3,RCNXT,(T3) ; Get next circuit
JUMPE T3,NMXSK2 ; Finished, return success
CAML T4,T2 ; Check to be sure we don't run off end
RNMXER (NF.MPE) ; NTMAN error if not enough room
LOAD T1,RCLID,(T3) ; Get circuit ID
MOVEM T1,(T4) ; Save into buffer
AOJ P2, ; Count it
AOJA T4,NMXSK1 ; Advance buffer and try another
NMXSK2: STOR P2,NFBLN,(P1) ; Save count
SKIPN T1,P2
RET
RETSKP
SUBTTL Network Management -- Return list of adjacencies on a circuit
NMXRAL: SAVEAC <Q1,Q2> ; We need more than the temps
LOAD T2,NFBLN,(P1) ; Get length of buffer
LOAD Q2,NFBUF,(P1) ; Get buffer address
ADD T2,Q2 ; Compute end of buffer
LOAD T1,NFEID,(P1) ; Get circuit identifier
SETZ T3, ; Count of entries written to buffer
LOAD Q1,RCAJQ,(RC) ; Get first in queue of adjacencies
NMXRA1: JUMPE Q1,NMXRA3 ; None, then done
LOAD T1,AJSTA,(Q1) ; Get adjacency state
CAIE T1,ADJ.UP ; Is it up?
JRST NMXRA2 ; No, skip it then
CAML Q2,T2 ; Check to be sure we don't run off end
RNMXER (NF.MPE) ; NTMAN error if not enough room
LOAD T1,AJADR,(Q1) ; Get node address
MOVEM T1,(Q2) ; Save into buffer
ADDI T3,1 ; Count as written
AOJ Q2, ; Advance buffer
NMXRA2: LOAD Q1,AJNXT,(Q1) ; Step to next adjacency
JUMPN Q1,NMXRA1 ; Try next
NMXRA3: STOR T3,NFBLN,(P1) ; Save count of number written for NTMAN
MOVE T1,T3 ; T1 is a success flag
RET
XRESCD
SUBTTL Network Management Event Interface -- Router Event Types
;These are the various events that occur in router which are reported
;to network management.
DEFINE EVENTS,<
RE APL,0, NON,<RTEPKH,RTENOD> ;AGED PACKET LOSS
RE NUR,1, CKT,<RTEPKH,RTENOD> ;NODE UNREACHABLE PACKET LOSS
RE NOR,2, CKT,<RTEPKH,RTENOD> ;NODE OUT-OF-RANGE PACKET LOSS
RE OPL,3, CKT,<RTEPKH,RTENOD> ;OVERSIZED PACKET LOSS
RE PFE,4, CKT,<RTEPKB,RTENOD> ;PACKET FORMAT ERROR
RE PRL,5, CKT,<RTEPKH,RTENOD,RTEHIA> ;PARTIAL ROUTING UPDATE LOSS
RE VRJ,6, CKT,RTENOD ;VERIFICATION REJECT
RE LDL,7, CKT,RTEREA ;CIRCUIT DOWN, CIRCUIT FAULT
RE ADS,8, CKT,<RTEREA,RTEPKH> ;ADJACENCY DOWN, SOFTWARE FAULT
RE ADO,9, CKT,<RTEREA,RTEPKH,RTEEXN> ;ADJACENCY DOWN, OPERATOR FAULT
RE LUP,10,CKT ;CIRCUIT UP
RE IFL,11,CKT,RTEREA ;INITIALIZATION FAILURE, CIRCUIT FAULT
RE IFS,12,CKT,<RTEREA,RTEPKH> ;INITIALIZATION FAILURE, SOFTWARE FAULT
RE IFO,13,CKT,<RTEREA,RTEPKH> ;INITIALIZATION FAILURE, OPERATOR FAULT
RE NRC,14,NOD,RTESTA ;NODE REACHABILITY CHANGE
RE AUP,15,CKT,RTENOD ;ADJACENCY UP
RE ARJ,16,CKT,RTENOD ;ADJACENCY REJECT
RE ARC,17,ARE,RTENOD ;AREA REACHABILITY CHANGE
RE AJD,18,CKT,RTENOD ;Adjacency down - Address change
RE ADO,19,CKT,RTENOD ;Adjacency down, operator initiated
>
DEFINE RE(EVENT,TYPE,ENTTYP,PARAMS),<
RE.'EVENT==^D<TYPE>> ;DEFINE THE RE MACRO
;Now expand the symbols.
EVENTS
;Now define the processor macro.
DEFINE RE(PREFIX,VALUE,ENTTYP,PARAMS),<
IFIW [MOVX T1,.NT'ENTTYP
STOR T1,NEETP,(P1)
SETZ T4, ;;INITIALIZE THE COUNT
IRP <PARAMS>,<
CALL PARAMS ;;STICK ON THE PARAMETER DATA
>
STOR T4,NEDLN,(P1) ;;GIVE ARG BLOCK THE LENGTH
RET]
>
;Make a table of event processors.
RTETAB: EVENTS
RET.LN==.-RTETAB
RET.MX==<.-RTETAB>-1
SUBTTL Network Management Event Interface -- Event Reason Definitions
;These are the various reasons which may be put in the reason field of
;events that include REASON as a event parameter.
DEFINE REASON(SUFFIX,VALUE),<
XP RS.'SUFFIX,^D'VALUE>
REASON LSL,0 ;Circuit synchronization lost
REASON DTE,1 ;Data errors
REASON UPT,2 ;Unexpected packet type
REASON RUC,3 ;Routing update checksum error
REASON ANA,4 ;Adjacent node address change
REASON VRT,5 ;Verification receive timeout
REASON VSK,6 ;Version skew
REASON ANO,7 ;Adjacency address out of range
REASON ABS,8 ;Adjacent node block size too small
REASON IVS,9 ;Invalid verification seed value
REASON ALT,10 ;Adjacent node listener receive timeout
REASON ALI,11 ;Adjacent node listener received invalid data
REASON CFD,12 ;Call failed
REASON VPR,13 ;Verification password required from P3 node
REASON DBA,14 ;Dropped by adjacent node
PURGE REASON
SUBTTL Network Management Event Interface -- RTNEVT - Event Reporter
;RTNEVT - Report Router event
;
; Call:
; T1/ Event type
; T2/ Entity ID (we know the entity type from RTETAB)
; T3/ Event specific word (REASON, STATUS, etc.)
; T4/ Message Block Pointer or zero if none given
; (Message Block must be DNGINIized before this is called)
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
;
;This calls something which will call network management to log this event
;which has taken place. This routine is called by the EVENT macro.
EVTMLN==^D50 ;MAXIMUM LENGTH OF EVENT PARAMETER DATA (BYTES)
RTNEVH: SKIPA CX,[^D96] ;Special event class
RTNEVT: SETZ CX,
MOVEM CX,ECLASS
SAVEAC <P1,P2,MB,MS> ;SAVE SOME ACS
STKVAR <EVTSIG> ;Flag if we should use signal processor
SETZM EVTSIG ;Initialize to "not a signal"
SKIPL P2,T1 ;RANGE CHECK THE
CAILE P2,RET.MX ;EVENT TYPE
BUG.(CHK,ROUUET,ROUTER,SOFT,<Unknown event type in RTNEVT>,,<
Cause: We supplied ourselves with a bad event code.
Action: Look for someone smashing T1 or a problem with the EVENTS macro
>,RTN)
MOVE P1,T2 ;SAVE THE ENTITY-ID
MOVEM T3,RTREVW ;SAVE THE EVENT ARGUMENT
MOVE MB,T4 ;Presumed MB pointer to MB
;Check if event should be thrown away
CAIE P2,RE.LDL ;Is this a line down event?
JRST RTNEV2 ;No, then filter it
LOAD T1,LIDEV,+P1 ;Get the device type
CAIN T1,LD.DTE ;DTE device?
JRST RTNEV4 ;No filtering for DTE's
RTNEV2: MOVX T1,.NCRTR ;ROUTER event class
STOR T1,FACCL,+T2
STOR P2,FACTY,+T2 ; and event type to T2
MOVX T1,EV.FIL ;Function code "filter event"
CALL NMXEVT
RET ; -throw it away
TRNA
RTNEV4: SETOM EVTSIG ;Send to signal processor
SKIPN RTRECP ;Verify that EC pointer is non-zero
RET ; -was zero, must have failed to initialize
;Ok, log event
SKIPN MB ;SET UP MESSAGE BLOCK (IF ANY)
JRST RTNEV5 ;NOT THERE, DON'T TRY TO SET POSITION
MOVE T1,MB ;PASS POINTER TO MESSAGE BLK TO DNGINI
CALL DNGINI ;SET UP FOR GETTING BYTES OUT OF MSG BLK
CALL DNRPOS ;GET OUR CURRENT POSITION IN MESSAGE
OPSTRM <EXCH T1,>,RMMK1,(MB) ;EXCHANGE WITH TOP OF MESSAGE POSITION
CALL DNGPOS ;GO TO THAT POSITION
RTNEV5: MOVX T1,NE.LEN+<<EVTMLN+3>/4> ;GET ENOUGH FOR ARG BLOCK AND
; MAXIMUM AMOUNT OF EVENT PARAMETER DATA
CALL DNGWDZ ;GET THE WORDS
BUG.(INF,ROUCGV,ROUTER,SOFT,<Couldn't get memory for event arg block>,,<
Cause: DECnet has exhausted its free space.
>,RTN)
STOR P1,NEEID,(T1) ;PUT ENTITY-ID IN EVENT BLOCK
MOVE P1,T1 ;SAVE THE POINTER TO THE BLOCK
MOVE T1,RTRECP ;Get EC pointer
STOR T1,NEECP,(P1) ; and store it in NE block
STOR P2,NECTY,(P1) ;PUT THE EVENT TYPE IN THE ARG BLOCK
SKIPN T1,ECLASS ;Special event class is 96. If 0 use Router's
MOVX T1,.NCRTR ;THE EVENT CLASS IS ROUTER
STOR T1,NECCL,(P1) ;PUT IN NE ARG BLOCK
XMOVEI T1,NE.LEN(P1) ;MAKE A FULLWORD POINTER TO DATA
STOR T1,NEDAT,(P1) ;STORE POINTER TO IT IN ARG BLOCK
MOVE T1,[POINT 8,NE.LEN(P1)] ;MAKE UP BYTE POINTER TO PARAMETER DATA
EXCH T1,P2 ;SWITCH FUNCTION AND POINTER
CALL @RTETAB(T1) ;CALL THE PARAMETER PROCESSOR
JUMPE MB,RTNEV6 ;DON'T REPOSITION IN NO-EXISTANT MESSAGE
LOAD T1,RMMK1,(MB) ;GET OUR LAST MESSAGE POSITION
CALL DNGPOS ;GO TO THERE
RTNEV6: MOVX T1,EV.LOG ;Assume function code "log an event"
SKIPE EVTSIG ;Should this be sent to the signal processor?
MOVX T1,EV.SIG ;Do a signal since it is guaranteed to get thru
MOVE T2,P1 ; and NE pointer in T2
CALL NMXEVT ;CALL THE EVENT PROCESSOR
TRN
RET ;Return, NTMAN will deallocate NE block
SUBTTL Network Management Event Interface -- Event Parameter Processors
;Put a packet header in the NE argument block string. This corresponds to
;parameter 0 for circuit events.
RTEPKH: STKVAR <MSGFLG>
SKIPN MB ;MUST HAVE A MESSAGE BLOCK HERE
BUG.(CHK,ROUEHM,ROUTER,SOFT,<No Message Block for Event data>,,<
Cause: We are attempting to read data from an MB to report in an event but
the caller failed to supply a message address.
Action: Check caller and see why it didn't supply a message block address.
>,RTN)
MOVEI T1,0 ;GET PARAMETER NUMBER
MOVEI T2,2 ;GET NUMBER OF BYTES
CALL PUTNBT ;INSTALL THE BYTES SWAPPED
CALL DNG1BY ;GET THE "FIRST" BYTE FROM RTR MESSAGE
RET ;COULND'T GET IT, JUST RETURN
TXZN T1,RM%MZ1 ;IS THE PAD FLAG SET?
IFSKP.
CALL PADSKP ;Skip over any pad bytes (NI) and return with
RET ; first byte of message. Error if PADSKP fails
ENDIF.
MOVEM T1,MSGFLG ;SAVE MESSAGE FLAGS FOR LATER
TMNN T1,RM%CTL ; Is this a control message?
TXNN T1,RM%MZ3 ; No, is it a long format data header?
IFSKP.
MOVEI T1,313 ;Yes, then a coded multiple with 11 fields
CALL PUTBYT
MOVEI T1,041 ;Data type = HEX image - one byte
CALL PUTBYT
MOVE T1,MSGFLG ;Recover message flags
CALL PUTBYT
CALL PUTENA ;Put in destination address
RET
CALL PUTENA ; and the source address
RET
CALL PUTDU1 ;Next area router
RET
CALL PUTDU1 ;Visit count
RET
MOVEI T1,041 ;Data type = Hex number - one byte
CALL PUTBYT
CALL DNG1BY
RET
CALL PUTBYT ;Service class
CALL PUTDU1 ; and finally the protocol type
TRN
ELSE. ;Here if control or short format data
TXNE T1,RM%CTL ;WAS IT A CONTROL MESSAGE?
SKIPA T1,[302] ;YES, CODED MULTIPLE, TWO FIELDS
MOVEI T1,304 ; NO, CODED MULTIPLE, FOUR FIELDS
CALL PUTBYT ;INSTALL DATA TYPE
MOVEI T1,041 ;NOT CODED, HEX NUMBER OF 1 BYTE
CALL PUTBYT ;INSTALL IT
MOVE T1,MSGFLG ;Recover message flag byte
CALL PUTBYT ;OUTPUT IT
TXNE T1,RM%CTL ;IS IT A CONTROL MESSAGE???
IFSKP.
CALL PUTDU2 ;Destination address
RET
ENDIF.
CALL PUTDU2 ;Source address
RET
MOVE T1,MSGFLG ;GET BACK MESSAGE HEADER
TXNE T1,RM%CTL ;IS IT A CONTROL MESSAGE
RET ;YES, SKIP THIS ONE TOO
CALL PUTDU1 ;No, include the the visit count
TRN
ENDIF.
RET
;Put a packet beginning in the NE argument block string.
RTEPKB: SKIPN MB ;MUST HAVE A MESSAGE BLOCK HERE
BUG.(CHK,ROUEHB,ROUTER,SOFT,<No Message Block for Event data>,,<
Cause: We are attempting to read data from an MB to report in an event but
the caller failed to supply a message address.
Action: Check caller and see why it didn't supply a message block address.
>,RTN)
MOVEI T1,1 ;GET PARAMETER NUMBER
MOVEI T2,2 ;GET NUMBER OF BYTES
CALL PUTNBT ;INSTALL THE BYTES SWAPPED
CALL DNG1BY ;GET THE FIRST BYTE
RET ;RAN OUT, GIVE ERROR RETURN
TXZN T1,RM%MZ1 ;IS THE PAD FLAG SET?
IFSKP.
CALL PADSKP ;Skip over any pad bytes (NI) and return with
RET ; first byte of message. Error if PADSKP fails
ENDIF.
MOVEI T1,1 ;Back up a byte so we are pointing to byte
CALL DNBKBY ; containing the message flags again
CALL PUTIMG ;And now the first 6 bytes of the message
TRN ;Ignore erorrs here
RET
;Put the Highest Address in the NE argument block string.
RTEHIA: MOVEI T1,2 ;GET PARAMETER NUMBER
MOVEI T2,2 ;GET NUMBER OF BYTES
CALL PUTNBT ;INSTALL THE BYTES SWAPPED
MOVEI T1,002 ;Data type - decimal unsigned, two bytes
CALL PUTBYT
MOVE T1,HIADDR ;Get highest address
MOVEI T2,2 ;Number of bytes to transfer
CALL PUTNBT ;Put data into event buffer
TRN
RET
;Put a node address in the NE argument block string.
RTENOD: MOVEI T1,3 ;GET PARAMETER NUMBER
RTEEX1: MOVEI T2,2 ;GET NUMBER OF BYTES
CALL PUTNBT ;INSTALL THE BYTES SWAPPED
MOVEI T1,301 ;CODED MULTIPLE, ONE FIELD
CALL PUTBYT ;INSTALL DATA TYPE
MOVEI T1,002 ;DECIMAL UNSIGNED, TWO BYTES
CALL PUTBYT ;INSTALL SUB-DATA TYPE
MOVE T1,RTREVW ;GET THE NODE NUMBER
MOVEI T2,2 ;NODE NUMBER IS TWO BYTES
CALLRET PUTNBT ;PUT THE NUMBER IN THE MESSAGE
;Put the Expected Node in the NE argument block string.
RTEEXN: MOVEI T1,4 ;GET PARAMETER NUMBER
JRST RTEEX1 ;OTHEWISE, SAME AS NODE
;Put the REASON type in the NE argument block string.
RTEREA: MOVEI T1,5 ;GET PARAMETER NUMBER
RTEST1: MOVEI T2,2 ;GET NUMBER OF BYTES
CALL PUTNBT ;INSTALL THE BYTES SWAPPED
MOVEI T1,201 ;CODED, SINGLE FIELD, LENGTH 1 BYTE
CALL PUTBYT ;STUFF IT
MOVE T1,RTREVW ;GET THE REASON
CALLRET PUTBYT ;STUFF IT AND RETURN
;Put the status in the NE argument block. This is a one byte field
;which we have in RTREVW, so just use RTEREA.
RTESTA: MOVEI T1,7 ;GET PARAMETER NUMBER
JRST RTEST1 ;STATUS PARAM IS JUST LIKE REASON
SUBTTL Network Management Event Interface --Event Processor Subroutines
;Put n (in T2) bytes in the string pointed to by the NE argument block.
;It also updates T4, which is the count of bytes put in so far.
PUTNBY: JUMPE T2,RSKP ;RETURN IF NO MORE BYTES LEFT
CALL DNG1BY ;GET ONE BYTE FROM THE MESSAGE BLOCK
RET ;PROPAGATE FAILURE
IDPB T1,P2 ;STORE THE BYTE IN SOME SPACE
ADDI T4,1 ;UPDATE THE GLOBAL COUNT
SOJA T2,PUTNBY ;SEE IF WE HAVE TO PUT IN MORE
;Put n (in T2) bytes of the number in T1.
PUTNBT: JUMPE T2,RTN ;RETURN IF NOTHING LEFT
IDPB T1,P2 ;PUT THE BYTE IN THE MESSAGE
LSH T1,-^D8 ;SHIFT OVER TO THE NEXT BYTE
ADDI T4,1 ;UPDATE THE COUNT
SOJA T2,PUTNBT ;DO THE REST
;Put one byte (in T1) into the data string for network management
PUTBYT: IDPB T1,P2 ;INSTALL THE BYTE
AOJA T4,RTN ;INCREMENT THE NUMBER OF BYTES
PUTENA: CALL PUTDU1 ;Area
RET
CALL PUTDU1 ;Sub-area
RET
CALLRET PUTIMG ;Now insert the Ethernet address as a HEX
; image of 6 bytes
PUTDU1: MOVEI T1,001 ;Put data type and data into event buffer
CALL PUTBYT
CALL DNG1BY ;Read a byte from the message
RET
CALL PUTBYT ; and put it into the event buffer
RETSKP
PUTDU2: MOVEI T1,002 ;Data type - decimal unsigned, two bytes
CALL PUTBYT
MOVEI T2,2 ;Number of bytes to transfer
CALL PUTNBY ;Put data into event buffer
RET
RETSKP
PUTIMG: MOVEI T1,040 ;NOT CODED, HEX IMAGE
CALL PUTBYT ;INSTALL DATA TYPE
MOVEI T1,6 ;LENGTH OF DATA IS ALWAYS 6 BYTES
CALL PUTBYT ;INSTALL LENGTH OF DATA
MOVX T2,6 ;WE ALWAYS WANT SIX BYTES
CALLRET PUTNBY ; PUT THEM IN THE NE BLOCK
SUBTTL Network Management Event Interface -- Miscellaneous Event Processors
;These are a bunch of routines to report different events. The events
;here are common to more than one routine, so they are collected
;together in this section.
;RTEMFE - Report Message Format Error Event
RTEMFE: MOVEM T1,MFEWHO ;Remember who gave us this event
MOVEM MB,MFEMSG ; and the MB being processed
LOAD T2,RCLID,(RC) ;GET THE LINE ID FOR ENTITY ID
SETZ T3, ;Default address to nothing
SKIPE AJ
LOAD T3,AJADR,(AJ) ;Get address of sender
EVENT RE.PFE,<Packet format error event>,MB
AOS RTRCPF ;Count number of errors
CALLRET FREMSG ;FREE MSG BLK AND RETURN
;RTEVRJ - Report Verficiation Reject Event
RTEVRJ: LOAD T2,RCLID,(RC) ;GET THE ENTITY ID (CIRCUIT)
LOAD T3,AJADR,(AJ) ; AND THE NEIGHBOR'S ADDRESS
MOVE T4,RTRHOM ;GET THE HOME AREA
DPB T4,[POINTR (T3,RN%ARE)] ;STORE IT IN T3
EVENT RE.VRJ,<Verification reject event>
AOS RTRCVR ; Count occurences
CALLRET FREMSG ;FREE MSG BLK AND RETURN
;RTELDL - Report Circuit Down, Hard Circuit Fault Event
RTELDL: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.LDL,<Circuit down, circuit fault>
INCR RCCCD,(RC) ;INCREMENT THE CIRCUIT DOWN COUNTER
RET ;RETURN, NO MSG TO FREE HERE
;RTELDS - Report Circuit Down, Software Fault Event
RTELDS: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.ADS,<Adjacency down, software fault>,MB
CALL SETRCC ;Set recompute routing flags
JN RCBCT,(RC),RTELD1
INCR RCCCD,(RC) ;Increment the circuit down counter
CALL RTRZCB ;Clean out the circuit block
CALL RTRSAO ;Set any remaining adjacencies to unused
CALLRET FREMSG ;FREE MSG BLK AND RETURN
RTELD1: 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.
CALLRET FREMSG ;FREE MSG BLK AND RETURN
;RTELDO - Report Circuit Down, Operator Fault Event
RTELDO: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.ADS,<Adjacency down, operator fault>,MB
INCR RCCCD,(RC) ;INCREMENT THE CIRCUIT DOWN COUNTER
RET
;RTEADO - Report Adjacency Down, Operator Fault Event
RTEADO: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.ADO,<Adjacency down, operator fault>,MB
INCR RCAJD,(RC) ;Increment the adjacency down counter
CALL SETRCA ;Set recompute routing flags
JN RCBCT,(RC),RTEAD1 ;No circuit down if broadcast
MOVX T1,RS.ANA ;Event reason: Adjacent node address change
CALL RTELDO ;Report circuit down - Circuit fault event
CALL CIRFAI ;Close the port and set reopen time
CALLRET FREMSG ; and return message
RTEAD1: 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.
CALLRET FREMSG ;FREE MSG BLK AND RETURN
;Event Processors - Continued from last page
;RTEINL - Report Initialization Failure, Hard Circuit Fault Event
RTEINL: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.IFL,<Initialization failure, circuit fault>
INCR RCCCD,(RC) ;INCREMENT THE CIRCUIT DOWN COUNTER
RET ;RETURN, NO MSG BLK TO FREE HERE
;RTEINS - Report Initialization Failure, Software Fault Event
RTEINS: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.IFS,<Initialization failure, software fault>,MB
INCR RCCCD,(RC) ;INCREMENT THE CIRCUIT DOWN COUNTER
CALL FREMSG ;FREE MSG BLK AND RETURN
CALLRET CIRFAI ;RE-INITIALIZE THE DLL
;RTEINO - Report Initialization Failure, Operator Fault Event
RTEINO: MOVE T3,T1 ;GET THE REASON
LOAD T2,RCLID,(RC) ;GET THE LINE ID
EVENT RE.IFO,<Initialization failure, operator fault>,MB
INCR RCCCD,(RC) ;INCREMENT THE CIRCUIT DOWN COUNTER
CALL FREMSG ;FREE MSG BLK AND RETURN
CALLRET CIRFAI ;RE-INITIALIZE THE DLL
SUBTTL Miscellaneous Routines -- RTRSAO - Set Adjacency off line
;RTRSAO - Set all adjacencies associated with a circuit block off line.
;
; Call:
; RC/ Pointer to circuit block
;
; RET ;With ADJ(RC) set to unused
;
; Uses: T1,T2,T3
RTRSAO: SAVEAC AJ
OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Get the first adjacency block
RTRSO2: LOAD AJ,AJNXT,(AJ) ;Get the next one
JUMPE AJ,RTN
SETZ T1,
STOR T1,AJFLA,(AJ) ;CLEAR OUT ALL FLAGS
STOR T1,AJADR,(AJ) ;CLEAR OUT THE NODE ADDRESS
MOVX T1,ADJ.UN ;Set adjacency to unused
STOR T1,AJSTA,(AJ) ;Set it
LOAD T1,AJRTV,(AJ) ;Get the address of the routing vector
JUMPE T1,RTRSO2 ;If no vector don't smear it
MOVE T2,RTRMXN ;Get the maximum number of nodes
ADD T2,T1 ;For end of smear
MOVX T3,RNCHG!RNHOP!RNCST ;Get INFH and INFC and set them in the
CALL DNSWDS ; vector
JRST RTRSO2 ;Try for another
SUBTTL Miscellaneous Routines -- RTRZCB - Zap Circuit Block
;RTRZCB - Zap circuit block and report circuit down event
;
; Call:
; RC/ Pointer to circuit block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1
RTRZCB: TMNE RCBCT,(RC) ;If point-to-point don't free adjacency
CALL RTRZAA ;Zap all the adjacencies
SETZ T1, ;Clear some fields
STOR T1,RCTLS,(RC) ;Time last message sent
STOR T1,RCTLR,(RC) ; and the time we sent last routing message
STOR T1,RCTIN,(RC) ; and restart timer
SETZRO <RCSRM,RCSHM>,(RC) ;Clear some flags
SETZRO RCDSL,(RC) ;Clear address of desiginated router
LOAD AJ,RCAJQ,(RC) ;Get pointer to adjacency block
JUMPE AJ,RTN ;Return if none
MOVE T1,RTRVER ;Reset adjacency version
STOR T1,AJVER,(AJ) ;...
MOVE T1,RTRECO ;...
STOR T1,AJECO,(AJ) ;...
MOVE T1,RTRCUS ;...
STOR T1,AJCUS,(AJ) ;...
RET ;Return
SUBTTL Miscellaneous Routines -- RTRZAA - Zap all Adjacancies associated with RC
;RTRZAA - Zap all adjacency blocks associated with a circuit block in RC
;
; Call:
; RC/ Router circuit block
;
; RET ; Return with all adjacencies freed
;
RTRZAA: LOAD T1,RCAJQ,(RC) ; Pointer to adjacencies
JUMPE T1,RTN ; None left
MOVE T2,RC ; Circuit block
CALL RTRZAB ; Adjacency must go
JRST RTRZAA ; Do the next one
SUBTTL RTRZAB - Zap an adjacency block
;RTRZAB - Zap an adjacency block - Returns adjacency block to DNFWDS
;
; Call:
; T1/ Adjacency to zap
; T2/ Circuit block adjacency belongs to
;
; RET ;Return with adjacency cleared out
; ; and adjacency in the off-line queue
RTRZAB: SAVEAC <P1,P2>
DMOVE P1,T1
LOAD T1,AJNTY,(P1) ;Get the adjacency type
CAIE T1,ADJ.LN ;It it an endnode?
JRST RTRZB1 ; No
SOS RTRBEA ;Yes, decrement count of endnode adjacencies
JRST RTRZB2
RTRZB1: OPSTR <SKIPE T1,>,AJRTV,(P1) ;Get the adjacencies routing vector
CALL DNFWDS ;Return it
SOS RTRBRA ;Decrement count of router adjacencies
DECR RCNRO,(RC) ; and count of the number on this Ethernet
RTRZB2: RMVQUE P1,<RC.AJQ(P2)>,AJ.NXT,T1 ;Dequeue the adjacency
SETZRO AJNXT,(P1) ; Clear next adjacency pointer
SKIPE T1,AJOFLQ ; Anything in the off-line queue?
STOR T1,AJNXT,(P1) ; Yes, link it to this one
MOVEM P1,AJOFLQ ; and make this one the first
MOVEI T1,ADJ.OL ; New state is off-line
STOR T1,AJSTA,(P1) ; and set it
RET
SUBTTL Miscellaneous Routines -- RTRMAJ - Make an Adjacency Block
;RTRMAJ - Allocate an adjacency block
;
; Call:
; T1/ Flag indicating routing/non-routing node (0=non-routing)
; RC/ Circuit block
;
; Return:
; RET ;Couldn't allocate block
; RETSKP ;Everything worked, (T1) = Adjacency block
;
; Uses: T1-T4
RTRMAJ: SAVEAC <P1,P2> ;SAVE A PEA OR TWO
MOVE P2,T1 ;Save adjacency type
MOVX T1,AJ.LEN ;GET THE LENGTH OF AN ADJACENCY BLOCK
CALL DNGWDZ ;GET THAT MANY WORDS
RET ;RETURN A FAILURE
MOVE P1,T1 ;SAVE THE POINTER TO THE ADJACENCY
MOVE T1,RTRMXN ;GET THE MAXIMUM NODE NUMBER
ADDI T1,1 ;ADD ONE FOR NODE ZERO (Nearest area router)
CALL DNGWDZ ;GET THAT MANY WORDS
JRST [MOVE T1,P1 ;GET THE ADDRESS OF THE ADJACENCY BLOCK
CALLRET DNFWDS] ;FREE THE WORDS AND GIVE ERROR RETURN
SKIPE P2 ;DON'T SAVE WORKING COPY IF A NON-ROUTER
STOR T1,AJRTV,(P1) ;STORE THE ADDRESS OF THE ROUTING VECTOR
STOR T1,AJRVC,(P1) ;STASH COPY AWAY TOO
MOVE T2,RTRMXN ;GET THE MAXIMUM NUMBER OF NODES
ADD T2,T1 ;FOR END OF SMEAR
MOVX T3,RNCHG!RNHOP!RNCST ;GET INFH AND INFC AND CHANGE FLAG
CALL DNSWDS ;SMEAR THE VECTOR
RTRMA1: STOR RC,AJCBP,(P1) ;SAVE THE ADDRESS OF HIS CIRCUIT BLOCK
MOVX T2,ADJ.IN ;THIS IS INITIALIZING
STOR T2,AJSTA,(P1) ;SAVE IT
MOVX T2,%RTTM4 ;GET THE DEFAULT LISTENER TIME-OUT VALUE
STOR T2,AJNHT,(P1) ;STORE IT IN THE ADJACENCY BLOCK
MOVE T1,RTRVER ;SET ADJACENCY VERSION INFO
STOR T1,AJVER,(P1) ;...
MOVE T1,RTRECO ;...
STOR T1,AJECO,(P1) ;...
MOVE T1,RTRCUS ;...
STOR T1,AJCUS,(P1) ;...
ENDQUE P1,<RC.AJQ(RC)>,AJ.NXT,T1 ;Add adjacency to the queue
MOVE T1,P1 ;GET THE ADDRESS OF THE ADJACENCY BLOCK IN T1
RETSKP ;RETURN SUCCESS
SUBTTL Miscellaneous Routines -- RTRMCB - Make a Circuit Block
;RTRMCB - Make a new circuit block and store the defaults
;
; Call:
; T1/ Line id
;
; Return:
; RET ;COULDN'T ALLOCATE BLOCK
; RETSKP ;EVERYTHING WORKED, T1 CONTAINING CIRCUIT BLOCK
; ; POINTER
; Uses: T1-T4
RTRMCB: SAVEAC P1 ;SAVE A PEA
MOVE P1,T1 ;SAVE THE LINE ID
MOVX T1,RC.LEN ;GET THE LENGTH OF A CIRCUIT BLOCK
CALL DNGWDZ ;GET THAT MANY WORDS
RET ;RETURN A FAILURE
STOR P1,RCLID,(T1) ;STORE THE LINE ID
LOAD T2,LIDEV,+RC.LID(T1) ;GET THE TYPE OF DEVICE
CAIE T2,LD.ETH ;Is it for the ethernet?
JRST RTRMC1 ;No, must something else
SETONE RCBCT,(T1) ;Mark as broadcast
MOVEI T3,%RTMXR ; Set default maximum number of routers
STOR T3,RCMXR,(T1) ; for this circuit
RTRMC1: MOVE T2,KONCST(T2) ;GET DEFAULT COST FOR THIS TYPE OF LINE
STOR T2,RCCST,(T1) ;STORE IT IN THE CIRCUIT BLOCK
MOVX T2,RCS.OF ;INITIAL STATE WILL BE "OFF"
STOR T2,RCSTA,(T1) ;STORE STATE CODE
MOVE T2,RTRBSZ ; Start with our block size as the minimum
STOR T2,RCBSZ,(T1)
MOVX T2,%RTTM3 ;GET THE DEFAULT HELLO MESSAGE TIMER VALUE
STOR T2,RCTM3,(T1) ;STORE IT IN THE CIRCUIT BLOCK
MOVE P1,T1 ;SAVE THE CIRCUIT BLOCK POINTER
AOS RTRNLN ;INCREMENT THE NUMBER OF CIRCUITS
CALL DNGTIM ;GET CURRENT TIME OF DAY
STOR T1,RCSLZ,(P1) ;STORE FOR USE BY SECONDS SINCE LAST ZEROED
MOVE T1,P1 ;RETURN THE CIRCUIT BLOCK POINTER IN T1
RETSKP ;RETURN SUCCESS
SUBTTL Miscellaneous Routines -- RTRGCB - Get Circuit Block Pointer
;RTRGCB - Get circuit block pointer from line id
;
; Call:
; T1/ Line id
;
; Return:
; RET ;WHEN WE COULDN'T FIND A MATCH
; RETSKP ;WHEN SUCCESSFUL, WITH RC POINTING TO THE
; ; CIRCUIT BLOCK
;
; Uses: T1,T2
;
;There aren't that many circuits, so a simple search is not too bad.
RTRGCB: SKIPN RC,RTRCBQ ;START LOOKING AT FIRST CIRCUIT
RET ;NONE THERE, JUST RETURN
RTRGC1: LOAD T2,RCLID,(RC) ;GET IT'S LINE ID
CAMN T1,T2 ;IS IT THE ONE WE'RE LOOKING FOR?
RETSKP ;GOOD RETURN (I SKIP OVER RETSKPS
; IF YOU DON'T LIKE THAT CHANGE IT)
LOAD RC,RCNXT,(RC) ;GET THE NEXT CIRCUIT BLOCK
JUMPN RC,RTRGC1 ;GO CHECK IT OUT
RET ;COULDN'T FIND IT, OH WELL
;RTRGAJ - Find the adjacency associated with a given node
;
; Call:
; T1/ 16 bit node number
; RC/ Circuit owning adjacency
;
; Return:
; RET ; Node is not in our area
; RETSKP ; Success with AJ pointing to adjacency
; ; block, or 0 if no such adjacency
;
; Uses: T1,T2,AJ
RTRGAJ: LDB T2,[POINTR(T1,RN%ARE)] ;Get the area number
CAME T2,RTRHOM ;Is it the same as mine?
RET ; No, can't be an adjacency
LDB T1,[POINTR(T1,RN%NOD)] ;GET JUST THE NODE NUMBER
OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Get first adjacency
RTRGJ2: LOAD AJ,AJNXT,(AJ) ;Ckeck next adjacency if any
JUMPE AJ,RSKP ;No more, try next circuit block
LOAD T2,AJNAN,(AJ) ;Get the node address of this adjacency
CAME T1,T2 ;Do we have a match?
JRST RTRGJ2 ; Nope. Try again
RETSKP ;Yes, give good return
; This routine will check the adjacency pointed to by AJ to determine if it is
; a known two-way adjacency.
CK2WAY: JUMPE AJ,RTN ;Give non-skip if no such adjacency
LOAD T1,AJSTA,(AJ) ;Get the state
CAXE T1,ADJ.UP ;Is this a known two-way?
RET ; Nope
RETSKP ;Yes.
; SUBTTL Miscellaneous Routines -- CVTSTN
;Convert low order of Ethernet address to 16 bit format
;Call:
; T2/ Low order (16 bits) of Ethernet address left justified in
; string format
;
;Ret:
; T1/ 16 bit address
; T2/ 16 Bit address
CVTSTN: SETZ T1, ; Address we want is in T2 left justified
LSHC T1,^D8 ; in string format. Shift nn-2 into T1
LSH T2,-^D20 ; Right justify the area+2
IORB T1,T2 ; and include the number
RET
SUBTTL Miscellaneous Routines -- CPYMSG - Copy all MSDs together
;CPYMSG - Gather all the MSDs into one (IN.MSD) in a new message block
;
; Call:
; MB/ Pointer to message block to make a copy of
;
; Return:
; RET ;ON FAILURE
; RETSKP ;DONE, WITH T1 POINTING TO THE NEW MESSAGE
;
; Uses: T1-T4
;
;Only the portions of the message block which are relavent to Router
;are copied, because the copied message will be sent to NSP, which
;believes that the message has come in over the network.
CPYMSG: CALL DNCPMS ;COPY MB'S MSDs INTO A NEW BLOCK
RET ;PROPOGATE ERROR
;T1 POINTS TO NEW MSG BLK
;Now copy all the relavent fields.
LOAD T2,RMFST,(MB) ;GET THE FIRST BYTE
STOR T2,RMFST,(T1) ; AND COPY IT
LOAD T2,MBLCL,(MB) ;GET THE COPY OF THE LOCAL BIT
STOR T2,MBLCL,(T1) ; AND COPY IT
LOAD T2,RMOAP,(MB) ;GET THE OUTPUT ADJACENCY POINTER
STOR T2,RMOAP,(T1) ; AND COPY IT
LOAD T2,RMIAP,(MB) ;GET THE INPUT ADJACENCY POINTER
STOR T2,RMIAP,(T1) ; AND COPY IT
LOAD T2,RMICP,(MB) ;GET THE INPUT CIRCUIT
STOR T2,RMICP,(T1) ; AND COPY IT (MONOTONOUS, ISN'T IT)
LOAD T2,MBSRC,(MB) ;GET SOURCE NODE ADDRESS
STOR T2,MBSRC,(T1) ; AND COPY IT INTO THE NEW COPY
LOAD T2,MBDST,(MB) ;GET THE DESTINATION NODE ADDRESS
STOR T2,MBDST,(T1) ; AND COPY IT INTO THE NEW COPY
RETSKP ;RETURN SUCCESS, T1 PTS TO NEW MSG BLK
SUBTTL Miscellaneous Routine -- RTRGBS - Get maximum blocksize
;RTRGBS - Called by SCLINK to get the maximum blocksize supported
; between this node and the requested node.
;Call:
; T1/ Node address (16 bit format)
;Return:
; T1/ Blocksize to use
INTERN RTRGBS
XRESCD
RTRGBS: LDB T2,[POINTR(T1,RN%ARE)] ; Extract the area number
TXZ T1,RN%ARE ; Clear the area number
CAMN T1,RTRADR ; Local connection?
CAME T2,RTRHOM ; ...
IFSKP.
LOAD T1,IBBSZ,+IBBLK ; Yes, use requested blocksize
RET
ENDIF.
SKIPN ENFLG ; Endnode?
IFSKP.
MOVE T1,RTRBSZ ; Then supply default
SKIPE T3,RTRCBQ ; unless the only circuit
LOAD T1,RCRBS,(T3) ; is initialized
RET
ENDIF.
CAME T2,RTRHOM ; Is it in our area?
IFSKP.
MOVE T2,T1 ; Yes, get the number
ADD T2,RTRNRV ; Add in the offset to routing vector
TMNN RNRCH,(T2) ; Is it reachable?
IFSKP.
ADD T2,RTROFS ; Yes, index into the output adjacency vector
MOVE T2,(T2) ; Get adjacency
OPSTR <CAME T1,>,AJNAN,(T2) ; Is it our adjacency?
IFSKP.
LOAD T1,AJBSZ,(T2); Yes, use its blocksize
OPSTR <CAMLE T1,>,IBBSZ,+IBBLK ; If it exceeds our capabilities
LOAD T1,IBBSZ,+IBBLK ; return only what we can
RET
ENDIF.
ENDIF.
ENDIF.
MOVE T1,RTRBSZ ; No, use default
RET
SUBTTL Miscellaneous Routines -- RTRCBS - Get useable blocksize
;Call:
; T1/ Node address
; T2/ Suggested blocksize
;Return:
; T1/ Blocksize we believe will work
INTERN RTRCBS
XRESCD
RTRCBS: STKVAR <NODADR,BSZ>
MOVEM T1,NODADR ; Save address
MOVEM T2,BSZ ; Save suggested blocksize
SKIPN ENFLG ; Endnode?
IFSKP.
TXZ T1,RN%ARE ; Yes, remove area number
ADD T1,RTRNRV ; Add address of cache vector
TMNN RNCCH,(T1) ; See if in cache
IFSKP.
MOVE T1,NODADR ; In cache, get address
CALL RTRGBS ; (T1) Get maximum we can handle
ELSE.
MOVE T1,RTRBSZ ; Not in cache, use default block size
ENDIF.
ELSE. ; This is a routing node, so
CALL RTRGBS ; (T1) see what segsize we can use
ENDIF.
CAMLE T1,BSZ ; Was what we were given too large?
MOVE T1,BSZ ; No, OK to use what we were given
RET
ENDSV.
SUBTTL Miscellaneous Routines -- FREMSG - Toss a Message
;FREMSG - Return an unwanted message to rightful sink
;
; Call:
; MB/ Pointing to Message Block
;
; Return:
; RET ;ALWAYS
;
; Uses: T1-T4
FREMSG: SKIPN T1,MB ;GET POINTER TO MESSAGE BLOCK
BUG.(CHK,ROUZXT,ROUTER,SOFT,<Tried to free msg with MB=0>,,<
Cause: FREMSG called to free an MB but was given a zero pointer.
Action: Check caller and see why no MB address was supplied.
>,RTN)
TMNE RMODN,(MB) ;DOES NSP WANT THIS BACK?
CALLRET R2NODN ;YES, GO GIVE "OUTPUT DONE"
;NO, GIVE MSG TO MEMORY MANAGER
TRASH MB, ;JUST CAREFUL
CALLRET DNFMSG ;FREE MESSAGE T1 POINTS TO
SUBTTL Miscellaneous Routines -- SETRCx - Set Recompute Routing Flags
;SETRCX - Set recompute routing flags for all nodes
;
; Call:
; CALL SETRCX
;
; Return:
; RET always
SETRCX: SAVEAC <P1> ;Save P1
MOVN P1,RTRMXN ;Get negative node count
HRLZS P1 ;Make into AOBJN pointer
SETRX1: MOVEI T1,(P1) ;Get node number
CALL SETRCF ;Set recompute routing flag
AOBJN P1,SETRX1 ;Loop back for all nodes
RET ;And return
;SETRCC - Set recompute routing flags for entire circuit
;
; Call:
; RC/ Address of circuit block
;
; Return:
; RET always
SETRCC: SAVEAC <AJ> ;Save AJ
OPSTR <SKIPA AJ,>,RCAJQ,(RC) ;Get address of first adjacency block
SETRC1: LOAD AJ,AJNXT,(AJ) ;Get address of next adjacency block
JUMPE AJ,RTN ;Return at end of adjacency list
CALL SETRCA ;Set recompute flags for this adjacency
JRST SETRC1 ;Loop back for all adjacencies
;SETRCA - Set recompute routing flags for an adjacency
;
; Call:
; AJ/ Address of adjacency block
;
; Return:
; RET always
SETRCA: LOAD T1,AJNAN,(AJ) ;Get node number of adjacent node
CALL SETRCF ;Set recompute flags for this node
OPSTR <SKIPN>,AJRTV,(AJ) ;Does adjacency have a routing vector?
RET ;No, return now
SETZ T3, ;Starting with node zero
MOVE T4,RTRNRV ;...
ADD T4,RTROFS ;Offset to output adjacency vector
SETRA1: CAMLE T3,RTRMXN ;Finished all nodes?
RET ;Yes, return now
MOVE T1,T3 ;Get current node number
CAMN AJ,(T4) ;Was this adjacency the route for this node?
CALL SETRCF ;Yes, set recompute routing flag for this node
ADDI T4,1 ;Update address of routing vector
AOJA T3,SETRA1 ;Update node address and loop for all nodes
;SETRCF - Set recompute routing flag for a node
;
; Call:
; T1/ Node address
;
; Return:
; RET always
;
;Routine must preserve T3 and T4
SETRCF: ANDX T1,RN%NOD ;Isolate node number
IDIVI T1,^D36 ;Compute bitmap entry
ADD T1,RTRNVB ;Offset into bitmap
MOVE T2,BITS(T2) ;Get bit to set
IORM T2,(T1) ;Set bit
SETOM RTRRCF ;Set recompute routing flag
RET ;And return
SUBTTL Miscellaneous Routines -- CKSNRM - Normalize Checksum
;CKSNRM - Make full word checksum into 16 bit checksum
;
; Call:
; T1/ Full word checksum
;
; Return:
; RET ;WITH T1 CONTAINING THE 16 BIT CHECKSUM
;
; Uses: T1-T2
CKSNRM: MOVE T2,T1 ;GET A COPY OF THE CHECKSUM
TDZE T2,[EXP ^-177777] ;IF ANY OVERFLOW, CLEAR IT
JRST [LSH T1,-^D16 ;ADD OVERFLOW BACK INTO
ADDB T2,T1 ; THE LOW ORDER BYTES
JRST .-1] ;LOOP UNTIL DONE
RET ;RETURN
;Here to get the uptime in jiffies for the message looper
;This is a separate routine so we don't have switch to section 1
;in so many places.
IFN FTRTST,<
TSTTIM: TORESCD
CALL UPDTCK ; Must be executed in section 1
TOXRESCD
RET
>
SUBTTL Local Router Storage
RESDT ;IMPURE STORAGE
CHKVAL: EXP ^D60 ;CHECKSUM RECOMPUTATION COUNTER VALUE
CHKCNT: EXP 0 ;CHECKSUM RECOMPUTATION COUNTER
IFN FTOPS20,< ;TOPS20 CALLS RTRSEC 10 TIMES A SECOND
SECCNT: EXP 0 ;COUNT-DOWN 100 MS CALLS AT RTRSEC
> ;END IFN FTOPS20
CCHTIM: EXP 0 ;INTERVAL COUNTER FOR CACHE FLUSHING (ENDNODE)
RTRCTO: %RTCTO ;Time we can spend in cache till flushed
RTRNTY: BLOCK 1 ;NODE TYPE FOR LOCAL NODE
ENFLG: EXP 0 ;Endnode (non-routing) flag
IFN FTOPS10,<
INTERNAL RTRNRV,RTROFS,RTRCBQ
>; END IFN FTOPS10
RTRNVB: BLOCK 1 ;"NORMAL" ROUTING VECTOR BITMAP
RTRNRV: BLOCK 1 ;"NORMAL" ROUTING VECTOR
RTRNOV: BLOCK 1 ;"NORMAL" OUTPUT-CIRCUIT VECTOR
RTROFS: BLOCK 1 ;OFFSET FROM NRV TO NOV
RTNBRA: %RTBRA ;MAXIMUM NUMBER OF BROADCAST ROUTER ADJACENCIES
RTNBEA: %RTBEA ;MAXIMUM NUMBER OF BROADCAST ENDNODE ADJACENCIES
RTRPRI: %RTPRI ;Our priority to be the designated router
RTRMCN: ^D20 ;Maximum number of circuits (default)
RTRCBQ: BLOCK QH.LEN ;CIRCUIT BLOCK QUEUE HEADER
AJOFLQ: 0 ;Queue of offline adjacencies to be freed
; after routing update
RTRNLN: BLOCK 1 ;Number of circuits in use
RTRMXC: %RTMXC ;Maximum circuit cost
RTRMXH: %RTMXH ;Maximum hops
RTRMXV: %RTMXV ;Maximum visits
RTRBRA: 0 ;Number of broadcast router adjacencies
RTRBEA: 0 ;Number of broadcast endnode adjacencies
RTRRCF: 0 ;RECOMPUTE ROUTING FLAG
RTRVRQ: 0 ;VERIFICATION REQUIRED FLAG
RTRNAD: BLOCK 1 ;Our address in 16 bit format
RTRCKS: BLOCK 1 ;CHECKSUM OF ROUTING MESSAGE
RTRLMG: BLOCK 1 ; OFFSET TO LAST ROUTING MESSAGE SENT
;TO ALLOW US TO SEND OUT THE SEGMENTS
;IN A DIFFERENT ORDER EACH TIME
RTRTYP: EXP 4 ;OUR TYPE OF NODE IS ROUTING.
RTRTM1: %RTTM1 ;ROUTING MESSAGE TIMER (P-P)
RTRBT1: %RTBT1 ;ROUTING MESSAGE TIMER (BROADCAST)
RTRTM2: DEC 1000 ;Minimum time between routing updates, and
; Ethernet hello messages.
RTRITM: %RTITM ;MAX TIME ALLOWED FROM PROTOCOL UP AND TI RCVD
RTRCRT: EXP <^D5*^D1000> ;Circuit re-open timer value
BMVTIM: BLOCK 1 ;Time of next maybe vector update
BMVIVL: DEC 15000 ;Interval between maybe vector updates
RTRALR: EXP %RTRMA,0 ;ID ALL-ROUTERS
RTRAEN: EXP %RTEMA,0 ;ID ALL END-NODES
RTRPRO::EXP 60003 ;PROTOCOL-TYPE FOR ALL ROUTERS
RTRRSQ: BLOCK QH.LEN ;RESEND QUEUE HEADER
IFN FTOPS20,<
;RTRLOK: EXP -1 ;THE ROUTER "INTERLOCK"
;RTRLKO: EXP -1 ;INTERLOCK OWNER
>
;RTRSSV: BLOCK 1 ;ONCE-A-SEC SERVICE NEEDED FLAG
MFEWHO: BLOCK 1 ; PC of routine detecting message format error
MFEMSG: BLOCK 1 ; MB containing bogus message
HIADDR: BLOCK 1 ; Argument for P.R.U.L. event
RTREVW: BLOCK 1 ;EVENT WORD (PLACE TO KEEP REASON, NODE, ETC.)
RTRECP: EXP 0 ;Event communication pointer
ECLASS: EXP 0 ;Event class
;NODE COUNTERS:
RTRCAP: BLOCK 1 ; (900) AGED PACKET LOSS
RTRCNU: BLOCK 1 ; (901) NODE UNREACHABLE PACKET LOSS
RTRCNO: BLOCK 1 ; (902) NODE OUT-OF-RANGE PACKET LOSS
RTRCOP: BLOCK 1 ; (903) OVERSIZED PACKET LOSS
RTRCPF: BLOCK 1 ; (910) PACKET FORMAT ERROR
RTRCPR: BLOCK 1 ; (920) PARTIAL ROUTING UPDATE LOSS
RTRCVR: BLOCK 1 ; (930) VERIFICATION REJECT
IFN FTRTST,<
TSTFLG: Z
TSTBLK::BLOCK TR.LEN
>
XRESCD ;BACK TO THE PURE SEGMENT
SUBTTL End of ROUTER
IFN FTOPS10, .XCMSY ;.XCREF SOME MACSYM SYMBOLS
IFN FTOPS20, TNXEND ;TOPS-20 ENDING
IFN FTOPS10,<
RESDT
RTRLOW::!
XRESCD
>; END IFN FTOPS10
END