diff --git a/config/default_cf_msgdefs.h b/config/default_cf_msgdefs.h
index 285aedf2..274becb8 100644
--- a/config/default_cf_msgdefs.h
+++ b/config/default_cf_msgdefs.h
@@ -50,6 +50,8 @@ typedef struct CF_HkSent
uint64 file_data_bytes; /**< \brief Sent File data bytes */
uint32 pdu; /**< \brief Sent PDUs counter */
uint32 nak_segment_requests; /**< \brief Sent NAK segment requests counter */
+ uint32 files_sent; /**< \brief Files successfully sent counter */
+ uint8 spare[4]; /**< \brief Alignment spare to avoid implicit padding */
} CF_HkSent_t;
/**
@@ -66,6 +68,8 @@ typedef struct CF_HkRecv
*/
uint16 dropped; /**< \brief Received PDUs dropped due to a transaction error */
uint32 nak_segment_requests; /**< \brief Received NAK segment requests counter */
+ uint32 files_recv; /**< \brief Files successfully received counter */
+ uint8 spare[4]; /**< \brief Alignment spare to avoid implicit padding */
} CF_HkRecv_t;
/**
diff --git a/cosmos/big_endian/CF/cf_tlm.txt b/cosmos/big_endian/CF/cf_tlm.txt
index 1bb09420..8f64619e 100644
--- a/cosmos/big_endian/CF/cf_tlm.txt
+++ b/cosmos/big_endian/CF/cf_tlm.txt
@@ -9,12 +9,16 @@ TELEMETRY CF HK_TLM_PKT BIG_ENDIAN "CFDP housekeeping Packet"
APPEND_ITEM SENT_FD0 64 UINT "File data bytes sent"
APPEND_ITEM SENT_PDU0 32 UINT "Count of PDUs sent"
APPEND_ITEM SENT_NAK_SR0 32 UINT "Count of sent segment requests"
+ APPEND_ITEM SENT_FILES0 32 UINT "Count of files successfully sent"
+ APPEND_ITEM SENT_SPARE0 32 UINT ""
APPEND_ITEM RECV_FD0 64 UINT "File data bytes received"
APPEND_ITEM RECV_PDU0 32 UINT "Count of PDUs received"
APPEND_ITEM RECV_PDU_ERROR0 32 UINT "Count of invalid PDUs received"
APPEND_ITEM RECV_PDU_SPURIOUS0 16 UINT "Count of spurious PDUs received"
APPEND_ITEM RECV_PDU_DROPPED0 16 UINT "Count of dropped PDUs received"
APPEND_ITEM RECV_NAK_SR0 32 UINT "Count of received segment requests"
+ APPEND_ITEM RECV_FILES0 32 UINT "Count of files successfully received"
+ APPEND_ITEM RECV_SPARE0 32 UINT ""
APPEND_ITEM FAULT_FILE_OPEN0 16 UINT "Count of file open errors"
APPEND_ITEM FAULT_FILE_READ0 16 UINT "Count of file read errors"
APPEND_ITEM FAULT_FILE_SEEK0 16 UINT "Count of file seek errors"
@@ -42,12 +46,16 @@ TELEMETRY CF HK_TLM_PKT BIG_ENDIAN "CFDP housekeeping Packet"
APPEND_ITEM SENT_FD1 64 UINT "File data bytes sent"
APPEND_ITEM SENT_PDU1 32 UINT "Count of PDUs sent"
APPEND_ITEM SENT_NAK_SR1 32 UINT "Count of sent segment requests"
+ APPEND_ITEM SENT_FILES1 32 UINT "Count of files successfully sent"
+ APPEND_ITEM SENT_SPARE1 32 UINT ""
APPEND_ITEM RECV_FD1 64 UINT "File data bytes received"
APPEND_ITEM RECV_PDU1 32 UINT "Count of PDUs received"
APPEND_ITEM RECV_PDU_ERROR1 32 UINT "Count of invalid PDUs received"
APPEND_ITEM RECV_PDU_SPURIOUS1 16 UINT "Count of spurious PDUs received"
APPEND_ITEM RECV_PDU_DROPPED1 16 UINT "Count of dropped PDUs received"
APPEND_ITEM RECV_NAK_SR1 32 UINT "Count of received segment requests"
+ APPEND_ITEM RECV_FILES1 32 UINT "Count of files successfully received"
+ APPEND_ITEM RECV_SPARE1 32 UINT ""
APPEND_ITEM FAULT_FILE_OPEN1 16 UINT "Count of file open errors"
APPEND_ITEM FAULT_FILE_READ1 16 UINT "Count of file read errors"
APPEND_ITEM FAULT_FILE_SEEK1 16 UINT "Count of file seek errors"
diff --git a/cosmos/little_endian/CF/cf_tlm.txt b/cosmos/little_endian/CF/cf_tlm.txt
index 4b3a3e52..2208e2dd 100644
--- a/cosmos/little_endian/CF/cf_tlm.txt
+++ b/cosmos/little_endian/CF/cf_tlm.txt
@@ -9,12 +9,16 @@ TELEMETRY CF HK_TLM_PKT LITTLE_ENDIAN "CFDP housekeeping Packet"
APPEND_ITEM SENT_FD0 64 UINT "File data bytes sent"
APPEND_ITEM SENT_PDU0 32 UINT "Count of PDUs sent"
APPEND_ITEM SENT_NAK_SR0 32 UINT "Count of sent segment requests"
+ APPEND_ITEM SENT_FILES0 32 UINT "Count of files successfully sent"
+ APPEND_ITEM SENT_SPARE0 32 UINT ""
APPEND_ITEM RECV_FD0 64 UINT "File data bytes received"
APPEND_ITEM RECV_PDU0 32 UINT "Count of PDUs received"
APPEND_ITEM RECV_PDU_ERROR0 32 UINT "Count of invalid PDUs received"
APPEND_ITEM RECV_PDU_SPURIOUS0 16 UINT "Count of spurious PDUs received"
APPEND_ITEM RECV_PDU_DROPPED0 16 UINT "Count of dropped PDUs received"
APPEND_ITEM RECV_NAK_SR0 32 UINT "Count of received segment requests"
+ APPEND_ITEM RECV_FILES0 32 UINT "Count of files successfully received"
+ APPEND_ITEM RECV_SPARE0 32 UINT ""
APPEND_ITEM FAULT_FILE_OPEN0 16 UINT "Count of file open errors"
APPEND_ITEM FAULT_FILE_READ0 16 UINT "Count of file read errors"
APPEND_ITEM FAULT_FILE_SEEK0 16 UINT "Count of file seek errors"
@@ -42,12 +46,16 @@ TELEMETRY CF HK_TLM_PKT LITTLE_ENDIAN "CFDP housekeeping Packet"
APPEND_ITEM SENT_FD1 64 UINT "File data bytes sent"
APPEND_ITEM SENT_PDU1 32 UINT "Count of PDUs sent"
APPEND_ITEM SENT_NAK_SR1 32 UINT "Count of sent segment requests"
+ APPEND_ITEM SENT_FILES1 32 UINT "Count of files successfully sent"
+ APPEND_ITEM SENT_SPARE1 32 UINT ""
APPEND_ITEM RECV_FD1 64 UINT "File data bytes received"
APPEND_ITEM RECV_PDU1 32 UINT "Count of PDUs received"
APPEND_ITEM RECV_PDU_ERROR1 32 UINT "Count of invalid PDUs received"
APPEND_ITEM RECV_PDU_SPURIOUS1 16 UINT "Count of spurious PDUs received"
APPEND_ITEM RECV_PDU_DROPPED1 16 UINT "Count of dropped PDUs received"
APPEND_ITEM RECV_NAK_SR1 32 UINT "Count of received segment requests"
+ APPEND_ITEM RECV_FILES1 32 UINT "Count of files successfully received"
+ APPEND_ITEM RECV_SPARE1 32 UINT ""
APPEND_ITEM FAULT_FILE_OPEN1 16 UINT "Count of file open errors"
APPEND_ITEM FAULT_FILE_READ1 16 UINT "Count of file read errors"
APPEND_ITEM FAULT_FILE_SEEK1 16 UINT "Count of file seek errors"
diff --git a/docs/cf_FunctionalRequirements.csv b/docs/cf_FunctionalRequirements.csv
index 9c14b1d4..9c4fe001 100644
--- a/docs/cf_FunctionalRequirements.csv
+++ b/docs/cf_FunctionalRequirements.csv
@@ -148,7 +148,9 @@ CF6000,CF6000,"The CF Housekeeping message shall include
11. Number of Inactivity Timer-Limit Faults
12. Number of CRC Mismatch Faults
13. Number of Filestore Rejection Faults (can be split by type)
-14. Number of Filesize Mismatch Faults",Operator interface that provides detailed status on operational state
+14. Number of Filesize Mismatch Faults
+15. Number of Files successfully sent
+16. Number of Files successfully received",Operator interface that provides detailed status on operational state
CF6001,CF6001,"The CF End of Transaction message shall include
1. Transaction identifier
2. Channel number
diff --git a/eds/cf.xml b/eds/cf.xml
index 21edcbc8..fb21c997 100644
--- a/eds/cf.xml
+++ b/eds/cf.xml
@@ -196,6 +196,8 @@
+
+
@@ -208,6 +210,8 @@
file directive FIN without matching active transaction counter" />
+
+
diff --git a/fsw/src/cf_cfdp_r.c b/fsw/src/cf_cfdp_r.c
index a0b69092..e263bddd 100644
--- a/fsw/src/cf_cfdp_r.c
+++ b/fsw/src/cf_cfdp_r.c
@@ -1065,6 +1065,11 @@ void CF_CFDP_R_CheckState(CF_Transaction_t *txn)
txn->flags.rx.send_fin = true;
break;
case CF_RxSubState_COMPLETE:
+ /* only a transaction that reached this point without error received a complete file */
+ if (CF_CFDP_TxnIsOK(txn))
+ {
+ ++CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.recv.files_recv;
+ }
/* This changes the txn state such that this function is no longer called. */
CF_CFDP_FinishTransaction(txn, true);
break;
diff --git a/fsw/src/cf_cfdp_s.c b/fsw/src/cf_cfdp_s.c
index 8ec9040f..5cdf8a26 100644
--- a/fsw/src/cf_cfdp_s.c
+++ b/fsw/src/cf_cfdp_s.c
@@ -868,6 +868,11 @@ void CF_CFDP_S_CheckState(CF_Transaction_t *txn)
txn->flags.tx.send_eof = true;
break;
case CF_TxSubState_COMPLETE:
+ /* only a transaction that reached this point without error sent a complete file */
+ if (CF_CFDP_TxnIsOK(txn))
+ {
+ ++CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.sent.files_sent;
+ }
/* This changes the txn state such that this function is no longer called. */
CF_CFDP_FinishTransaction(txn, true);
break;
diff --git a/unit-test/cf_cfdp_r_tests.c b/unit-test/cf_cfdp_r_tests.c
index d4e8a2fd..364f0674 100644
--- a/unit-test/cf_cfdp_r_tests.c
+++ b/unit-test/cf_cfdp_r_tests.c
@@ -1214,10 +1214,13 @@ void Test_CF_CFDP_R_CheckState_FINACK(void)
txn->flags.com.ack_timer_armed = false;
txn->state_data.sub_state = CF_RxSubState_FINACK;
UT_SetDeferredRetcode(UT_KEY(CF_CFDP_CheckAckNakCount), 1, false);
+ UT_SetDefaultReturnValue(UT_KEY(CF_CFDP_TxnIsOK), true);
UtAssert_VOIDCALL(CF_CFDP_R_CheckState(txn));
UtAssert_UINT8_EQ(txn->state_data.sub_state, CF_RxSubState_COMPLETE);
UtAssert_BOOL_FALSE(txn->flags.rx.send_fin);
UtAssert_STUB_COUNT(CF_CFDP_FinishTransaction, 1);
+ /* the fin-ack never arrived but the file itself was received without error */
+ UtAssert_UINT32_EQ(CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.recv.files_recv, 1);
/* FINACK state, R2, fin sent, not acked, inactivity reached */
UT_ResetState(0);
@@ -1227,10 +1230,13 @@ void Test_CF_CFDP_R_CheckState_FINACK(void)
txn->flags.rx.send_fin = false;
txn->flags.com.inactivity_fired = true;
txn->state_data.sub_state = CF_RxSubState_FINACK;
+ UT_SetDefaultReturnValue(UT_KEY(CF_CFDP_TxnIsOK), false);
UtAssert_VOIDCALL(CF_CFDP_R_CheckState(txn));
UtAssert_UINT8_EQ(txn->state_data.sub_state, CF_RxSubState_COMPLETE);
UtAssert_BOOL_FALSE(txn->flags.rx.send_fin);
UtAssert_STUB_COUNT(CF_CFDP_FinishTransaction, 1);
+ /* inactivity is a failure, so the count must remain at the 1 from the prior case */
+ UtAssert_UINT32_EQ(CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.recv.files_recv, 1);
}
void Test_CF_CFDP_R_CheckState_COMPLETE(void)
diff --git a/unit-test/cf_cfdp_s_tests.c b/unit-test/cf_cfdp_s_tests.c
index 4c9f77f7..00fe5c37 100644
--- a/unit-test/cf_cfdp_s_tests.c
+++ b/unit-test/cf_cfdp_s_tests.c
@@ -1068,11 +1068,25 @@ void Test_CF_CFDP_S_CheckState_FILESTORE(void)
*/
CF_Transaction_t *txn;
+ /* nominal, transaction reached the end without error */
UT_CFDP_S_SetupBasicTestState(UT_CF_Setup_NONE, NULL, NULL, NULL, &txn, NULL);
+ UT_SetDefaultReturnValue(UT_KEY(CF_CFDP_TxnIsOK), true);
+ txn->state_data.sub_state = CF_TxSubState_FILESTORE;
+ UtAssert_VOIDCALL(CF_CFDP_S_CheckState(txn));
+ UtAssert_UINT8_EQ(txn->state_data.sub_state, CF_TxSubState_COMPLETE);
+ UtAssert_STUB_COUNT(CF_CFDP_FinishTransaction, 1);
+ UtAssert_UINT32_EQ(CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.sent.files_sent, 1);
+
+ /* transaction reached the end in an error state, so no file was successfully sent */
+ UT_ResetState(0);
+ UT_CFDP_S_SetupBasicTestState(UT_CF_Setup_NONE, NULL, NULL, NULL, &txn, NULL);
+ UT_SetDefaultReturnValue(UT_KEY(CF_CFDP_TxnIsOK), false);
txn->state_data.sub_state = CF_TxSubState_FILESTORE;
UtAssert_VOIDCALL(CF_CFDP_S_CheckState(txn));
UtAssert_UINT8_EQ(txn->state_data.sub_state, CF_TxSubState_COMPLETE);
UtAssert_STUB_COUNT(CF_CFDP_FinishTransaction, 1);
+ /* the error case must not count, so the total remains at the 1 from the prior case */
+ UtAssert_UINT32_EQ(CF_AppData.hk.Payload.channel_hk[txn->chan_num].counters.sent.files_sent, 1);
}
void Test_CF_CFDP_S_CheckState_COMPLETE(void)
diff --git a/unit-test/cf_cmd_tests.c b/unit-test/cf_cmd_tests.c
index c9c7fcc2..e72a1910 100644
--- a/unit-test/cf_cmd_tests.c
+++ b/unit-test/cf_cmd_tests.c
@@ -267,7 +267,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_fault_ResetAllHkFaultCount
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.fault.inactivity_timer);
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.fault,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.fault),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.fault),
"fault channel %d was completely cleared to 0",
i);
}
@@ -295,6 +295,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_up_AndResetAllHkRecvCountS
CF_AppData.hk.Payload.channel_hk[i].counters.recv.spurious = Any_uint16_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.recv.dropped = Any_uint16_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.recv.nak_segment_requests = Any_uint32_Except(0);
+ CF_AppData.hk.Payload.channel_hk[i].counters.recv.files_recv = Any_uint32_Except(0);
}
CF_AppData.hk.Payload.counters.cmd = initial_hk_cmd_counter;
@@ -314,9 +315,10 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_up_AndResetAllHkRecvCountS
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.recv.spurious);
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.recv.pdu);
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.recv.nak_segment_requests);
+ UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.recv.files_recv);
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.recv,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.recv),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.recv),
"recv channel %d was completely cleared to 0",
i);
}
@@ -341,6 +343,7 @@ void Test_CF_ResetCountersCmd_tests_SWhenCommandByteIs_down_AndResetAllHkSentCou
CF_AppData.hk.Payload.channel_hk[i].counters.sent.file_data_bytes = Any_uint64_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.sent.nak_segment_requests = Any_uint32_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.sent.pdu = Any_uint32_Except(0);
+ CF_AppData.hk.Payload.channel_hk[i].counters.sent.files_sent = Any_uint32_Except(0);
}
CF_AppData.hk.Payload.counters.cmd = initial_hk_cmd_counter;
@@ -357,9 +360,10 @@ void Test_CF_ResetCountersCmd_tests_SWhenCommandByteIs_down_AndResetAllHkSentCou
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.sent.file_data_bytes);
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.sent.nak_segment_requests);
UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.sent.pdu);
+ UtAssert_ZERO(CF_AppData.hk.Payload.channel_hk[i].counters.sent.files_sent);
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.sent,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.sent),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.sent),
"sent channel %d was completely cleared to 0",
i);
}
@@ -404,6 +408,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_all_AndResetAllMemValuesSe
CF_AppData.hk.Payload.channel_hk[i].counters.recv.spurious = Any_uint16_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.recv.dropped = Any_uint16_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.recv.nak_segment_requests = Any_uint32_Except(0);
+ CF_AppData.hk.Payload.channel_hk[i].counters.recv.files_recv = Any_uint32_Except(0);
}
for (i = 0; i < CF_NUM_CHANNELS; ++i)
@@ -411,6 +416,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_all_AndResetAllMemValuesSe
CF_AppData.hk.Payload.channel_hk[i].counters.sent.file_data_bytes = Any_uint64_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.sent.nak_segment_requests = Any_uint32_Except(0);
CF_AppData.hk.Payload.channel_hk[i].counters.sent.pdu = Any_uint32_Except(0);
+ CF_AppData.hk.Payload.channel_hk[i].counters.sent.files_sent = Any_uint32_Except(0);
}
/* Act */
@@ -426,7 +432,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_all_AndResetAllMemValuesSe
{
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.fault,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.fault),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.fault),
"fault channel %d was completely cleared to 0",
i);
}
@@ -434,7 +440,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_all_AndResetAllMemValuesSe
{
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.recv,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.recv),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.recv),
"recv channel %d was completely cleared to 0",
i);
}
@@ -442,7 +448,7 @@ void Test_CF_ResetCountersCmd_tests_WhenCommandByteIs_all_AndResetAllMemValuesSe
{
UtAssert_MemCmpValue(&CF_AppData.hk.Payload.channel_hk[i].counters.sent,
0,
- sizeof(&CF_AppData.hk.Payload.channel_hk[i].counters.sent),
+ sizeof(CF_AppData.hk.Payload.channel_hk[i].counters.sent),
"sent channel %d was completely cleared to 0",
i);
}