mirror of
https://github.com/PDP-10/stacken.git
synced 2026-02-28 17:09:15 +00:00
6223 lines
210 KiB
Plaintext
6223 lines
210 KiB
Plaintext
;TITLE ROUTER - Routing Layer Service for DECnet-36 V105
|
||
|
||
|
||
;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.
|
||
;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 29-DEC-87
|
||
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,105
|
||
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,1988>
|
||
>;END OF IFN FTOPS10
|
||
D36SYM ;SET UP D36 SPECIFIC PARAMETERS
|
||
|
||
IFN FTOPS10,<$RELOC>
|
||
XRESCD ;RELOC TO HIGHSEG (RSCOD PSECT ON TOPS-20)
|
||
SUBTTL Table of Contents
|
||
|
||
; Table of Contents for ROUTER
|
||
;
|
||
;
|
||
; Section Page
|
||
; 1. V. Brownell & Anthony J. Rizzolo/Tarl/AJR/HMP 15 Jan 85 3
|
||
; 2. Table of Contents. . . . . . . . . . . . . . . . . . . 4
|
||
; 3. Definitions
|
||
; 3.1. External References . . . . . . . . . . . . . 5
|
||
; 3.2. Accumulators. . . . . . . . . . . . . . . . . 7
|
||
; 3.3. Macros. . . . . . . . . . . . . . . . . . . . 8
|
||
; 3.4. Packet Route Header . . . . . . . . . . . . . 9
|
||
; 3.5. Router Control Message. . . . . . . . . . . . 10
|
||
; 3.6. Routing Vectors . . . . . . . . . . . . . . . 11
|
||
; 3.7. NI Hello IINFO format . . . . . . . . . . . . 12
|
||
; 3.8. Miscellaneous . . . . . . . . . . . . . . . . 13
|
||
; 4. Network management tables. . . . . . . . . . . . . . . 14
|
||
; 4.1. Executor counters . . . . . . . . . . . . . . 14
|
||
; 4.2. Circuit counters. . . . . . . . . . . . . . . 15
|
||
; 4.3. Node parameters . . . . . . . . . . . . . . . 16
|
||
; 4.4. Executor parameters . . . . . . . . . . . . . 17
|
||
; 4.5. Circuit parameters. . . . . . . . . . . . . . 18
|
||
; 5. RTRINI - Initialize Router User. . . . . . . . . . . . 19
|
||
; 6. RTRON - Turn Router (and DECnet) On. . . . . . . . . . 20
|
||
; 7. RTROFF - Turn Router (and DECnet) Off. . . . . . . . . 21
|
||
; 8. RTRSEC - Once a second processing for Router . . . . . 22
|
||
; 9. RTRJIF - Once a jiffy processing for Router. . . . . . 23
|
||
; 10. RTRLCK - Get the RTR interlock . . . . . . . . . . . . 25
|
||
; 11. RTRXMT - NSP's entry into Router . . . . . . . . . . . 27
|
||
; 12. RTRFWD - Perform Routing of Message. . . . . . . . . . 28
|
||
; 13. RTR2RM - Send Message to Remote Node . . . . . . . . . 34
|
||
; 14. RTRBEH - Build header for ethernet data messages . . . 37
|
||
; 15. R2NODN - Return Output Done to NSP . . . . . . . . . . 38
|
||
; 16. R2NRTN - Return Message to NSP . . . . . . . . . . . . 39
|
||
; 17. R2NRCV - Pass received Message to NSP. . . . . . . . . 40
|
||
; 18. R2KINI - Initialize a Kontroller's Circuit . . . . . . 41
|
||
; 19. R2KCLS - Close the data link circuit . . . . . . . . . 42
|
||
; 20. CALKON - Call the Kontroller . . . . . . . . . . . . . 43
|
||
; 21. CALQOB - Call CALKON for queued output.. . . . . . . . 44
|
||
; 22. XMTFAI/CIRFAI - Transmit/Line failed . . . . . . . . . 45
|
||
; 23. RTRRCR - Recompute Routing . . . . . . . . . . . . . . 46
|
||
; 24. RTRBSV - Build scratch routing vector. . . . . . . . . 47
|
||
; 25. RTRBNV - Build the normal vector from scratch vector . 48
|
||
; 26. RTRBMV - Maybe vector update when running as an endnode 49
|
||
; 27. RTRUPD - Send routing messages if needed . . . . . . . 50
|
||
; 28. RTRSNI - Send hello/routing message on the NI. . . . . 57
|
||
; 29. CKECTO - Check the cache timer for each node . . . . . 58
|
||
; 30. SELDSR - Select a desiginated router . . . . . . . . . 59
|
||
; 31. RTRTMR - Routine to perform timer functions. . . . . . 60
|
||
; 32. RTRENH - Send Ethernet end-node hello. . . . . . . . . 67
|
||
; 33. RTRCHH - Build common part of Ethernet hellos. . . . . 68
|
||
; 34. DSRCHK - Check the DSR timer for each circuit. . . . . 69
|
||
; 35. Data Link Layer Interface. . . . . . . . . . . . . . . 70
|
||
; 35.1. RTRDLE - Entry into Router from DLL . . . . . 70
|
||
; 35.2. RTICCB - Create circuit block . . . . . . . . 72
|
||
; 35.3. RTILSC - Process line state change. . . . . . 73
|
||
; 35.4. RTIOTC - Process Output Complete. . . . . . . 74
|
||
; 35.5. RTIINC - Process Input Complete . . . . . . . 75
|
||
; 36. RTRSTI - Send routing intitialization message. . . . . 78
|
||
; 37. Control Message Processors
|
||
; 37.1. RTCINI - Inititialization Messages. . . . . . 80
|
||
; 37.2. RTCVER - Verification Messages. . . . . . . . 82
|
||
; 37.3. RTCRTE - Routing Messages . . . . . . . . . . 83
|
||
; 37.4. RTCTST - Test or Hello Messages . . . . . . . 85
|
||
; 37.5. RTCL2M - Level 2 Routing Messages . . . . . . 86
|
||
; 37.6. RTCERH - Ethernet Router Hello. . . . . . . . 87
|
||
; 37.7. RHMASR - Hello message if Endnode . . . . . . 88
|
||
; 37.8. RHMASR - Hello message if Router. . . . . . . 89
|
||
; 37.9. RTCNIE - NI Endnode Hello message . . . . . . 91
|
||
; 38. RTCILL - Illegal message received. . . . . . . . . . . 92
|
||
; 39. RTRBAV - Build adjacency's routing vector from routing update 93
|
||
; 40. RTCRME - Routing message error processor . . . . . . . 96
|
||
; 41. RTRPNI - Parse a Message Header for NI Hello messages 97
|
||
; 42. PSINFO - Parse the info field of Ethernet router hello 98
|
||
; 43. RTRRCV - Read version information from message . . . . 99
|
||
; 44. RTRHDP - Parse a Input Router Message Header . . . . . 100
|
||
; 45. RTRCTD - Check for valid test pattern in Hello/Test message 103
|
||
; 46. RTRGNA - Get node address from message header. . . . . 104
|
||
; 47. PADSKP - Skip over pad bytes in an Ethernet message header 105
|
||
; 48. Network Management
|
||
; 48.1. RTRNMX - Entry into Router. . . . . . . . . . 106
|
||
; 48.2. Read/Set/Clear a parameter. . . . . . . . . . 107
|
||
; 49. Network management
|
||
; 49.1. Common routine for parameters . . . . . . . . 108
|
||
; 49.2. Setup for loading parameter data. . . . . . . 109
|
||
; 50. Network Management
|
||
; 50.1. Qualified parameters. . . . . . . . . . . . . 110
|
||
; 50.2. READ node/executor state. . . . . . . . . . . 111
|
||
; 50.3. Read circuit state. . . . . . . . . . . . . . 112
|
||
; 50.4. Set/Clear executor state. . . . . . . . . . . 113
|
||
; 50.5. Set/Clear circuit state . . . . . . . . . . . 114
|
||
; 50.6. Show counters . . . . . . . . . . . . . . . . 115
|
||
; 50.7. Show and zero counters. . . . . . . . . . . . 115
|
||
; 50.8. Return list . . . . . . . . . . . . . . . . . 116
|
||
; 50.9. Show known/active nodes . . . . . . . . . . . 117
|
||
; 50.10. Show adjacent nodes . . . . . . . . . . . . . 118
|
||
; 50.11. Show active circuits. . . . . . . . . . . . . 119
|
||
; 50.12. Show known circuits . . . . . . . . . . . . . 120
|
||
; 50.13. Return list of adjacencies on a circuit . . . 121
|
||
; 51. Network Management Event Interface
|
||
; 51.1. Router Event Types. . . . . . . . . . . . . . 122
|
||
; 51.2. Event Reason Definitions. . . . . . . . . . . 124
|
||
; 51.3. RTNEVT - Event Reporter . . . . . . . . . . . 125
|
||
; 51.4. Event Parameter Processors. . . . . . . . . . 126
|
||
; 51.5. Event Processor Subroutines . . . . . . . . . 129
|
||
; 51.6. Miscellaneous Event Processors. . . . . . . . 130
|
||
; 52. Miscellaneous Routines
|
||
; 52.1. RTRSAO - Set Adjacency off line . . . . . . . 132
|
||
; 52.2. RTRZCB - Zap Circuit Block. . . . . . . . . . 133
|
||
; 52.3. RTRZAA - Zap all Adjacancies associated with RC 134
|
||
; 53. RTRZAB - Zap an adjacency block. . . . . . . . . . . . 135
|
||
; 54. Miscellaneous Routines
|
||
; 54.1. RTRMAJ - Make an Adjacency Block. . . . . . . 136
|
||
; 54.2. RTRMCB - Make a Circuit Block . . . . . . . . 137
|
||
; 54.3. RTRGCB - Get Circuit Block Pointer. . . . . . 138
|
||
; 54.4. CPYMSG - Copy all MSDs together . . . . . . . 141
|
||
; 55. Miscellaneous Routine
|
||
; 55.1. RTRGBS - Get maximum blocksize. . . . . . . . 142
|
||
; 56. Miscellaneous Routines
|
||
; 56.1. RTRCBS - Get useable blocksize. . . . . . . . 143
|
||
; 56.2. FREMSG - Toss a Message . . . . . . . . . . . 144
|
||
; 56.3. CKSNRM - Normalize Checksum . . . . . . . . . 145
|
||
; 57. Local Router Storage . . . . . . . . . . . . . . . . . 146
|
||
; 58. End of ROUTER. . . . . . . . . . . . . . . . . . . . . 147
|
||
|
||
SUBTTL Definitions -- External References
|
||
|
||
;These are the external references to the D36COM library of routines.
|
||
|
||
EXT DNGINI ;INITIALIZE FOR INPUT (DGXYBY)
|
||
EXT DNPINI ;INITIALIZE FOR OUTPUT (DPXYBY)
|
||
|
||
EXT DNP1BY ;PUT ONE BYTE IN MESSAGE
|
||
EXT DNP2BY ;PUT TWO BYTES IN MESSAGE
|
||
EXT DNPHIO ;Put 4 bytes of ethernet address into message
|
||
EXT DNPENA ;DEPOSIT 6 BYTES FOR NI ADDRESSES
|
||
EXT DNPEBY ;PUT AN EXTENSIBLE BYTE IN MESSAGE
|
||
EXT DNPZB ;Write (T1) bytes of zeros into the message
|
||
|
||
EXT DNG1BY ;GET ONE BYTE FROM MESSAGE
|
||
EXT DNG2BY ;GET TWO BYTES FROM MESSAGE
|
||
EXT DNGHIO ;Get four bytes of hi-order ethernet address
|
||
EXT DNGENA ;GET SIX BYTES FROM MESSAGE
|
||
EXT DNGEBY ;GET EXTENSIBLE BYTE FROM MESSAGE
|
||
|
||
EXT DNGMSG ;GET DECNET-36 MESSAGE BLOCK
|
||
EXT DNFMSG ;FREE MESSAGE BLOCK
|
||
EXT DNMINI ;RE-USE MESSAGE BLOCK
|
||
|
||
EXT DNNMSG ;GET NUMBER OF BUFFERS AVAILABLE TO ROUTER
|
||
|
||
EXT DNLENG ;GET THE MESSAGE LENGTH
|
||
EXT DNSLNG ;FIND THE SEGMENT LENGTH
|
||
|
||
EXT DNGWDS ;GET SOME WORDS
|
||
EXT DNGWDZ ;GET SOME ZEROED WORDS
|
||
EXT DNFWDS ;FREE SOME WORDS
|
||
EXT DNSWDS ;SMEAR SOME WORDS
|
||
|
||
EXT DNBKBY ;GO BACKWARDS SOME BYTES
|
||
EXT DNSKBY ;SKIP SOME BYTES
|
||
|
||
EXT DNRPOS ;RETURN POSTION IN MESSAGE
|
||
EXT DNGPOS ;GO TO POSITION IN MESSAGE
|
||
EXT DNGOPS ;GO TO POSITION IN OUTPUT MESSAGE
|
||
|
||
EXT DNLMSS ;LINK MESSAGE SEGMENT INTO MESSAGE BLOCK
|
||
EXT DNCPMS ;COPY MESSAGE BLOCKS
|
||
|
||
IFN FTRTST,<
|
||
EXT UPDTCK ; Better TODCLK
|
||
>
|
||
EXT DNGTIM ;RETURN CURRENT UPTIME (IN MS)
|
||
EXT NTPARM ; Routine to load parameters
|
||
EXT NTCTRS ; Routine to load counters
|
||
|
||
EXT TIMBAS ;Fractions of a second used for time
|
||
; computation
|
||
|
||
;References to DNADLL
|
||
|
||
EXT DNDDSP ;Entry into DNADLL
|
||
EXT DNDINI ;Initialization point for DNADLL
|
||
EXT DNDSEC ;DNADLL second routine
|
||
|
||
;These are external data locations.
|
||
|
||
EXT DCNSTA ;THE STATE VARIABLE OF DECNET
|
||
EXT DCNTSB ;Maximum system buffers
|
||
EXT RTRHOM ; Home area
|
||
EXT RTRADR ; Our node number
|
||
EXT RTRHIO ; High order Ethernet address
|
||
EXT RTRLOO ; Low order Ethernet address
|
||
EXT RTRBSZ ; Blocksize we advertise
|
||
EXT RTRMXN ; Maximum node address we talk to
|
||
EXT RTRMX3 ; Maximum number of Phase III nodes
|
||
EXT RTRVER ; Version of ROUTER
|
||
EXT RTRECO ; ECO level of ROUTER
|
||
EXT RTRCUS ; Customer version
|
||
EXT RTRXPW ; Our transmit password
|
||
|
||
EXT IBBLK ;DECnet-36 initialization block
|
||
|
||
;This is the reference to LLINKS.
|
||
|
||
EXT NSPRTR ;THE ONE AND ONLY
|
||
|
||
;We need to know our node name for Phase II NI messages.
|
||
|
||
EXT SCTA2N ;PERFORM TRANSLATION FROM ADDRESS TO NODE NAME
|
||
;These are some default parameters
|
||
|
||
EXT %RTMXN ;DEFAULT MAXIMUM NODE NUMBER
|
||
EXT %RTMXC ;DEFAULT MAXIMUM CIRCUIT COST
|
||
EXT %RTMXH ;DEFAULT MAXIMUM HOPS
|
||
EXT %RTMX3 ;MAXIMUM NUMBER OF PHASE III NODES
|
||
EXT %RTMXV ;MAXIMUM VISITS COUNT
|
||
IFN FTOPS10,EXT %RTADR ;DEFAULT LOCAL ADDRESS
|
||
EXT %RTRMA ;"ALL ROUTERS" MULTICAST ADDRESS
|
||
EXT %RTEMA ;"ALL ENDNODES" MULTICAST ADDRESS
|
||
EXT %RTHIO ;HI PART OF THE NI ADDRESS
|
||
EXT %RTHOM ;HOME AREA FOR THIS NODE
|
||
EXT %RTMXR ;Default maximum number of routers on the NI
|
||
EXT %RTBRA ;NUMBER OF BROADCAST ROUTER ADJACENCIES
|
||
EXT %RTBEA ;NUMBER OF BROADCAST ENDNODE ADJACENCIES
|
||
EXT %RTPRI ;Priority to be the designated router (NI)
|
||
EXT %RTTM1 ;LONG TIMER FOR POINT TO POINT
|
||
EXT %RTBT1 ;LONG TIMER FOR BROADCAST
|
||
EXT %RTTM3 ;DEFAULT HELLO MESSAGE TIMER
|
||
EXT %RTTM4 ;DEFAULT NODE LISTENER TIMEOUT VALUE
|
||
EXT %RTT3M ;HELLO TIMER MULTIPLIER FOR NON-BROADCAST
|
||
EXT %RTB3M ;HELLO TIMER MULTIPLIER FOR BROADCAST CIRCUITS
|
||
EXT %RTITM ;TI TIMER
|
||
EXT %RTCTO ;Time we can spend in cache without update
|
||
EXT %RTCST ;DEFAULT CIRCUIT COST
|
||
EXT %RTVER ;ROUTER VERSION NUMBER
|
||
EXT %RTECO ;EDIT LEVEL
|
||
EXT %RTCUS ;CUSTOMER EDIT LEVEL
|
||
|
||
;Other external references
|
||
|
||
EXT NMXEVT ;REPORT AN EVENT TO NMX
|
||
EXT NTEIPV ;TELL NETWORK MANAGEMENT THAT BAD VALUE
|
||
|
||
EXT KONCST ;TABLE OF DEFAULT COSTS PER KONTROLLER TYPE
|
||
|
||
EXT EVSDRP ;Whether as an endnode we listen to packets
|
||
; sent to multicast ID "all routers"
|
||
|
||
EXT RTN ;NON-SKIP RETURN
|
||
EXT RSKP ;SKIP RETURN
|
||
IFN FTOPS10,<
|
||
EXT BITTBL ;TABLE OF BITS
|
||
BITS==BITTBL
|
||
>; END IFN FTOPS10
|
||
|
||
|
||
;Interlock management
|
||
|
||
IFN FTOPS10,<
|
||
; EXT RTRLOK ;ROUTER INTERLOCK
|
||
; EXT RTRLKO ;INTERLOCK OWNER
|
||
EXT .CPCPN ;CURRENT CPU NUMBER
|
||
EXT .CPSK0 ;SKIP IF CURRENT CPU IS BOOT CPU
|
||
>
|
||
SUBTTL Definitions -- Accumulators
|
||
|
||
;These are some local AC defintions for Router-36.
|
||
|
||
RC=FREE1 ;RC USUALLY POINTS TO THE CIRCUIT BLOCK
|
||
AJ=FREE2 ;AJ USUALLY POINTS TO THE ADJACENCY ENTRY
|
||
|
||
PURGE FREE1 ;LOSE THIS SYMBOL
|
||
PURGE FREE2 ;LOSE THIS ONE TOO
|
||
|
||
IFN FTOPS10,<
|
||
Q1=T5 ;RE-DEFINE THESE AGAIN
|
||
Q2=T6 ;TO MATCH TOPS-20
|
||
>
|
||
|
||
SUBTTL Definitions -- Macros
|
||
|
||
;Event Logging Macro
|
||
|
||
DEFINE EVENT(TYPE,TEXT,MSGBLK),<
|
||
CALL [
|
||
IFN FTTRACE,<
|
||
ETRACE RTR,<RTR Event: 'TEXT>
|
||
>
|
||
MOVX T1,TYPE ;;PUT EVENT TYPE IN T1
|
||
IFNB <MSGBLK>,MOVE T4,'MSGBLK ;;IF HE GAVE MB POINTER, GIVE IT
|
||
IFB <MSGBLK>, SETZ T4, ;;IF NOT, GIVE RTNEVT A ZERO
|
||
CALLRET RTNEVT] ;;CALL THE EVENT PROCESSOR AND RETURN
|
||
>
|
||
|
||
REPEAT 0,<
|
||
DEFINE EVENT(TYPE,TEXT,MSGBLK),<
|
||
CALL RTNEVT
|
||
CAI [IFN FTTRACE,<ETRACE RTR,<RTR Event: 'TEXT>>
|
||
TYPE
|
||
MSGBLK]
|
||
>
|
||
>
|
||
SUBTTL Definitions -- Packet Route Header
|
||
|
||
;The first byte of the packet route header is defined in the Router
|
||
;section of the message block structure. This is purely for convience
|
||
;sake. The whole byte is called RMFST and each bit is defined within
|
||
;this field.
|
||
|
||
;The only other field that has to be defined (other than the source and
|
||
;destination address) is the FORWARD field which simply consists of the
|
||
;VISITS field.
|
||
|
||
BEGSTR FW ;FORWARD BYTE
|
||
FIELDM VST,77 ; VISITS COUNT
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Router Control Message
|
||
|
||
;The following are field definitions for the Router Control messages.
|
||
|
||
;Control message all begin with the field CTLFLG, which specifies the type
|
||
;of control message.
|
||
|
||
BEGSTR CM ;CTLFLG
|
||
FIELDM TYP,7_1 ; TYPE OF MESSAGE
|
||
FIELDM CTL,1
|
||
ENDSTR
|
||
|
||
;These are the various types of router control messages (in CMTYP).
|
||
|
||
XP RCM.TI,0 ;Router init
|
||
XP RCM.TV,1 ;Router verification
|
||
XP RCM.TT,2 ;Router hello and test
|
||
XP RCM.1R,3 ;Level 1 routing message
|
||
XP RCM.2R,4 ;Level 2 routing message
|
||
XP RCM.RH,5 ;Ethernet Router hello message
|
||
XP RCM.EH,6 ;Ethernet Endnode hello mesaage
|
||
|
||
;Routing control messages consist of a RTGINFO entry for every node in
|
||
;the network, followed by a two byte checksum.
|
||
|
||
BEGSTR RG ;RTGINFO
|
||
FIELDM HOP,37_^D10 ; HOPS
|
||
FIELDM CST,1777 ; COST
|
||
ENDSTR
|
||
|
||
|
||
;Transport Initialization control messages start with field TIINFO which
|
||
;contains the node type and verification required flags.
|
||
|
||
BEGSTR TI ;TIINFO
|
||
FIELDM RSV,36_3 ; RESERVED
|
||
FIELDM BLO,1_3 ;BLOCKING REQUESTED
|
||
FIELDM VER,1_2 ; VERIFY FLAG
|
||
FIELDM NTY,3 ; NODE TYPE
|
||
ENDSTR
|
||
|
||
XP TI.MXL,^D12 ;MAX LENGTH OF ROUTER INIT MSG
|
||
|
||
;These are the possible types of nodes that can be at the other end
|
||
;of a circuit (in FIELD TINTY).
|
||
|
||
XP ANT.XX,0 ;RESERVED
|
||
XP ANT.L2,1 ;LEVEL 2 ROUTER
|
||
XP ANT.L1,2 ;LEVEL 1 ROUTER
|
||
XP ANT.RT,2 ;ROUTING
|
||
XP ANT.NR,3 ;NON-ROUTING
|
||
|
||
|
||
;Router hello message has NO.HEL bytes of the byte HEL.LO.
|
||
|
||
XP NO.HEL,^D10 ;NUMBER OF TEST BYTES
|
||
XP NO.NIH,^D64 ;Number of test bytes in endnode hello
|
||
XP HEL.LO,^O252 ;CONSTANT FOR HELLO AND TEST MESSAGES
|
||
|
||
SUBTTL Definitions -- Routing Vectors
|
||
|
||
;These are the definitions for each entry in both the scratch and the
|
||
;normal routing vectors. The vectors consist of one entry for each
|
||
;possible node in the network. Non-existant (un-reachable) nodes are
|
||
;set to the maximum node cost and hops.
|
||
|
||
BEGSTR RN
|
||
FIELD FLG,6 ;Flags
|
||
BIT RCH ;If set, node is reachable
|
||
BIT LCL ;Node is local NSP user
|
||
BIT CHG ;Node status was changed
|
||
BIT CCH ;Node is in the on-ethernet cache
|
||
BIT MBY ;Node maybe reachable (if we are an endnode)
|
||
FILLER 15
|
||
FIELD HOP,5 ;MIN HOPS
|
||
FIELD CST,10 ;MIN COST
|
||
ENDSTR
|
||
|
||
;Define right justified symbols for max-cost and max-hops.
|
||
|
||
XP RN%CST,MASK.(WID(RNCST),^D35) ;MAX COST
|
||
XP RN%HOP,MASK.(WID(RNHOP),^D35) ;MAX HOPS
|
||
|
||
SUBTTL Definitions -- NI Hello IINFO format
|
||
|
||
BEGSTR II
|
||
FIELDM TYP,3 ;NODE TYPE
|
||
FIELDM VRQ,1_2 ;VERIFICATION REQUIRED (0 FOR NI)
|
||
FIELDM RJF,1_3 ;REJECT FLAG
|
||
FIELDM VFL,1_4 ;VERIFICATION FAILED
|
||
FIELDM MTA,1_5 ;NO MULTI-CAST ACCEPTED
|
||
FIELDM BRQ,1_6 ;BLOCKING REQUESTED FLAG
|
||
FIELDM RSV,1_7 ;RESERVED BIT
|
||
ENDSTR
|
||
|
||
;These are the values in the IITYP field
|
||
|
||
XP IIT.L2,1 ;LEVEL 2 ROUTER
|
||
XP IIT.L1,2 ;LEVEL 1 ROUTER
|
||
XP IIT.EN,3 ;ENDNODE
|
||
|
||
SUBTTL Definitions -- Miscellaneous
|
||
|
||
|
||
SUBTTL Network management tables
|
||
SUBTTL Network management tables -- Executor counters
|
||
|
||
;Generate the executor counter table
|
||
XSWAPCD
|
||
EXCTAB:
|
||
|
||
COUNTER(^D900,^D8,<MOVE T1,RTRCAP>,<SETZM RTRCAP>,,<Aged packet loss>)
|
||
COUNTER(^D901,^D16,<MOVE T1,RTRCNU>,<SETZM RTRCNU>,,<
|
||
Node unreachable packet loss>)
|
||
COUNTER(^D902,^D8,<MOVE T1,RTRCNO>,<SETZM RTRCNO>,,<
|
||
Node out-of-range packet loss>)
|
||
COUNTER(^D903,^D8,<MOVE T1,RTRCOP>,<SETZM RTRCOP>,,<Oversized packet loss>)
|
||
COUNTER(^D910,^D8,<MOVE T1,RTRCPF>,<SETZM RTRCPF>,,<Packet format error>)
|
||
COUNTER(^D920,^D8,<MOVE T1,RTRCPR>,<SETZM RTRCPR>,,<
|
||
Partial routing update loss>)
|
||
COUNTER(^D930,^D8,<MOVE T1,RTRCVR>,<SETZM RTRCVR>,,<Verification reject>)
|
||
|
||
EXCTBL==.-EXCTAB
|
||
|
||
SUBTTL Network management tables -- Circuit counters
|
||
|
||
CICTAB: ;Circuit counters maintained by the circuit
|
||
|
||
COUNTER (^D0,^D16,<CALL [SAVEAC <T2>
|
||
LOAD T2,RCSLZ,(RC) ; Time stamp of last zeroed
|
||
CALL DNGTIM ; Current time
|
||
SUB T1,T2 ; Compute milliseconds
|
||
IDIVI T1,TIMBAS ; and return as seconds
|
||
RET ]>,<
|
||
CALL [CALL DNGTIM
|
||
STOR T1,RCSLZ,(RC)
|
||
RET ]>,,<Seconds since zeroed>)
|
||
|
||
COUNTER(^D800,^D32,<LOAD T1,RCCAP,(RC)>,<SETZRO RCCAP,(RC)>,,<
|
||
Terminating packets received>)
|
||
COUNTER(^D801,^D32,<LOAD T1,RCCDP,(RC)>,<SETZRO RCCDP,(RC)>,,<
|
||
Originating packets sent>)
|
||
COUNTER(^D802,^D16,<LOAD T1,RCCAL,(RC)>,<SETZRO RCCAL,(RC)>,,<
|
||
Terminating congestion loss>)
|
||
COUNTER(^D810,^D32,<LOAD T1,RCCTR,(RC)>,<SETZRO RCCTR,(RC)>,,<
|
||
Transit packets received>)
|
||
COUNTER(^D811,^D32,<LOAD T1,RCCTS,(RC)>,<SETZRO RCCTS,(RC)>,,<
|
||
Transit packets sent>)
|
||
COUNTER(^D812,^D16,<LOAD T1,RCCTL,(RC)>,<SETZRO RCCTL,(RC)>,,<
|
||
Transit congestion loss>)
|
||
COUNTER(^D820,^D8,<LOAD T1,RCCCD,(RC)>,<SETZRO RCCCD,(RC)>,,<Circuit down>)
|
||
COUNTER(^D821,^D8,<LOAD T1,RCCIF,(RC)>,<SETZRO RCCIF,(RC)>,,<
|
||
Initialization failure>)
|
||
COUNTER (^D2500,^D16,<LOAD T1,RCBSX,(RC)>,<SETZRO RCBSX,(RC)>,,<
|
||
Transmit packets discarded-blocksize exceeded>)
|
||
|
||
CICTBL==.-CICTAB
|
||
|
||
SUBTTL Network management tables -- Node parameters
|
||
|
||
NOSET==PANST ;From BEGSTR in D36PAR
|
||
NOCLR==PANCL
|
||
BEX==PABEX ;Buffer expected
|
||
|
||
NDPTAB:
|
||
PARAMETER(0,<NOSET!NOCLR>,,,,,<CALL NMXRNS>,,<Node state>)
|
||
PARAMETER(^D810,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN AJ
|
||
RNMXND
|
||
LOAD T2,AJNTY,(AJ)
|
||
RNMXOK ]>,<TRN>,<
|
||
Adjacency type>)
|
||
PARAMETER(^D820,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN P2
|
||
RNMXND
|
||
LOAD T2,RNCST,(P2)
|
||
RNMXOK ]>,<TRN>,<Cost>)
|
||
PARAMETER(^D821,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN P2
|
||
RNMXND
|
||
LOAD T2,RNHOP,(P2)
|
||
RNMXOK ]>,<TRN>,<Hops>)
|
||
PARAMETER(^D822,<NOSET!NOCLR>,,,,<TRN>,<LOAD T2,RCLID,(RC)>,<TRN>,<Circuit>)
|
||
PARAMETER(^D830,<NOSET!NOCLR>,,,,<TRN>,< CALL [SKIPN AJ
|
||
RNMXND
|
||
MOVE T2,RTRNTY
|
||
CAIE T2,RNT.NR
|
||
IFSKP.
|
||
LOAD T2,NFEID,(P1)
|
||
MOVE T1,T2
|
||
LSH T1,-^D10
|
||
CAME T1,RTRHOM
|
||
IFSKP.
|
||
TXZ T2,RN%ARE
|
||
ADD T2,RTRNRV
|
||
TMNN RNCCH,(T2)
|
||
IFSKP.
|
||
LOAD T2,NFEID,(P1)
|
||
RNMXOK
|
||
ENDIF.
|
||
ENDIF.
|
||
ENDIF.
|
||
LOAD T2,AJADR,(AJ)
|
||
RNMXOK ]>,<TRN>,<
|
||
Next node>)
|
||
|
||
;Note: The following parmameter is used for the NODE JSYS function .NDGNT
|
||
; only. Is is NEVER used by NTMAN and is not part of the specified
|
||
; DECnet architecture.
|
||
|
||
PARAMETER(^D2503,<NOSET!NOCLR>,,,,,<CALL NMXRNS>,,<Node state-I DECnet only>)
|
||
|
||
NDPTBL==.-NDPTAB
|
||
|
||
SUBTTL Network management tables -- Executor parameters
|
||
|
||
EXPTAB:
|
||
|
||
PARAMETER(0,,,,<DS.ON>,<CALL NMXSES>,<CALL NMXRNS>,<CALL NMXSES>,<
|
||
Executor state>)
|
||
PARAMETER(^D900,<NOSET!NOCLR>,,,,,<CALL [ MOVE T1,RTRVER
|
||
STOR T1,VNVER,+T2
|
||
MOVE T1,RTRECO
|
||
STOR T1,VNECO,+T2
|
||
MOVE T1,RTRCUS
|
||
STOR T1,VNUCO,+T2
|
||
RNMXOK]>,<TRN>,<Routing version>)
|
||
PARAMETER(^D901,,,,<RNT.L1>,<TRN>,<MOVE T2,RTRNTY>,<TRN>,<Router type>)
|
||
PARAMETER(^D910,,^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 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
|
||
|
||
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
|
||
JUMPE P2,RTRMA1 ;DON'T MAKE ROUTING VECTOR FOR NON-ROUTING NODE
|
||
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
|
||
STOR T1,AJRTV,(P1) ;YES, STORE THE ADDRESS OF THE ROUTING VECTOR
|
||
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
|