Skip to content

Commit

Permalink
Fix nasa#325, add more concise transaction status code
Browse files Browse the repository at this point in the history
Adds a new concept of "transaction status" to replace use of CFDP
condition code to indicate the result of a transaction.  To aid in
transition this is equivalent in numeric value to the defined CFDP CC
values but is extended with additional values for other conditions
that can occur in the implementation but do not necessarily result
in sending a FIN/EOF PDU.

This also adds setting of Transaction Status for some off-nominal
cases where no CFDP CC was set.
  • Loading branch information
jphickey committed Oct 4, 2022
1 parent ceca7b1 commit eb93a91
Show file tree
Hide file tree
Showing 23 changed files with 545 additions and 101 deletions.
26 changes: 22 additions & 4 deletions fsw/src/cf_cfdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,11 @@ CF_SendRet_t CF_CFDP_SendEof(CF_Transaction_t *t)
{
eof = &ph->int_header.eof;

eof->cc = t->history->cc;
eof->cc = CF_TxnStatus_To_ConditionCode(t->history->txn_stat);
eof->crc = t->crc.result;
eof->size = t->fsize;

if (t->history->cc != CF_CFDP_ConditionCode_NO_ERROR)
if (eof->cc != CF_CFDP_ConditionCode_NO_ERROR)
{
CF_CFDP_AppendTlv(&eof->tlv_list, CF_CFDP_TLV_TYPE_ENTITY_ID);
}
Expand Down Expand Up @@ -787,6 +787,7 @@ int CF_CFDP_RecvFd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
{
CFE_EVS_SendEvent(CF_EID_ERR_PDU_FD_SHORT, CFE_EVS_EventType_ERROR,
"CF: filedata pdu too short: %lu bytes received", (unsigned long)CF_CODEC_GET_SIZE(ph->pdec));
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_PROTOCOL_ERROR);
++CF_AppData.hk.channel_hk[t->chan_num].counters.recv.error;
ret = -1;
}
Expand All @@ -795,6 +796,7 @@ int CF_CFDP_RecvFd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
/* If recv PDU has the "segment_meta_flag" set, this is not currently handled in CF. */
CFE_EVS_SendEvent(CF_EID_ERR_PDU_FD_UNSUPPORTED, CFE_EVS_EventType_ERROR,
"CF: filedata pdu with segment metadata received");
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_PROTOCOL_ERROR);
++CF_AppData.hk.channel_hk[t->chan_num].counters.recv.error;
ret = -1;
}
Expand Down Expand Up @@ -1733,6 +1735,22 @@ void CF_CFDP_ResetTransaction(CF_Transaction_t *t, int keep_history)
CF_FreeTransaction(t);
}

/*----------------------------------------------------------------
*
* Function: CF_CFDP_SetTxnStatus
*
* Application-scope internal function
* See description in cf_cfdp_r.h for argument/return detail
*
*-----------------------------------------------------------------*/
void CF_CFDP_SetTxnStatus(CF_Transaction_t *t, CF_TxnStatus_t txn_stat)
{
if (!CF_TxnStatus_IsError(t->history->txn_stat))
{
t->history->txn_stat = txn_stat;
}
}

/*----------------------------------------------------------------
*
* Function: CF_CFDP_SendEotPkt
Expand All @@ -1758,7 +1776,7 @@ void CF_CFDP_SendEotPkt(CF_Transaction_t *t)
PktBuf->eot.direction = t->history->dir;
PktBuf->eot.fnames = t->history->fnames;
PktBuf->eot.state = t->state;
PktBuf->eot.cc = t->history->cc;
PktBuf->eot.txn_stat = t->history->txn_stat;
PktBuf->eot.src_eid = t->history->src_eid;
PktBuf->eot.peer_eid = t->history->peer_eid;
PktBuf->eot.seq_num = t->history->seq_num;
Expand Down Expand Up @@ -1809,7 +1827,7 @@ void CF_CFDP_CancelTransaction(CF_Transaction_t *t)
if (!t->flags.com.canceled)
{
t->flags.com.canceled = 1;
t->history->cc = CF_CFDP_ConditionCode_CANCEL_REQUEST_RECEIVED;
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_CANCEL_REQUEST_RECEIVED);
fns[!!CF_CFDP_IsSender(t)](t);
}
}
Expand Down
14 changes: 14 additions & 0 deletions fsw/src/cf_cfdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ void CF_CFDP_DecodeStart(CF_DecoderState_t *pdec, const void *msgbuf, CF_Logical
*/
void CF_CFDP_ResetTransaction(CF_Transaction_t *t, int keep_history);

/************************************************************************/
/** @brief Helper function to store transaction status code only
*
* This records the status in the history block but does not set FIN flag
* or take any other protocol/state machine actions.
*
* @par Assumptions, External Events, and Notes:
* t must not be NULL.
*
* @param t Pointer to the transaction object
* @param cc Status Code value to set within transaction
*/
void CF_CFDP_SetTxnStatus(CF_Transaction_t *t, CF_TxnStatus_t txn_stat);

/************************************************************************/
/** @brief Send an end of transaction packet.
*
Expand Down
2 changes: 1 addition & 1 deletion fsw/src/cf_cfdp_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void CF_CFDP_R_DispatchRecv(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph,
}
else
{
if (t->history->cc == CF_CFDP_ConditionCode_NO_ERROR)
if (!CF_TxnStatus_IsError(t->history->txn_stat))
{
selected_handler = fd_fn;
}
Expand Down
58 changes: 32 additions & 26 deletions fsw/src/cf_cfdp_r.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@

/*----------------------------------------------------------------
*
* Function: CF_CFDP_R2_SetCc
* Function: CF_CFDP_R2_SetFinTxnStatus
*
* Application-scope internal function
* See description in cf_cfdp_r.h for argument/return detail
*
*-----------------------------------------------------------------*/
void CF_CFDP_R2_SetCc(CF_Transaction_t *t, CF_CFDP_ConditionCode_t cc)
void CF_CFDP_R2_SetFinTxnStatus(CF_Transaction_t *t, CF_TxnStatus_t txn_stat)
{
t->history->cc = cc;
CF_CFDP_SetTxnStatus(t, txn_stat);
t->flags.rx.send_fin = 1;
}

Expand Down Expand Up @@ -76,8 +76,8 @@ void CF_CFDP_R1_Reset(CF_Transaction_t *t)
void CF_CFDP_R2_Reset(CF_Transaction_t *t)
{
if ((t->state_data.r.sub_state == CF_RxSubState_WAIT_FOR_FIN_ACK) ||
(t->state_data.r.r2.eof_cc != CF_CFDP_ConditionCode_NO_ERROR) ||
(t->history->cc != CF_CFDP_ConditionCode_NO_ERROR) || t->flags.com.canceled)
(t->state_data.r.r2.eof_cc != CF_CFDP_ConditionCode_NO_ERROR) || CF_TxnStatus_IsError(t->history->txn_stat) ||
t->flags.com.canceled)
{
CF_CFDP_R1_Reset(t); /* it's done */
}
Expand Down Expand Up @@ -129,7 +129,7 @@ void CF_CFDP_R2_Complete(CF_Transaction_t *t, int ok_to_send_nak)
/* checking if r2 is complete. Check nak list, and send NAK if appropriate */
/* if all data is present, then there will be no gaps in the chunk */

if (t->history->cc == CF_CFDP_ConditionCode_NO_ERROR)
if (!CF_TxnStatus_IsError(t->history->txn_stat))
{
/* first, check if md is received. If not, send specialized nak */
if (!t->flags.rx.md_recv)
Expand Down Expand Up @@ -166,9 +166,9 @@ void CF_CFDP_R2_Complete(CF_Transaction_t *t, int ok_to_send_nak)
(unsigned long)t->history->src_eid, (unsigned long)t->history->seq_num);
send_fin = 1;
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.nak_limit;
t->history->cc = CF_CFDP_ConditionCode_NAK_LIMIT_REACHED; /* don't use CF_CFDP_R2_SetCc because many
places in this function set send_fin */
t->state_data.r.r2.acknak_count = 0; /* reset for fin/ack */
/* don't use CF_CFDP_R2_SetFinTxnStatus because many places in this function set send_fin */
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_NAK_LIMIT_REACHED);
t->state_data.r.r2.acknak_count = 0; /* reset for fin/ack */
}
else
{
Expand All @@ -178,8 +178,11 @@ void CF_CFDP_R2_Complete(CF_Transaction_t *t, int ok_to_send_nak)

if (send_fin)
{
t->flags.rx.send_fin = 1;
t->flags.rx.complete = 1; /* latch completeness, since send_fin is cleared later */

/* the transaction is now considered complete, but this will not overwrite an
* error status code if there was one set */
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_NO_ERROR);
}

/* always go to CF_RxSubState_FILEDATA, and let tick change state */
Expand Down Expand Up @@ -220,7 +223,7 @@ int CF_CFDP_R_ProcessFd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
"CF R%d(%lu:%lu): failed to seek offset %ld, got %ld", (t->state == CF_TxnState_R2),
(unsigned long)t->history->src_eid, (unsigned long)t->history->seq_num, (long)fd->offset,
(long)fret);
t->history->cc = CF_CFDP_ConditionCode_FILE_SIZE_ERROR;
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_FILE_SIZE_ERROR);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_seek;
ret = -1; /* connection will reset in caller */
}
Expand All @@ -235,9 +238,9 @@ int CF_CFDP_R_ProcessFd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
"CF R%d(%lu:%lu): OS_write expected %ld, got %ld", (t->state == CF_TxnState_R2),
(unsigned long)t->history->src_eid, (unsigned long)t->history->seq_num,
(long)fd->data_len, (long)fret);
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_FILESTORE_REJECTION);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_write;
t->history->cc = CF_CFDP_ConditionCode_FILESTORE_REJECTION;
ret = -1; /* connection will reset in caller */
ret = -1; /* connection will reset in caller */
}
else
{
Expand Down Expand Up @@ -363,6 +366,7 @@ void CF_CFDP_R2_SubstateRecvEof(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
}
else
{
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_From_ConditionCode(t->state_data.r.r2.eof_cc));
CF_CFDP_R2_Reset(t);
}
}
Expand All @@ -371,7 +375,7 @@ void CF_CFDP_R2_SubstateRecvEof(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
/* bad eof sent? */
if (ret == CF_RxEofRet_FSIZE_MISMATCH)
{
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILE_SIZE_ERROR);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILE_SIZE_ERROR);
}
else
{
Expand Down Expand Up @@ -525,8 +529,8 @@ int CF_CFDP_R_SubstateSendNak(CF_Transaction_t *t)
nak->scope_start = 0;
cret = CF_ChunkList_ComputeGaps(&t->chunks->chunks,
(t->chunks->chunks.count < t->chunks->chunks.max_chunks)
? t->chunks->chunks.max_chunks
: (t->chunks->chunks.max_chunks - 1),
? t->chunks->chunks.max_chunks
: (t->chunks->chunks.max_chunks - 1),
t->fsize, 0, CF_CFDP_R2_GapCompute, &args);

if (!cret)
Expand Down Expand Up @@ -621,7 +625,7 @@ void CF_CFDP_R_Init(CF_Transaction_t *t)
t->fd = OS_OBJECT_ID_UNDEFINED; /* just in case */
if (t->state == CF_TxnState_R2)
{
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILESTORE_REJECTION);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILESTORE_REJECTION);
}
else
{
Expand Down Expand Up @@ -685,7 +689,7 @@ int CF_CFDP_R2_CalcCrcChunk(CF_Transaction_t *t)
"CF R%d(%lu:%lu): failed to seek offset %lu, got %ld", (t->state == CF_TxnState_R2),
(unsigned long)t->history->src_eid, (unsigned long)t->history->seq_num,
(unsigned long)t->state_data.r.r2.rx_crc_calc_bytes, (long)fret);
t->history->cc = CF_CFDP_ConditionCode_FILE_SIZE_ERROR; /* should be ok to use this one */
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_FILE_SIZE_ERROR);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_seek;
success = false;
break;
Expand All @@ -699,7 +703,7 @@ int CF_CFDP_R2_CalcCrcChunk(CF_Transaction_t *t)
"CF R%d(%lu:%lu): failed to read file expected %lu, got %ld",
(t->state == CF_TxnState_R2), (unsigned long)t->history->src_eid,
(unsigned long)t->history->seq_num, (unsigned long)read_size, (long)fret);
t->history->cc = CF_CFDP_ConditionCode_FILE_SIZE_ERROR; /* should be ok to use this one */
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_FILE_SIZE_ERROR);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_read;
success = false;
break;
Expand All @@ -725,7 +729,7 @@ int CF_CFDP_R2_CalcCrcChunk(CF_Transaction_t *t)
}
else
{
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILE_CHECKSUM_FAILURE);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILE_CHECKSUM_FAILURE);
}

t->flags.com.crc_calc = 1;
Expand All @@ -749,7 +753,7 @@ int CF_CFDP_R2_SubstateSendFin(CF_Transaction_t *t)
CF_SendRet_t sret;
int ret = 0;

