📄 cippd_protocol.c
字号:
* example, datagrams are never supplied when the machine is invoked to * process path failures( event == CNFE_PATH_FAIL ) or processing errors( * event == CNFE_PROC_ERROR ). * 9. Datagrams must never be disposed of as a side effect of executing some * action, but only by those action functions/routines which exist solely * for this purpose. They are also purposely deallocated during abortion * of formative paths following premature termination of event processing. * 10. SCS sequenced messages must never be deallocated by the CI PPD finite * state machine even when their processing leads to failure of the target * path. They are always returned to the original invocators of the finite * state machine who have the proper contexts to dispose of them correctly. * 11. The finite state machine never explicitly crashes formative paths. An * action function wishing to crash a formative path returns a failure * status. Such a status prematurely terminates event processing and * aborts establishment of the formative path. * * * These basic rules must be careful obeyed when modifying the CI PPD finite * state machine, especially when changing existing action functions/routines. * Action routines should not be changed to return status and the conditions * under which failure statuses are returned by action functions should not be * modified without a thorough understanding of the consequences. * * Only CI PPD path related asynchronous events processed directly by the CI * PPD finite state machine are documented by the CI PPD state table. There * are other events important to the CI PPD but not processed directly by the * finite state machine including: * * 1. Asynchronous notification of port starting. * 2. Asynchronous notification of port failure. * 3. CI PPD interval timer events. * 4. Asynchronous path clean up. * * The first event activates the finite state machine on the specified local * port and schedules its first interval timer event. The second event aborts * the establishment of formative paths, terminates existing paths, cancels all * interval timers, and in general deactivates the finite state machine on the * specified local port. In between local port start up and failure, interval * timer events drive the discovery of new remote CI PPDs through polling for * their remote port identifications. It is also through these events that the * timeouts listed in the CI PPD state table are declared on specific formative * paths. Finally, the last event in the list is scheduled by the CI PPD * finite state machine itself and its asynchronous occurrence cleans up the * specified CI PPD path. * * NOTE: The action "Send STOP CI PPD Datagram" is specified for many of the * event-state combinations listed in the CI PPD state table. Yet, it is * also true that the local SYSAP never notifies its remote counterpart * of local termination of a path. This apparent discrepancy requires * further clarification. The DEC standard SCA CI PPD protocol specifies * a HOST SHUTDOWN CI PPD datagram. An attempt was made by Ultrix to * redefine this datagram as a more general STOP CI PPD datagram. While * this attempt was in progress and in anticipation of its success, the * CI PPD was modified to send this datagram whenever it terminated a * path. Needless to say the attempt to ECO the SCA architecture failed * mainly due to an extremely pig headed VMS programmer( who shall remain * nameless because he does not even deserve to be mentioned ). Anyway, * to conform to the SCA architecture Ultrix was forced to abandon use of * the STOP CI PPD datagram. This was accomplished by just commenting * out the action function responsible for its transmission. Attempts to * transmit a STOP CI PPD datagram were left in place as were all * comments on when such a datagram should be transmitted. Just nothing * is transmitted. This strategy allows for quick resumption of STOP CI * PPD datagram transmission should the situation change and a modified * version of the STOP CI PPD datagram was accepted by the SCA * architecture group. *//* Libraries and Include Files. */#include "../h/types.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/vmmac.h"#include "../h/time.h"#include "../h/ksched.h"#include "../h/errlog.h"#include "../h/smp_lock.h"#include "../io/scs/sca.h"#include "../io/scs/scaparam.h"#include "../io/ci/cippdsysap.h"#include "../io/ci/cisysap.h"#include "../io/msi/msisysap.h"#include "../io/bi/bvpsysap.h"#include "../io/gvp/gvpsysap.h"#include "../io/uba/uqsysap.h"#include "../io/sysap/sysap.h"#include "../io/ci/cippdscs.h"#include "../io/ci/ciscs.h"#include "../io/msi/msiscs.h"#include "../io/bi/bvpscs.h"#include "../io/gvp/gvpscs.h"#include "../io/uba/uqscs.h"#include "../io/scs/scs.h"#include "../io/gvp/gvp.h"#include "../io/ci/cippd.h"/* External Variables and Routines. */extern SCSIB lscs;extern struct lock_t lk_scadb;extern sbq scs_config_db;extern struct timeval boottime, time;extern PB *cippd_get_pb();extern SB *scs_alloc_sb();extern u_long cippd_dispatch();extern u_short cippd_itime, cippd_map_pc[], cippd_map_spc[], scs_map_pc[], scs_map_spc[];extern void cippd_clean_pb(), cippd_clean_fpb(), cippd_crash_pb(), cippd_csyslev(), cippd_log_path(), cippd_log_sys(), scs_dealloc_pb(), scs_dealloc_sb(), scs_new_path(), scs_unix_to_vms();extern CIPPD_STAB cippd_stab[ PS_MAX_STATE + 1 ][ CNFE_MAX_EVENT + 1];/* Name: cippd_dispatch - CI PPD Action Dispatcher * * Abstract: This function dispatches the current event according to the * current path state event. There are many possible side effects * from such dispatching and the CI PPD state table at the * beginning of this module should be consulted for an * understanding of them. * * Many of the event-state combinations represent errors and * directly abort path establishment through explicit crashing of * the path. The path is also terminated when errors are * encountered during processing of the current event. Several * event-state combinations may also log remote errors. * * Any optional port specific datagram buffer provided is * consumed by the action of the finite state machine either * through transmission or addition to the appropriate local port * free queue. * * Any optional port specific message buffer provided is NOT and * must not be consumed by the action of the finite state machine. * Disposal of such buffers always occurs outside the context of * the CI PPD finite state machine. * * Inputs: * * IPL_SCS - Interrupt processor level * cippdbp - Address CI PPD header in datagram( OPTIONAL ) * cippd_stab - CI PPD State Transition table * event - Event * pb - Path Block pointer * pccb - Port Command and Control Block pointer * * Outputs: * * IPL_SCS - Interrupt processor level * pb - Path Block pointer * pinfo.reason - General path failure reason * pinfo.state - Path state * * Return Values: * * RET_SUCCESS - State transition successfully occurred * RET_FAILURE - Path establishment aborted * * SMP: The PCCB is locked( EXTERNALLY ) allowing exclusive access to * PCCB contents within the finite state machine. * * The PB is locked( EXTERNALLY ) postponing potential deletion * and allowing exclusive access to PB contents. */u_longcippd_dispatch( pccb, pb, event, cippdbp ) PCCB *pccb; register PB *pb; u_long event; GVPPPDH *cippdbp;{ register CIPPD_ATAB *ap; register u_long state; /* Dispatch the current event by executing the set of actions on the target * path appropriate for the event - path state combination. Successful * execution of all actions transitions the CI PPD path to a new state as * specified by the CI PPD state table. Failure of any action in the set * is handled as follows by this function: * * 1. Optionally deallocate the CI PPD datagram buffer( it must be present * and it must BE a datagram and not a SCS message buffer ). * 2. Store the reason for terminating the path for latter SYSAP( remote ) * consumption. * 3. Iteratively invoke the finite state machine to terminate and clean up * the path( event == CNFE_PROC_ERROR ). * 4. Return a failure status. * * There is never any need to either terminate established( path state == * PS_OPEN ) or failed( path state == PS_PATH_FAILURE ) paths in this * fashion. Execution of their actions is always successful. Furthermore, * execution of actions associated with path failure( event == * CNFE_PATH_FAIL ) or processing error( event == CNFE_PROC_ERROR ) events * is also always successful protecting paths undergoing termination from * repeated terminations. * * There is one exception to this rule. The action function * cippd_enter_db() must temporarily release all locks. By the time it re * obtains its PB lock it is possible for the corresponding path to have * failed, but not cleaned up, and for its state to have been transitioned * to PS_PATH_FAILURE. This causes cippd_enter_db() to immediately return * failure and this function to iteratively invoke itself to terminate the * path( event == CNFE_PROC_ERROR ). Thus, under such obscure * circumstances it is possible for the finite state machine to be invoked * to handle processing errors on paths that have already failed. The * finite state machine is prepared for such occurrences by completely * ignoring them and performing no processing as is done for invocations of * the finite state machine to handle failure of already failed paths. * * Each action executed during processing of the current event is * represented by its own function/routine. Functions return status while * routines do not. Function status is occasionally ignored whenever it * is known to always be good under the current set of circumstances. The * interface to all functions/routines is consistent allowing them to be * invoked with regard to only whether or not they return status. */ if(( state = pb->pinfo.state ) > PS_MAX_STATE ) { ( void )panic( PPDPANIC_PSTATE ); } else if( event > CNFE_MAX_EVENT ) { ( void )panic( PPDPANIC_EVENT ); } for( ap = cippd_stab[ state ][ event ].actions; ap->action; ap++ ) { if( ap->flags == CIPPD_NOSTATUS ) { ( void )( *ap->action )( pccb, pb, cippdbp ); } else if(( *ap->action )( pccb, pb, cippdbp ) != RET_SUCCESS ) { if( cippdbp && ( event != CNFE_SCSMSG_REC )) { ( void )( *pccb->Add_dg )( pccb, Ppd_to_scs( cippdbp )); } pb->pinfo.reason = PF_PPDPROTOCOL; ( void )cippd_dispatch( pccb, pb, CNFE_PROC_ERROR, NULL ); return( RET_FAILURE ); } } pb->pinfo.state = cippd_stab[ state ][ event ].fstate; return( RET_SUCCESS );}/* Name: cippd_ack_rec - Discard Received ACK CI PPD Datagram * * Abstract: This action routine discards received ACK CI PPD datagrams by * deallocating them. It is only invoked when the reception of an * ACK transitions the formative path into a fully established * path. The datagrams are deallocated because they represent * those datagrams temporarily allocated for all protocol * exchanges during path establishment when such establishment was * originally initiated. * * Inputs: * * IPL_SCS - Interrupt processor level * cippdbp - Address of CI PPD header in datagram * pb - Path Block pointer * pinfo.state - PS_STACK_SNT * pccb - Port Command and Control Block pointer * * Outputs: * * IPL_SCS - Interrupt processor level * * SMP: No locks are required. PCCB addresses are always valid * allowing access to static fields because these data structures * are never deleted once their corresponding ports have been * initialized( The PCCB is locked EXTERNALLY anyway ). */voidcippd_ack_rec( pccb, pb, cippdbp ) PCCB *pccb; PB *pb; GVPPPDH *cippdbp;{ ( void )( *pccb->Dealloc_dg )( pccb, Ppd_to_scs( cippdbp ));}/* Name: cippd_build_sb - Build Formative System Block * * Abstract: This action function builds a formative System Block from a * START/STACK CI PPD datagram. * * Inputs:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -