|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 31488 (0x7b00) Types: TextFile Names: »routproc«
└─⟦a41ae585a⟧ Bits:30001842 SW-save af projekt 1000, Alarm-system └─⟦72244f0ef⟧ └─⟦this⟧ »routproc« └─⟦this⟧ »routproc«
prefix search_table; function search_table(local_key: ! integer; var local_index: integer; local_top: ! integer; local_bottom: ! integer; var local_table: indextab): boolean; (***********************************************************************) (* *) (* search_table *) (* *) (* parameters: *) (* local_key: the key that is searched for (call parameter). *) (* local_index: the index in the local_table, where local_key *) (* is found. it is unchanged, if local_key is not found (return *) (* parameter). *) (* local_top: first element in local_table (call parameter). *) (* local_bottom: last element in local_table (call parameter). *) (* local_table: specifies the actual index table that is used (call *) (* parameter). *) (* call of other procedures: none. *) (* use of global variables: none. *) (* waiting points: none. *) (* function: search the local_table for an element with *) (* local_key as key. local_index returns with the index in *) (* local_table, if the element is found, else it is unchanged. *) (* search_table is true if the element is found else false. *) (* *) (***********************************************************************) var top, bottom, middle: integer; begin if local_bottom >= local_top then begin (* local_table is not empty *) top:= local_top; bottom:= local_bottom; repeat middle:= (top + bottom) div 2; if local_key > local_table(middle).skey then top:= middle + 1 else bottom:= middle - 1; until (local_key = local_table(middle).skey) or (top > bottom); if local_key = local_table(middle).skey then begin local_index:= middle; search_table:= true; end (* if local_key = local_table(middle).key *) else (* local_key <> local_table(middle).key *) search_table:= false; end (* if local_bottom >= local_top *) else (* local_bottom < local_top *) search_table:= false; end. (* search_table *) endbody; \f prefix insert_table; function insert_table(local_key: ! integer; var local_index: integer; local_top: ! integer; var local_bottom: integer; var local_table: indextab): boolean; (*********************************************************************) (* *) (* insert_table *) (* *) (* parameters: *) (* local_key: the key of the element that is to be inserted in *) (* the ordered local_table (call parameter). *) (* local_index: second part of the element that is to be inserted *) (* in the local_table. if the element is inserted, then *) (* local_index is unchanged at return. if the element is not *) (* inserted, then local_index returns with the index in the *) (* local_table, where the element already exist (call and return *) (* parameter). *) (* local_top: first element in local_table (call parameter). *) (* local_bottom: last element in local_table. if element is *) (* inserted, then local_bottom is incremented (call and return *) (* parameter). *) (* local_table: specifies the actual index table that is used *) (* (call and return parameter). *) (* call of other procedures: search_table. *) (* use of global variables: none. *) (* waiting points: none. *) (* function: the function inserts the element that consists of *) (* local_key and local_index in the ordered local_table. *) (* local_key is the key. if the element is not already present *) (* in the table then insert_table is true, else it is false, and *) (* the element is not inserted. *) (* *) (*********************************************************************) var destination, source: integer; local_inx: integer; local_cont: boolean:= true; begin if not search_table(local_key, local_inx, local_top, local_bottom, local_table) then begin (* element is not already in the table *) source:= local_bottom; local_bottom:= local_bottom + 1; destination:= local_bottom; if local_bottom > local_top then while local_cont do if source < local_top then local_cont:= false else (* source >= local_top *) if local_table(source).skey > local_key then begin local_table(destination):=local_table(source); destination:= destination - 1; source:= source - 1; end (* if local_table(source).key > local_key *) else local_cont:= false; local_table(destination).skey:= local_key; local_table(destination).index:= local_index; insert_table:= true; end (* if not search_table(local_key, .... ) *) else (* search_table(local_key, .... ) *) begin (* element is already in the table *) local_index:= local_inx; insert_table:= false; end; (* else search_table(local_key, .... ) *) end. (* insert_table *) endbody; \f prefix remove_table; function remove_table(local_key: ! integer; var local_index: integer; local_top: ! integer; var local_bottom: integer; var local_table: indextab): boolean; (********************************************************************) (* *) (* remove_table *) (* *) (* parameters: *) (* local_key: the key of the element that is to be removed from *) (* the ordered local_table (call parameter). *) (* local_index: second part of the element that is removed from *) (* local_table. it is unchanged, if the element is not found *) (* (return parameter). *) (* local_top: first element in local_table (call parameter). *) (* local_bottom: last element in local_table. if the specified *) (* element is removed, then local_bottom is decremented (call *) (* and return parameter). *) (* local_table: specifies the actual index table that is used *) (* (call and return parameter). *) (* call of other procedures: search_table. *) (* use of global variables: none. *) (* waiting points: none. *) (* function: the function removes the element pointed out by *) (* local_key from the local_table. if the element is found *) (* then remove_table is true else remove_table is false at *) (* return. *) (* *) (********************************************************************) var destination, source: integer; begin if search_table(local_key, destination, local_top, local_bottom, local_table) then begin (* element is in the table *) local_index:= local_table(destination).index; source:= destination + 1; while source <= local_bottom do begin local_table(destination):= local_table(source); destination:= destination + 1; source:= source + 1; end; (* while source <= local_bottom *) local_bottom:= local_bottom - 1; remove_table:= true; end (* if search_table(local_key, .... ) *) else (* not search_table(local_key, .... ) *) remove_table:= false; end. (* remove_table *) endbody; \f prefix answ_lcp; procedure answ_lcp(var ref: reference; stat: set of sp_status_bit; bcnt: integer); begin lock ref as p: r_lcp_head do with p.sp_head do begin status:=stat; bytecount:= bcnt; end; ref^.u2:=ok; return(ref); end. endbody; \f prefix copy_event; procedure copy_event (var r: reference); (* this procedure copies an internal router event report to the ncp event buffer deliveed along with it. The top of r (popped off) which is the internal event is returned in r and the rest af the message is returned by a return call after the copying. *) var top: reference; begin pop (top, r); lock r as ncp_ev: r_lcp_event do lock top as int_ev: int_event_type do begin ncp_ev.evtrec:= int_ev.evtrec; ncp_ev.data:= int_ev.data; ncp_ev.sp_head.bytecount:=2+int_ev.evtrec.bytecount; ncp_ev.last:=ncp_ev.first-1+ncp_ev.sp_head.bytecount+sp_head_lgt; end; r^.u2:= ok; return (r); (* return event buf to ncp *) r:=: top; (* return top in returnparam r *) end. (* procedure copy_event *) endbody; \f prefix find_dest; procedure find_dest(own_addr,dest_addr: nwadr; var dest_level: integer); (* the procedure finds the destination level as an index in the destination address array *) begin dest_level:=rlmax; while (dest_level<>1) and (own_addr(dest_level)=dest_addr(dest_level)) do dest_level:=dest_level-1; end. endbody; \f prefix get_addr; procedure get_addr(var p: pack1; var addr: nwadr); (* the destination address (ext,reg,net) of the specified packet is placed in the address array - element no 1 is the node no *) begin if rlmax>=1 then addr(1):=p.head.node_dst; if rlmax>=2 then addr(2):=p.head.reg_dst; if rlmax>=3 then addr(3):=p.head.net_dst; end. endbody; \f prefix swaph1; procedure swaph1(var packet: pack1); (* the origin/destination addresses are swapped *) var h:phead1; begin with packet do begin h.net_dst:=head.net_dst; h.reg_dst:=head.reg_dst; h.node_dst:=head.node_dst; h.ext_dst:=head.ext_dst; with head do begin net_dst:=net_org; reg_dst:=reg_org; node_dst:=node_org; ext_dst:=ext_org; end; head.net_org:=h.net_dst; head.reg_org:=h.reg_dst; head.node_org:=h.node_dst; head.ext_org:=h.ext_dst; end; end. endbody; \f prefix update_queue; procedure update_queue(var queues: qinftable; conn_no,update: integer); (* the procedure updates the queuelength for the specified connector no - queue(conn_no):=queue(conn_no)+update. Note that the procedure contains a waiting point as it waits for the queues semaphore *) var ref: reference; begin wait (ref, queues.key); (* enter critical region *) queues.qlgt(conn_no):= queues.qlgt(conn_no)+ update; signal(ref,queues.key); (* exit critical region *) end. endbody; \f prefix update_range; procedure update_range (update: integer; var rng: packnnp); (* the procedure updates a received rangevector by adding update to each stated range in the vector. *) var i,lgt: integer; begin lgt:= (rng.drvbuf.last - rng.drvbuf.first + 1 - pnnph_lgt-rparam_lgt) div 2; for i:=1 to lgt do rng.data(i):= rng.data(i) + update; end. endbody; \f prefix check_hshake; function check_hshake (var p: packnnp; var hshake: handshake): boolean; (* the procedure checks the received handshake packet against the handshake packet (password etc.) kept in this node in var hshake. if the compare is satisfying the result is true. *) var i: integer; begin check_hshake:= true; for i:= 1 to lgt_hshake do if p.data(i) > hshake(i) then check_hshake:= false; end. (* check hshake *) endbody; \f prefix chup_nwtime; procedure chup_nwtime (actual: int32; var time: nwtime); (* the procedure checks the actual (received) networktime against the network time in this node. If actual is greatest the local network time is updated (to actual) *) var r: reference; begin wait (r, time.key); (* critical region *) if comp32 (actual, time.t)= gr then time.t:= actual; (* update network time *) signal (r, time.key); end. endbody; \f prefix rout_table_update; procedure rout_table_update (var t: routtable; var p: packnnp; conn_no: integer; var upd: cboolarray); (* this procedure updates a routing matrix on basis of a received range vector. the procedure inserts the new range column in the routing matrix at column index conn_no. in the return parameter upd is stated which connectors needs to transmit new nnp information. if upd(i) after return is true then connector no i must transmit a new range vector. *) var nn, dnew, dold, dmin, i: integer; c_upd: integer:= -1; rt: reference; begin (* procedure begin *) for i:= 1 to cmax do upd(i):= false; (* init no updates *) wait (rt, t.key); (* enter critical region *) for nn:= 1 to t.act_nmax do begin (* loop through range vector *) dnew:= p.data(nn); (* get range to nn *) if dnew> t.infway then dnew:= t.infway; dold:= t.tab(nn, conn_no); if dnew <> dold then begin (* distance changed *) t.tab(nn, conn_no):= dnew; if c_upd <> 0 then begin (* check which connectors needs to change *) if dnew < dold then dmin:= dnew else dmin:= dold; c_upd:= 0; for i:= 1 to cmax do if (i <> conn_no) and (dmin >= t.tab(nn, i)) then if c_upd= 0 then c_upd:= i else c_upd:= -1; if c_upd= 0 then (* all must change *) begin for i:= 1 to cmax do if i <> conn_no then upd(i):= true end else if c_upd> 0 then upd(c_upd):= true; (* one must change *) (* c_upd= -1: none must change *) end; (* check which connectors ... *) end; (* dnew <> dold *) end; (* loop through range vector (nn-loop) *) signal (rt, t.key); (* exit critical region *) end. (* procedure *) endbody; \f prefix insert_local_node; procedure insert_local_node (var t: routtable; conn_no, node_no: integer); (* this procedure performs the updating of the node routing table needed when a local connector connects itself to the router, i.e. inserts the range vector with one zero (the node no) and infinite in all other posi- tions *) var rngvec: packnnp; upd: cboolarray; i: integer; begin rngvec.drvbuf.first:=6; rngvec.drvbuf.last:=5+pnnph_lgt+rparam_lgt+(2*t.act_nmax); for i:= 1 to t.act_nmax do rngvec.data(i):= t.infway; rngvec.data(node_no):= 0; (* range to this node = 0 *) rout_table_update (t, rngvec, conn_no, upd); end. (* procedure insert local node *) endbody; \f prefix conn_down; procedure conn_down (var rtabs: rtabarray; conn_no: integer); (* this procedure performs the updating of the routing tables needed when a connector (line connector) goes down. The routing tables of the levels relevant to this connector are updated so that infinite is inserted in the column corresponding to this connector. *) var rngvec: packnnp; upd: cboolarray; level, i: integer; begin for level:= 1 to rlmax do begin for i:= 1 to pnnpmax do rngvec.data(i):= rtabs(level).infway; rout_table_update (rtabs(level), rngvec, conn_no, upd); end; (* level loop *) end. (* procedure conn_down *) endbody; \f prefix new_conn_state; procedure nwe_conn_state(var queues: qinftable; conn_no:integer; state:c_state_type); (* The procedure sets a new connector state *) var r:reference; begin wait(r,queues.key); queues.state(conn_no):=state; signal(r,queues.key); end. endbody; \f prefix ret_nnp_req; procedure ret_nnp_req(var waiting: semaphore); (* the procedure returns a nnp event request if there is one *) var r: reference; begin if open(waiting) then begin wait(r,waiting); r^.u2:=ok; return(r); end; end. endbody; \f prefix get_nnpfl; function get_nnpfl(var flagtable: nnpfltable; conn_no: integer; var inx: integer): boolean; (* the function reads the nnp flag table and returns the nnp function according to the first flag set. The flag is then reset. If no flags are set the function is false. Note that the function contains a waiting point as it waits for the nnp flag table. *) var ref: reference; b: boolean; begin wait(ref,flagtable.key); (* enter critical region *) b:= false; with flagtable do begin inx:=0; repeat inx:=inx+1; if flag(conn_no,inx)=1 then begin (* flag found *) flag(conn_no,inx):=0; (* reset flag *) cnt(conn_no):=cnt(conn_no)-1; b:= true; end; until b or (inx= nnpmax); end; signal(ref,flagtable.key); (* exit critical region *) get_nnpfl:= b; end. endbody; \f prefix set_nnp_fl; function set_nnp_fl(conn_no,index: integer; var tab: nnpfltable): boolean; (* the function sets the specified flag in the nnp flag table. The function is false if the flag was set already. the nnp flag table must be waited for before the function is called *) begin with tab do if flag(conn_no,index)=1 then set_nnp_fl:=false else begin flag(conn_no,index):=1; cnt(conn_no):=cnt(conn_no)+1; set_nnp_fl:=true; end; end. endbody; \f prefix build_hshake; procedure build_hshake (var h: handshake; var packet: packnnp); (* this procedure creates the handshake nnp packet (nnp protocol) with the data part defined in the var param h. First and last is initialized. And packet header except function is initialized. *) var i: integer; begin with packet.head do begin format:= dg_form3; priority:= nnp_prio; typ:= int_sup_p; end; (* with head do *) packet.drvbuf.first:=6+rparam_lgt; packet.drvbuf.last:=2*lgt_hshake+pnnph_lgt+6+rparam_lgt-1; for i:= 1 to lgt_hshake do packet.data(i):= h(i); end. (* procedure *) endbody; \f prefix build_nwtime; procedure build_nwtime (var nwt: nwtime; var packet: packnnp); (* this procedure creates the nnp networktime packet (nnp protocol) both data part and header (incl. first and last) except function. *) var r: reference; begin with packet.head do begin format:= dg_form3; priority:= nnp_prio; typ:= int_sup_p; end; (* with head do *) packet.drvbuf.first:=6+rparam_lgt; packet.drvbuf.last:=4+pnnph_lgt+6+rparam_lgt-1; wait (r, nwt.key); (* get network time *) packet.data(1):= nwt.t.msp; packet.data(2):= nwt.t.lsp; signal (r, nwt.key); (* release network time *) end. (* procedure *) endbody; \f prefix build_rngvec; procedure build_rngvec (var t: routtable; var packet: packnnp; conn: integer); (* this procedure creates a rangevector packet (nnp protocol) on basis of the routing matrix t. The column with index no conn is not used. First and last is initialized. And packet- head format, priority and type but not function is initiali- zed. *) var ref: reference; i,j,r,d: integer; inx: integer:= 0; begin wait (ref, t.key); (* enter critical region *) with packet.head do begin format:= dg_form3; priority:= nnp_prio; typ:= int_sup_p; end; packet.drvbuf.first:=6+rparam_lgt; packet.drvbuf.last:=2*t.act_nmax+pnnph_lgt+6+rparam_lgt-1; for i:= 1 to t.act_nmax do begin d:= t.infway; for j:= 1 to cmax do if j <> conn then begin r:= t.tab(i,j); if r < d then d:= r; end; inx:= inx+1; packet.data(inx):= d; (* least distance found *) end; (* i-loop *) signal (ref, t.key); (* exit critical region *) end. endbody; \f prefix reject; function reject(var packet: pack1; rej_state:integer) : boolean; (* the function tests whether or not the specified packet may be rejected. If so the packet is changed to a rejected packet with state as parameter rej_state. A packet may be rejected if state = 0 and facility reject bit is true. Or if state = 0, facility 'reject by exceeded lifetime' is true and parameter rej_state indicates exceeded lifetime. *) begin reject:= false; if packet.head.state= 0 then if (packet.head.fac.rej= 1) or ((rej_state= st_ltexceed) and (packet.head.fac.rejlt= 1)) then begin (* packet may be rejected *) reject:= true; swaph1 (packet); with packet do begin if head.fac.hrej= 1 then drvbuf.last:= drvbuf.first+phead1_lgt; head.state:= rej_state; end; end; end. (* reject function *) endbody; \f prefix route; function route (var t: routtable; var q: qinftable; var dest: integer; dyn: boolean): boolean; (* finds the optimal direction towards dest. The found conn.no. is returned in dest. *) var c, lastused, min, dist, conn: integer; rt, rq: reference; begin if (dest>0) and (dest<=t.act_nmax) then begin wait (rq, q.key); (* get queueinformation *) wait (rt, t.key); (* get routing table *) min:= t.infway; conn:= 0; lastused:= t.lastconn(dest); for c:= 1 to cmax do begin if q.state(c) = running then begin if dyn then dist:= t.tab(dest,c)+q.qlgt(c) else dist:= t.tab(dest,c); if dist < t.infway then begin if dist < min then begin min:= dist; conn:= c; (* minimal path so far *) end else if dist = min then if conn = lastused then conn:= c; end; end; end; (* search through row n *) if conn = 0 then route:= false (* no path found *) else begin t.lastconn(dest):= conn; q.qlgt(conn):= q.qlgt(conn) + 1; (* incr queuelgt *) dest:= conn; route:= true; end; signal (rt, t.key); (* release routing table *) signal (rq, q.key); (*release queueinformation *) end else route:=false; end. (* routing procedure *) endbody; \f prefix masterroute; function masterroute (var packet: pack1; var dest: integer; var ownadr, destadr: nwadr; var rtables: rtabarray; var queues: qinftable): boolean; (* performs the routing/rejecting of one packet *) var destlev: integer; b: boolean; begin find_dest (ownadr, destadr, destlev); dest:= destadr(destlev); b:= route (rtables(destlev), queues, dest, false); if b then masterroute:= b else begin if reject (packet,st_extunkn-destlev) then begin get_addr (packet, destadr); masterroute:= masterroute (packet, dest, ownadr, destadr, rtables, queues) end else masterroute:= false; end; end. endbody; \f prefix check_node; function check_node(var t: routtable; node: integer;var dest:integer) : boolean; (* The function tests if the specified node is this node i.e. the row in the routing table pointed out by node is searched to find a zero. if a zero is found the node is this node (connector number dest ) and the function is true else false. - Note that the function contains a waiting point as it waits for the routing table *) var ref: reference; b: boolean:= false; begin wait(ref,t.key); (* get routing table *) dest:=0; repeat dest:= dest+1; if t.tab(node,dest)=0 then b:=true; until b or (dest=cmax); check_node:=b; signal(ref,t.key); (* release routing table *) end. endbody; \f prefix check_neighb; function check_neighb(var t: routtable; node: integer; var dest: integer) : boolean; (* The function tests if the specified node is a neigbhour i.e. the row in the routing table pointed out by node is searched for elements smaller than infway. For each of these elements the involved column is searched to check whether or not the element is the smallest element in the column. If the element is the smallest element the node is a neigbhour node on connector number dest and the function is true else false. - note that the function contains a waiting point as it waits for the routing table *) var ref: reference; b: boolean:= false; j: integer; begin wait(ref,t.key); (* get routing table *) dest:=0; repeat dest:= dest+1; if t.tab(node,dest) < t.infway then begin j:=0; b:=true; repeat j:= j+1; if j<>node then if t.tab(j,dest) < t.tab(node,dest) then b:=false; until not(b) or (j=t.act_nmax); end; until b or (dest=cmax); check_neighb:=b; signal(ref,t.key); (* release routing table *) end. endbody; \f prefix lifetime_exc; function lifetime_exc(var p: pack1; var netwtime: nwtime):boolean; (* the function checks whether or not the lifetime control is on and if on, the function checks if the lifetime of the packet has exceeded. If the lifetime has exceeded the function is true else false. If the link measurement is on the link limit is decremented - note that only the right byte of the linklimit is significant *) var i: integer; b: boolean; begin b:=false; if p.head.fac.linklt=1 then begin (* link control on *) if p.data(p.head.top_of_data+link_limit+1) = 0 then (* link exceeded *) b:=true else p.data(p.head.top_of_data+link_limit+1):= p.data(p.head.top_of_data+link_limit+1)-1; end; if (p.head.fac.timelt=1) and not(b) then begin (* time control on *) i:=(p.data(p.head.top_of_data+tim_limit))*256 + p.data(p.head.top_of_data+tim_limit+1); if dif16(i,netwtime.t.lsp) < 0 then b:=true; end; lifetime_exc:=b; end. endbody; \f prefix upd_nxt_rec; function upd_nxt_rec(var p:pack1; toprec:integer; var nextrec: integer) : boolean; (* the function updates the next record in the trailer of the packet and the variable nextrec. the updating is equal to trrec_lgt. if there is not enough room in the packet no updating is issued and the function is false else true. - note that only the right byte of the next record field is significant *) begin if nextrec + trrec_lgt <= toprec then begin nextrec:=nextrec+trrec_lgt; p.data(p.head.top_of_data+next_rec+1):=nextrec; upd_nxt_rec:=true; end else upd_nxt_rec:=false; end. endbody; \f prefix place_trace; procedure place_trace(var p:pack1; toprec: integer; var nextrec:integer; var netwtime: nwtime; var ownadr: nwadr); (* if room, the procedure places a trailer record in the specified packet at the index pointed out by nextrec. The variable nextrec and next record in the trailer are updated with trrec_lgt *) begin if nextrec+trrec_lgt<=toprec then begin p.data(nextrec+tr_rec_reg):=ownadr(2); (* region *) p.data(nextrec+tr_rec_node):=ownadr(1); (* node *) p.data(nextrec+tr_rec_time):=netwtime.t.lsp div 256; p.data(nextrec+tr_rec_time+1):=netwtime.t.lsp mod 256; nextrec:=nextrec+trrec_lgt; p.data(p.head.top_of_data+next_rec+1):=nextrec; end; end. endbody; \f prefix check_path; function check_path(var p:pack1; var rt:rtabarray; toprec: integer; var nextrec: integer; var dest : integer; var daddr: nwadr; var ownaddr: nwadr) : pfacttype; (* the function handles the fixed path bit which must be set when the function is called - the actions are: 1) if the path has exceeded i.e. nextrec>toprec the function is route_p and daddr contains the destination address read from the packet header. The packet should then be routed using masterroute. 2) if the path has not exceeded it is tested whether or not the node pointed out by nextrec in the trailer is this node. If so , the next record in the packet and the variable nextrec are updated. If the node is not this node no updating is issued. If the updating results in an overflow the actions are as described in 1). 3a) If fixed path is specified in the facility mask: Then the node of the next record is tested for being a neighbour node. If so the function is route_to_dest and the variable dest contains the connector number to which the packet should be routed. If the node is not a neighbour node the function is reject_p ( the packet should be rejected ). 3b) If selected path is specified in the facility mask: The destination address held in the next record of the trailer is placed in daddr. The function is route_p and the packet should be routed using masterroute. Note that the function contains waiting points as it calls check_node and check_neigh *) begin if nextrec>toprec then begin (* path exceeded *) check_path:=route_p; get_addr(p,daddr); end else begin if check_node(rt(1),p.data(nextrec+tr_rec_node),dest) then begin (* this node *) nextrec:=nextrec+trrec_lgt; p.data(p.head.top_of_data+next_rec+1):=nextrec; end; if nextrec>toprec then begin (* path exceeded *) check_path:=route_p; get_addr(p,daddr); end else begin (* path not exceeded *) if p.head.fac.fpath=1 then begin (* fixed path *) if check_neighb(rt(1),p.data(nextrec+tr_rec_node),dest) then check_path:=route_to_dest else check_path:=reject_p; end else begin (* selected path *) daddr(3):=ownaddr(3); (* net *) daddr(2):=p.data(nextrec+tr_rec_reg); (* region *) daddr(1):=p.data(nextrec+tr_rec_node); (* node *) check_path:=route_p; end; end; end; end. endbody; \f prefix check_facility; function check_facility(var p: pack1; var rt:rtabarray; toprec: integer; var nextrec: integer; var dest: integer; var daddr: nwadr; var ownaddr: nwadr; var prejst: byte; var netwtime: nwtime; mode:integer) : pfacttype; (* The function checks the facility mask of the specified packet. The value of the function: reject_p: The packet should be rejected with the reject cause as specified in prejst. The function has this value when: - The lifetime of the packet has exceeded(not tested if mode=0) (prejst=st_ltexceed) - If the node in the trailer of a fixed path record is not a neighbour node to this node. (prejst=st_fpatherr) route_p: The packet should be routed to the destination address held in daddr using the function masterroute. route_to_dest: The packet should be routed (signalled) to the connector number held in dest. route_to_sup: The packet should be routed (signalled) to the supervisor (only if the broadcast bit is set). Note that the facility mask should be <>0 when the function is called. If unknown facility bits are set the value og the function is route_p. The function should only be called by transmitter processes in the Router. Note that the function contains waiting points if the fixed or selected path bits are set as the function check_path is called.*) label return1; begin if mode <> 0 then if lifetime_exc(p,netwtime) then begin (* lifetime exceeded *) check_facility:=reject_p; prejst:=st_ltexceed; goto return1; end; if p.head.fac.bcast=1 then check_facility:=route_to_sup else begin (* broadcast not set *) if (p.head.fac.fpath=1) or (p.head.fac.spath=1) then begin (* fixed or selected path *) check_facility:=check_path(p,rt,toprec,nextrec,dest,daddr,ownaddr); prejst:=st_fpatherr; (* used if reject_p *) end (* fixed or selected path *) else if p.head.fac.trace=1 then begin (* trace *) place_trace(p,toprec,nextrec,netwtime,ownaddr); get_addr(p,daddr); check_facility:=route_p; end (* trace *) else begin (* other facility bits set *) get_addr(p,daddr); check_facility:=route_p; end; end; (* broadcast not set *) return1: end. (* function *); endbody; . ▶EOF◀