summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchit Gupta <71798289+archigup@users.noreply.github.com>2021-03-05 17:56:28 -0800
committerGitHub <noreply@github.com>2021-03-05 17:56:28 -0800
commitc8fa483b68c6c1149c2a7a8bc1e901b38860ec9b (patch)
tree40e9383a842160981cf05ed91c33636f00307b1b
parente61730c9b1ab5fd4445513966dfc67e86ffb7905 (diff)
downloadfreertos-git-c8fa483b68c6c1149c2a7a8bc1e901b38860ec9b.tar.gz
Add custom metrics to defender demo (#507)
Adds custom metrics to the defender demo. The metrics added are a list of the task ids and the stack high water mark.
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/DemoTasks/DefenderDemoExample.c74
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/FreeRTOSConfig.h12
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/defender_config.h40
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/demo_config.h7
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/metrics_collector.c3
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.c351
-rw-r--r--FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.h12
m---------FreeRTOS-Plus/Source/AWS/device-defender0
8 files changed, 379 insertions, 120 deletions
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/DemoTasks/DefenderDemoExample.c b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/DemoTasks/DefenderDemoExample.c
index 732538bc1..96e490885 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/DemoTasks/DefenderDemoExample.c
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/DemoTasks/DefenderDemoExample.c
@@ -35,18 +35,20 @@
* with another MQTT library. This demo requires using the AWS IoT broker as
* Device Defender is an AWS service.
*
- * This demo connects to the AWS IoT broker and subscribes to the device
- * defender topics. It then collects metrics for the open ports and sockets on
- * the device using FreeRTOS+TCP, and generates a device defender report. The
+ * This demo subscribes to the device defender topics. It then collects metrics
+ * for the open ports and sockets on the device using FreeRTOS+TCP. Additonally
+ * the stack high water mark and task IDs are collected for custom metrics.
+ * These metrics are used to generate a device defender report. The
* report is then published, and the demo waits for a response from the device
- * defender service. Upon receiving the response or timing out, the demo
- * finishes.
+ * defender service. Upon receiving an accepted response, the demo finishes.
+ * If the demo receives a rejected response or times out, the demo repeats up to
+ * a maximum of DEFENDER_MAX_DEMO_LOOP_COUNT times.
*
* This demo sets the report ID to xTaskGetTickCount(), which may collide if
* the device is reset. Reports for a Thing with a previously used report ID
* will be assumed to be duplicates and discarded by the Device Defender
* service. The report ID needs to be unique per report sent with a given
- * Thing. We recommend using an increasing unique id such as the current
+ * Thing. We recommend using an increasing unique ID such as the current
* timestamp.
*/
@@ -97,7 +99,7 @@
#define DEFENDER_RESPONSE_WAIT_SECONDS ( 2 )
/**
- * @brief Name of the report id field in the response from the AWS IoT Device
+ * @brief Name of the report ID field in the response from the AWS IoT Device
* Defender service.
*/
#define DEFENDER_RESPONSE_REPORT_ID_FIELD "reportId"
@@ -133,8 +135,8 @@ typedef enum
ReportStatusRejected
} ReportStatus_t;
-/**
- * @brief Each compilation unit that consumes the NetworkContext must define it.
+/**
+ * @brief Each compilation unit that consumes the NetworkContext must define it.
* It should contain a single pointer to the type of your desired transport.
* When using multiple transports in the same compilation unit, define this pointer as void *.
*
@@ -196,6 +198,16 @@ static uint16_t pusOpenUdpPorts[ democonfigOPEN_UDP_PORTS_ARRAY_SIZE ];
static Connection_t pxEstablishedConnections[ democonfigESTABLISHED_CONNECTIONS_ARRAY_SIZE ];
/**
+ * @brief Array of task statuses, used to generate custom metrics.
+ */
+static TaskStatus_t pxTaskStatusList[ democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE ];
+
+/**
+ * @brief Task numbers custom metric array.
+ */
+static uint32_t pulCustomMetricsTaskNumbers[ democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE ];
+
+/**
* @brief All the metrics sent in the device defender report.
*/
static ReportMetrics_t xDeviceMetrics;
@@ -211,9 +223,10 @@ static ReportStatus_t xReportStatus;
static char pcDeviceMetricsJsonReport[ democonfigDEVICE_METRICS_REPORT_BUFFER_SIZE ];
/**
- * @brief Report Id sent in the defender report.
+ * @brief Report ID sent in the defender report.
*/
static uint32_t ulReportId = 0UL;
+
/*-----------------------------------------------------------*/
/**
@@ -463,7 +476,9 @@ static bool prvCollectDeviceMetrics( void )
{
bool xStatus = false;
eMetricsCollectorStatus eMetricsCollectorStatus;
- uint32_t ulNumOpenTcpPorts = 0UL, ulNumOpenUdpPorts = 0UL, ulNumEstablishedConnections = 0UL;
+ uint32_t ulNumOpenTcpPorts = 0UL, ulNumOpenUdpPorts = 0UL, ulNumEstablishedConnections = 0UL, i;
+ UBaseType_t uxTasksWritten = { 0 };
+ TaskStatus_t pxTaskStatus = { 0 };
/* Collect bytes and packets sent and received. */
eMetricsCollectorStatus = eGetNetworkStats( &( xNetworkStats ) );
@@ -516,6 +531,36 @@ static bool prvCollectDeviceMetrics( void )
}
}
+ /* Collect custom metrics. This demo sends this task's stack high water mark
+ * as a number type custom metric and the current task IDs as a list of
+ * numbers type custom metric. */
+ if( eMetricsCollectorStatus == eMetricsCollectorSuccess )
+ {
+ vTaskGetInfo(
+ /* Query this task. */
+ NULL,
+ &pxTaskStatus,
+ /* Include the stack high water mark value. */
+ pdTRUE,
+ /* Don't include the task state in the TaskStatus_t structure. */
+ 0 );
+ uxTasksWritten = uxTaskGetSystemState( pxTaskStatusList, democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE, NULL );
+
+ if( uxTasksWritten == 0 )
+ {
+ eMetricsCollectorStatus = eMetricsCollectorCollectionFailed;
+ LogError( ( "Failed to collect system state. uxTaskGetSystemState() failed due to insufficient buffer space.",
+ eMetricsCollectorStatus ) );
+ }
+ else
+ {
+ for( i = 0; i < uxTasksWritten; i++ )
+ {
+ pulCustomMetricsTaskNumbers[ i ] = pxTaskStatusList[ i ].xTaskNumber;
+ }
+ }
+ }
+
/* Populate device metrics. */
if( eMetricsCollectorStatus == eMetricsCollectorSuccess )
{
@@ -527,6 +572,9 @@ static bool prvCollectDeviceMetrics( void )
xDeviceMetrics.ulOpenUdpPortsArrayLength = ulNumOpenUdpPorts;
xDeviceMetrics.pxEstablishedConnectionsArray = &( pxEstablishedConnections[ 0 ] );
xDeviceMetrics.ulEstablishedConnectionsArrayLength = ulNumEstablishedConnections;
+ xDeviceMetrics.ulStackHighWaterMark = pxTaskStatus.usStackHighWaterMark;
+ xDeviceMetrics.pulTaskIdArray = pulCustomMetricsTaskNumbers;
+ xDeviceMetrics.ulTaskIdArrayLength = uxTasksWritten;
}
return xStatus;
@@ -671,14 +719,14 @@ void prvDefenderDemoTask( void * pvParameters )
* DEFENDER_MAX_DEMO_LOOP_COUNT times. */
do
{
- /* Set a report Id to be used.
+ /* Set a report ID to be used.
*
* !!!NOTE!!!
* This demo sets the report ID to xTaskGetTickCount(), which may collide
* if the device is reset. Reports for a Thing with a previously used
* report ID will be assumed to be duplicates and discarded by the Device
* Defender service. The report ID needs to be unique per report sent with
- * a given Thing. We recommend using an increasing unique id such as the
+ * a given Thing. We recommend using an increasing unique ID such as the
* current timestamp. */
ulReportId = ( uint32_t ) xTaskGetTickCount();
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/FreeRTOSConfig.h b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/FreeRTOSConfig.h
index 7aa77d93f..05f20147a 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/FreeRTOSConfig.h
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/FreeRTOSConfig.h
@@ -48,7 +48,8 @@
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 60 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the Win32 thread. */
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2048U * 1024U ) )
#define configMAX_TASK_NAME_LEN ( 15 )
-#define configUSE_TRACE_FACILITY 0
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_CO_ROUTINES 0
@@ -103,15 +104,6 @@
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_pcTaskGetTaskName 1
-/* This demo makes use of one or more example stats formatting functions. These
- * format the raw data provided by the uxTaskGetSystemState() function in to human
- * readable ASCII form. See the notes in the implementation of vTaskList() within
- * FreeRTOS/Source/tasks.c for limitations. configUSE_STATS_FORMATTING_FUNCTIONS
- * is set to 2 so the formatting functions are included without the stdio.h being
- * included in tasks.c. That is because this project defines its own sprintf()
- * functions. */
-#define configUSE_STATS_FORMATTING_FUNCTIONS 1
-
/* Assert call defined for debug builds. */
#ifdef _DEBUG
extern void vAssertCalled( const char * pcFile,
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/defender_config.h b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/defender_config.h
index 496881a26..22c7d116f 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/defender_config.h
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/defender_config.h
@@ -52,4 +52,44 @@
/************ End of logging configuration ****************/
+/**
+ * AWS IoT Device Defender Service supports both long and short names for keys
+ * in the report sent by a device. For example,
+ *
+ * A device defender report using long key names:
+ * {
+ * "header": {
+ * "report_id": 1530304554,
+ * "version": "1.0"
+ * },
+ * "metrics": {
+ * "network_stats": {
+ * "bytes_in": 29358693495,
+ * "bytes_out": 26485035,
+ * "packets_in": 10013573555,
+ * "packets_out": 11382615
+ * }
+ * }
+ * }
+ *
+ * An equivalent report using short key names:
+ * {
+ * "hed": {
+ * "rid": 1530304554,
+ * "v": "1.0"
+ * },
+ * "met": {
+ * "ns": {
+ * "bi": 29358693495,
+ * "bo": 26485035,
+ * "pi": 10013573555,
+ * "po": 11382615
+ * }
+ * }
+ * }
+ *
+ * Set to 1 to enable use of long key names in the defender report.
+ */
+#define DEFENDER_USE_LONG_KEYS 0
+
#endif /* ifndef DEFENDER_CONFIG_H_ */
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/demo_config.h b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/demo_config.h
index d9bd3cbad..123ed4888 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/demo_config.h
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/demo_config.h
@@ -262,6 +262,13 @@ extern void vLoggingPrintf( const char * pcFormatString,
#define democonfigESTABLISHED_CONNECTIONS_ARRAY_SIZE 10
/**
+ * @brief Size of the task numbers array.
+ *
+ * This must be at least the number of tasks used.
+ */
+#define democonfigCUSTOM_METRICS_TASKS_ARRAY_SIZE 10
+
+/**
* @brief Size of the buffer which contains the generated device defender report.
*
* If the generated report is larger than this, it is rejected.
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/metrics_collector.c b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/metrics_collector.c
index 426bc49a2..02437bf67 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/metrics_collector.c
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/metrics_collector.c
@@ -43,9 +43,6 @@
#include "FreeRTOS.h"
#include "FreeRTOS_IP.h"
-/* FreeRTOS+TCP tcp_netstat utility include. */
-#include "tcp_netstat.h"
-
/* Demo config. */
#include "demo_config.h"
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.c b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.c
index 3d467287d..d5906cf0b 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.c
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.c
@@ -36,6 +36,9 @@
/* Demo config. */
#include "demo_config.h"
+/* Device Defender Client Library. */
+#include "defender.h"
+
/* Interface include. */
#include "report_builder.h"
@@ -50,53 +53,68 @@
/* Formats used to generate the JSON report. */
#define reportbuilderJSON_PORT_OBJECT_FORMAT \
"{" \
- "\"port\": %u" \
+ "\"%s\": %u" \
"},"
#define reportbuilderJSON_CONNECTION_OBJECT_FORMAT \
"{" \
- "\"local_port\": %u," \
- "\"remote_addr\": \"%u.%u.%u.%u:%u\"" \
+ "\"%s\": %u," \
+ "\"%s\": \"%u.%u.%u.%u:%u\"" \
"},"
#define reportbuilderJSON_REPORT_FORMAT_PART1 \
"{" \
- "\"header\": {" \
- "\"report_id\": %u," \
- "\"version\": \"%u.%u\"" \
+ "\"%s\": {" \
+ "\"%s\": %u," \
+ "\"%s\": \"%u.%u\"" \
"}," \
- "\"metrics\": {" \
- "\"listening_tcp_ports\": {" \
- "\"ports\": "
+ "\"%s\": {" \
+ "\"%s\": {" \
+ "\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART2 \
"," \
- "\"total\": %u" \
+ "\"%s\": %u" \
"}," \
- "\"listening_udp_ports\": {" \
- "\"ports\": "
+ "\"%s\": {" \
+ "\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART3 \
"," \
- "\"total\": %u" \
+ "\"%s\": %u" \
"}," \
- "\"network_stats\": {" \
- "\"bytes_in\": %u," \
- "\"bytes_out\": %u," \
- "\"packets_in\": %u," \
- "\"packets_out\": %u" \
+ "\"%s\": {" \
+ "\"%s\": %u," \
+ "\"%s\": %u," \
+ "\"%s\": %u," \
+ "\"%s\": %u" \
"}," \
- "\"tcp_connections\": {" \
- "\"established_connections\": {" \
- "\"connections\": "
+ "\"%s\": {" \
+ "\"%s\": {" \
+ "\"%s\": "
#define reportbuilderJSON_REPORT_FORMAT_PART4 \
"," \
- "\"total\": %u" \
+ "\"%s\": %u" \
+ "}" \
"}" \
+ "}," \
+ "\"%s\": {" \
+ "\"stack_high_water_mark\": [" \
+ "{" \
+ "\"%s\": %u" \
+ "}" \
+ "]," \
+ "\"task_numbers\": [" \
+ "{" \
+ "\"%s\": "
+
+#define reportbuilderJSON_REPORT_FORMAT_PART5 \
"}" \
+ "]" \
"}" \
"}"
+
/*-----------------------------------------------------------*/
/**
@@ -158,6 +176,24 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
const Connection_t * pxConnectionsArray,
uint32_t ulConnectionsArrayLength,
uint32_t * pulOutCharsWritten );
+
+/**
+ * @brief Write task ID array to the given buffer as a JSON array.
+ *
+ * @param[in] pcBuffer The buffer to write the array of task IDs.
+ * @param[in] ulBufferLength The length of the buffer.
+ * @param[in] pulTaskIdArray The array containing the task IDs.
+ * @param[in] pulTaskIdArrayLength Length of the pulTaskIdsArray array.
+ * @param[out] pulOutCharsWritten Number of characters written to the buffer.
+ *
+ * @return #ReportBuilderSuccess if the array is successfully written;
+ * #ReportBuilderBufferTooSmall if the buffer cannot hold the full array.
+ */
+static eReportBuilderStatus prvWriteTaskIdArray( char * pcBuffer,
+ uint32_t ulBufferLength,
+ const uint32_t * pulTaskIdArray,
+ uint32_t pulTaskIdArrayLength,
+ uint32_t * pulOutCharsWritten );
/*-----------------------------------------------------------*/
static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
@@ -168,7 +204,7 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
{
char * pcCurrentWritePos = pcBuffer;
uint32_t i, ulRemainingBufferLength = ulBufferLength;
- int32_t ulCharactersWritten;
+ int32_t lCharactersWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
configASSERT( pcBuffer != NULL );
@@ -190,20 +226,20 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
/* Write the array elements. */
for( i = 0; ( ( i < ulOpenPortsArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
{
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_PORT_OBJECT_FORMAT,
- pusOpenPortsArray[ i ] );
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_PORT_OBJECT_FORMAT,
+ DEFENDER_REPORT_PORT_KEY,
+ pusOpenPortsArray[ i ] );
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
eStatus = eReportBuilderBufferTooSmall;
- break;
}
else
{
- ulRemainingBufferLength -= ( uint32_t ) ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= ( uint32_t ) lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
}
}
@@ -222,6 +258,7 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
*pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
+ *pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
else
{
@@ -229,11 +266,6 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
}
}
- if( eStatus == eReportBuilderSuccess )
- {
- *pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
- }
-
return eStatus;
}
/*-----------------------------------------------------------*/
@@ -246,7 +278,7 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
{
char * pcCurrentWritePos = pcBuffer;
uint32_t i, ulRemainingBufferLength = ulBufferLength;
- int32_t ulCharactersWritten;
+ int32_t lCharactersWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
const Connection_t * pxConn;
@@ -270,25 +302,26 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
for( i = 0; ( ( i < ulConnectionsArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
{
pxConn = &( pxConnectionsArray[ i ] );
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_CONNECTION_OBJECT_FORMAT,
- pxConn->usLocalPort,
- ( pxConn->ulRemoteIp >> 24 ) & 0xFF,
- ( pxConn->ulRemoteIp >> 16 ) & 0xFF,
- ( pxConn->ulRemoteIp >> 8 ) & 0xFF,
- ( pxConn->ulRemoteIp ) & 0xFF,
- pxConn->usRemotePort );
-
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_CONNECTION_OBJECT_FORMAT,
+ DEFENDER_REPORT_LOCAL_PORT_KEY,
+ pxConn->usLocalPort,
+ DEFENDER_REPORT_REMOTE_ADDR_KEY,
+ ( pxConn->ulRemoteIp >> 24 ) & 0xFF,
+ ( pxConn->ulRemoteIp >> 16 ) & 0xFF,
+ ( pxConn->ulRemoteIp >> 8 ) & 0xFF,
+ ( pxConn->ulRemoteIp ) & 0xFF,
+ pxConn->usRemotePort );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
eStatus = eReportBuilderBufferTooSmall;
- break;
}
else
{
- ulRemainingBufferLength -= ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
}
}
@@ -307,6 +340,7 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
*pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
ulRemainingBufferLength -= 1;
pcCurrentWritePos += 1;
+ *pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
}
else
{
@@ -314,9 +348,77 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
}
}
+ return eStatus;
+}
+/*-----------------------------------------------------------*/
+
+static eReportBuilderStatus prvWriteTaskIdArray( char * pcBuffer,
+ uint32_t ulBufferLength,
+ const uint32_t * pulTaskIdArray,
+ uint32_t pulTaskIdArrayLength,
+ uint32_t * pulOutCharsWritten )
+{
+ char * pcCurrentWritePos = pcBuffer;
+ uint32_t i, ulRemainingBufferLength = ulBufferLength;
+ int32_t lCharactersWritten;
+ eReportBuilderStatus eStatus = eReportBuilderSuccess;
+
+ configASSERT( pcBuffer != NULL );
+ configASSERT( pulTaskIdArray != NULL );
+ configASSERT( pulOutCharsWritten != NULL );
+
+ /* Write the JSON array open marker. */
+ if( ulRemainingBufferLength > 1 )
+ {
+ *pcCurrentWritePos = reportbuilderJSON_ARRAY_OPEN_MARKER;
+ ulRemainingBufferLength -= 1;
+ pcCurrentWritePos += 1;
+ }
+ else
+ {
+ eStatus = eReportBuilderBufferTooSmall;
+ }
+
+ /* Write the array elements. */
+ for( i = 0; ( ( i < pulTaskIdArrayLength ) && ( eStatus == eReportBuilderSuccess ) ); i++ )
+ {
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ "%u,",
+ pulTaskIdArray[ i ] );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
+ {
+ eStatus = eReportBuilderBufferTooSmall;
+ }
+ else
+ {
+ ulRemainingBufferLength -= ( uint32_t ) lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
+ }
+ }
+
if( eStatus == eReportBuilderSuccess )
{
- *pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
+ /* Discard the last comma. */
+ if( pulTaskIdArrayLength > 0 )
+ {
+ pcCurrentWritePos -= 1;
+ ulRemainingBufferLength += 1;
+ }
+
+ /* Write the JSON array close marker. */
+ if( ulRemainingBufferLength > 1 )
+ {
+ *pcCurrentWritePos = reportbuilderJSON_ARRAY_CLOSE_MARKER;
+ ulRemainingBufferLength -= 1;
+ pcCurrentWritePos += 1;
+ *pulOutCharsWritten = ulBufferLength - ulRemainingBufferLength;
+ }
+ else
+ {
+ eStatus = eReportBuilderBufferTooSmall;
+ }
}
return eStatus;
@@ -332,9 +434,10 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
uint32_t * pulOutReportLength )
{
char * pcCurrentWritePos = pcBuffer;
- uint32_t ulRemainingBufferLength = ulBufferLength, bufferWritten;
+ uint32_t ulRemainingBufferLength = ulBufferLength;
+ uint32_t bufferWritten;
eReportBuilderStatus eStatus = eReportBuilderSuccess;
- int32_t ulCharactersWritten;
+ int32_t lCharactersWritten;
configASSERT( pcBuffer != NULL );
configASSERT( pxMetrics != NULL );
@@ -358,22 +461,29 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part1. */
if( eStatus == eReportBuilderSuccess )
{
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_REPORT_FORMAT_PART1,
- ulReportId,
- ulMajorReportVersion,
- ulMinorReportVersion );
-
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_REPORT_FORMAT_PART1,
+ DEFENDER_REPORT_HEADER_KEY,
+ DEFENDER_REPORT_ID_KEY,
+ ulReportId,
+ DEFENDER_REPORT_VERSION_KEY,
+ ulMajorReportVersion,
+ ulMinorReportVersion,
+ DEFENDER_REPORT_METRICS_KEY,
+ DEFENDER_REPORT_TCP_LISTENING_PORTS_KEY,
+ DEFENDER_REPORT_PORTS_KEY
+ );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 1." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
- ulRemainingBufferLength -= ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
}
}
@@ -400,20 +510,24 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part2. */
if( eStatus == eReportBuilderSuccess )
{
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_REPORT_FORMAT_PART2,
- pxMetrics->ulOpenTcpPortsArrayLength );
-
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_REPORT_FORMAT_PART2,
+ DEFENDER_REPORT_TOTAL_KEY,
+ pxMetrics->ulOpenTcpPortsArrayLength,
+ DEFENDER_REPORT_UDP_LISTENING_PORTS_KEY,
+ DEFENDER_REPORT_PORTS_KEY
+ );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 2." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
- ulRemainingBufferLength -= ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
}
}
@@ -440,24 +554,34 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part3. */
if( eStatus == eReportBuilderSuccess )
{
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_REPORT_FORMAT_PART3,
- pxMetrics->ulOpenUdpPortsArrayLength,
- pxMetrics->pxNetworkStats->ulBytesReceived,
- pxMetrics->pxNetworkStats->ulBytesSent,
- pxMetrics->pxNetworkStats->ulPacketsReceived,
- pxMetrics->pxNetworkStats->ulPacketsSent );
-
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_REPORT_FORMAT_PART3,
+ DEFENDER_REPORT_TOTAL_KEY,
+ pxMetrics->ulOpenUdpPortsArrayLength,
+ DEFENDER_REPORT_NETWORK_STATS_KEY,
+ DEFENDER_REPORT_BYTES_IN_KEY,
+ pxMetrics->pxNetworkStats->ulBytesReceived,
+ DEFENDER_REPORT_BYTES_OUT_KEY,
+ pxMetrics->pxNetworkStats->ulBytesSent,
+ DEFENDER_REPORT_PKTS_IN_KEY,
+ pxMetrics->pxNetworkStats->ulPacketsReceived,
+ DEFENDER_REPORT_PKTS_OUT_KEY,
+ pxMetrics->pxNetworkStats->ulPacketsSent,
+ DEFENDER_REPORT_TCP_CONNECTIONS_KEY,
+ DEFENDER_REPORT_ESTABLISHED_CONNECTIONS_KEY,
+ DEFENDER_REPORT_CONNECTIONS_KEY
+ );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 3." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
- ulRemainingBufferLength -= ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
}
}
@@ -484,26 +608,67 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
/* Write part4. */
if( eStatus == eReportBuilderSuccess )
{
- ulCharactersWritten = snprintf( pcCurrentWritePos,
- ulRemainingBufferLength,
- reportbuilderJSON_REPORT_FORMAT_PART4,
- pxMetrics->ulEstablishedConnectionsArrayLength );
-
- if( !reportbuilderSNPRINTF_SUCCESS( ulCharactersWritten, ulRemainingBufferLength ) )
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_REPORT_FORMAT_PART4,
+ DEFENDER_REPORT_TOTAL_KEY,
+ pxMetrics->ulEstablishedConnectionsArrayLength,
+ DEFENDER_REPORT_CUSTOM_METRICS_KEY,
+ DEFENDER_REPORT_NUMBER_KEY,
+ pxMetrics->ulStackHighWaterMark,
+ DEFENDER_REPORT_NUMBER_LIST_KEY
+ );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
{
LogError( ( "Failed to write part 4." ) );
eStatus = eReportBuilderBufferTooSmall;
}
else
{
- ulRemainingBufferLength -= ulCharactersWritten;
- pcCurrentWritePos += ulCharactersWritten;
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
+ }
+ }
+
+ /* Write task ids array. */
+ if( eStatus == eReportBuilderSuccess )
+ {
+ eStatus = prvWriteTaskIdArray( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ pxMetrics->pulTaskIdArray,
+ pxMetrics->ulTaskIdArrayLength,
+ &( bufferWritten ) );
+
+ if( eStatus == eReportBuilderSuccess )
+ {
+ pcCurrentWritePos += bufferWritten;
+ ulRemainingBufferLength -= bufferWritten;
+ }
+ else
+ {
+ LogError( ( "Failed to write task ID array." ) );
}
}
+ /* Write part5. */
if( eStatus == eReportBuilderSuccess )
{
- *pulOutReportLength = ulBufferLength - ulRemainingBufferLength;
+ lCharactersWritten = snprintf( pcCurrentWritePos,
+ ulRemainingBufferLength,
+ reportbuilderJSON_REPORT_FORMAT_PART5 );
+
+ if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, ulRemainingBufferLength ) )
+ {
+ LogError( ( "Failed to write part 5." ) );
+ eStatus = eReportBuilderBufferTooSmall;
+ }
+ else
+ {
+ ulRemainingBufferLength -= lCharactersWritten;
+ pcCurrentWritePos += lCharactersWritten;
+ *pulOutReportLength = ulBufferLength - ulRemainingBufferLength;
+ }
}
return eStatus;
diff --git a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.h b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.h
index c9b54ae15..f89d8b9e2 100644
--- a/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.h
+++ b/FreeRTOS-Plus/Demo/AWS/Device_Defender_Windows_Simulator/Device_Defender_Demo/report_builder.h
@@ -41,7 +41,13 @@ typedef enum
} eReportBuilderStatus;
/**
- * @brief Represents metrics to be included in the report.
+ * @brief Represents metrics to be included in the report, including custom metrics.
+ *
+ * This demo demonstrates the use of the stack high water mark and list of
+ * running task ids as custom metrics sent to AWS IoT Device Defender service.
+ *
+ * For more information on custom metrics, refer to the following AWS document:
+ * https://docs.aws.amazon.com/iot/latest/developerguide/dd-detect-custom-metrics.html
*/
typedef struct ReportMetrics
{
@@ -52,6 +58,10 @@ typedef struct ReportMetrics
uint32_t ulOpenUdpPortsArrayLength;
Connection_t * pxEstablishedConnectionsArray;
uint32_t ulEstablishedConnectionsArrayLength;
+ /* Custom metrics */
+ uint32_t ulStackHighWaterMark;
+ uint32_t * pulTaskIdArray;
+ uint32_t ulTaskIdArrayLength;
} ReportMetrics_t;
/**
diff --git a/FreeRTOS-Plus/Source/AWS/device-defender b/FreeRTOS-Plus/Source/AWS/device-defender
-Subproject e15db4c22cfdd534d1e0693cdbdf467c7b09e89
+Subproject ce98843504b037a81fbfbccd90d90d6f2bb1f41