if (t->history->cc == CF_CFDP_ConditionCode_NO_ERROR && !t->flags.com.crc_calc)
if (!CF_TxnStatus_IsError(t->history->txn_stat) && !t->flags.com.crc_calc)
{
/* no error, and haven't checked crc -- so start checking it */
if (CF_CFDP_R2_CalcCrcChunk(t))
Expand All @@ -760,7 +764,8 @@ int CF_CFDP_R2_SubstateSendFin(CF_Transaction_t *t)

if (ret != -1)
{
sret = CF_CFDP_SendFin(t, t->state_data.r.r2.dc, t->state_data.r.r2.fs, t->history->cc);
sret = CF_CFDP_SendFin(t, t->state_data.r.r2.dc, t->state_data.r.r2.fs,
CF_TxnStatus_To_ConditionCode(t->history->txn_stat));
CF_Assert(sret != CF_SendRet_ERROR); /* CF_CFDP_SendFin does not return CF_SendRet_ERROR */
t->state_data.r.sub_state =
CF_RxSubState_WAIT_FOR_FIN_ACK; /* whether or not fin send successful, ok to transition state */
Expand Down Expand Up @@ -838,7 +843,7 @@ void CF_CFDP_R2_RecvMd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
(unsigned long)t->history->seq_num, (unsigned long)t->fsize,
(unsigned long)t->state_data.r.r2.eof_size);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_size_mismatch;
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILE_SIZE_ERROR);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILE_SIZE_ERROR);
success = false;
}
}
Expand All @@ -860,7 +865,7 @@ void CF_CFDP_R2_RecvMd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
(t->state == CF_TxnState_R2), (unsigned long)t->history->src_eid,
(unsigned long)t->history->seq_num, (long)status);
t->fd = OS_OBJECT_ID_UNDEFINED;
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILESTORE_REJECTION);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILESTORE_REJECTION);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_rename;
success = false;
}
Expand All @@ -874,7 +879,7 @@ void CF_CFDP_R2_RecvMd(CF_Transaction_t *t, CF_Logical_PduBuffer_t *ph)
"CF R%d(%lu:%lu): failed to open renamed file in R2, error=%ld",
(t->state == CF_TxnState_R2), (unsigned long)t->history->src_eid,
(unsigned long)t->history->seq_num, (long)ret);
CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_FILESTORE_REJECTION);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_FILESTORE_REJECTION);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.file_open;
t->fd = OS_OBJECT_ID_UNDEFINED; /* just in case */
success = false;
Expand Down Expand Up @@ -1012,7 +1017,7 @@ void CF_CFDP_R_Tick(CF_Transaction_t *t, int *cont /* unused */)
{
CF_CFDP_R_SendInactivityEvent(t);

CF_CFDP_R2_SetCc(t, CF_CFDP_ConditionCode_INACTIVITY_DETECTED);
CF_CFDP_R2_SetFinTxnStatus(t, CF_TxnStatus_INACTIVITY_DETECTED);
t->flags.rx.inactivity_fired = 1;
}
else
Expand Down Expand Up @@ -1074,6 +1079,7 @@ void CF_CFDP_R_Tick(CF_Transaction_t *t, int *cont /* unused */)
CFE_EVS_SendEvent(CF_EID_ERR_CFDP_R_ACK_LIMIT, CFE_EVS_EventType_ERROR,
"CF R2(%lu:%lu): ack limit reached, no fin-ack",
(unsigned long)t->history->src_eid, (unsigned long)t->history->seq_num);
CF_CFDP_SetTxnStatus(t, CF_TxnStatus_ACK_LIMIT_NO_FIN);
++CF_AppData.hk.channel_hk[t->chan_num].counters.fault.ack_limit;
CF_CFDP_R2_Reset(t);
success = false;
Expand Down
6 changes: 3 additions & 3 deletions fsw/src/cf_cfdp_r.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ void CF_CFDP_R_Cancel(CF_Transaction_t *t);
void CF_CFDP_R_Init(CF_Transaction_t *t);

/************************************************************************/
/** @brief Helper function to store condition code set send_fin flag.
/** @brief Helper function to store transaction status code and set send_fin flag.
*
* @par Assumptions, External Events, and Notes:
* t must not be NULL.
*
* @param t Pointer to the transaction object
* @param cc Condition Code value to set within transaction
* @param cc Status Code value to set within transaction
*/
void CF_CFDP_R2_SetCc(CF_Transaction_t *t, CF_CFDP_ConditionCode_t cc);
void CF_CFDP_R2_SetFinTxnStatus(CF_Transaction_t *t, CF_TxnStatus_t txn_stat);

/************************************************************************/
/** @brief CFDP R1 transaction reset function.
Expand Down
Loading

0 comments on commit eb93a91

Please sign in to comment.