;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, > MOVX T1,TYPE ;;PUT EVENT TYPE IN T1 IFNB ,MOVE T4,'MSGBLK ;;IF HE GAVE MB POINTER, GIVE IT IFB , 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,> 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,,,,) COUNTER(^D901,^D16,,,,< Node unreachable packet loss>) COUNTER(^D902,^D8,,,,< Node out-of-range packet loss>) COUNTER(^D903,^D8,,,,) COUNTER(^D910,^D8,,,,) COUNTER(^D920,^D8,,,,< Partial routing update loss>) COUNTER(^D930,^D8,,,,) EXCTBL==.-EXCTAB SUBTTL Network management tables -- Circuit counters CICTAB: ;Circuit counters maintained by the circuit COUNTER (^D0,^D16, 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 ]>,,) COUNTER(^D800,^D32,,,,< Terminating packets received>) COUNTER(^D801,^D32,,,,< Originating packets sent>) COUNTER(^D802,^D16,,,,< Terminating congestion loss>) COUNTER(^D810,^D32,,,,< Transit packets received>) COUNTER(^D811,^D32,,,,< Transit packets sent>) COUNTER(^D812,^D16,,,,< Transit congestion loss>) COUNTER(^D820,^D8,,,,) COUNTER(^D821,^D8,,,,< Initialization failure>) COUNTER (^D2500,^D16,,,,< 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,,,,,,,,) PARAMETER(^D810,,,,,,< CALL [SKIPN AJ RNMXND LOAD T2,AJNTY,(AJ) RNMXOK ]>,,< Adjacency type>) PARAMETER(^D820,,,,,,< CALL [SKIPN P2 RNMXND LOAD T2,RNCST,(P2) RNMXOK ]>,,) PARAMETER(^D821,,,,,,< CALL [SKIPN P2 RNMXND LOAD T2,RNHOP,(P2) RNMXOK ]>,,) PARAMETER(^D822,,,,,,,,) PARAMETER(^D830,,,,,,< 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 ]>,,< 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,,,,,,,,) NDPTBL==.-NDPTAB SUBTTL Network management tables -- Executor parameters EXPTAB: PARAMETER(0,,,,,,,,< Executor state>) PARAMETER(^D900,,,,,,,,) PARAMETER(^D901,,,,,,,,) PARAMETER(^D910,,^D65535*TIMBAS,,<%RTTM1>,,,,) PARAMETER(^D912,,^D65535*TIMBAS,,<%RTBT1>,,,,) PARAMETER(^D920,,,,,,,,) PARAMETER(^D921,,<^D20>,<^D1>,<^D20>,,,< MOVEM T2,RTRMCN>,) PARAMETER(^D922,,<^D1022>,<1>,<%RTMXC>,,,< MOVEM T2,RTRMXC>,) PARAMETER(^D923,,<^D30>,<1>,<%RTMXH>,,,< MOVEM T2,RTRMXH>,) PARAMETER(^D924,,<^D30>,<1>,<%RTMXV>,,,< MOVEM T2,RTRMXV>,) PARAMETER(^D926,,<^D1022>,<0>,<%RTBEA>,,,< MOVEM T2,RTNBEA>,) PARAMETER(^D927,,<^D64>,<0>,<%RTBRA>,,,< MOVEM T2,RTNBRA>,) PARAMETER(^D930,,,,,,,,) PARAMETER(^D931,,,,,,,,) PARAMETER(^D932,,,,,,,,) ;See note above PARAMETER(^D2503,,,,,,,,) EXPTBL==.-EXPTAB SUBTTL Network management tables -- Circuit parameters CCPTAB: PARAMETER(0,,,,,,,,< Circuit state>) PARAMETER(^D800,,,,,,,,) PARAMETER(^D801,,,,,,,,) PARAMETER(^D810,,,,,,,,) PARAMETER(^D900,,<^D25>,<1>,<1>,,< LOAD T2,RCCST,(RC)>,< CALL [ STOR T2,RCCST,(RC) CALL SETRCX RNMXOK]>,) PARAMETER(^D901,,<^D255>,<0>,<%RTMXR>,,< LOAD T2,RCMXR,(RC)>,< STOR T2,RCMXR,(RC)>,) PARAMETER(^D902,,<^D127>,<0>,<0>,,,< MOVEM T2,RTRPRI>,) PARAMETER(^D906,,<^D8191*TIMBAS>,<1*TIMBAS>,<%RTTM3>,,,,) PARAMETER(^D907,,,,,,,,< 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, ;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 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 ,(T1) ;LOCAL AND REACHABLE and in cache SETZRO ,(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 ;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 ;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, ;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 ;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 ;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,,,< 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,,,< 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 ,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 ,(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 ,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 ,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,,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 ,(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,,,< 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,,,< 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,,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 ,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,,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, 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 ,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, 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 ,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,,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,,,< 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,,,< 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 ,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 ;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,,,< 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, STKVAR 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 SETZM UPDCNT ;Initialize update count IFN FTOPS20,< STKVAR 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,,,,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 ,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, 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 ,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 ,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 STKVAR 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 ,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,,,< 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),)] ;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),)] ;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),)] ;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,,,< 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, 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 ,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 ,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 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 ,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, 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 ,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 ,AJTLR,(AJ) ;SUBTRACT THE TIME LAST MESSAGE WAS RECEIVED OPSTR ,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,, CALL SETRCA ;Yes, set recompute routing flags JN RCBCT,(RC),RTRCH3 ;No circuit down if broadcast ETRACE RTR, 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 ,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, 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 ,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 ,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 ,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,,,< 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 ,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, 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 ,RCTLH,(RC) ;Compute time since the last hello CAMG T1,RTRTM2 ;Has enough time elapsed? JRST RTRSH1 ; Nope, come back later MOVEI T1, ;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, 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,,,< 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 ;SAVE SOME AC'S STKVAR ; 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,,,< 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, 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, CALLRET CIRFAI] ;TRY TO REINITIALIZE THE CIRCUIT LOAD T2,RCLID,(RC) ;Get the line-id for the event EVENT RE.LUP, ;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, 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, 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 ;ROUTER INITIALIZATION (0) IFIW ;ROUTER VERIFICATION (1) IFIW ;ROUTER TEST MESSAGE (2) IFIW ;ROUTER ROUTING MESSAGE (3) IFIW ;ROUTER LEVEL 2 ROUTING MESSAGE (4) IFIW ;NI ROUTER HELLO MESSAGE (5) IFIW ;NI ENDNODE HELLO MESSAGE (6) IFIW ;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, CALLRET FREMSG] CALLRET RTRFWD ;FORWARD THE MESSAGE ;Here to discard an arriving packet due to congestion. RTIINF: OPSTR ,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, 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, CAIE T1,RCS.TI ;ARE WE IN RTR INIT WAIT STATE? JRST [ETRACE RTR, 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, 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, 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, CAIE T1,RCS.TV ;ARE WE WAITING FOR A VERIFICATION JRST [ETRACE RTR, 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, CAIE T1,RCS.TT ;CHECK OUR STATE FOR EITHER TEST OR CAIN T1,RCS.RN ; OK STATE TRNA ;WE SEEM ALRIGHT JRST [ETRACE RTR, 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,,<>,< 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 ,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, CAIE T1,RCS.TT ;ARE WE IN TEST OR CAIN T1,RCS.RN ; OK MODE? TRNA ;YES JRST [ETRACE RTR, 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 ,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 <> ;STORAGE FOR CURRENT RS LIST ID TRACE RTR, CAIE T1,RCS.TT ;ARE WE IN TEST OR CAIN T1,RCS.RN ; OK MODE? TRNA ;YES JRST [ETRACE RTR, 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, ;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, 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,,,< 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 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, ; 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,, 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, 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, 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, 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,,,< 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 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,,,< 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,,,< 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,,<>,< 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,,<>,< 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,,,< 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 ,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 ,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,,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 ;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 ,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, 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,^- ;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 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,,,< 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,,,< 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 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,,,< 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,,,< 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 MOVE T1,NMXDSP(T1) ; Routine to do processing CALLRET (T1) ; Go to it NMXDSP: IFIW! ; Set Parameter IFIW! ; Clear Parameter IFIW! ; Read Parameter IFIW! ; Show Counters IFIW! ; Show and Zero Counters IFIW! ; 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 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 ,(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 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 ; SIGNIFICANT nodes not supported IFIW ; ADJACENT nodes IFIW ; LOOP Nodes IFIW ; ACTIVE Nodes IFIW ](T2) ; KNOWN Nodes ELSE. CAIE T1,.NTCKT ; Is the entity circuit? IFSKP. CALLRET <-.NTSGN>+@[ IFIW ; SIGNIFICANT nodes not supported IFIW ; ADJACENT circuits IFIW ; LOOP circuits IFIW ; ACTIVE circuits IFIW ](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 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 ; 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 ; 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, ;AGED PACKET LOSS RE NUR,1, CKT, ;NODE UNREACHABLE PACKET LOSS RE NOR,2, CKT, ;NODE OUT-OF-RANGE PACKET LOSS RE OPL,3, CKT, ;OVERSIZED PACKET LOSS RE PFE,4, CKT, ;PACKET FORMAT ERROR RE PRL,5, CKT, ;PARTIAL ROUTING UPDATE LOSS RE VRJ,6, CKT,RTENOD ;VERIFICATION REJECT RE LDL,7, CKT,RTEREA ;CIRCUIT DOWN, CIRCUIT FAULT RE ADS,8, CKT, ;ADJACENCY DOWN, SOFTWARE FAULT RE ADO,9, CKT, ;ADJACENCY DOWN, OPERATOR FAULT RE LUP,10,CKT ;CIRCUIT UP RE IFL,11,CKT,RTEREA ;INITIALIZATION FAILURE, CIRCUIT FAULT RE IFS,12,CKT, ;INITIALIZATION FAILURE, SOFTWARE FAULT RE IFO,13,CKT, ;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> ;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 ,< 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 ;SAVE SOME ACS STKVAR ;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,,,< 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 ,RMMK1,(MB) ;EXCHANGE WITH TOP OF MESSAGE POSITION CALL DNGPOS ;GO TO THAT POSITION RTNEV5: MOVX T1,NE.LEN+</4> ;GET ENOUGH FOR ARG BLOCK AND ; MAXIMUM AMOUNT OF EVENT PARAMETER DATA CALL DNGWDZ ;GET THE WORDS BUG.(INF,ROUCGV,ROUTER,SOFT,,,< 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 SKIPN MB ;MUST HAVE A MESSAGE BLOCK HERE BUG.(CHK,ROUEHM,ROUTER,SOFT,,,< 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,,,< 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,,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, 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, 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,,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,,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,,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, 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,,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,,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 ,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 ,(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 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 ,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,,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 ;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,,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 ,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 ,AJNAN,(T2) ; Is it our adjacency? IFSKP. LOAD T1,AJBSZ,(T2); Yes, use its blocksize OPSTR ,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 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,,,< 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 ;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 ;Save AJ OPSTR ,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 ,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