home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * $Header: ~eden/Kernel/Em/hotsUpDown.c Revision 1.0 85/07/08 eric Exp$
- *
- * FUNCTION: This module contains routines for managing HOTS table
- * entries in the presence "unexpected" occurences such
- * as node death, transmission failures and arrival of
- * messages from previously unknown nodes. Handlers for these
- * circumstances are defined as "upcall" routines which
- * all called from the lower level MM routines which actually
- * detect occurrence of the event. This code is derived from
- * the old DataStructs/initHots.c
- *
- * EXPORTS: InitHOTS(): Master initialization code for HOTS/MM protocol.
- * AddHOTS() : Insert newly alive node in HOTS table and
- * initialize protocol fields.
- * ChangeHOTS(): Change a known node from one state to another
- * with attendant port/protocol cleanup.
- *
- * FIXME: This module should know nothing about the VOIT, in
- * particular the fakey VOIT entries for nodes. Unfortunately
- * the death detection routines and KMD stuff make this
- * a difficult bit of surgery without restructuring a lot
- * of other code as well.
- *
- * $Log:$
- * Revision 1.0 85/06/11 12:16:27 oystr
- * First release of this code in its current incarnation. Following
- * comments relate to the old file structure.
- *
- * Revision 3.7 85/03/11 13:38:21 eric
- * Changed AddHOTS and ChangeHOTS to have more uniform semantics.
- * Both now ensure proper cleanup when a local node dies.
- *
- * Revision 3.6 84/11/19 13:38:21 schwartz
- * Added fServiceName parameter to initHots() so that other Service Ports
- * than EDENKERNELSERVICEPORT could be used (EFTSERVICEPORT in particular)
- *
- * Revision 3.5 84/09/28 13:42:31 schwartz
- * Changed DeclareDead() to call MMRemoteNodeDeath() after ChangeHOTS()
- * to clean up protocol fields of Dead node.
- *
- * Revision 3.4 84/09/25 14:00:12 schwartz
- * Changed ChangeHOTS() so that it uses DebugLevel 2 to print out the
- * EtherAddr of the changed node (it used to always be printed).
- *
- * Revision 3.3 84/08/20 14:18:32 schwartz
- * Made InitHOTS() return the status from its call to MMInitMsgModule.
- *
- * Revision 3.2 84/08/07 11:54:08 schwartz
- * Split InitHOTS() into InitHOTS() and BootKernel() so that these functions
- * can be used separately (e.g. the broadcast process needs only InitHOTS).
- * Made AddHOTS() global; moved InitNextHOTS() to hotsTypes.h.
- *
- * Revision 3.1 84/07/25 02:47:08 schwartz
- * Minor changes to accommodate EFT's new usage of the MM
- *
- * Revision 3.0 84/07/03 23:50:08 schwartz
- * Changes to accommodate use of Unix 4.2 sockets for network communication.
- *
- * Revision 2.2 84/06/20 20:14:08 schwartz
- * Added routines DeclareDead (formerly called MMDeclareDead; used
- * to reside in ../MsgOps/msgCode.c) and BigRetransCountHandler, to handle
- * big retransmission count errors (in order to keep this procedural
- * information encapsulated in the higher layer protocols, rather than in
- * the low level message module)
- *
- * Revision 2.1 84/02/16 22:14:08 oystr
- * Version 2 baseline.
- *
- * Revision 1.7 84/02/16 15:23:54 eric
- * Minor changes caused by new Message Module:
- * Mostly new initialization routines inserted.
- *
- * Revision 1.1 83/05/04 07:03:52 jim
- * Initial revision
- *
- */
-
- #ifdef RCSID
- static char rcsid[] = "$Header$";
- #endif
-
- #include <stdio.h>
-
- #include "Kernel/h/system.h"
- #include "Kernel/h/stdTypes.h"
- #include "Kernel/h/mmCodes.h"
- #include "Kernel/h/errMsgs.h"
- #include "Kernel/h/mmTypes.h"
- #include "Kernel/h/mmMsgDefs.h"
- #include "Kernel/h/mmMsgTypes.h"
- #include "Kernel/h/kBootCodes.h"
- #include "Kernel/h/kEvents.h"
- #include "Kernel/h/dstCodes.h"
- #include "Kernel/h/hotsTypes.h"
- #include "Kernel/h/kBootTypes.h"
- #include "Kernel/h/kmdTypes.h"
-
- extern KKStatus HOTSSearchPtr();
- extern time_t nodeIncarnationId; /* imported from main.c */
- extern void KillImposter();
- extern void ScheduleBootReply();
- extern void NodeStateChanged();
-
-
- /* Forward */
- void AddHOTS(), ChangeHOTS();
-
- /*###*/
-
- static int Cleanup[5][5] = {
- /* Dead */ { 0, 0, 0, 0, 0},
- /* Alive */ { 1, 0, 0, 0, 0},
- /* Deaf */ { 1, 0, 0, 0, 0},
- /* Dumb */ { 1, 0, 0, 0, 0},
- /* Booting */ { 1, 0, 0, 0, 0}
- };
-
- static char *NodeStatNames[] = {
- "Dead", "Alive", "Deaf", "Dumb", "Booting",
- };
-
-
- /***********************************************************************/
- /* Upcall handlers for MM: */
- /* DeclareDead Declares a node dead. */
- /* BigRetransCountHandler Too many retransmits for msg. */
- /* EdenPortDeathHandler A port dies - check for host death.*/
- /* NoHOTSEntryHandler We missed its bootup. */
- /* CheckMsg Checks every incoming msg. */
- /***********************************************************************/
-
- HResult DeclareDead(fLNN)
- NodeNum fLNN;
- /* Scheduled by BigRetransCountHandler when an excessive number of
- retransmits is reached for a node or when an Edenport has died.
- Checks to see if the node is still Deaf and if so cleansup. */
- {
- HOTSRecord *fHOTS;
-
- if (!mSUCCESS(HOTSSearchPtr(fLNN, &fHOTS) ) ) return; /* Entry deleted.*/
-
- if (fHOTS->NodeStat == Deaf) {
- /* The node has died and the state set to deaf.
- Now do the cleanup. */
- ErrMsg("DeclareDead: LNN = %d, incarnation %.15s\n", fLNN,
- 4+ctime(&fHOTS->NodeIncarnationId));
- ChangeHOTS(fHOTS->LNN, Dead);
- } /* else other action (e.g., reboot) caused cleanup action. */
- }
-
- KKStatus BigRetransCountHandler(fHOTSRec)
- HOTSRecord *fHOTSRec;
- {
- ErrMsg( ">>> Declaring node %d Deaf\n", fHOTSRec->LNN);
- /* The cleanup should be done by a scheduled tasks as the caller of
- this routine may still hold pointers to the HOTS stuff. */
- HoldSigs();
- fHOTSRec->NodeStat = Deaf;
- QueueTask( (HandlerPtr)DeclareDead, (char *)fHOTSRec->LNN);
- ReleaseSigs();
- return( MMSS_Success);
- }
-
- KKStatus EdenPortDeathHandler()
- {
- ErrMsg("EdenPortDeathHandler not supported\n");
- }
-
-
- KKStatus NoHOTSEntryHandler()
- /* MessagePtr fMsg; */
- /* Check the message to see if it is a first flow-controlled
- message and if so change his state. */
- {
- ErrMsg("NoHOTSEntryHandler called - should not happen!\n");
- return(MMSF_BadConfig);
- };
-
-
- KKStatus CheckMsgSrc(fMsg, fHOTS)
- MessagePtr fMsg;
- HOTSRecord **fHOTS;
- /* Verify that the msg source is actually up and return a pointer to the
- HOTS table entry for the node */
- {
- KKStatus kstat;
- EtherNetAddress nodeAddr;
- register MessageHeaderPtr hdr = &fMsg->MsgHdr;
-
- kstat = HOTSSearchPtr(hdr->MsgSrc, fHOTS);
- if (!mSUCCESS(kstat)) {
- if (kstat == DSTF_HOTSSearchNoEntry) {
- /* Well, then create an entry */
- KMDTrace("HOTSUpDown", 5,
- "CheckMsgSrc: Inserting new node into HOTS, LNN %d\n",
- hdr->MsgSrc);
- nodeAddr = MMLocalEtherNet;
- nodeAddr.sin_port = hdr->SrcSinPort;
- nodeAddr.sin_addr = hdr->SrcSinAddr;
- AddHOTS(nodeAddr, hdr->MsgSrc, IsActiveNode, Booting,
- hdr->SrcIncarnationId);
- /* Must look it up again since AddHOTS now has added it */
- return (HOTSSearchPtr(hdr->MsgSrc, fHOTS));
- } else {
- /* Some serious error */
- CantDoIt("CheckMsgSrc ", kstat);
- return(kstat);
- };
- }
- /* Now check incarnation */
- if ((*fHOTS)->NodeIncarnationId == hdr->SrcIncarnationId) {
- /* Rejoice, we know it */
- return(MMSS_Success);
- };
- /* Problems: Incarnation Ids do not match */
- /* First do a duplicate node detection */
- if (hdr->MsgSrc == GetLNN()) {
- /* Ups, this guy is impersonating us -- let the newest guy win. */
- if (nodeIncarnationId < hdr->SrcIncarnationId) {
- /* He is newer - so let him continue */
- ErrMsg("**** Duplicate LNN %d of %.15s at %s\n",
- hdr->MsgSrc, 4+ctime(&hdr->SrcIncarnationId),
- mGetHostName((EtherNetAddress *) &hdr->SrcSinAddr));
- ErrMsg("**** Aborting this incarnation %.15s\n",
- 4+ctime(&nodeIncarnationId));
- abort();
- }
- /* OK, so we are newer, send him a msg telling him to croak */
- /* Note, this is very tricky since we cannot send him a msg directly
- since he is not in our HOTS! Therefore use a broadcast (sigh)
- which is not very efficient and not very reliable. */
- KillImposter(fMsg);
- return(MMSF_NodeDown);
- } else if ((*fHOTS)->NodeIncarnationId < hdr->SrcIncarnationId) {
- /* Fine, the old one is dead, merely add the new one to the
- HOTS table */
- {
- KMDTrace("HOTSUpDown", 5, "CheckMsgSrc: LNN %2d incarnation %.15s has died. \n",
- hdr->MsgSrc, 4+ctime(&(*fHOTS)->NodeIncarnationId));
- KMDTrace("HOTSUpDown", 5, "Will be replaced by incarnation %.15s\n",
- 4+ctime(&hdr->SrcIncarnationId));
- nodeAddr = MMLocalEtherNet;
- nodeAddr.sin_port = hdr->SrcSinPort;
- nodeAddr.sin_addr = hdr->SrcSinAddr;
- AddHOTS(nodeAddr, hdr->MsgSrc, IsActiveNode, Alive,
- hdr->SrcIncarnationId);
- }
- } else {
- /* This is an old Msg; we know of a newer incarnation, so drop
- the message */
- KMDTrace("HOTSUpDown", 2, "Dropping old msg #%d from %d of %s\n",
- hdr->MsgSeq, hdr->MsgSrc, 4+ctime(&hdr->SrcIncarnationId));
- return(MMSF_NodeDown);
- }
- return(MMSS_Success);
- }
-
- /****************************************************************
- * Snapshots to modify Dead/Alive status of nodes. *
- ****************************************************************/
-
- void PullUp(fLNN)
- int fLNN;
- /* Force this node to think that the node specified by LNN is Alive. */
- {
- HOTSRecord *hptmp;
-
- if ( mSUCCESS( HOTSSearchPtr(fLNN, &hptmp) ) ) {
- /* The node is in the HOTS - use ChangeHOTS. */
- if ( (hptmp->NodeStat != Dead) || (hptmp->NodeStat != Dead) ) {
- KMDPrint("Node %d not considered Dead - nothing changed.\n",
- fLNN);
- KMDPrint(" (use PullDown first)\n");
- } else {
- KMDPrint("Setting node %d to Alive.\n", fLNN);
- ChangeHOTS(fLNN, Alive);
- }
- } else {
- KMDPrint("Can't find node %d in HOTS.\n", fLNN);
- }
- }
-
- void PullDown(fLNN)
- int fLNN;
- /* Force this node to think that the node specified by LNN is Dead
- by calling ChangeHOTS */
- {
- HOTSRecord *hptmp;
-
- if ( mSUCCESS( HOTSSearchPtr(fLNN, &hptmp) ) ) {
- ChangeHOTS(fLNN, Dead);
- KMDPrint("Node %d declared Dead.\n", fLNN);
- } else {
- KMDPrint("Can't find node %d in HOTS.\n", fLNN);
- }
- }
-
- /*
- * General failure routine to save some space. Never returns.
- */
- /*VARARGS*/
- static CantDoIt( fString, fStatus )
- char *fString;
- KKStatus fStatus;
- {
- ErrMsg("Can't initialize %s: %08x....\n",fString,fStatus);
- PutEdenMsg((int)fStatus, (FILE *)0, (char **)0);
- #ifdef BSD
- system("Whatisup");
- #endif
- exit(3);
- }
-
- /*
- * Initializes the HOTS table stuff.
- */
- void InitHOTS(fPort)
- int fPort;
- {
- KKStatus lStatus;
-
- KMDSetTrace(HOTSUpDown);
-
- /* Create an empty HOTS. */
- lStatus = HOTSCreate();
- if (!mSUCCESS(lStatus))
- CantDoIt("HOTS");
-
- /* Asociate BigRetransCountHandler routine with event BIGRETRANSCOUNT */
- lStatus = MMDefineUpcallHandler((HandlerPtr) BigRetransCountHandler,
- BIGRETRANSCOUNT);
- if (!mSUCCESS(lStatus))
- CantDoIt("BigRetransCount Handler");
-
- /* Associate HOTSSearchPtr routine with event HOTSSEARCHPTR */
- lStatus = MMDefineUpcallHandler((HandlerPtr) HOTSSearchPtr,
- HOTSSEARCHPTR);
- if (!mSUCCESS(lStatus))
- CantDoIt("HOTSSearchPtr Handler");
-
- /* Associate HOTSCheckMsgSrc routine with event CHECKMSG */
- lStatus = MMDefineUpcallHandler((HandlerPtr) CheckMsgSrc, CHECKMSG);
- if (!mSUCCESS(lStatus))
- CantDoIt("CheckMsgSrc Handler");
-
- /* Associate EdenPortDeathHandler routine with event EDENPORTDEATH */
- lStatus = MMDefineUpcallHandler((HandlerPtr) EdenPortDeathHandler,
- EDENPORTDEATH);
- if (!mSUCCESS(lStatus))
- CantDoIt("EdenPortDeath Handler");
-
- /* Associate NoHOTSEntryHandler routine with event NOHOTSENTRY */
- lStatus = MMDefineUpcallHandler((HandlerPtr) NoHOTSEntryHandler,
- NOHOTSENTRY);
- if (!mSUCCESS(lStatus))
- CantDoIt("NoHOTSEntry Handler");
-
- /* NOTE: these calls to define upcall handlers MUST be executed before
- calling MMInitMsgModule for the first time, since MMInitMsgModule
- makes use of these upcalls */
-
- /* Init the MM. */
- lStatus = MMInitMsgModule(fPort);
- if (!mSUCCESS(lStatus))
- CantDoIt("MM");
-
- /* Define PullUp and PullDown snapshots for fudging the Dead/Alive
- status of known nodes.
- Note, these call should not be necessary after the boot protocol
- has been fixed, Eric Jul, 1986-05-28 */
-
- KMDSetSnap(PullUp);
- KMDSetSnap(PullDown);
-
- return;
- }
-
- /***********************************************************************/
-
- /*ARGSUSED*/
- void AddHOTS(fAddr, fLNN, fNodeType, fState, fIncarnationId)
- EtherNetAddress fAddr;
- NodeNum fLNN;
- BitMap32 fNodeType;
- NodeStatus fState;
- time_t fIncarnationId;
- {
- KKStatus lStatus;
- HOTSRecord *hotp, hot;
- time_t theTime = time((time_t *) 0);
- char now[200];
-
- (void) strcpy(now, 4+ctime(&theTime));
-
- KMDTrace("HOTSUpDown", 5, "AddHOTS LNN %d of %.15s, state: %s\n",
- fLNN, 4+ctime(&fIncarnationId), NodeStatNames[(int) fState]);
- lStatus = HOTSSearchPtr(fLNN, &hotp);
- /* We have to split into two cases depending on
- whether we have heard from the node before. */
- if (!mSUCCESS(lStatus)) {
- KMDTrace("HOTSUpDown", 2, "AddHOTS: New LNN %d of %.15s\n", fLNN,
- 4+ctime(&fIncarnationId));
- hot.LNN = fLNN;
- hot.NodeStat = fState;
- hot.NodeIsLocal = mEtherIsEqual(&fAddr, &MMLocalEtherNet);
- hot.NodeNetPort = NULLEDENPORT;
- hot.NodeIncarnationId = fIncarnationId;
- hot.LastMsgTs = time((time_t *) 0);
- hot.incomingLMQueue = (struct LMMsg *) NULL;
- mEtherCopy(&fAddr, &(hot.EtherAddr));
- lStatus = HOTSInsert(hot);
- if (!mSUCCESS(lStatus)) {
- ErrMsg(">>> AddHOTS: HOTSInsert failure: 0x%08x\n",
- lStatus);
- return;
- };
- /* Now we unfortunately must look it up - HOTSInsert does not
- give us the pointer back. (Stupid.) */
- lStatus = HOTSSearchPtr(fLNN, &hotp);
- if (!mSUCCESS(lStatus)) {
- ErrMsg(">>> AddHOTS: Bad HOTSSearchPtr status: 0x%08x\n",
- lStatus);
- return;
- };
- MMInitHOTSEntry(hotp); /* Initialize protocol part. */
-
- KMDTrace("HOTSUpDown", 1,
- "%-15.15s: AddHOTS LNN %d of %.15s @ %s\n",
- now, (int) fLNN,
- 4+ctime(&hotp->NodeIncarnationId),
- mGetHostName(&(hotp->EtherAddr)));
- ScheduleBootReply(fLNN);
- if (fState == Alive) NodeStateChanged(hotp);
- } else {
- /* Was already in HOTS, check incarnation id */
- if (hotp->NodeIncarnationId < fIncarnationId) {
- /* Kill off the old one. */
- KMDTrace("HOTSUpDown", 3, "AddHOTS: killing LNN %d, incarnation %.15s\n",
- fLNN, 4+ctime(&hotp->NodeIncarnationId));
- ChangeHOTS(fLNN, Dead);
- /* Now the previous incarnation has been purged. */
- /* Start up a new one. */
- hotp->NodeIsLocal = mEtherIsEqual(&fAddr, &MMLocalEtherNet);
- hotp->NodeNetPort = NULLEDENPORT;
- hotp->NodeIncarnationId = fIncarnationId;
- mEtherCopy(&fAddr, &(hotp->EtherAddr));
- MMInitHOTSEntry(hotp); /* Initialize protocol part. */
- ChangeHOTS(fLNN, fState);
- } else {
- /* Our HOTS table contains a reference to the right stuff */
- ChangeHOTS(fLNN, fState);
- }
- }
- }
-
-
- /**********************************************************************/
- /* ChangeHOTS */
- /**********************************************************************/
- void ChangeHOTS(fLNN, fNewState)
- NodeNum fLNN;
- NodeStatus fNewState;
- {
- KKStatus lStatus;
- HOTSRecord *hotp;
- NodeStatus oldstat;
- time_t theTime = time((time_t *) 0);
- char now[200];
-
- (void) strcpy(now, 4+ctime(&theTime));
-
- KMDTrace("HOTSUpDown", 6,"ChangeHOTS: LNN %d, newstate = %s\n", fLNN,
- NodeStatNames[(int) fNewState]);
-
- lStatus = HOTSSearchPtr(fLNN, &hotp);
- if (!mSUCCESS(lStatus)) {
- ErrMsg("ChangeHOTS: Can't find LNN %04x in HOTS: 0x%08x...\n",
- (int) fLNN, lStatus);
- (void) PutEdenMsg((int)lStatus, (FILE *)0, (char **)0);
- return;
- }
- oldstat = hotp->NodeStat;
- KMDTrace("HOTSUpDown", 5, " oldstate = %s, newstate = %s\n",
- NodeStatNames[(int) oldstat], NodeStatNames[(int) fNewState]);
- hotp->NodeStat = fNewState;
- hotp->LastMsgTs = time((time_t *) 0);
- KMDTrace("HOTSUpDown", 3,
- "%-15.15s: ChangeHOTS LNN %d of %.15s @ %s from %s to %s\n",
- now, (int) fLNN,
- 4+ctime(&hotp->NodeIncarnationId),
- mGetHostName(&(hotp->EtherAddr)),
- NodeStatNames[(int) oldstat], NodeStatNames[(int) fNewState]);
- /*
- * Cleanup any lines of communication between ourselves
- * and the remote node.
- */
- if ( 1 == Cleanup[(int) oldstat][(int) fNewState] ) {
- /* Null the port. */
- hotp->NodeNetPort = NULLEDENPORT;
- MMRemoteNodeDeath(hotp);
- };
- if ( (oldstat != fNewState) && ((fNewState == Booting)
- || (fNewState == Alive))) {
- ScheduleBootReply(fLNN);
- };
-
- if ((oldstat != fNewState) && ((fNewState == Alive) ||
- fNewState == Dead)) NodeStateChanged(hotp);
- }
-