From 80bce1a5bbe549dc817ea47fc032a22d83135321 Mon Sep 17 00:00:00 2001 From: Jacob Hageman Date: Tue, 6 Oct 2020 14:51:49 -0400 Subject: [PATCH] WIP - core compiles --- fsw/cfe-core/src/inc/cfe_sb_extern_typedefs.h | 2 +- fsw/cfe-core/src/inc/cfe_sb_msg.h | 4 +- .../inc/private/cfe_sb_destination_typedef.h | 52 ++ fsw/cfe-core/src/sb/cfe_sb_api.c | 286 ++++------- fsw/cfe-core/src/sb/cfe_sb_init.c | 69 +-- fsw/cfe-core/src/sb/cfe_sb_msg_id_util.c | 23 - fsw/cfe-core/src/sb/cfe_sb_priv.c | 364 +++---------- fsw/cfe-core/src/sb/cfe_sb_priv.h | 258 +--------- fsw/cfe-core/src/sb/cfe_sb_task.c | 480 ++++++++---------- fsw/cfe-core/src/sb/cfe_sbr.h | 236 +++++++++ fsw/cfe-core/src/sb/cfe_sbr_route.c | 201 ++++++++ 11 files changed, 927 insertions(+), 1048 deletions(-) create mode 100644 fsw/cfe-core/src/inc/private/cfe_sb_destination_typedef.h create mode 100644 fsw/cfe-core/src/sb/cfe_sbr.h create mode 100644 fsw/cfe-core/src/sb/cfe_sbr_route.c diff --git a/fsw/cfe-core/src/inc/cfe_sb_extern_typedefs.h b/fsw/cfe-core/src/inc/cfe_sb_extern_typedefs.h index 810355005..8eaea63e7 100644 --- a/fsw/cfe-core/src/inc/cfe_sb_extern_typedefs.h +++ b/fsw/cfe-core/src/inc/cfe_sb_extern_typedefs.h @@ -88,7 +88,7 @@ typedef uint8 CFE_SB_QosReliability_E /** * @brief An integer type that should be used for indexing into the Routing Table */ -typedef uint16 CFE_SB_MsgRouteIdx_Atom_t; +typedef uint16 CFE_SB_RouteId_Atom_t; /** * @brief CFE_SB_MsgId_Atom_t primitive type definition diff --git a/fsw/cfe-core/src/inc/cfe_sb_msg.h b/fsw/cfe-core/src/inc/cfe_sb_msg.h index f8ad212bc..03407b0c9 100644 --- a/fsw/cfe-core/src/inc/cfe_sb_msg.h +++ b/fsw/cfe-core/src/inc/cfe_sb_msg.h @@ -683,8 +683,8 @@ typedef struct CFE_SB_RoutingFileEntry { ** Structure of one element of the map information in response to #CFE_SB_SEND_MAP_INFO_CC */ typedef struct CFE_SB_MsgMapFileEntry { - CFE_SB_MsgId_t MsgId;/**< \brief Message Id which has been subscribed to */ - CFE_SB_MsgRouteIdx_Atom_t Index;/**< \brief Routing table index where pipe destinations are found */ + CFE_SB_MsgId_t MsgId;/**< \brief Message Id which has been subscribed to */ + CFE_SB_RouteId_Atom_t Index;/**< \brief Routing raw index value (0 based, not Route ID) */ }CFE_SB_MsgMapFileEntry_t; diff --git a/fsw/cfe-core/src/inc/private/cfe_sb_destination_typedef.h b/fsw/cfe-core/src/inc/private/cfe_sb_destination_typedef.h new file mode 100644 index 000000000..8627b8476 --- /dev/null +++ b/fsw/cfe-core/src/inc/private/cfe_sb_destination_typedef.h @@ -0,0 +1,52 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/** + * Definition of the CFE_SB_DestinationD_t type. + * This was moved into its own header file since it is referenced by multiple CFE modules. + */ + +#ifndef CFE_SB_DESTINATION_TYPEDEF_H_ +#define CFE_SB_DESTINATION_TYPEDEF_H_ + +#include "common_types.h" +#include "cfe_sb.h" /* Required for CFE_SB_PipeId_t definition */ + +/****************************************************************************** + * This structure defines a DESTINATION DESCRIPTOR used to specify + * each destination pipe for a message. + * + * Note: Changing the size of this structure may require the memory pool + * block sizes to change. + */ +typedef struct +{ + CFE_SB_PipeId_t PipeId; + uint8 Active; + uint16 MsgId2PipeLim; + uint16 BuffCount; + uint16 DestCnt; + uint8 Scope; + uint8 Spare[3]; + void *Prev; + void *Next; +} CFE_SB_DestinationD_t; + +#endif /* CFE_SB_DESTINATION_TYPEDEF_H_ */ diff --git a/fsw/cfe-core/src/sb/cfe_sb_api.c b/fsw/cfe-core/src/sb/cfe_sb_api.c index 44a7019a6..19b2ffd9c 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_api.c +++ b/fsw/cfe-core/src/sb/cfe_sb_api.c @@ -246,7 +246,23 @@ int32 CFE_SB_DeletePipeWithAppId(CFE_SB_PipeId_t PipeId, CFE_ES_ResourceID_t App }/* end CFE_SB_DeletePipeWithAppId */ +/****************************************************************************** + * Local callback helper for deleting a pipe from a route + */ +void CFE_SB_RemovePipeFromRoute(CFE_SBR_RouteId_t RouteId, void *ArgPtr) +{ + CFE_SB_DestinationD_t *destptr; + CFE_SB_PipeId_t *pipeidptr; + pipeidptr = (CFE_SB_PipeId_t *)ArgPtr; + + destptr = CFE_SB_GetDestPtr(RouteId, *pipeidptr); + + if (destptr != NULL) + { + CFE_SB_RemoveDest(RouteId, destptr); + } +} /****************************************************************************** ** Function: CFE_SB_DeletePipeFull() @@ -265,14 +281,13 @@ int32 CFE_SB_DeletePipeWithAppId(CFE_SB_PipeId_t PipeId, CFE_ES_ResourceID_t App */ int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId) { - uint8 PipeTblIdx; - int32 RtnFromVal,Stat; - CFE_ES_ResourceID_t Owner; - uint32 i; - CFE_ES_ResourceID_t TskId; - CFE_SB_Msg_t *PipeMsgPtr; - CFE_SB_DestinationD_t *DestPtr = NULL; - char FullName[(OS_MAX_API_NAME * 2)]; + uint8 PipeTblIdx; + int32 RtnFromVal; + int32 Stat; + CFE_ES_ResourceID_t Owner; + CFE_ES_ResourceID_t TskId; + CFE_SB_Msg_t *PipeMsgPtr; + char FullName[(OS_MAX_API_NAME * 2)]; /* get TaskId of caller for events */ CFE_ES_GetTaskID(&TskId); @@ -306,30 +321,8 @@ int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId) return CFE_SB_BAD_ARGUMENT; }/* end if */ - /* check destination list of every in-use MsgId, for the given pipeid. */ - /* when found, remove the pipe ID from the destination list via 'unsubscribe' */ - for(i=0;i PipeId == PipeId){ - /* release the semaphore, unsubscribe will need to take it */ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_SB_UnsubscribeWithAppId(CFE_SB.RoutingTbl[i].MsgId, - PipeId,AppId); - CFE_SB_LockSharedData(__func__,__LINE__); - }/* end if */ - - DestPtr = DestPtr -> Next; - - }/* end while */ - - }/* end if */ - }/* end for */ + /* Remove the pipe from all routes */ + CFE_SBR_ForEachRouteId(CFE_SB_RemovePipeFromRoute, &PipeId); if (CFE_SB.PipeTbl[PipeTblIdx].ToTrashBuff != NULL) { @@ -728,14 +721,13 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, uint16 MsgLim, uint8 Scope) { - CFE_SB_MsgRouteIdx_t RouteIdx; - CFE_SB_RouteEntry_t* RoutePtr; + CFE_SBR_RouteId_t RouteId; int32 Stat; - CFE_SB_MsgKey_t MsgKey; CFE_ES_ResourceID_t TskId; CFE_ES_ResourceID_t AppId; uint8 PipeIdx; - CFE_SB_DestinationD_t *DestBlkPtr = NULL; + CFE_SB_DestinationD_t *DestPtr = NULL; + uint32 DestCount = 0; char FullName[(OS_MAX_API_NAME * 2)]; char PipeName[OS_MAX_API_NAME] = {'\0'}; @@ -783,48 +775,44 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, return CFE_SB_BAD_ARGUMENT; }/* end if */ - /* Convert the API MsgId into the SB internal representation MsgKey */ - MsgKey = CFE_SB_ConvertMsgIdtoMsgKey(MsgId); - - /* check for duplicate subscription */ - if(CFE_SB_DuplicateSubscribeCheck(MsgKey,PipeId)==CFE_SB_DUPLICATE){ - CFE_SB.HKTlmMsg.Payload.DuplicateSubscriptionsCounter++; - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_DUP_SUBSCRIP_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, - "Duplicate Subscription,MsgId 0x%x on %s pipe,app %s", - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName,CFE_SB_GetAppTskName(TskId,FullName)); - return CFE_SUCCESS; - }/* end if */ - - /* - ** If there has been a subscription for this message id earlier, - ** get the element number in the routing table. - */ - RouteIdx = CFE_SB_GetRoutingTblIdx(MsgKey); - - /* if not first subscription for this message KEY ... */ - if(CFE_SB_IsValidRouteIdx(RouteIdx)) + RouteId = CFE_SBR_GetRouteId(MsgId); + if (CFE_SBR_IsValidRouteId(RouteId)) { - RoutePtr = CFE_SB_GetRoutePtrFromIdx(RouteIdx); + /* check for duplicate subscription */ + if(CFE_SB_GetDestPtr(RouteId, PipeId) != NULL) + { + CFE_SB.HKTlmMsg.Payload.DuplicateSubscriptionsCounter++; + CFE_SB_UnlockSharedData(__func__,__LINE__); + CFE_EVS_SendEventWithAppID(CFE_SB_DUP_SUBSCRIP_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, + "Duplicate Subscription,MsgId 0x%x on %s pipe,app %s", + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName,CFE_SB_GetAppTskName(TskId,FullName)); + return CFE_SUCCESS; + } - /* - * FIXME: If a hash or other conversion is used between MsgId and MsgKey, - * then it is possible that this existing route is for a different MsgId. - * - * The MsgId should be checked against the "MsgId" in the route here. - * - * However it is not possible to have a mismatch in the default case where - * MsgKey == MsgId - */ + /* Check for destination limit */ + for (DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) + { + DestCount++; + } + if(DestCount >= CFE_PLATFORM_SB_MAX_DEST_PER_PKT){ + CFE_SB_UnlockSharedData(__func__,__LINE__); + CFE_EVS_SendEventWithAppID(CFE_SB_MAX_DESTS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, + "Subscribe Err:Max Dests(%d)In Use For Msg 0x%x,pipe %s,app %s", + CFE_PLATFORM_SB_MAX_DEST_PER_PKT, + (unsigned int)CFE_SB_MsgIdToValue(MsgId), + PipeName, CFE_SB_GetAppTskName(TskId,FullName)); + + return CFE_SB_MAX_DESTS_MET; + } } else { - /* Get the index to the first available element in the routing table */ - RouteIdx = CFE_SB_RouteIdxPop_Unsync(); + /* Add the route */ + RouteId = CFE_SBR_AddRoute(MsgId); /* if all routing table elements are used, send event */ - if(!CFE_SB_IsValidRouteIdx(RouteIdx)){ + if(CFE_SBR_IsValidRouteId(RouteId)){ CFE_SB_UnlockSharedData(__func__,__LINE__); CFE_EVS_SendEventWithAppID(CFE_SB_MAX_MSGS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, "Subscribe Err:Max Msgs(%d)In Use,MsgId 0x%x,pipe %s,app %s", @@ -841,28 +829,10 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, CFE_SB.StatTlmMsg.Payload.PeakMsgIdsInUse = CFE_SB.StatTlmMsg.Payload.MsgIdsInUse; }/* end if */ - /* populate the look up table with the routing table index */ - CFE_SB_SetRoutingTblIdx(MsgKey,RouteIdx); - - /* label the new routing block with the message identifier */ - RoutePtr = CFE_SB_GetRoutePtrFromIdx(RouteIdx); - RoutePtr->MsgId = MsgId; - }/* end if */ - if(RoutePtr->Destinations >= CFE_PLATFORM_SB_MAX_DEST_PER_PKT){ - CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_EVS_SendEventWithAppID(CFE_SB_MAX_DESTS_MET_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, - "Subscribe Err:Max Dests(%d)In Use For Msg 0x%x,pipe %s,app %s", - CFE_PLATFORM_SB_MAX_DEST_PER_PKT, - (unsigned int)CFE_SB_MsgIdToValue(MsgId), - PipeName, CFE_SB_GetAppTskName(TskId,FullName)); - - return CFE_SB_MAX_DESTS_MET; - }/* end if */ - - DestBlkPtr = CFE_SB_GetDestinationBlk(); - if(DestBlkPtr == NULL){ + DestPtr = CFE_SB_GetDestinationBlk(); + if(DestPtr == NULL){ CFE_SB_UnlockSharedData(__func__,__LINE__); CFE_EVS_SendEventWithAppID(CFE_SB_DEST_BLK_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, "Subscribe Err:Request for Destination Blk failed for Msg 0x%x", @@ -871,19 +841,17 @@ int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, }/* end if */ /* initialize destination block */ - DestBlkPtr -> PipeId = PipeId; - DestBlkPtr -> MsgId2PipeLim = (uint16)MsgLim; - DestBlkPtr -> Active = CFE_SB_ACTIVE; - DestBlkPtr -> BuffCount = 0; - DestBlkPtr -> DestCnt = 0; - DestBlkPtr -> Scope = Scope; - DestBlkPtr -> Prev = NULL; - DestBlkPtr -> Next = NULL; - - /* add destination block to head of list */ - CFE_SB_AddDest(RoutePtr, DestBlkPtr); - - RoutePtr->Destinations++; + DestPtr->PipeId = PipeId; + DestPtr->MsgId2PipeLim = (uint16)MsgLim; + DestPtr->Active = CFE_SB_ACTIVE; + DestPtr->BuffCount = 0; + DestPtr->DestCnt = 0; + DestPtr->Scope = Scope; + DestPtr->Prev = NULL; + DestPtr->Next = NULL; + + /* add destination node */ + CFE_SB_AddDestNode(RouteId, DestPtr); CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse++; if(CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse > CFE_SB.StatTlmMsg.Payload.PeakSubscriptionsInUse) @@ -1021,13 +989,12 @@ int32 CFE_SB_UnsubscribeWithAppId(CFE_SB_MsgId_t MsgId, int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, uint8 Scope,CFE_ES_ResourceID_t AppId) { - CFE_SB_MsgKey_t MsgKey; - CFE_SB_MsgRouteIdx_t RouteIdx; - CFE_SB_RouteEntry_t* RoutePtr; + CFE_SBR_RouteId_t RouteId; uint32 PipeIdx; CFE_ES_ResourceID_t TskId; CFE_SB_DestinationD_t *DestPtr = NULL; char FullName[(OS_MAX_API_NAME * 2)]; + char PipeName[OS_MAX_API_NAME] = {'\0'}; /* get TaskId of caller for events */ CFE_ES_GetTaskID(&TskId); @@ -1070,15 +1037,12 @@ int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, return CFE_SB_BAD_ARGUMENT; }/* end if */ - /* get index into routing table */ - MsgKey = CFE_SB_ConvertMsgIdtoMsgKey(MsgId); - RouteIdx = CFE_SB_GetRoutingTblIdx(MsgKey); + /* get routing pointer */ + RouteId = CFE_SBR_GetRouteId(MsgId); /* if there have never been subscriptions for this message id... */ - if(!CFE_SB_IsValidRouteIdx(RouteIdx)) + if(CFE_SBR_IsValidRouteId(RouteId)) { - char PipeName[OS_MAX_API_NAME] = {'\0'}; - CFE_SB_UnlockSharedData(__func__,__LINE__); CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); @@ -1090,22 +1054,13 @@ int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, return CFE_SUCCESS; }/* end if */ - RoutePtr = CFE_SB_GetRoutePtrFromIdx(RouteIdx); + /* Get the destination pointer */ + DestPtr = CFE_SB_GetDestPtr(RouteId, PipeId); - /* search the list for a matching pipe id */ - for (DestPtr = RoutePtr->ListHeadPtr; DestPtr != NULL && DestPtr->PipeId != PipeId; DestPtr = DestPtr->Next) - ; - - if(DestPtr) + if(DestPtr != NULL) { - /* match found, remove node from list */ - CFE_SB_RemoveDest(RoutePtr,DestPtr); - - /* return node to memory pool */ - CFE_SB_PutDestinationBlk(DestPtr); - - RoutePtr->Destinations--; - CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse--; + /* match found, remove destination */ + CFE_SB_RemoveDest(RouteId,DestPtr); CFE_EVS_SendEventWithAppID(CFE_SB_SUBSCRIPTION_REMOVED_EID,CFE_EVS_EventType_DEBUG,CFE_SB.AppId, "Subscription Removed:Msg 0x%x on pipe %d,app %s", @@ -1114,8 +1069,6 @@ int32 CFE_SB_UnsubscribeFull(CFE_SB_MsgId_t MsgId,CFE_SB_PipeId_t PipeId, } else { - char PipeName[OS_MAX_API_NAME] = {'\0'}; - CFE_SB_GetPipeName(PipeName, sizeof(PipeName), PipeId); CFE_EVS_SendEventWithAppID(CFE_SB_UNSUB_NO_SUBS_EID,CFE_EVS_EventType_INFORMATION,CFE_SB.AppId, @@ -1188,21 +1141,20 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, uint32 TlmCntIncrements, uint32 CopyMode) { - CFE_SB_MsgKey_t MsgKey; CFE_SB_MsgId_t MsgId; int32 Status; CFE_SB_DestinationD_t *DestPtr = NULL; CFE_SB_PipeD_t *PipeDscPtr; - CFE_SB_RouteEntry_t *RtgTblPtr; + CFE_SBR_RouteId_t RouteId; CFE_SB_BufferD_t *BufDscPtr; uint16 TotalMsgSize; - CFE_SB_MsgRouteIdx_t RtgTblIdx; CFE_ES_ResourceID_t AppId; CFE_ES_ResourceID_t TskId; uint32 i; char FullName[(OS_MAX_API_NAME * 2)]; CFE_SB_EventBuf_t SBSndErr; char PipeName[OS_MAX_API_NAME] = {'\0'}; + CFE_SB_PipeDepthStats_t *StatObj; SBSndErr.EvtsToSnd = 0; @@ -1262,16 +1214,15 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, return CFE_SB_MSG_TOO_BIG; }/* end if */ - MsgKey = CFE_SB_ConvertMsgIdtoMsgKey(MsgId); - /* take semaphore to prevent a task switch during this call */ CFE_SB_LockSharedData(__func__,__LINE__); - RtgTblIdx = CFE_SB_GetRoutingTblIdx(MsgKey); + /* Get the routing pointer */ + RouteId = CFE_SBR_GetRouteId(MsgId); /* if there have been no subscriptions for this pkt, */ /* increment the dropped pkt cnt, send event and return success */ - if(!CFE_SB_IsValidRouteIdx(RtgTblIdx)){ + if(!CFE_SBR_IsValidRouteId(RouteId)){ CFE_SB.HKTlmMsg.Payload.NoSubscribersCounter++; @@ -1329,30 +1280,16 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, memcpy( BufDscPtr->Buffer, MsgPtr, (uint16)TotalMsgSize ); } - /* Obtain the actual routing table entry from the selected index */ - RtgTblPtr = CFE_SB_GetRoutePtrFromIdx(RtgTblIdx); - /* For Tlm packets, increment the seq count if requested */ if((CFE_SB_GetPktType(MsgId)==CFE_SB_PKTTYPE_TLM) && (TlmCntIncrements==CFE_SB_INCREMENT_TLM)){ - RtgTblPtr->SeqCnt++; - CFE_SB_SetMsgSeqCnt((CFE_SB_Msg_t *)BufDscPtr->Buffer, - RtgTblPtr->SeqCnt); + CFE_SBR_IncrementSequenceCounter(RouteId); + CFE_SB_SetMsgSeqCnt((CFE_SB_Msg_t *)BufDscPtr->Buffer, CFE_SBR_GetSequenceCounter(RouteId)); }/* end if */ - /* At this point there must be at least one destination for pkt */ - /* Send the packet to all destinations */ - for (i=0, DestPtr = RtgTblPtr -> ListHeadPtr; - i < RtgTblPtr -> Destinations; i++, DestPtr = DestPtr -> Next) + for(DestPtr = CFE_SBR_GetDestListHeadPtr(RouteId); DestPtr != NULL; DestPtr = DestPtr->Next) { - /* The DestPtr should never be NULL in this loop, this is just extra - protection in case of the unforseen */ - if(DestPtr == NULL) - { - break; - } - if (DestPtr->Active == CFE_SB_INACTIVE) /* destination is active */ { continue; @@ -1383,42 +1320,41 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, ** Write the buffer descriptor to the queue of the pipe. If the write ** failed, log info and increment the pipe's error counter. */ - Status = OS_QueuePut(PipeDscPtr->SysQueueId,(void *)&BufDscPtr, - sizeof(CFE_SB_BufferD_t *),0); + Status = OS_QueuePut(PipeDscPtr->SysQueueId, (void *)&BufDscPtr, sizeof(CFE_SB_BufferD_t *), 0); - if (Status == OS_SUCCESS) { + if (Status == OS_SUCCESS) + { BufDscPtr->UseCount++; /* used for releasing buffer */ DestPtr->BuffCount++; /* used for checking MsgId2PipeLimit */ DestPtr->DestCnt++; /* used for statistics */ if (DestPtr->PipeId < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) { - CFE_SB_PipeDepthStats_t *StatObj = - &CFE_SB.StatTlmMsg.Payload.PipeDepthStats[DestPtr->PipeId]; + StatObj = &CFE_SB.StatTlmMsg.Payload.PipeDepthStats[DestPtr->PipeId]; StatObj->InUse++; - if(StatObj->InUse > StatObj->PeakInUse){ + if(StatObj->InUse > StatObj->PeakInUse) + { StatObj->PeakInUse = StatObj->InUse; }/* end if */ } - - }else if(Status == OS_QUEUE_FULL) { - + } + else if(Status == OS_QUEUE_FULL) + { SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_FULL_ERR_EID; SBSndErr.EvtsToSnd++; CFE_SB.HKTlmMsg.Payload.PipeOverflowErrorCounter++; PipeDscPtr->SendErrors++; - - - }else{ /* Unexpected error while writing to queue. */ - + } + else + { + /* Unexpected error while writing to queue. */ SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].PipeId = DestPtr->PipeId; SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].EventId = CFE_SB_Q_WR_ERR_EID; SBSndErr.EvtBuf[SBSndErr.EvtsToSnd].ErrStat = Status; SBSndErr.EvtsToSnd++; CFE_SB.HKTlmMsg.Payload.InternalErrorCounter++; PipeDscPtr->SendErrors++; - - }/*end if */ + }/*end if */ } /* end loop over destinations */ @@ -1434,7 +1370,6 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, /* release the semaphore */ CFE_SB_UnlockSharedData(__func__,__LINE__); - /* send an event for each pipe write error that may have occurred */ for(i=0;i < SBSndErr.EvtsToSnd; i++) { @@ -1451,7 +1386,7 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, CFE_EVS_SendEventWithAppID(CFE_SB_MSGID_LIM_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, "Msg Limit Err,MsgId 0x%x,pipe %s,sender %s", - (unsigned int)CFE_SB_MsgIdToValue(RtgTblPtr->MsgId), + (unsigned int)CFE_SB_MsgIdToValue(MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName)); /* clear the bit so the task may send this event again */ @@ -1470,7 +1405,7 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, CFE_EVS_SendEventWithAppID(CFE_SB_Q_FULL_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, "Pipe Overflow,MsgId 0x%x,pipe %s,sender %s", - (unsigned int)CFE_SB_MsgIdToValue(RtgTblPtr->MsgId), + (unsigned int)CFE_SB_MsgIdToValue(MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName)); /* clear the bit so the task may send this event again */ @@ -1486,7 +1421,7 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, CFE_EVS_SendEventWithAppID(CFE_SB_Q_WR_ERR_EID,CFE_EVS_EventType_ERROR,CFE_SB.AppId, "Pipe Write Err,MsgId 0x%x,pipe %s,sender %s,stat 0x%x", - (unsigned int)CFE_SB_MsgIdToValue(RtgTblPtr->MsgId), + (unsigned int)CFE_SB_MsgIdToValue(MsgId), PipeName, CFE_SB_GetAppTskName(TskId,FullName), (unsigned int)SBSndErr.EvtBuf[i].ErrStat); @@ -1497,7 +1432,6 @@ int32 CFE_SB_SendMsgFull(CFE_SB_Msg_t *MsgPtr, }/* end if */ } - return CFE_SUCCESS; }/* end CFE_SB_SendMsgFull */ @@ -1515,6 +1449,7 @@ int32 CFE_SB_RcvMsg(CFE_SB_MsgPtr_t *BufPtr, CFE_SB_BufferD_t *Message; CFE_SB_PipeD_t *PipeDscPtr; CFE_SB_DestinationD_t *DestPtr = NULL; + CFE_SBR_RouteId_t RouteId; CFE_ES_ResourceID_t TskId; char FullName[(OS_MAX_API_NAME * 2)]; @@ -1586,7 +1521,8 @@ int32 CFE_SB_RcvMsg(CFE_SB_MsgPtr_t *BufPtr, *BufPtr = (CFE_SB_MsgPtr_t) Message->Buffer; /* get pointer to destination to be used in decrementing msg limit cnt*/ - DestPtr = CFE_SB_GetDestPtr(CFE_SB_ConvertMsgIdtoMsgKey(PipeDscPtr->CurrentBuff->MsgId), PipeDscPtr->PipeId); + RouteId = CFE_SBR_GetRouteId(PipeDscPtr->CurrentBuff->MsgId); + DestPtr = CFE_SB_GetDestPtr(RouteId, PipeDscPtr->PipeId); /* ** DestPtr would be NULL if the msg is unsubscribed to while it is on @@ -1604,7 +1540,7 @@ int32 CFE_SB_RcvMsg(CFE_SB_MsgPtr_t *BufPtr, if (PipeDscPtr->PipeId < CFE_SB_TLM_PIPEDEPTHSTATS_SIZE) { - CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeDscPtr->PipeId].InUse--; + CFE_SB.StatTlmMsg.Payload.PipeDepthStats[PipeDscPtr->PipeId].InUse--; } }else{ diff --git a/fsw/cfe-core/src/sb/cfe_sb_init.c b/fsw/cfe-core/src/sb/cfe_sb_init.c index 3a831269a..5095e1f95 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_init.c +++ b/fsw/cfe-core/src/sb/cfe_sb_init.c @@ -112,15 +112,9 @@ int32 CFE_SB_EarlyInit (void) { /* Initialize the pipe table. */ CFE_SB_InitPipeTbl(); - /* Initialize the routing index look up table */ - CFE_SB_InitMsgMap(); + /* Initialize the routing module */ + CFE_SBR_Init(); - /* Initialize the routing table. */ - CFE_SB_InitRoutingTbl(); - - /* Initialize the APID to routing index map table */ - CFE_SB_InitIdxStack(); - /* Initialize the SB Statistics Pkt */ CFE_SB_InitMsg(&CFE_SB.StatTlmMsg, CFE_SB_ValueToMsgId(CFE_SB_STATS_TLM_MID), @@ -198,63 +192,4 @@ void CFE_SB_InitPipeTbl(void){ }/* end CFE_SB_InitPipeTbl */ - - -/****************************************************************************** -** Function: CFE_SB_InitMsgMap() -** -** Purpose: -** Initialize the Software Bus Message Map. -** -** Arguments: -** -** Notes: -** This function MUST be called before any SB API's are called. -** -** Return: -** none -*/ -void CFE_SB_InitMsgMap(void){ - - CFE_SB_MsgKey_Atom_t KeyVal; - - for (KeyVal=0; KeyVal < CFE_SB_MAX_NUMBER_OF_MSG_KEYS; KeyVal++) - { - CFE_SB.MsgMap[KeyVal] = CFE_SB_INVALID_ROUTE_IDX; - } - -}/* end CFE_SB_InitMsgMap */ - - - -/****************************************************************************** -** Function: CFE_SB_InitRoutingTbl() -** -** Purpose: -** Initialize the Software Bus Routing Table. -** -** Arguments: -** -** Notes: -** This function MUST be called before any SB API's are called. -** -** Return: -** none -*/ -void CFE_SB_InitRoutingTbl(void){ - - uint32 i; - - /* Initialize routing table */ - for(i=0;i -/****************************************************************************** -** Function: CFE_SB_InitIdxStack() -** -** Purpose: Initialize a push/pop stack of routing table indexes. -** On init each must be unique. After system initialization SB_Idx_top -** will always point/index to the next available routing table index -** -** Arguments: -** -** Return: -** None -*/ - -void CFE_SB_InitIdxStack(void) -{ - uint16 i; - - CFE_SB.RouteIdxTop = 0; - for (i=0; i= CFE_PLATFORM_SB_MAX_MSG_IDS) { - retValue = CFE_SB_INVALID_ROUTE_IDX; /* no more Idx remaining, all used */ - } else { - retValue = CFE_SB.RouteIdxStack[CFE_SB.RouteIdxTop]; - ++CFE_SB.RouteIdxTop; - } - - return (retValue); -} /* end CFE_SB_IdxPop_Unsync */ - - -/****************************************************************************** -** Function: CFE_SB_RouteIdxPush_Unsync() -** -** Purpose: -** SB internal function to return a Routing Table element to the available stack -** (CFE_SB_RouteEntry_t). Typically called when an application un-subscribes -** to a message. 0 is a valid idx. -** -** Assumptions, External Events, and Notes: -** Calls to this function assumed to be protected by a semaphore -** -** Arguments: -** None -** -** Return: -** None -*/ -void CFE_SB_RouteIdxPush_Unsync (CFE_SB_MsgRouteIdx_t idx) { - - /* This stack grows from 0 to (CFE_PLATFORM_SB_MAX_MSG_IDS - 1) */ - if (CFE_SB.RouteIdxTop > 0) { - --CFE_SB.RouteIdxTop; - CFE_SB.RouteIdxStack[CFE_SB.RouteIdxTop] = idx; - } -} /* end CFE_SB_IdxPush_Unsync */ /****************************************************************************** ** Function: CFE_SB_GetPipeIdx() @@ -363,176 +280,38 @@ CFE_SB_PipeD_t *CFE_SB_GetPipePtr(CFE_SB_PipeId_t PipeId) { }/* end CFE_SB_GetPipePtr */ - - /****************************************************************************** -** Function: CFE_SB_GetDestPtr() -** -** Purpose: -** SB internal function to get a pointer to the destination descriptor -** associated with the given message id/pipe id combination. +** SB internal function to get destination pointer given route ID +** and pipe ID. ** ** Arguments: -** MsgId : ID of the message -** PipeId : Pipe ID for the destination. -** -** Return: -** Pointer to the destination descriptor that corresponds to the msg/pipe -** combination. If the destination does not exist, return NULL. -*/ -CFE_SB_DestinationD_t *CFE_SB_GetDestPtr(CFE_SB_MsgKey_t MsgKey, - CFE_SB_PipeId_t PipeId){ - - CFE_SB_MsgRouteIdx_t Idx; - CFE_SB_DestinationD_t *DestPtr; - - Idx = CFE_SB_GetRoutingTblIdx(MsgKey); - - if(!CFE_SB_IsValidRouteIdx(Idx)) - { - return NULL; - }/* end if */ - - DestPtr = CFE_SB_GetRoutePtrFromIdx(Idx)->ListHeadPtr; - - while(DestPtr != NULL){ - - if(DestPtr -> PipeId == PipeId){ - return DestPtr; - }/* end if */ - - DestPtr = DestPtr->Next; - - }/* end while */ - - return NULL; - -}/* end CFE_SB_GetDestPtr */ - - - -/****************************************************************************** -** Function: CFE_SB_GetRoutingTblIdx() -** -** Purpose: -** SB internal function to get the index of the routing table element -** associated with the given message id. -** -** Assumptions: -** Calls to this are predicated by a call to CFE_SB_IsValidMsgKey -** which already check the MsgKey argument -** -** Arguments: -** MsgKey : ID of the message -** PipeId : Pipe ID for the destination. -** -** Return: -** Will return the index of the routing table element for the given message ID -*/ -CFE_SB_MsgRouteIdx_t CFE_SB_GetRoutingTblIdx(CFE_SB_MsgKey_t MsgKey){ - - return CFE_SB.MsgMap[CFE_SB_MsgKeyToValue(MsgKey)]; - -}/* end CFE_SB_GetRoutingTblIdx */ - - - -/****************************************************************************** -** Function: CFE_SB_SetRoutingTblIdx() -** -** Purpose: -** SB internal function to set a value in the message map. The "Value" is -** the routing table index of the given message ID. The message map is used -** for quick routing table index lookups of a given message ID. The cost of -** this quick lookup is 8K bytes of memory(for CCSDS). -** -** Assumptions: -** Calls to this are predicated by a call to CFE_SB_IsValidMsgKey -** which already check the MsgKey argument -** -** Arguments: -** MsgKey : ID of the message -** Value : value to set. -** -** Return: -** -*/ -void CFE_SB_SetRoutingTblIdx(CFE_SB_MsgKey_t MsgKey, CFE_SB_MsgRouteIdx_t Value){ - - CFE_SB.MsgMap[CFE_SB_MsgKeyToValue(MsgKey)] = Value; - -}/* end CFE_SB_SetRoutingTblIdx */ - - -/****************************************************************************** -** Function: CFE_SB_GetRoutePtrFromIdx() -** -** Purpose: -** SB internal function to obtain a pointer to a routing table entry -** based on a CFE_SB_MsgRouteIdx_t value. +** RouteId: Route ID +** PipeId : ID of the pipe ** ** Assumptions: -** Calls to this are predicated by a call to CFE_SB_IsValidRouteIdx -** which already check the RouteIdx argument -** -** Arguments: -** RouteIdx : ID of the route to get +** Must be protected by SB lock ** ** Return: -** Pointer to route entry -** +** Destination pointer if found or NULL */ -CFE_SB_RouteEntry_t* CFE_SB_GetRoutePtrFromIdx(CFE_SB_MsgRouteIdx_t RouteIdx) +CFE_SB_DestinationD_t *CFE_SB_GetDestPtr(CFE_SBR_RouteId_t RouteId, CFE_SB_PipeId_t PipeId) { - return &CFE_SB.RoutingTbl[CFE_SB_RouteIdxToValue(RouteIdx)]; -} /* end CFE_SB_GetRouteFromIdx */ - -/****************************************************************************** -** Function: CFE_SB_DuplicateSubscribeCheck() -** -** Purpose: -** SB internal function to check for a duplicate subscription. -** -** Arguments: -** MsgId : ID of the message -** PipeId : ID of the pipe -** -** Return: -** Will return CFE_SB_DUPLICATE if the given MsgId/PipeId subscription -** exists in SB routing tables, otherwise will return CFE_SB_NO_DUPLICATE. -*/ -int32 CFE_SB_DuplicateSubscribeCheck(CFE_SB_MsgKey_t MsgKey, - CFE_SB_PipeId_t PipeId){ - - CFE_SB_MsgRouteIdx_t Idx; - CFE_SB_DestinationD_t *DestPtr; + CFE_SB_DestinationD_t *destptr = NULL; - Idx = CFE_SB_GetRoutingTblIdx(MsgKey); + destptr = CFE_SBR_GetDestListHeadPtr(RouteId); - if(!CFE_SB_IsValidRouteIdx(Idx)) + /* Check all destinations */ + while(destptr != NULL) { - DestPtr = NULL; + if(destptr->PipeId == PipeId) + { + break; + } + destptr = destptr->Next; } - else - { - DestPtr = CFE_SB_GetRoutePtrFromIdx(Idx)->ListHeadPtr; - }/* end if */ - - while(DestPtr != NULL){ - - if(DestPtr -> PipeId == PipeId){ - return CFE_SB_DUPLICATE; - }/* end if */ - - DestPtr = DestPtr->Next; - - }/* end while */ - - return CFE_SB_NO_DUPLICATE; - -}/* end CFE_SB_DuplicateSubscribeCheck */ - + return destptr; +} /****************************************************************************** ** Function: CFE_SB_SetMsgSeqCnt() @@ -724,7 +503,7 @@ void CFE_SB_FinishSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit){ /****************************************************************************** -** Function: CFE_SB_AddDest() +** Function: CFE_SB_AddDestNode() ** ** Purpose: ** This function will add the given node to the head of the list. @@ -736,23 +515,23 @@ void CFE_SB_FinishSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit){ ** Return: ** */ -int32 CFE_SB_AddDest(CFE_SB_RouteEntry_t *RouteEntry, CFE_SB_DestinationD_t *NewNode){ +int32 CFE_SB_AddDestNode(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *NewNode){ CFE_SB_DestinationD_t *WBS;/* Will Be Second (WBS) node */ + CFE_SB_DestinationD_t *listheadptr; - /* if first node in list */ - if(RouteEntry->ListHeadPtr == NULL){ + listheadptr = CFE_SBR_GetDestListHeadPtr(RouteId); + /* if first node in list */ + if(listheadptr == NULL) + { /* initialize the new node */ NewNode->Next = NULL; NewNode->Prev = NULL; - - /* insert the new node */ - RouteEntry->ListHeadPtr = NewNode; - - }else{ - - WBS = RouteEntry->ListHeadPtr; + } + else + { + WBS = listheadptr; /* initialize the new node */ NewNode->Next = WBS; @@ -760,75 +539,80 @@ int32 CFE_SB_AddDest(CFE_SB_RouteEntry_t *RouteEntry, CFE_SB_DestinationD_t *New /* insert the new node */ WBS -> Prev = NewNode; - RouteEntry->ListHeadPtr = NewNode; - }/* end if */ - return CFE_SUCCESS; - -}/* CFE_SB_AddDest */ - + /* Update Head */ + CFE_SBR_SetDestListHeadPtr(RouteId, NewNode); + return CFE_SUCCESS; +} /****************************************************************************** -** Function: CFE_SB_RemoveDest() +** Remove a destination - Removes node, returns block, decrements counters ** -** Purpose: -** This function will remove the given node from the list. -** This function assumes there is at least one node in the list. +** Assumptions: +** At least one node in the list. +** Pointers are valid ** ** Arguments: ** RtgTblIdx - Routing table index ** Dest - Pointer to the destination block to remove from the list +*/ +void CFE_SB_RemoveDest(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *DestPtr) +{ + CFE_SB_RemoveDestNode(RouteId, DestPtr); + CFE_SB_PutDestinationBlk(DestPtr); + CFE_SB.StatTlmMsg.Payload.SubscriptionsInUse--; +} + + +/****************************************************************************** +** This function will remove the given node from the list. ** -** Return: +** Assumptions: +** At least one node in the list. +** Pointers are valid ** +** Arguments: +** RtgTblIdx - Routing table index +** Dest - Pointer to the destination block to remove from the list */ -int32 CFE_SB_RemoveDest(CFE_SB_RouteEntry_t *RouteEntry, CFE_SB_DestinationD_t *NodeToRemove){ - +void CFE_SB_RemoveDestNode(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *NodeToRemove) +{ CFE_SB_DestinationD_t *PrevNode; CFE_SB_DestinationD_t *NextNode; - /* if this is the only node in the list */ - if((NodeToRemove->Prev == NULL) && (NodeToRemove->Next == NULL)){ - - RouteEntry->ListHeadPtr = NULL; - - /* if first node in the list and list has more than one */ - }else if(NodeToRemove->Prev == NULL){ - + if((NodeToRemove->Prev == NULL) && (NodeToRemove->Next == NULL)) + { + /* Clear destinations if this is the only node in the list */ + CFE_SBR_SetDestListHeadPtr(RouteId, NULL); + } + else if(NodeToRemove->Prev == NULL) + { + /* First in the list, set the next node to list head */ NextNode = NodeToRemove->Next; - NextNode -> Prev = NULL; + CFE_SBR_SetDestListHeadPtr(RouteId, NextNode); + } + else if(NodeToRemove->Next == NULL){ - RouteEntry->ListHeadPtr = NextNode; - - /* if last node in the list and list has more than one */ - }else if(NodeToRemove->Next == NULL){ - + /* Last in the list, remove previous pointer */ PrevNode = NodeToRemove->Prev; - PrevNode -> Next = NULL; - - /* NodeToRemove has node(s) before and node(s) after */ - }else{ - + } + else + { + /* Middle of list, remove */ PrevNode = NodeToRemove->Prev; NextNode = NodeToRemove->Next; - PrevNode -> Next = NextNode; NextNode -> Prev = PrevNode; - - }/* end if */ - + } /* initialize the node before returning it to the heap */ NodeToRemove -> Next = NULL; NodeToRemove -> Prev = NULL; - - return CFE_SUCCESS; - -}/* CFE_SB_RemoveDest */ +} /****************************************************************************** diff --git a/fsw/cfe-core/src/sb/cfe_sb_priv.h b/fsw/cfe-core/src/sb/cfe_sb_priv.h index f0a3bdcfd..381ee5d8c 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_priv.h +++ b/fsw/cfe-core/src/sb/cfe_sb_priv.h @@ -37,17 +37,17 @@ */ #include "common_types.h" #include "private/cfe_private.h" +#include "private/cfe_sb_destination_typedef.h" #include "cfe_sb.h" #include "cfe_sb_msg.h" #include "cfe_time.h" #include "cfe_es.h" +#include "cfe_sbr.h" /* ** Macro Definitions */ -#define CFE_SB_INVALID_ROUTE_IDX ((CFE_SB_MsgRouteIdx_t){ .RouteIdx = 0 }) -#define CFE_SB_INVALID_MSG_KEY ((CFE_SB_MsgKey_t){ .KeyIdx = 0 }) #define CFE_SB_UNUSED_QUEUE OS_OBJECT_ID_UNDEFINED #define CFE_SB_INVALID_PIPE 0xFF #define CFE_SB_NO_DESTINATION 0xFF @@ -98,64 +98,10 @@ #define CFE_SB_Q_FULL_ERR_EID_BIT 3 #define CFE_SB_Q_WR_ERR_EID_BIT 4 -/* - * Using the default configuration where there is a 1:1 mapping between MsgID - * and message key values, the number of keys is equal to the number of MsgIDs. - * - * If using an alternative key function / hash, this may change. - */ -#define CFE_SB_MAX_NUMBER_OF_MSG_KEYS (1+CFE_PLATFORM_SB_HIGHEST_VALID_MSGID) /* ** Type Definitions */ - -/****************************************************************************** -** Typedef: CFE_SB_MsgKey_Atom_t -** -** Purpose: -** Defines the an integer type for the numeric key that is used for routing -** table lookups. This is the "raw value" type and typically should not -** be used directly, except by internal table lookups. -** -*/ -typedef uint32 CFE_SB_MsgKey_Atom_t; - -/****************************************************************************** -** Typedef: CFE_SB_MsgKey_t -** -** Purpose: -** This is a "holding structure" for the related integer CFE_SB_MsgKey_Atom_t values. -** This defines the data type that is stored in other structures and/or passed between -** software bus functions. -** -** It is implemented this way to improve type safety and help ensure that "MsgKey" -** values are not inadvertently exchanged with MsgId or Routing Index values. -** -*/ -typedef struct -{ - CFE_SB_MsgKey_Atom_t KeyIdx; /**< Holding value, do not use directly */ -} CFE_SB_MsgKey_t; - -/******************************************************************************/ -/** - * @brief An wrapper for holding a routing table index - * - * This is intended as a form of "strong typedef" where direct assignments should - * be restricted. Software bus uses numeric indexes into multiple tables to perform - * its duties, and it is important that these index values are distinct and separate - * and not mixed together. - * - * Using this holding structure prevents assignment directly into a different index - * or direct usage as numeric value. - */ -typedef struct -{ - CFE_SB_MsgRouteIdx_Atom_t RouteIdx; /**< Holding value, do not use directly in code */ -} CFE_SB_MsgRouteIdx_t; - - /****************************************************************************** ** Typedef: CFE_SB_BufferD_t ** @@ -174,31 +120,6 @@ typedef struct { void *Buffer; } CFE_SB_BufferD_t; - -/****************************************************************************** -** Typedef: CFE_SB_DestinationD_t -** -** Purpose: -** This structure defines a DESTINATION DESCRIPTOR used to specify -** each destination pipe for a message. -** -** Note: Changing the size of this structure may require the memory pool -** block sizes to change. -*/ - -typedef struct { - CFE_SB_PipeId_t PipeId; - uint8 Active; - uint16 MsgId2PipeLim; - uint16 BuffCount; - uint16 DestCnt; - uint8 Scope; - uint8 Spare[3]; - void *Prev; - void *Next; -} CFE_SB_DestinationD_t; - - /****************************************************************************** ** Typedef: CFE_SB_ZeroCopyD_t ** @@ -218,22 +139,6 @@ typedef struct { void *Prev; } CFE_SB_ZeroCopyD_t; - -/****************************************************************************** -** Typedef: CFE_SB_RouteEntry_t -** -** Purpose: -** This structure defines an entry in the routing table -*/ - -typedef struct { - CFE_SB_MsgId_t MsgId; /**< Original Message Id when the subscription was created */ - uint16 Destinations; - uint32 SeqCnt; - CFE_SB_DestinationD_t *ListHeadPtr; -} CFE_SB_RouteEntry_t; - - /****************************************************************************** ** Typedef: CFE_SB_PipeD_t ** @@ -257,8 +162,6 @@ typedef struct { CFE_SB_BufferD_t *ToTrashBuff; } CFE_SB_PipeD_t; - - /****************************************************************************** ** Typedef: CFE_SB_BufParams_t ** @@ -279,29 +182,24 @@ typedef struct { ** Purpose: ** This structure contains the SB global variables. */ -typedef struct { - osal_id_t SharedDataMutexId; - uint32 SubscriptionReporting; - uint32 SenderReporting; - CFE_ES_ResourceID_t AppId; - uint32 StopRecurseFlags[OS_MAX_TASKS]; - void *ZeroCopyTail; - CFE_SB_PipeD_t PipeTbl[CFE_PLATFORM_SB_MAX_PIPES]; - CFE_SB_HousekeepingTlm_t HKTlmMsg; - CFE_SB_StatsTlm_t StatTlmMsg; - CFE_SB_PipeId_t CmdPipe; - CFE_SB_Msg_t *CmdPipePktPtr; - CFE_SB_MemParams_t Mem; - CFE_SB_MsgRouteIdx_t MsgMap[CFE_SB_MAX_NUMBER_OF_MSG_KEYS]; - CFE_SB_RouteEntry_t RoutingTbl[CFE_PLATFORM_SB_MAX_MSG_IDS]; - CFE_SB_AllSubscriptionsTlm_t PrevSubMsg; - CFE_SB_SingleSubscriptionTlm_t SubRprtMsg; - CFE_EVS_BinFilter_t EventFilters[CFE_SB_MAX_CFG_FILE_EVENTS_TO_FILTER]; - - uint16 RouteIdxTop; - CFE_SB_MsgRouteIdx_t RouteIdxStack[CFE_PLATFORM_SB_MAX_MSG_IDS]; - -}cfe_sb_t; +typedef struct +{ + osal_id_t SharedDataMutexId; + uint32 SubscriptionReporting; + uint32 SenderReporting; + CFE_ES_ResourceID_t AppId; + uint32 StopRecurseFlags[OS_MAX_TASKS]; + void *ZeroCopyTail; + CFE_SB_PipeD_t PipeTbl[CFE_PLATFORM_SB_MAX_PIPES]; + CFE_SB_HousekeepingTlm_t HKTlmMsg; + CFE_SB_StatsTlm_t StatTlmMsg; + CFE_SB_PipeId_t CmdPipe; + CFE_SB_Msg_t *CmdPipePktPtr; + CFE_SB_MemParams_t Mem; + CFE_SB_AllSubscriptionsTlm_t PrevSubMsg; + CFE_SB_SingleSubscriptionTlm_t SubRprtMsg; + CFE_EVS_BinFilter_t EventFilters[CFE_SB_MAX_CFG_FILE_EVENTS_TO_FILTER]; +} cfe_sb_t; /****************************************************************************** @@ -336,13 +234,8 @@ typedef struct{ int32 CFE_SB_AppInit(void); int32 CFE_SB_InitBuffers(void); void CFE_SB_InitPipeTbl(void); -void CFE_SB_InitMsgMap(void); -void CFE_SB_InitRoutingTbl(void); void CFE_SB_InitIdxStack(void); void CFE_SB_ResetCounts(void); -void CFE_SB_RouteIdxPush_Unsync(CFE_SB_MsgRouteIdx_t idx); -CFE_SB_MsgRouteIdx_t CFE_SB_RouteIdxPop_Unsync(void); -CFE_SB_MsgKey_t CFE_SB_ConvertMsgIdtoMsgKey(CFE_SB_MsgId_t MsgId); void CFE_SB_LockSharedData(const char *FuncName, int32 LineNumber); void CFE_SB_UnlockSharedData(const char *FuncName, int32 LineNumber); void CFE_SB_ReleaseBuffer (CFE_SB_BufferD_t *bd, CFE_SB_DestinationD_t *dest); @@ -350,13 +243,9 @@ int32 CFE_SB_ReadQueue(CFE_SB_PipeD_t *PipeDscPtr,CFE_ES_ResourceID_t TskId, CFE_SB_TimeOut_t Time_Out,CFE_SB_BufferD_t **Message ); int32 CFE_SB_WriteQueue(CFE_SB_PipeD_t *pd,uint32 TskId, const CFE_SB_BufferD_t *bd,CFE_SB_MsgId_t MsgId ); -CFE_SB_MsgRouteIdx_t CFE_SB_GetRoutingTblIdx(CFE_SB_MsgKey_t MsgKey); uint8 CFE_SB_GetPipeIdx(CFE_SB_PipeId_t PipeId); int32 CFE_SB_ReturnBufferToPool(CFE_SB_BufferD_t *bd); void CFE_SB_ProcessCmdPipePkt(void); -int32 CFE_SB_DuplicateSubscribeCheck(CFE_SB_MsgKey_t MsgKey,CFE_SB_PipeId_t PipeId); -void CFE_SB_SetRoutingTblIdx(CFE_SB_MsgKey_t MsgKey, CFE_SB_MsgRouteIdx_t Value); -CFE_SB_RouteEntry_t* CFE_SB_GetRoutePtrFromIdx(CFE_SB_MsgRouteIdx_t RouteIdx); void CFE_SB_ResetCounters(void); void CFE_SB_SetMsgSeqCnt(CFE_SB_MsgPtr_t MsgPtr,uint32 Count); char *CFE_SB_GetAppTskName(CFE_ES_ResourceID_t TaskId, char* FullName); @@ -364,7 +253,6 @@ CFE_SB_BufferD_t *CFE_SB_GetBufferFromPool(CFE_SB_MsgId_t MsgId, uint16 Size); CFE_SB_BufferD_t *CFE_SB_GetBufferFromCaller(CFE_SB_MsgId_t MsgId, void *Address); CFE_SB_PipeD_t *CFE_SB_GetPipePtr(CFE_SB_PipeId_t PipeId); CFE_SB_PipeId_t CFE_SB_GetAvailPipeIdx(void); -CFE_SB_DestinationD_t *CFE_SB_GetDestPtr (CFE_SB_MsgKey_t MsgKey, CFE_SB_PipeId_t PipeId); int32 CFE_SB_DeletePipeWithAppId(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId); int32 CFE_SB_DeletePipeFull(CFE_SB_PipeId_t PipeId,CFE_ES_ResourceID_t AppId); int32 CFE_SB_SubscribeFull(CFE_SB_MsgId_t MsgId, @@ -390,14 +278,18 @@ int32 CFE_SB_ValidatePipeId(CFE_SB_PipeId_t PipeId); void CFE_SB_IncrCmdCtr(int32 status); void CFE_SB_FileWriteByteCntErr(const char *Filename,uint32 Requested,uint32 Actual); void CFE_SB_SetSubscriptionReporting(uint32 state); -uint32 CFE_SB_FindGlobalMsgIdCnt(void); uint32 CFE_SB_RequestToSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit); void CFE_SB_FinishSendEvent(CFE_ES_ResourceID_t TaskId, uint32 Bit); CFE_SB_DestinationD_t *CFE_SB_GetDestinationBlk(void); int32 CFE_SB_PutDestinationBlk(CFE_SB_DestinationD_t *Dest); -int32 CFE_SB_AddDest(CFE_SB_RouteEntry_t *RouteEntry, CFE_SB_DestinationD_t *NewNode); -int32 CFE_SB_RemoveDest(CFE_SB_RouteEntry_t *RouteEntry, CFE_SB_DestinationD_t *NodeToRemove); +int32 CFE_SB_AddDestNode(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *NewNode); +void CFE_SB_RemoveDestNode(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *NodeToRemove); + +void CFE_SB_RemoveDest(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *DestPtr); + +/* TODO document */ +CFE_SB_DestinationD_t *CFE_SB_GetDestPtr(CFE_SBR_RouteId_t RouteId, CFE_SB_PipeId_t PipeId); /*****************************************************************************/ /** @@ -452,101 +344,5 @@ int32 CFE_SB_SendPrevSubsCmd(const CFE_SB_SendPrevSubs_t *data); extern cfe_sb_t CFE_SB; - - -/* --------------------------------------------------------- - * HELPER FUNCTIONS FOR TYPE-SAFE WRAPPERS / HOLDING STRUCTS - * - * These functions implement the type conversions between "bare numbers" and - * the holding structures, as well as sanity tests for the holding structures. - * - * The data within the holding structures should never be directly in the app, - * one of these helpers should be used once it is verified that the conversion - * or use case is legitimate. - * --------------------------------------------------------- */ - -/** - * @brief Identifies whether a given CFE_SB_MsgKey_t is valid - * - * Implements a basic sanity check on the value provided - * - * @returns true if sanity checks passed, false otherwise. - */ -static inline bool CFE_SB_IsValidMsgKey(CFE_SB_MsgKey_t MsgKey) -{ - return (MsgKey.KeyIdx != 0 && MsgKey.KeyIdx <= CFE_SB_MAX_NUMBER_OF_MSG_KEYS); -} - -/** - * @brief Identifies whether a given CFE_SB_MsgRouteIdx_t is valid - * - * Implements a basic sanity check on the value provided - * - * @returns true if sanity checks passed, false otherwise. - */ -static inline bool CFE_SB_IsValidRouteIdx(CFE_SB_MsgRouteIdx_t RouteIdx) -{ - return (RouteIdx.RouteIdx != 0 && RouteIdx.RouteIdx <= CFE_PLATFORM_SB_MAX_MSG_IDS); -} - -/** - * @brief Converts between a CFE_SB_MsgKey_t and a raw value - * - * Converts the supplied value into a "bare number" suitable for performing - * array lookups or other tasks for which the holding structure cannot be used directly. - * - * Use with caution, as this removes the type safety information from the value. - * - * @note It is assumed the value has already been validated using CFE_SB_IsValidMsgKey() - * - * @returns The underlying index value - */ -static inline CFE_SB_MsgKey_Atom_t CFE_SB_MsgKeyToValue(CFE_SB_MsgKey_t MsgKey) -{ - return (MsgKey.KeyIdx - 1); -} - -/** - * @brief Converts between a CFE_SB_MsgKey_t and a raw value - * - * Converts the supplied "bare number" into a type-safe CFE_SB_MsgKey_t value - * - * @returns A CFE_SB_MsgKey_t value - */ -static inline CFE_SB_MsgKey_t CFE_SB_ValueToMsgKey(CFE_SB_MsgKey_Atom_t KeyIdx) -{ - return ((CFE_SB_MsgKey_t){ .KeyIdx = 1 + KeyIdx }); -} - -/** - * @brief Converts between a CFE_SB_MsgRouteIdx_t and a raw value - * - * Converts the supplied "bare number" into a type-safe CFE_SB_MsgRouteIdx_t value - * - * @returns A CFE_SB_MsgRouteIdx_t value - */ -static inline CFE_SB_MsgRouteIdx_t CFE_SB_ValueToRouteIdx(CFE_SB_MsgRouteIdx_Atom_t TableIdx) -{ - return ((CFE_SB_MsgRouteIdx_t){ .RouteIdx = 1 + TableIdx }); -} - -/** - * @brief Converts between a CFE_SB_MsgRouteIdx_t and a raw value - * - * Converts the supplied value into a "bare number" suitable for performing - * array lookups or other tasks for which the holding structure cannot be used directly. - * - * Use with caution, as this removes the type safety information from the value. - * - * @note It is assumed the value has already been validated using CFE_SB_IsValidRouteIdx() - * - * @returns The underlying index value - */ -static inline CFE_SB_MsgRouteIdx_Atom_t CFE_SB_RouteIdxToValue(CFE_SB_MsgRouteIdx_t RouteIdx) -{ - return (RouteIdx.RouteIdx - 1); -} - - #endif /* _cfe_sb_priv_ */ /*****************************************************************************/ diff --git a/fsw/cfe-core/src/sb/cfe_sb_task.c b/fsw/cfe-core/src/sb/cfe_sb_task.c index 3ead76756..c37d689c8 100644 --- a/fsw/cfe-core/src/sb/cfe_sb_task.c +++ b/fsw/cfe-core/src/sb/cfe_sb_task.c @@ -48,6 +48,15 @@ cfe_sb_t CFE_SB; CFE_SB_Qos_t CFE_SB_Default_Qos; +/* Local structure for file writing callbacks */ +typedef struct +{ + const char *Filename; /* File name for error reporting */ + osal_id_t Fd; /* File id for writing */ + uint32 FileSize; /* File size for reporting */ + uint32 EntryCount; /* Entry count for reporting */ + int32 Status; /* File write status */ +} CFE_SB_FileWriteCallback_t; /****************************************************************************** ** Function: CFE_SB_TaskMain() @@ -638,7 +647,7 @@ int32 CFE_SB_EnableRouteCmd(const CFE_SB_EnableRoute_t *data) return CFE_SUCCESS; }/* end if */ - DestPtr = CFE_SB_GetDestPtr(CFE_SB_ConvertMsgIdtoMsgKey(MsgId), PipeId); + DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), PipeId); if(DestPtr == NULL){ CFE_EVS_SendEvent(CFE_SB_ENBL_RTE1_EID,CFE_EVS_EventType_ERROR, "Enbl Route Cmd:Route does not exist.Msg 0x%x,Pipe %d", @@ -702,7 +711,7 @@ int32 CFE_SB_DisableRouteCmd(const CFE_SB_DisableRoute_t *data) return CFE_SUCCESS; }/* end if */ - DestPtr = CFE_SB_GetDestPtr(CFE_SB_ConvertMsgIdtoMsgKey(MsgId), PipeId); + DestPtr = CFE_SB_GetDestPtr(CFE_SBR_GetRouteId(MsgId), PipeId); if(DestPtr == NULL){ CFE_EVS_SendEvent(CFE_SB_DSBL_RTE1_EID,CFE_EVS_EventType_ERROR, "Disable Route Cmd:Route does not exist,Msg 0x%x,Pipe %d", @@ -843,6 +852,61 @@ int32 CFE_SB_SendMapInfoCmd(const CFE_SB_SendMapInfo_t *data) return CFE_SUCCESS; }/* end CFE_SB_SendMapInfoCmd */ +/****************************************************************************** + * Local callback helper for writing routing info to a file + */ +void CFE_SB_WriteRouteToFile(CFE_SBR_RouteId_t RouteId, void *ArgPtr) +{ + CFE_SB_FileWriteCallback_t *args; + CFE_SB_DestinationD_t *destptr; + CFE_SB_PipeD_t *pipedptr; + int32 status; + CFE_SB_RoutingFileEntry_t entry; + + /* Cast arguments for local use */ + args = (CFE_SB_FileWriteCallback_t *)ArgPtr; + + destptr = CFE_SBR_GetDestListHeadPtr(RouteId); + + while((destptr != NULL) && (args->Status != CFE_SB_FILE_IO_ERR)) + { + + pipedptr = CFE_SB_GetPipePtr(destptr->PipeId); + + /* If invalid id, continue on to next entry */ + if (pipedptr != NULL) + { + + entry.MsgId = CFE_SBR_GetMsgId(RouteId); + entry.PipeId = destptr->PipeId; + entry.State = destptr->Active; + entry.MsgCnt = destptr->DestCnt; + + entry.AppName[0] = 0; + /* + * NOTE: as long as CFE_ES_GetAppName() returns success, then it + * guarantees null termination of the output. Return code is not + * checked here (bad) but in case of error it does not seem to touch + * the buffer, therefore the initialization above will protect for now + */ + CFE_ES_GetAppName(entry.AppName, pipedptr->AppId, sizeof(entry.AppName)); + CFE_SB_GetPipeName(entry.PipeName, sizeof(entry.PipeName), entry.PipeId); + + status = OS_write (args->Fd, &entry, sizeof(CFE_SB_RoutingFileEntry_t)); + if(status != sizeof(CFE_SB_RoutingFileEntry_t)) + { + CFE_SB_FileWriteByteCntErr(args->Filename, sizeof(CFE_SB_RoutingFileEntry_t), status); + OS_close(args->Fd); + args->Status = CFE_SB_FILE_IO_ERR; + } + + args->FileSize += status; + args->EntryCount++; + } + + destptr = destptr->Next; + } +} /****************************************************************************** ** Function: CFE_SB_SendRoutingInfo() @@ -858,103 +922,49 @@ int32 CFE_SB_SendMapInfoCmd(const CFE_SB_SendMapInfo_t *data) */ int32 CFE_SB_SendRtgInfo(const char *Filename) { - CFE_SB_MsgRouteIdx_t RtgTblIdx; - const CFE_SB_RouteEntry_t* RtgTblPtr; - CFE_SB_MsgKey_Atom_t MsgKeyVal; - osal_id_t fd; + CFE_SB_FileWriteCallback_t args = {0}; int32 Status; - uint32 FileSize = 0; - uint32 EntryCount = 0; - CFE_SB_RoutingFileEntry_t Entry; CFE_FS_Header_t FileHdr; - CFE_SB_PipeD_t *pd; - CFE_SB_DestinationD_t *DestPtr; - Status = OS_OpenCreate(&fd, Filename, - OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); - if(Status < OS_SUCCESS){ - CFE_EVS_SendEvent(CFE_SB_SND_RTG_ERR1_EID,CFE_EVS_EventType_ERROR, + Status = OS_OpenCreate(&args.Fd, Filename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); + if(Status < OS_SUCCESS) + { + CFE_EVS_SendEvent(CFE_SB_SND_RTG_ERR1_EID, CFE_EVS_EventType_ERROR, "Error creating file %s, stat=0x%x", - Filename,(unsigned int)Status); + Filename, (unsigned int)Status); return CFE_SB_FILE_IO_ERR; - }/* end if */ + } /* clear out the cfe file header fields, then populate description and subtype */ CFE_FS_InitHeader(&FileHdr, "SB Routing Information", CFE_FS_SubType_SB_ROUTEDATA); - Status = CFE_FS_WriteHeader(fd, &FileHdr); - if(Status != sizeof(CFE_FS_Header_t)){ + Status = CFE_FS_WriteHeader(args.Fd, &FileHdr); + if(Status != sizeof(CFE_FS_Header_t)) + { CFE_SB_FileWriteByteCntErr(Filename,sizeof(CFE_FS_Header_t),Status); - OS_close(fd); + OS_close(args.Fd); return CFE_SB_FILE_IO_ERR; - }/* end if */ - - FileSize = Status; - - /* loop through the entire MsgMap */ - for(MsgKeyVal=0; MsgKeyVal < CFE_SB_MAX_NUMBER_OF_MSG_KEYS; ++MsgKeyVal) - { - RtgTblIdx = CFE_SB.MsgMap[MsgKeyVal]; - - /* Only process table entry if it is used. */ - if(!CFE_SB_IsValidRouteIdx(RtgTblIdx)) - { - DestPtr = NULL; - RtgTblPtr = NULL; - } - else - { - RtgTblPtr = CFE_SB_GetRoutePtrFromIdx(RtgTblIdx); - DestPtr = RtgTblPtr->ListHeadPtr; - } - - while(DestPtr != NULL){ - - pd = CFE_SB_GetPipePtr(DestPtr -> PipeId); - /* If invalid id, continue on to next entry */ - if (pd != NULL) { - - Entry.MsgId = RtgTblPtr->MsgId; - Entry.PipeId = DestPtr -> PipeId; - Entry.State = DestPtr -> Active; - Entry.MsgCnt = DestPtr -> DestCnt; - - Entry.AppName[0] = 0; - /* - * NOTE: as long as CFE_ES_GetAppName() returns success, then it - * guarantees null termination of the output. Return code is not - * checked here (bad) but in case of error it does not seem to touch - * the buffer, therefore the initialization above will protect for now - */ - CFE_ES_GetAppName(&Entry.AppName[0], pd->AppId, sizeof(Entry.AppName)); - CFE_SB_GetPipeName(Entry.PipeName, sizeof(Entry.PipeName), Entry.PipeId); - - Status = OS_write (fd, &Entry, sizeof(CFE_SB_RoutingFileEntry_t)); - if(Status != sizeof(CFE_SB_RoutingFileEntry_t)){ - CFE_SB_FileWriteByteCntErr(Filename, - sizeof(CFE_SB_RoutingFileEntry_t), - Status); - OS_close(fd); - return CFE_SB_FILE_IO_ERR; - }/* end if */ - - FileSize += Status; - EntryCount ++; - } - - DestPtr = DestPtr->Next; - - }/* end while */ - - }/* end for */ + } - OS_close(fd); + /* Initialize the reset of the nonzero callback argument elements */ + args.FileSize = Status; + args.Filename = Filename; - CFE_EVS_SendEvent(CFE_SB_SND_RTG_EID,CFE_EVS_EventType_DEBUG, - "%s written:Size=%d,Entries=%d", - Filename,(int)FileSize,(int)EntryCount); + /* Write route info to file in MsgId order */ + CFE_SBR_ForEachMsgId(CFE_SB_WriteRouteToFile, &args); - return CFE_SUCCESS; + if (args.Status != 0) + { + return args.Status; + } + else + { + OS_close(args.Fd); + CFE_EVS_SendEvent(CFE_SB_SND_RTG_EID,CFE_EVS_EventType_DEBUG, + "%s written:Size=%d,Entries=%d", + Filename, (int)args.FileSize, (int)args.EntryCount); + return CFE_SUCCESS; + } }/* end CFE_SB_SendRtgInfo */ @@ -1031,6 +1041,36 @@ int32 CFE_SB_SendPipeInfo(const char *Filename) }/* end CFE_SB_SendPipeInfo */ +/****************************************************************************** + * Local callback helper for writing map info to a file + */ +void CFE_SB_WriteMapToFile(CFE_SBR_RouteId_t RouteId, void *ArgPtr) +{ + CFE_SB_FileWriteCallback_t *args; + int32 status; + CFE_SB_MsgMapFileEntry_t entry; + + /* Cast arguments for local use */ + args = (CFE_SB_FileWriteCallback_t *)ArgPtr; + + if(args->Status != CFE_SB_FILE_IO_ERR) + { + entry.MsgId = CFE_SBR_GetMsgId(RouteId); + entry.Index = CFE_SBR_RouteIdToValue(RouteId); + + status = OS_write (args->Fd, &entry, sizeof(CFE_SB_MsgMapFileEntry_t)); + if(status != sizeof(CFE_SB_MsgMapFileEntry_t)) + { + CFE_SB_FileWriteByteCntErr(args->Filename, sizeof(CFE_SB_MsgMapFileEntry_t), status); + OS_close(args->Fd); + args->Status = CFE_SB_FILE_IO_ERR; + } + + args->FileSize += status; + args->EntryCount++; + } +} + /****************************************************************************** ** Function: CFE_SB_SendMapInfo() ** @@ -1045,73 +1085,103 @@ int32 CFE_SB_SendPipeInfo(const char *Filename) */ int32 CFE_SB_SendMapInfo(const char *Filename) { - const CFE_SB_RouteEntry_t* RtgTblPtr; - CFE_SB_MsgRouteIdx_t RtgTblIdx; - CFE_SB_MsgKey_Atom_t MsgKeyVal; - osal_id_t fd; - int32 Status; - uint32 FileSize = 0; - uint32 EntryCount = 0; - CFE_SB_MsgMapFileEntry_t Entry; - CFE_FS_Header_t FileHdr; + CFE_SB_FileWriteCallback_t args = {0}; + int32 Status; + CFE_FS_Header_t FileHdr; - Status = OS_OpenCreate(&fd, Filename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); + Status = OS_OpenCreate(&args.Fd, Filename, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY); - if (Status < OS_SUCCESS){ - CFE_EVS_SendEvent(CFE_SB_SND_RTG_ERR1_EID,CFE_EVS_EventType_ERROR, + if (Status < OS_SUCCESS) + { + CFE_EVS_SendEvent(CFE_SB_SND_RTG_ERR1_EID, CFE_EVS_EventType_ERROR, "Error creating file %s, stat=0x%x", - Filename,(unsigned int)Status); + Filename, (unsigned int)Status); return CFE_SB_FILE_IO_ERR; - }/* end if */ + } /* clear out the cfe file header fields, then populate description and subtype */ CFE_FS_InitHeader(&FileHdr, "SB Message Map Information", CFE_FS_SubType_SB_MAPDATA); - Status = CFE_FS_WriteHeader(fd, &FileHdr); - if(Status != sizeof(CFE_FS_Header_t)){ - CFE_SB_FileWriteByteCntErr(Filename,sizeof(CFE_FS_Header_t),Status); - OS_close(fd); - return CFE_SB_FILE_IO_ERR; - }/* end if */ - - FileSize = Status; - - /* loop through the entire MsgMap */ - for(MsgKeyVal=0; MsgKeyVal < CFE_SB_MAX_NUMBER_OF_MSG_KEYS; ++MsgKeyVal) + Status = CFE_FS_WriteHeader(args.Fd, &FileHdr); + if(Status != sizeof(CFE_FS_Header_t)) { - RtgTblIdx = CFE_SB_GetRoutingTblIdx(CFE_SB_ValueToMsgKey(MsgKeyVal)); + CFE_SB_FileWriteByteCntErr(Filename, sizeof(CFE_FS_Header_t), Status); + OS_close(args.Fd); + return CFE_SB_FILE_IO_ERR; + } - if(CFE_SB_IsValidRouteIdx(RtgTblIdx)) - { - RtgTblPtr = CFE_SB_GetRoutePtrFromIdx(RtgTblIdx); + /* Initialize the reset of the nonzero callback argument elements */ + args.FileSize = Status; + args.Filename = Filename; - Entry.MsgId = RtgTblPtr->MsgId; - Entry.Index = CFE_SB_RouteIdxToValue(RtgTblIdx); + /* Write route info to file in MsgId order */ + CFE_SBR_ForEachMsgId(CFE_SB_WriteMapToFile, &args); - Status = OS_write (fd, &Entry, sizeof(CFE_SB_MsgMapFileEntry_t)); - if(Status != sizeof(CFE_SB_MsgMapFileEntry_t)){ - CFE_SB_FileWriteByteCntErr(Filename,sizeof(CFE_SB_MsgMapFileEntry_t),Status); - OS_close(fd); - return CFE_SB_FILE_IO_ERR; - }/* end if */ + if (args.Status != 0) + { + return args.Status; + } + else + { + OS_close(args.Fd); + CFE_EVS_SendEvent(CFE_SB_SND_RTG_EID, CFE_EVS_EventType_DEBUG, + "%s written:Size=%d,Entries=%d", + Filename, (int)args.FileSize, (int)args.EntryCount); + return CFE_SUCCESS; + } +} - FileSize += Status; - EntryCount ++; +/****************************************************************************** + * Local callback helper for sending route subscriptions + */ +void CFE_SB_SendRouteSub(CFE_SBR_RouteId_t RouteId, void *ArgPtr) +{ + CFE_SB_DestinationD_t *destptr; + int32 status; - }/* end for */ - }/* end for */ + destptr = CFE_SBR_GetDestListHeadPtr(RouteId); - OS_close(fd); + /* Loop through destinations */ + while(destptr != NULL) + { - CFE_EVS_SendEvent(CFE_SB_SND_RTG_EID,CFE_EVS_EventType_DEBUG, - "%s written:Size=%d,Entries=%d", - Filename,(int)FileSize,(int)EntryCount); + if(destptr->Scope == CFE_SB_GLOBAL) + { - return CFE_SUCCESS; + /* ...add entry into pkt */ + CFE_SB.PrevSubMsg.Payload.Entry[CFE_SB.PrevSubMsg.Payload.Entries].MsgId = CFE_SBR_GetMsgId(RouteId); + CFE_SB.PrevSubMsg.Payload.Entry[CFE_SB.PrevSubMsg.Payload.Entries].Qos.Priority = 0; + CFE_SB.PrevSubMsg.Payload.Entry[CFE_SB.PrevSubMsg.Payload.Entries].Qos.Reliability = 0; + CFE_SB.PrevSubMsg.Payload.Entries++; + + /* send pkt if full */ + if(CFE_SB.PrevSubMsg.Payload.Entries >= CFE_SB_SUB_ENTRIES_PER_PKT) + { + CFE_SB_UnlockSharedData(__func__,__LINE__); + status = CFE_SB_SendMsg((CFE_SB_Msg_t *)&CFE_SB.PrevSubMsg); + CFE_SB_LockSharedData(__func__,__LINE__); + CFE_EVS_SendEvent(CFE_SB_FULL_SUB_PKT_EID, CFE_EVS_EventType_DEBUG, + "Full Sub Pkt %d Sent,Entries=%d,Stat=0x%x\n", + (int)CFE_SB.PrevSubMsg.Payload.PktSegment, + (int)CFE_SB.PrevSubMsg.Payload.Entries, (unsigned int)status); + CFE_SB.PrevSubMsg.Payload.Entries = 0; + CFE_SB.PrevSubMsg.Payload.PktSegment++; + } -}/* end CFE_SB_SendMapInfo */ + /* + * break while loop through destinations, onto next route + * This is done because we want only one network subscription per msgid + * Later when Qos is used, we may want to take just the highest priority + * subscription if there are more than one + */ + break; + } + /* Advance to next destination */ + destptr = destptr->Next; + } +} /****************************************************************************** ** Function: CFE_SB_SendPrevSubsCmd() @@ -1129,140 +1199,32 @@ int32 CFE_SB_SendMapInfo(const char *Filename) */ int32 CFE_SB_SendPrevSubsCmd(const CFE_SB_SendPrevSubs_t *data) { - CFE_SB_MsgRouteIdx_Atom_t i; - const CFE_SB_RouteEntry_t* RoutePtr; - uint32 EntryNum = 0; - uint32 SegNum = 1; - int32 Stat; - CFE_SB_DestinationD_t *DestPtr = NULL; - - /* Take semaphore to ensure data does not change during this function */ - CFE_SB_LockSharedData(__func__,__LINE__); - - /* seek msgids that are in use */ - for(i=0;iMsgId)) - { - DestPtr = NULL; - } - else - { - DestPtr = CFE_SB.RoutingTbl[i].ListHeadPtr; - } - - while(DestPtr != NULL){ - - if(DestPtr->Scope == CFE_SB_GLOBAL){ - - /* ...add entry into pkt */ - CFE_SB.PrevSubMsg.Payload.Entry[EntryNum].MsgId = RoutePtr->MsgId; - CFE_SB.PrevSubMsg.Payload.Entry[EntryNum].Qos.Priority = 0; - CFE_SB.PrevSubMsg.Payload.Entry[EntryNum].Qos.Reliability = 0; - EntryNum++; - - /* send pkt if full */ - if(EntryNum >= CFE_SB_SUB_ENTRIES_PER_PKT){ - CFE_SB.PrevSubMsg.Payload.PktSegment = SegNum; - CFE_SB.PrevSubMsg.Payload.Entries = EntryNum; - CFE_SB_UnlockSharedData(__func__,__LINE__); - Stat = CFE_SB_SendMsg((CFE_SB_Msg_t *)&CFE_SB.PrevSubMsg); - CFE_SB_LockSharedData(__func__,__LINE__); - CFE_EVS_SendEvent(CFE_SB_FULL_SUB_PKT_EID,CFE_EVS_EventType_DEBUG, - "Full Sub Pkt %d Sent,Entries=%d,Stat=0x%x\n",(int)SegNum,(int)EntryNum,(unsigned int)Stat); - EntryNum = 0; - SegNum++; - }/* end if */ - - /* break while loop through destinations, onto next CFE_SB.RoutingTbl index */ - /* This is done because we want only one network subscription per msgid */ - /* Later when Qos is used, we may want to take just the highest priority */ - /* subscription if there are more than one */ - break; - - }/* end if */ - - /* Check next destination (if another exists) for global scope */ - DestPtr = DestPtr -> Next; - - }/* end while */ - - }/* end for */ - - /* if pkt has any number of entries, send it as a partial pkt */ - if(EntryNum > 0){ - CFE_SB.PrevSubMsg.Payload.PktSegment = SegNum; - CFE_SB.PrevSubMsg.Payload.Entries = EntryNum; - CFE_SB_UnlockSharedData(__func__,__LINE__); - Stat = CFE_SB_SendMsg((CFE_SB_Msg_t *)&CFE_SB.PrevSubMsg); - CFE_SB_LockSharedData(__func__,__LINE__); - CFE_EVS_SendEvent(CFE_SB_PART_SUB_PKT_EID,CFE_EVS_EventType_DEBUG, - "Partial Sub Pkt %d Sent,Entries=%d,Stat=0x%x",(int)SegNum,(int)EntryNum,(unsigned int)Stat); - }/* end if */ + int32 status; - CFE_SB_UnlockSharedData(__func__,__LINE__); + /* Take semaphore to ensure data does not change during this function */ + CFE_SB_LockSharedData(__func__,__LINE__); - return CFE_SUCCESS; -}/* end CFE_SB_SendPrevSubsCmd */ + /* Initialize entry/segment tracking */ + CFE_SB.PrevSubMsg.Payload.PktSegment = 1; + CFE_SB.PrevSubMsg.Payload.Entries = 0; + /* Send subcription for each route */ + CFE_SBR_ForEachRouteId(CFE_SB_SendRouteSub, NULL); -/****************************************************************************** -** Function: CFE_SB_FindGlobalMsgIdCnt() -** -** Purpose: -** SB internal function to get a count of the global message ids in use. -** -** Notes: -** Subscriptions made with CFE_SB_SubscribeLocal would not be counted. -** Subscription made with a subscribe API other than CFE_SB_SubscribeLocal are -** considerd to be global subscriptions. MsgIds with both global and local -** subscriptions would be counted. -** -** Arguments: -** -** Return: -** None -*/ -uint32 CFE_SB_FindGlobalMsgIdCnt(void){ + CFE_SB_UnlockSharedData(__func__,__LINE__); - CFE_SB_MsgRouteIdx_Atom_t i; - uint32 cnt = 0; - const CFE_SB_RouteEntry_t* RoutePtr; - CFE_SB_DestinationD_t *DestPtr = NULL; - - for(i=0;i 0) { - RoutePtr = CFE_SB_GetRoutePtrFromIdx(CFE_SB_ValueToRouteIdx(i)); - if(!CFE_SB_IsValidMsgId(RoutePtr->MsgId)) - { - DestPtr = NULL; - } - else - { - DestPtr = RoutePtr->ListHeadPtr; - } - - while(DestPtr != NULL){ - - if(DestPtr->Scope == CFE_SB_GLOBAL){ - - cnt++; - break; - - }/* end if */ - - /* Check next destination (if another exists) for global scope */ - DestPtr = DestPtr -> Next; - - }/* end while */ - - }/* end for */ - - return cnt; - -}/* end CFE_SB_FindGlobalMsgIdCnt */ + status = CFE_SB_SendMsg((CFE_SB_Msg_t *)&CFE_SB.PrevSubMsg); + CFE_EVS_SendEvent(CFE_SB_PART_SUB_PKT_EID, CFE_EVS_EventType_DEBUG, + "Partial Sub Pkt %d Sent,Entries=%d,Stat=0x%x", + (int)CFE_SB.PrevSubMsg.Payload.PktSegment, (int)CFE_SB.PrevSubMsg.Payload.Entries, + (unsigned int)status); + } + return CFE_SUCCESS; +}/* end CFE_SB_SendPrevSubsCmd */ diff --git a/fsw/cfe-core/src/sb/cfe_sbr.h b/fsw/cfe-core/src/sb/cfe_sbr.h new file mode 100644 index 000000000..07ff5f981 --- /dev/null +++ b/fsw/cfe-core/src/sb/cfe_sbr.h @@ -0,0 +1,236 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/****************************************************************************** + * File: cfe_sbr.h + * + * Purpose: + * Prototypes for private functions and type definitions for SB + * routing internal use. + *****************************************************************************/ + +#ifndef CFE_SBR_H_ +#define CFE_SBR_H_ + +/* + * Includes + */ +#include "common_types.h" +#include "private/cfe_sb_destination_typedef.h" + +/* TODO prune */ +#include "private/cfe_private.h" +#include "cfe_sb.h" +#include "cfe_sb_msg.h" +#include "cfe_time.h" +#include "cfe_es.h" + +/* TODO split into local and API, keep entry and data local */ + +/* + * Macro Definitions + */ + +/** \brief Invalid route id */ +#define CFE_SBR_INVALID_ROUTE_ID ((CFE_SBR_RouteId_t){ .RouteId = 0 }) + +/** +* \brief Message map size +* TODO should be local! +* +* For direct mapping, map size is maximum valid MsgId value + 1 (since MsgId 0 is valid) +*/ +#define CFE_SBR_MSG_MAP_SIZE (CFE_PLATFORM_SB_HIGHEST_VALID_MSGID + 1) + +/****************************************************************************** + * Type Definitions + */ + +/** + * \brief Routing table id + * + * This is intended as a form of "strong typedef" where direct assignments should + * be restricted. Software bus uses numeric indexes into multiple tables to perform + * its duties, and it is important that these index values are distinct and separate + * and not mixed together. + * + * Using this holding structure prevents assignment directly into a different index + * or direct usage as numeric value. + */ +typedef struct +{ + CFE_SB_RouteId_Atom_t RouteId; /**< \brief Holding value, do not use directly in code */ +} CFE_SBR_RouteId_t; + +/** \brief Routing table entry */ +typedef struct +{ + CFE_SB_MsgId_t MsgId; /**< \brief Message ID associated with route */ + uint16 Destinations; /**< \brief Destinations counter TODO delete */ + uint32 SeqCnt; /**< \brief Message sequence counter */ + CFE_SB_DestinationD_t *ListHeadPtr; /**< \brief Destination list head */ +} CFE_SBR_RouteEntry_t; + +/** \brief Module data */ +typedef struct +{ + CFE_SBR_RouteId_t MsgMap[CFE_SBR_MSG_MAP_SIZE]; /**< \brief Message map */ + CFE_SBR_RouteEntry_t RoutingTbl[CFE_PLATFORM_SB_MAX_MSG_IDS]; /**< \brief Routing table */ + CFE_SB_RouteId_Atom_t RouteIdxTop; /**< \brief First unused entry in RoutingTbl */ +} cfe_sbr_t; + +/** \brief For each id callback function prototype */ +typedef void (*CFE_SBR_CallbackPtr_t)(CFE_SBR_RouteId_t RouteId, void *ArgPtr); + +/****************************************************************************** + * Function prototypes + */ + +/** + * \brief Initialize software bus routing module + */ +void CFE_SBR_Init(void); + +/** + * \brief Add a route for the given a message id + * + * Called for the first subscription to a message ID, uses up one + * element in the routing table. Assumes check for existing + * route was already performed or routes could leak + * + * \param[in] MsgId Message ID of the route to add + * + * \returns Route ID + */ +CFE_SBR_RouteId_t CFE_SBR_AddRoute(CFE_SB_MsgId_t MsgId); + +/** + * \brief Obtain the route id given a message id + * + * \param[in] MsgId Message ID of the route to get + * + * \returns Route ID + */ +CFE_SBR_RouteId_t CFE_SBR_GetRouteId(CFE_SB_MsgId_t MsgId); + +/** + * \brief Obtain the message id given a route id + * + * \param[in] RouteId Route ID of the message id to get + * + * \returns Message ID + */ +CFE_SB_MsgId_t CFE_SBR_GetMsgId(CFE_SBR_RouteId_t RouteId); + +/** + * \brief Obtain the destination list head pointer given a route id + * + * \param[in] RouteId Route ID + * + * \returns Destination list head pointer for the given route id + */ +CFE_SB_DestinationD_t *CFE_SBR_GetDestListHeadPtr(CFE_SBR_RouteId_t RouteId); + +/** + * \brief Set the destination list head pointer for given route id + * + * \param[in] RouteId Route Id + * \param[in] DestPtr Destination list head pointer + */ +void CFE_SBR_SetDestListHeadPtr(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *DestPtr); + +/* TODO add description */ +void CFE_SBR_IncrementSequenceCounter(CFE_SBR_RouteId_t RouteId); +uint32 CFE_SBR_GetSequenceCounter(CFE_SBR_RouteId_t RouteId); + +/** + * \brief Call the supplied callback function for all routes in MsgId order + * + * For certain routing implementations this is slower than CFE_SBR_ForEachRouteId, + * but guaranteed to be called in order of increasing MsgId raw values. Only + * invokes callback if route exists. + * + * \param[in] CallbackPtr Function to invoke for each matching ID + * \param[in] ArgPtr Opaque argument to pass to callback function + */ +void CFE_SBR_ForEachMsgId(CFE_SBR_CallbackPtr_t CallbackPtr, void *ArgPtr); + +/** + * \brief Call the supplied callback function for all routes + * + * For certain routing implementations this is faster than CFE_SBR_ForEachMsgId, + * but should only be used when MsgId order doesn't matter. Invokes callback + * for each route in the table. + * + * \param[in] CallbackPtr Function to invoke for each matching ID + * \param[in] ArgPtr Opaque argument to pass to callback function + */ +void CFE_SBR_ForEachRouteId(CFE_SBR_CallbackPtr_t CallbackPtr, void *ArgPtr); + +/* TODO think about removing these two... just use the head and process on SB side of interface */ +CFE_SB_DestinationD_t *CFE_SBR_GetDestPtrFromRoute(CFE_SBR_RouteId_t RouteId, CFE_SB_PipeId_t PipeId); +CFE_SB_DestinationD_t *CFE_SBR_GetDestPtrFromMsgId(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeId); + +/****************************************************************************** +** Inline functions +*/ + +/** + * \brief Identifies whether a given CFE_SBR_RouteId_t is valid + * + * Implements a basic sanity check on the value provided + * + * \returns true if sanity checks passed, false otherwise. + */ +static inline bool CFE_SBR_IsValidRouteId(CFE_SBR_RouteId_t RouteId) +{ + return (RouteId.RouteId != 0 && RouteId.RouteId <= CFE_PLATFORM_SB_MAX_MSG_IDS); +} + +/** + * \brief Converts from raw value to CFE_SBR_RouteId_t + * + * Converts the supplied "bare number" into a type-safe CFE_SBR_RouteId_t value + * + * \returns A CFE_SBR_RouteId_t + */ +static inline CFE_SBR_RouteId_t CFE_SBR_ValueToRouteId(CFE_SB_RouteId_Atom_t Value) +{ + return ((CFE_SBR_RouteId_t){ .RouteId = 1 + Value }); +} + +/** + * \brief Converts from CFE_SBR_RouteId_t to raw value + * + * Converts the supplied route id into a "bare number" suitable for performing + * array lookups or other tasks for which the holding structure cannot be used directly. + * + * Use with caution, as this removes the type safety information from the value. + * + * \note It is assumed the value has already been validated using CFE_SB_IsValidRouteId() + * + * \returns The underlying value + */ +static inline CFE_SB_RouteId_Atom_t CFE_SBR_RouteIdToValue(CFE_SBR_RouteId_t RouteId) +{ + return (RouteId.RouteId - 1); +} + +#endif /* CFE_SBR_H_ */ diff --git a/fsw/cfe-core/src/sb/cfe_sbr_route.c b/fsw/cfe-core/src/sb/cfe_sbr_route.c new file mode 100644 index 000000000..896bd9348 --- /dev/null +++ b/fsw/cfe-core/src/sb/cfe_sbr_route.c @@ -0,0 +1,201 @@ +/* +** GSC-18128-1, "Core Flight Executive Version 6.7" +** +** Copyright (c) 2006-2019 United States Government as represented by +** the Administrator of the National Aeronautics and Space Administration. +** All Rights Reserved. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +/****************************************************************************** +** File: cfe_sb_route.c +** +** Purpose: +** This header file contains private (SB) functions for routing +** +** Notes: +** These functions manipulate/access global variables and need +** to be protected by the SB Shared data lock. +** +******************************************************************************/ + +/* +** Include Files +*/ + +#include "common_types.h" +#include "cfe_sbr.h" +/* #include "osapi.h" TODO +#include "private/cfe_private.h" +#include "cfe_sb_priv.h" +#include "cfe_sb.h" +#include "ccsds.h" +#include "cfe_error.h" +#include "cfe_es.h" +#include "cfe_msg_api.h" +#include */ + +/* Routing module shared data */ +cfe_sbr_t CFE_SBR; + +/****************************************************************************** + * Interface function - see API for description + * + * NOTE - for this implementation 0 is invalid route id, so no need to initalize + * message map entries. + */ +void CFE_SBR_Init(void) +{ + CFE_SB_RouteId_Atom_t routeidx; + + /* Only non-zero value for shared data initialization is the invalid MsgId */ + for(routeidx = 0; routeidx < CFE_PLATFORM_SB_MAX_MSG_IDS; routeidx++) + { + CFE_SBR.RoutingTbl[routeidx].MsgId = CFE_SB_INVALID_MSG_ID; + } +} + + +/****************************************************************************** + * Interface function - see API for description + */ +CFE_SBR_RouteId_t CFE_SBR_AddRoute(CFE_SB_MsgId_t MsgId) +{ + CFE_SBR_RouteId_t routeid = CFE_SBR_INVALID_ROUTE_ID; + + if (CFE_SB_IsValidMsgId(MsgId) && (CFE_SBR.RouteIdxTop < CFE_PLATFORM_SB_MAX_MSG_IDS)) + { + routeid = CFE_SBR_ValueToRouteId(CFE_SBR.RouteIdxTop); + CFE_SBR.MsgMap[CFE_SB_MsgIdToValue(MsgId)] = routeid; + CFE_SBR.RoutingTbl[CFE_SBR.RouteIdxTop].MsgId = MsgId; + CFE_SBR.RouteIdxTop++; + } + + return routeid; +} + +/****************************************************************************** + * Interface function - see API for description + */ +CFE_SBR_RouteId_t CFE_SBR_GetRouteId(CFE_SB_MsgId_t MsgId) +{ + CFE_SBR_RouteId_t routeid = CFE_SBR_INVALID_ROUTE_ID; + + if (CFE_SB_IsValidMsgId(MsgId)) + { + routeid = CFE_SBR.MsgMap[CFE_SB_MsgIdToValue(MsgId)]; + } + + return routeid; +} + +/****************************************************************************** + * Interface function - see API for description + */ +CFE_SB_MsgId_t CFE_SBR_GetMsgId(CFE_SBR_RouteId_t RouteId) +{ + CFE_SB_MsgId_t msgid = CFE_SB_INVALID_MSG_ID; + + if (CFE_SBR_IsValidRouteId(RouteId)) + { + msgid = CFE_SBR.RoutingTbl[CFE_SBR_RouteIdToValue(RouteId)].MsgId; + } + + return msgid; +} + +/****************************************************************************** + * Interface function - see API for description + */ +CFE_SB_DestinationD_t *CFE_SBR_GetDestListHeadPtr(CFE_SBR_RouteId_t RouteId) +{ + + CFE_SB_DestinationD_t *destptr = NULL; + + if (CFE_SBR_IsValidRouteId(RouteId)) + { + destptr = CFE_SBR.RoutingTbl[CFE_SBR_RouteIdToValue(RouteId)].ListHeadPtr; + } + + return destptr; +} + +/****************************************************************************** + * Interface function - see API for description + */ +void CFE_SBR_SetDestListHeadPtr(CFE_SBR_RouteId_t RouteId, CFE_SB_DestinationD_t *DestPtr) +{ + + if (CFE_SBR_IsValidRouteId(RouteId)) + { + CFE_SBR.RoutingTbl[CFE_SBR_RouteIdToValue(RouteId)].ListHeadPtr = DestPtr; + } +} + +/****************************************************************************** + * Interface function - see API for description + */ +void CFE_SBR_IncrementSequenceCounter(CFE_SBR_RouteId_t RouteId) +{ + if (CFE_SBR_IsValidRouteId(RouteId)) + { + CFE_SBR.RoutingTbl[CFE_SBR_RouteIdToValue(RouteId)].SeqCnt++; + } +} + +/****************************************************************************** + * Interface function - see API for description + */ +uint32 CFE_SBR_GetSequenceCounter(CFE_SBR_RouteId_t RouteId) +{ + uint32 seqcnt = 0; + + if (CFE_SBR_IsValidRouteId(RouteId)) + { + seqcnt = CFE_SBR.RoutingTbl[CFE_SBR_RouteIdToValue(RouteId)].SeqCnt; + } + + return seqcnt; +} + +/****************************************************************************** + * Interface function - see API for description + */ +void CFE_SBR_ForEachMsgId(CFE_SBR_CallbackPtr_t CallbackPtr, void *ArgPtr) +{ + CFE_SB_MsgId_Atom_t msgidx; + CFE_SBR_RouteId_t routeid; + + for (msgidx = 0; msgidx <= CFE_PLATFORM_SB_HIGHEST_VALID_MSGID; msgidx++) + { + routeid = CFE_SBR_GetRouteId(CFE_SB_ValueToMsgId(msgidx)); + if (CFE_SBR_IsValidRouteId(routeid)) + { + (*CallbackPtr)(routeid, ArgPtr); + } + } +} + +/****************************************************************************** + * Interface function - see API for description + */ +void CFE_SBR_ForEachRouteId(CFE_SBR_CallbackPtr_t CallbackPtr, void *ArgPtr) +{ + CFE_SB_RouteId_Atom_t routeidx; + + for (routeidx = 0; routeidx < CFE_SBR.RouteIdxTop; routeidx++) + { + (*CallbackPtr)(CFE_SBR_ValueToRouteId(routeidx), ArgPtr); + } +}