From be9fe45d8ec440f7750de0f4870b28de39b10a3b Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Fri, 18 Dec 2020 13:09:46 -0800 Subject: [PATCH 01/11] Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify --- FreeRTOS_IP.c | 4 ++++ FreeRTOS_TCP_IP.c | 13 ++++++++++--- tools/tcp_utilities/tcp_mem_stats.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/FreeRTOS_IP.c b/FreeRTOS_IP.c index 9b57525c4e..2cf9f5d7f5 100644 --- a/FreeRTOS_IP.c +++ b/FreeRTOS_IP.c @@ -354,6 +354,8 @@ static BaseType_t xIPTaskInitialised = pdFALSE; /*-----------------------------------------------------------*/ +#include "random.h" + /* Coverity wants to make pvParameters const, which would make it incompatible. Leave the * function signature as is. */ @@ -434,6 +436,8 @@ static void prvIPTask( void * pvParameters ) iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType ); + vAddBytesToPool( xReceivedEvent.eEventType ); + switch( xReceivedEvent.eEventType ) { case eNetworkDownEvent: diff --git a/FreeRTOS_TCP_IP.c b/FreeRTOS_TCP_IP.c index 314d2b24bf..c62ca7e5a5 100644 --- a/FreeRTOS_TCP_IP.c +++ b/FreeRTOS_TCP_IP.c @@ -1498,6 +1498,12 @@ uxIndex += ( size_t ) ucLen; } } + + #if ( ipconfigUSE_TCP_WIN == 0 ) + /* Avoid compiler warnings when TCP window is not used. */ + ( void ) xHasSYNFlag; + #endif + return uxIndex; } /*-----------------------------------------------------------*/ @@ -2595,11 +2601,12 @@ TCPHeader_t * pxTCPHeader = &pxProtocolHeaders->xTCPHeader; const TCPWindow_t * pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow; UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength; - /* memcpy() helper variables for MISRA Rule 21.15 compliance*/ - const void * pvCopySource; - void * pvCopyDest; #if ( ipconfigUSE_TCP_WIN == 1 ) + /* memcpy() helper variables for MISRA Rule 21.15 compliance*/ + const void * pvCopySource; + void * pvCopyDest; + if( uxOptionsLength != 0U ) { /* TCP options must be sent because a packet which is out-of-order diff --git a/tools/tcp_utilities/tcp_mem_stats.c b/tools/tcp_utilities/tcp_mem_stats.c index b3aa87c54e..6a426339d1 100644 --- a/tools/tcp_utilities/tcp_mem_stats.c +++ b/tools/tcp_utilities/tcp_mem_stats.c @@ -49,7 +49,7 @@ #ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u - #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" +// #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" #endif #if ( ipconfigUSE_TCP_MEM_STATS != 0 ) From a342f508bf7fe6a2b95cff35645258ad804714e1 Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 6 Jan 2021 04:44:29 +0800 Subject: [PATCH 02/11] parent be9fe45d8ec440f7750de0f4870b28de39b10a3b author Hein Tibosch 1609879469 +0800 committer Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> 1619029134 -0700 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update litani submodule (#147) Co-authored-by: Mark R. Tuttle Fix doxygen check (#149) * Update doxygen version * update the config file TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update litani submodule (#147) Co-authored-by: Mark R. Tuttle Fix doxygen check (#149) * Update doxygen version * update the config file TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify Create uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml Update uncrustify.yml --- .github/lexicon.txt | 4 + .github/workflows/ci.yml | 2 +- .github/workflows/uncrustify.yml | 45 ++ FreeRTOS_ARP.c | 84 +++- FreeRTOS_DNS.c | 9 + FreeRTOS_IP.c | 413 ++++++++++++++++-- FreeRTOS_Sockets.c | 49 ++- FreeRTOS_Stream_Buffer.c | 220 ++++++++++ FreeRTOS_TCP_IP.c | 18 +- FreeRTOS_TCP_WIN.c | 2 +- FreeRTOS_UDP_IP.c | 9 + docs/doxygen/config.doxyfile | 192 ++++---- include/FreeRTOSIPConfigDefaults.h | 12 + include/FreeRTOS_IP.h | 83 +--- include/FreeRTOS_IP_Private.h | 170 ++----- include/FreeRTOS_Sockets.h | 19 +- include/FreeRTOS_Stream_Buffer.h | 176 +------- .../MPS2_AN385/NetworkInterface.c | 66 +-- .../ether_lan9118/smsc9220_eth_drv.c | 55 ++- .../STM32Fxx/NetworkInterface.c | 6 +- portable/NetworkInterface/STM32Hxx/readme.md | 22 +- .../pic32mzef/NetworkInterface_eth.c | 14 - test/Coverity/CMakeLists.txt | 61 +++ test/Coverity/ConfigFiles/FreeRTOSConfig.h | 119 +++++ test/Coverity/ConfigFiles/FreeRTOSIPConfig.h | 310 +++++++++++++ test/Coverity/ConfigFiles/pack_struct_end.h | 35 ++ test/Coverity/ConfigFiles/pack_struct_start.h | 33 ++ test/Coverity/ConfigFiles/portmacro.h | 161 +++++++ test/Coverity/Portable.c | 112 +++++ .../cbmc/proofs/ARP/ARPAgeCache/Makefile.json | 1 + .../ARPGenerateRequestPacket/Makefile.json | 1 + .../Configurations.json | 1 + .../Configurations.json | 1 + .../Configurations.json | 1 + test/cbmc/proofs/CheckOptions/Makefile.json | 1 + .../TCP/prvTCPHandleState/Makefile.json | 3 +- .../TCP/prvTCPPrepareSend/Makefile.json | 1 + .../TCP/prvTCPReturnPacket/Makefile.json | 2 + .../TCPReturnPacket_harness.c | 26 +- .../vProcessGeneratedUDPPacket/Makefile.json | 1 + .../ProcessReceivedTCPPacket/Makefile.json | 1 + test/litani | 2 +- test/unit-test/FreeRTOS_TCP_Unit_test.c | 4 + test/unit-test/TCPFilePaths.cmake | 8 + test/unit-test/stubs/FreeRTOS_ARP_stubs.c | 171 ++++---- test/unit-test/unit_test_build.cmake | 3 + tools/tcp_utilities/tcp_mem_stats.c | 2 +- 47 files changed, 2075 insertions(+), 656 deletions(-) create mode 100644 .github/workflows/uncrustify.yml create mode 100644 test/Coverity/CMakeLists.txt create mode 100644 test/Coverity/ConfigFiles/FreeRTOSConfig.h create mode 100644 test/Coverity/ConfigFiles/FreeRTOSIPConfig.h create mode 100644 test/Coverity/ConfigFiles/pack_struct_end.h create mode 100644 test/Coverity/ConfigFiles/pack_struct_start.h create mode 100644 test/Coverity/ConfigFiles/portmacro.h create mode 100644 test/Coverity/Portable.c diff --git a/.github/lexicon.txt b/.github/lexicon.txt index b827c6564c..98538a49fe 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -91,6 +91,7 @@ callbacklist calloc camen carriersense +castingmacrofunctions cbmc ccfg cchannel @@ -620,6 +621,7 @@ posix pparam ppkt ppointer +ppucdata ppucrecvdata ppxnetworkbuffer pr @@ -714,6 +716,7 @@ pullups pulnetmask pulnumber pulvalue +pvargument pvbuffer pvdata pvdestination @@ -1239,6 +1242,7 @@ uxstreambufferget uxstreambuffermidspace uxtail uxtaskgetsystemstate +uxtickstowait uxtimeout uxtimeoutstate uxtotaldatalength diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1876550c0..1021c26fec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,7 @@ jobs: - uses: actions/checkout@v2 - name: Install Doxygen run: | - wget -qO- "http://doxygen.nl/files/doxygen-1.8.20.linux.bin.tar.gz" | sudo tar --strip-components=1 -xz -C /usr/local + wget -qO- "http://doxygen.nl/files/doxygen-1.9.1.linux.bin.tar.gz" | sudo tar --strip-components=1 -xz -C /usr/local sudo apt-get install -y libclang-9-dev - name: Run Doxygen And Verify Stdout Is Empty run: | diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml new file mode 100644 index 0000000000..f6eb973f4a --- /dev/null +++ b/.github/workflows/uncrustify.yml @@ -0,0 +1,45 @@ +name: Uncrustify the source code + +on: + issue_comment: + types: [created] + +jobs: + Uncrustify: + name: Run_Uncrustify + if: ${{ github.event.issue.pull_request }} + # && contains(github.event.comment.body, 'confirm Uncrustify') + runs-on: ubuntu-18.04 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - name: get pullrequest url + run: | + echo ${{ github.event.issue.pull_request.url }} + - name: get upstream branch + id: upstreambranch + run: | + echo "::set-output name=branchname::$(curl -v -H "Accept: application/vnd.github.sailor-v-preview+json" --url ${{ secrets.PAT }} ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')" + - name: echo upstream branch + run: | + echo ${{ steps.upstreambranch.outputs }} + - name: Checkout upstream repo + uses: actions/checkout@v2 + with: + ref: ${{ steps.upstreambranch.outputs.branchname }} + - name: Install Uncrustify + run: sudo apt-get install uncrustify + - name: Run Uncrustify + run: | + uncrustify --version + find . -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + + echo "hello there" > hello.txt + - name: GitHub Action for committing changes to a repository + run: | + git config --global user.name 'Aniruddha Kanhere' + git config --global user.email '60444055+AniruddhaKanhere@users.noreply.github.com' + git add -A + git commit -m "test" + git push diff --git a/FreeRTOS_ARP.c b/FreeRTOS_ARP.c index 91baca8a4b..9295f126ed 100644 --- a/FreeRTOS_ARP.c +++ b/FreeRTOS_ARP.c @@ -271,12 +271,8 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, uint8_t ucMinAgeFound = 0U; #if ( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 ) - - /* Only process the IP address if it is on the local network. - * Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address - * and netmask are still unknown. */ - if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) || - ( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) ) + /* Only process the IP address if it is on the local network. */ + if( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) #else /* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with @@ -492,16 +488,6 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress, ulAddressToLookup = *pulIPAddress; - #if ( ipconfigUSE_LLMNR == 1 ) - if( ulAddressToLookup == ipLLMNR_IP_ADDR ) /* Is in network byte order. */ - { - /* The LLMNR IP-address has a fixed virtual MAC address. */ - ( void ) memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) ); - eReturn = eARPCacheHit; - } - else - #endif - if( xIsIPv4Multicast( ulAddressToLookup ) != 0 ) { /* Get the lowest 23 bits of the IP-address. */ @@ -522,6 +508,12 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress, * can be done. */ eReturn = eCantSendPacket; } + else if( *ipLOCAL_IP_ADDRESS_POINTER == *pulIPAddress ) + { + /* The address of this device. May be useful for the loopback device. */ + eReturn = eARPCacheHit; + memcpy( pxMACAddress->ucBytes, ipLOCAL_MAC_ADDRESS, sizeof( pxMACAddress->ucBytes ) ); + } else { eReturn = eARPCacheMiss; @@ -747,7 +739,7 @@ void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress ) } #endif /* if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES ) */ - if( xIsCallingFromIPTask() != 0 ) + if( xIsCallingFromIPTask() != pdFALSE ) { iptraceNETWORK_INTERFACE_OUTPUT( pxNetworkBuffer->xDataLength, pxNetworkBuffer->pucEthernetBuffer ); /* Only the IP-task is allowed to call this function directly. */ @@ -769,7 +761,63 @@ void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress ) } } } -/*--------------------------------------*/ +/*-----------------------------------------------------------*/ + +/** + * @brief Wait for address resolution: look-up the IP-address in the ARP-cache, and if + * needed send an ARP request, and wait for a reply. This function is useful when + * called before FreeRTOS_sendto(). + * + * @param[in] ulIPAddress: The IP-address to look-up. + * @param[in] uxTicksToWait: The maximum number of clock ticks to wait for a reply. + * + * @return Zero when successful. + */ +BaseType_t xARPWaitResolution( uint32_t ulIPAddress, + TickType_t uxTicksToWait ) +{ + BaseType_t xResult = -pdFREERTOS_ERRNO_EADDRNOTAVAIL; + TimeOut_t xTimeOut; + MACAddress_t xMACAddress; + eARPLookupResult_t xLookupResult; + size_t uxSendCount = ipconfigMAX_ARP_RETRANSMISSIONS; + + /* The IP-task is not supposed to call this function. */ + configASSERT( xIsCallingFromIPTask() == pdFALSE ); + + xLookupResult = eARPGetCacheEntry( &( ulIPAddress ), &( xMACAddress ) ); + + if( xLookupResult == eARPCacheMiss ) + { + const TickType_t uxSleepTime = pdMS_TO_TICKS( 250U ); + + /* We might use ipconfigMAX_ARP_RETRANSMISSIONS here. */ + vTaskSetTimeOutState( &xTimeOut ); + + while( uxSendCount > 0 ) + { + FreeRTOS_OutputARPRequest( ulIPAddress ); + + vTaskDelay( uxSleepTime ); + + xLookupResult = eARPGetCacheEntry( &( ulIPAddress ), &( xMACAddress ) ); + + if( ( xTaskCheckForTimeOut( &( xTimeOut ), &( uxTicksToWait ) ) == pdTRUE ) || + ( xLookupResult != eARPCacheMiss ) ) + { + break; + } + } + } + + if( xLookupResult == eARPCacheHit ) + { + xResult = 0; + } + + return xResult; +} +/*-----------------------------------------------------------*/ /** * @brief Generate an ARP request packet by copying various constant details to diff --git a/FreeRTOS_DNS.c b/FreeRTOS_DNS.c index 6bc06f22e1..c6f36457f2 100644 --- a/FreeRTOS_DNS.c +++ b/FreeRTOS_DNS.c @@ -1947,6 +1947,15 @@ pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER; pxIPHeader->ucTimeToLive = ipconfigUDP_TIME_TO_LIVE; pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier ); + + /* The stack doesn't support fragments, so the fragment offset field must always be zero. + * The header was never memset to zero, so set both the fragment offset and fragmentation flags in one go. + */ + #if ( ipconfigFORCE_IP_DONT_FRAGMENT != 0 ) + pxIPHeader->usFragmentOffset = ipFRAGMENT_FLAGS_DONT_FRAGMENT; + #else + pxIPHeader->usFragmentOffset = 0U; + #endif usPacketIdentifier++; pxUDPHeader->usLength = FreeRTOS_htons( ( uint32_t ) lNetLength + ipSIZE_OF_UDP_HEADER ); vFlip_16( pxUDPHeader->usSourcePort, pxUDPHeader->usDestinationPort ); diff --git a/FreeRTOS_IP.c b/FreeRTOS_IP.c index 2cf9f5d7f5..05c4be25be 100644 --- a/FreeRTOS_IP.c +++ b/FreeRTOS_IP.c @@ -115,16 +115,6 @@ #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #endif -#if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) - #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) - /** @brief The bits in the two byte IP header field that make up the fragment offset value. */ - #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f ) - #else - /** @brief The bits in the two byte IP header field that make up the fragment offset value. */ - #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) - #endif /* ipconfigBYTE_ORDER */ -#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ - /** @brief The maximum time the IP task is allowed to remain in the Blocked state if no * events are posted to the network event queue. */ #ifndef ipconfigMAX_IP_TASK_SLEEP_TIME @@ -354,8 +344,6 @@ static BaseType_t xIPTaskInitialised = pdFALSE; /*-----------------------------------------------------------*/ -#include "random.h" - /* Coverity wants to make pvParameters const, which would make it incompatible. Leave the * function signature as is. */ @@ -436,8 +424,6 @@ static void prvIPTask( void * pvParameters ) iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType ); - vAddBytesToPool( xReceivedEvent.eEventType ); - switch( xReceivedEvent.eEventType ) { case eNetworkDownEvent: @@ -1154,21 +1140,21 @@ BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES { /* This is a 64-bit platform, make sure there is enough space in * pucEthernetBuffer to store a pointer. */ - configASSERT( ipconfigBUFFER_PADDING == 14 ); + configASSERT( ipconfigBUFFER_PADDING >= 14 ); + + /* But it must have this strange alignment: */ + configASSERT( ( ( ( ipconfigBUFFER_PADDING ) + 2 ) % 4 ) == 0 ); } - #ifndef _lint - { - /* Check if MTU is big enough. */ - configASSERT( ( ( size_t ) ipconfigNETWORK_MTU ) >= ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + ipconfigTCP_MSS ) ); - /* Check structure packing is correct. */ - configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE ); - configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE ); - configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE ); - configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE ); - configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE ); - } - #endif /* ifndef _lint */ + /* Check if MTU is big enough. */ + configASSERT( ( ( size_t ) ipconfigNETWORK_MTU ) >= ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + ipconfigTCP_MSS ) ); + /* Check structure packing is correct. */ + configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE ); + configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE ); + configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE ); + configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE ); + configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE ); + /* Attempt to create the queue used to communicate with the IP task. */ xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); configASSERT( xNetworkEventQueue != NULL ); @@ -1857,10 +1843,11 @@ static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPP * This method may decrease the usage of sparse network buffers. */ uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; - /* Ensure that the incoming packet is not fragmented (only outgoing - * packets can be fragmented) as these are the only handled IP frames - * currently. */ - if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) + /* Ensure that the incoming packet is not fragmented because the stack + * doesn't not support IP fragmentation. All but the last fragment coming in will have their + * "more fragments" flag set and the last fragment will have a non-zero offset. + * We need to drop the packet in either of those cases. */ + if( ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) || ( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_FLAGS_MORE_FRAGMENTS ) != 0U ) ) { /* Can not handle, fragmented packet. */ eReturn = eReleaseBuffer; @@ -2253,6 +2240,15 @@ static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * pxIPPacket, pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress; pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER; + /* The stack doesn't support fragments, so the fragment offset field must always be zero. + * The header was never memset to zero, so set both the fragment offset and fragmentation flags in one go. + */ + #if ( ipconfigFORCE_IP_DONT_FRAGMENT != 0 ) + pxIPHeader->usFragmentOffset = ipFRAGMENT_FLAGS_DONT_FRAGMENT; + #else + pxIPHeader->usFragmentOffset = 0U; + #endif + /* Update the checksum because the ucTypeOfMessage member in the header * has been changed to ipICMP_ECHO_REPLY. This is faster than calling * usGenerateChecksum(). */ @@ -3416,6 +3412,361 @@ const char * FreeRTOS_strerror_r( BaseType_t xErrnum, } /*-----------------------------------------------------------*/ +/** + * @brief Get the highest value of two int32's. + * @param[in] a: the first value. + * @param[in] b: the second value. + * @return The highest of the two values. + */ +int32_t FreeRTOS_max_int32( int32_t a, + int32_t b ) +{ + return ( a >= b ) ? a : b; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the highest value of two uint32_t's. + * @param[in] a: the first value. + * @param[in] b: the second value. + * @return The highest of the two values. + */ +uint32_t FreeRTOS_max_uint32( uint32_t a, + uint32_t b ) +{ + return ( a >= b ) ? a : b; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the lowest value of two int32_t's. + * @param[in] a: the first value. + * @param[in] b: the second value. + * @return The lowest of the two values. + */ +int32_t FreeRTOS_min_int32( int32_t a, + int32_t b ) +{ + return ( a <= b ) ? a : b; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the lowest value of two uint32_t's. + * @param[in] a: the first value. + * @param[in] b: the second value. + * @return The lowest of the two values. + */ +uint32_t FreeRTOS_min_uint32( uint32_t a, + uint32_t b ) +{ + return ( a <= b ) ? a : b; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Round-up a number to a multiple of 'd'. + * @param[in] a: the first value. + * @param[in] d: the second value. + * @return A multiple of d. + */ +uint32_t FreeRTOS_round_up( uint32_t a, + uint32_t d ) +{ + return d * ( ( a + d - 1U ) / d ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Round-down a number to a multiple of 'd'. + * @param[in] a: the first value. + * @param[in] d: the second value. + * @return A multiple of d. + */ +uint32_t FreeRTOS_round_down( uint32_t a, + uint32_t d ) +{ + return d * ( a / d ); +} +/*-----------------------------------------------------------*/ + +/** + * @defgroup CastingMacroFunctions Utility casting functions + * @brief These functions are used to cast various types of pointers + * to other types. A major use would be to map various + * headers/packets on to the incoming byte stream. + * + * @param[in] pvArgument: Pointer to be casted to another type. + * + * @retval Casted pointer will be returned without violating MISRA + * rules. + * @{ + */ + +/** + * @brief Cast a given pointer to EthernetHeader_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ) +{ + return ( EthernetHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to EthernetHeader_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ) +{ + return ( const EthernetHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to IPHeader_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPHeader_t ) +{ + return ( IPHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to IPHeader_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPHeader_t ) +{ + return ( const IPHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to ICMPHeader_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ) +{ + return ( ICMPHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to ICMPHeader_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ) +{ + return ( const ICMPHeader_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to ARPPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) +{ + return ( ARPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to ARPPacket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) +{ + return ( const ARPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to IPPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPPacket_t ) +{ + return ( IPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to IPPacket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPPacket_t ) +{ + return ( const IPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to ICMPPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPPacket_t ) +{ + return ( ICMPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to UDPPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( UDPPacket_t ) +{ + return ( UDPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to UDPPacket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( UDPPacket_t ) +{ + return ( const UDPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to TCPPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( TCPPacket_t ) +{ + return ( TCPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to TCPPacket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( TCPPacket_t ) +{ + return ( const TCPPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to ProtocolPacket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ) +{ + return ( ProtocolPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to ProtocolPacket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ) +{ + return ( const ProtocolPacket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to ProtocolHeaders_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ) +{ + return ( ProtocolHeaders_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to ProtocolHeaders_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ) +{ + return ( const ProtocolHeaders_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to FreeRTOS_Socket_t type pointer. + */ +ipDECL_CAST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ) +{ + return ( FreeRTOS_Socket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to FreeRTOS_Socket_t type pointer. + */ +ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ) +{ + return ( const FreeRTOS_Socket_t * ) pvArgument; +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) + +/** + * @brief Cast a given pointer to SocketSelect_t type pointer. + */ + ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelect_t ) + { + return ( SocketSelect_t * ) pvArgument; + } + /*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to SocketSelect_t type pointer. + */ + ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelect_t ) + { + return ( const SocketSelect_t * ) pvArgument; + } + /*-----------------------------------------------------------*/ + +/** + * @brief Cast a given pointer to SocketSelectMessage_t type pointer. + */ + ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ) + { + return ( SocketSelectMessage_t * ) pvArgument; + } + /*-----------------------------------------------------------*/ + +/** + * @brief Cast a given constant pointer to SocketSelectMessage_t type pointer. + */ + ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ) + { + return ( const SocketSelectMessage_t * ) pvArgument; + } + /*-----------------------------------------------------------*/ +#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */ +/** @} */ + +/** + * @brief Convert character array (of size 4) to equivalent 32-bit value. + * @param[in] pucPtr: The character array. + * @return 32-bit equivalent value extracted from the character array. + * + * @note Going by MISRA rules, these utility functions should not be defined + * if they are not being used anywhere. But their use depends on the + * application and hence these functions are defined unconditionally. + */ +uint32_t ulChar2u32( const uint8_t * pucPtr ) +{ + return ( ( ( uint32_t ) pucPtr[ 0 ] ) << 24 ) | + ( ( ( uint32_t ) pucPtr[ 1 ] ) << 16 ) | + ( ( ( uint32_t ) pucPtr[ 2 ] ) << 8 ) | + ( ( ( uint32_t ) pucPtr[ 3 ] ) ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Convert character array (of size 2) to equivalent 16-bit value. + * @param[in] pucPtr: The character array. + * @return 16-bit equivalent value extracted from the character array. + * + * @note Going by MISRA rules, these utility functions should not be defined + * if they are not being used anywhere. But their use depends on the + * application and hence these functions are defined unconditionally. + */ +uint16_t usChar2u16( const uint8_t * pucPtr ) +{ + return ( uint16_t ) + ( ( ( ( uint32_t ) pucPtr[ 0 ] ) << 8 ) | + ( ( ( uint32_t ) pucPtr[ 1 ] ) ) ); +} +/*-----------------------------------------------------------*/ + /* Provide access to private members for verification. */ #ifdef FREERTOS_TCP_ENABLE_VERIFICATION #include "aws_freertos_ip_verification_access_ip_define.h" diff --git a/FreeRTOS_Sockets.c b/FreeRTOS_Sockets.c index 2ed1e9a107..c854bf460d 100644 --- a/FreeRTOS_Sockets.c +++ b/FreeRTOS_Sockets.c @@ -99,11 +99,14 @@ { return ( F_TCP_UDP_Handler_t * ) pvArgument; } + /*-----------------------------------------------------------*/ + static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( F_TCP_UDP_Handler_t ) { return ( const F_TCP_UDP_Handler_t * ) pvArgument; } -#endif + /*-----------------------------------------------------------*/ +#endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */ /** @@ -115,7 +118,7 @@ static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( NetworkBufferDescriptor_t ) { return ( NetworkBufferDescriptor_t * ) pvArgument; } - +/*-----------------------------------------------------------*/ /** * @brief Utility function to cast pointer of a type to pointer of type StreamBuffer_t. @@ -3294,17 +3297,24 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) if( pxBuffer != NULL ) { - BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer ); - BaseType_t xRemain = ( BaseType_t ) pxBuffer->LENGTH - ( BaseType_t ) pxBuffer->uxHead; + size_t uxSpace = uxStreamBufferGetSpace( pxBuffer ); + size_t uxRemain = pxBuffer->LENGTH - pxBuffer->uxHead; + + if( uxRemain <= uxSpace ) + { + *pxLength = uxRemain; + } + else + { + *pxLength = uxSpace; + } - *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain ); pucReturn = &( pxBuffer->ucArray[ pxBuffer->uxHead ] ); } } return pucReturn; } - #endif /* ipconfigUSE_TCP */ /*-----------------------------------------------------------*/ @@ -4356,6 +4366,33 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) #endif /* ipconfigUSE_TCP */ /*-----------------------------------------------------------*/ +/** + * @brief Check whether a given socket is valid or not. Validity is defined + * as the socket not being NULL and not being Invalid. + * @param[in] xSocket: The socket to be checked. + * @return pdTRUE if the socket is valid, else pdFALSE. + * + */ +BaseType_t xSocketValid( Socket_t xSocket ) +{ + BaseType_t xReturnValue = pdFALSE; + + /* + * There are two values which can indicate an invalid socket: + * FREERTOS_INVALID_SOCKET and NULL. In order to compare against + * both values, the code cannot be compliant with rule 11.4, + * hence the Coverity suppression statement below. + */ + /* coverity[misra_c_2012_rule_11_4_violation] */ + if( ( xSocket != FREERTOS_INVALID_SOCKET ) && ( xSocket != NULL ) ) + { + xReturnValue = pdTRUE; + } + + return xReturnValue; +} +/*-----------------------------------------------------------*/ + #if 0 /** diff --git a/FreeRTOS_Stream_Buffer.c b/FreeRTOS_Stream_Buffer.c index c824c4fd65..73e2ed30a5 100644 --- a/FreeRTOS_Stream_Buffer.c +++ b/FreeRTOS_Stream_Buffer.c @@ -43,6 +43,226 @@ #include "FreeRTOS_IP_Private.h" +/** + * @brief Get the space between lower and upper value provided to the function. + * @param[in] pxBuffer: The circular stream buffer. + * @param[in] uxLower: The lower value. + * @param[in] uxUpper: The upper value. + * @return The space between uxLower and uxUpper, which equals to the distance + * minus 1. + */ +size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer, + const size_t uxLower, + const size_t uxUpper ) +{ + size_t uxCount; + + uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1U; + + if( uxCount >= pxBuffer->LENGTH ) + { + uxCount -= pxBuffer->LENGTH; + } + + return uxCount; +} + +/** + * @brief Get the distance between lower and upper value provided to the function. + * @param[in] pxBuffer: The circular stream buffer. + * @param[in] uxLower: The lower value. + * @param[in] uxUpper: The upper value. + * @return The distance between uxLower and uxUpper. + */ +size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer, + const size_t uxLower, + const size_t uxUpper ) +{ + size_t uxCount; + + uxCount = pxBuffer->LENGTH + uxUpper - uxLower; + + if( uxCount >= pxBuffer->LENGTH ) + { + uxCount -= pxBuffer->LENGTH; + } + + return uxCount; +} + +/** + * @brief Get the number of items which can be added to the buffer at + * the head before reaching the tail. + * @param[in] pxBuffer: The circular stream buffer. + * @return The number of items which can still be added to uxHead + * before hitting on uxTail + */ +size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer ) +{ + size_t uxHead = pxBuffer->uxHead; + size_t uxTail = pxBuffer->uxTail; + + return uxStreamBufferSpace( pxBuffer, uxHead, uxTail ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the distance between the pointer in free space and the tail. + * @param[in] pxBuffer: The circular stream buffer. + * @return Distance between uxFront and uxTail or the number of items + * which can still be added to uxFront, before hitting on uxTail. + */ +size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer ) +{ + size_t uxFront = pxBuffer->uxFront; + size_t uxTail = pxBuffer->uxTail; + + return uxStreamBufferSpace( pxBuffer, uxFront, uxTail ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the number of items which can be read from the tail before + * reaching the head. + * @param[in] pxBuffer: The circular stream buffer. + * @return The number of items which can be read from the tail before + * reaching the head. + */ +size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer ) +{ + size_t uxHead = pxBuffer->uxHead; + size_t uxTail = pxBuffer->uxTail; + + return uxStreamBufferDistance( pxBuffer, uxTail, uxHead ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the space between the mid pointer and the head in the stream + * buffer. + * @param[in] pxBuffer: The circular stream buffer. + * @return The space between the mid pointer and the head. + */ +size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer ) +{ + size_t uxHead = pxBuffer->uxHead; + size_t uxMid = pxBuffer->uxMid; + + return uxStreamBufferDistance( pxBuffer, uxMid, uxHead ); +} +/*-----------------------------------------------------------*/ + +/** + * @brief Move Clear the stream buffer. + * @param[in] pxBuffer: The circular stream buffer. + */ +void vStreamBufferClear( StreamBuffer_t * pxBuffer ) +{ + /* Make the circular buffer empty */ + pxBuffer->uxHead = 0U; + pxBuffer->uxTail = 0U; + pxBuffer->uxFront = 0U; + pxBuffer->uxMid = 0U; +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Move the mid pointer forward by given byte count + * @param[in] pxBuffer: The circular stream buffer. + * @param[in] uxCount: The byte count by which the mid pointer is to be moved. + */ +void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer, + size_t uxCount ) +{ + /* Increment uxMid, but no further than uxHead */ + size_t uxSize = uxStreamBufferMidSpace( pxBuffer ); + size_t uxMid = pxBuffer->uxMid; + size_t uxMoveCount = uxCount; + + if( uxMoveCount > uxSize ) + { + uxMoveCount = uxSize; + } + + uxMid += uxMoveCount; + + if( uxMid >= pxBuffer->LENGTH ) + { + uxMid -= pxBuffer->LENGTH; + } + + pxBuffer->uxMid = uxMid; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Check whether the value in left is less than or equal to the + * value in right from the perspective of the circular stream + * buffer. + * @param[in] pxBuffer: The circular stream buffer. + * @param[in] uxLeft: The left pointer in the stream buffer. + * @param[in] uxRight: The right value pointer in the stream buffer. + * @return pdTRUE if uxLeft <= uxRight, else pdFALSE. + */ +BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer, + const size_t uxLeft, + const size_t uxRight ) +{ + BaseType_t xReturn; + size_t uxTail = pxBuffer->uxTail; + + /* Returns true if ( uxLeft < uxRight ) */ + if( ( ( ( uxLeft < uxTail ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U ) + { + if( uxRight < uxTail ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + else + { + if( uxLeft <= uxRight ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +/** + * @brief Get the pointer to data and the amount of data which can be read in one go. + * + * @param[in] pxBuffer: The circular stream buffer. + * @param[out] ppucData: Pointer to the data pointer which will point to the + * data which can be read. + * + * @return The number of bytes which can be read in one go (which might be less than + * actual number of available bytes since this is a circular buffer and tail + * can loop back to the start of the buffer). + */ +size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer, + uint8_t ** ppucData ) +{ + size_t uxNextTail = pxBuffer->uxTail; + size_t uxSize = uxStreamBufferGetSize( pxBuffer ); + + *ppucData = pxBuffer->ucArray + uxNextTail; + + return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail ); +} +/*-----------------------------------------------------------*/ + /** * @brief Adds data to a stream buffer. * diff --git a/FreeRTOS_TCP_IP.c b/FreeRTOS_TCP_IP.c index c62ca7e5a5..bd51860cf3 100644 --- a/FreeRTOS_TCP_IP.c +++ b/FreeRTOS_TCP_IP.c @@ -810,12 +810,14 @@ { pxNetworkBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( size_t ) pxNetworkBuffer->xDataLength ); - if( pxNetworkBuffer == NULL ) + if( pxNetworkBuffer != NULL ) + { + xDoRelease = pdTRUE; + } + else { FreeRTOS_debug_printf( ( "prvTCPReturnPacket: duplicate failed\n" ) ); } - - xDoRelease = pdTRUE; } } #endif /* ipconfigZERO_COPY_TX_DRIVER */ @@ -962,7 +964,15 @@ /* Just an increasing number. */ pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier ); usPacketIdentifier++; - pxIPHeader->usFragmentOffset = 0U; + + /* The stack doesn't support fragments, so the fragment offset field must always be zero. + * The header was never memset to zero, so set both the fragment offset and fragmentation flags in one go. + */ + #if ( ipconfigFORCE_IP_DONT_FRAGMENT != 0 ) + pxIPHeader->usFragmentOffset = ipFRAGMENT_FLAGS_DONT_FRAGMENT; + #else + pxIPHeader->usFragmentOffset = 0U; + #endif /* Important: tell NIC driver how many bytes must be sent. */ pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER; diff --git a/FreeRTOS_TCP_WIN.c b/FreeRTOS_TCP_WIN.c index 7670c3eea6..adff6b0d50 100644 --- a/FreeRTOS_TCP_WIN.c +++ b/FreeRTOS_TCP_WIN.c @@ -1631,7 +1631,7 @@ { TCPSegment_t * pxSegment; uint32_t ulMaxTime; - uint32_t ulReturn = ~0UL; + uint32_t ulReturn = ( ( uint32_t ) ~0UL ); /* Fetches data to be sent-out now. diff --git a/FreeRTOS_UDP_IP.c b/FreeRTOS_UDP_IP.c index 9f34fd31ef..8a79ff83da 100644 --- a/FreeRTOS_UDP_IP.c +++ b/FreeRTOS_UDP_IP.c @@ -195,6 +195,15 @@ void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuff pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength ); pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress; + /* The stack doesn't support fragments, so the fragment offset field must always be zero. + * The header was never memset to zero, so set both the fragment offset and fragmentation flags in one go. + */ + #if ( ipconfigFORCE_IP_DONT_FRAGMENT != 0 ) + pxIPHeader->usFragmentOffset = ipFRAGMENT_FLAGS_DONT_FRAGMENT; + #else + pxIPHeader->usFragmentOffset = 0U; + #endif + #if ( ipconfigUSE_LLMNR == 1 ) { /* LLMNR messages are typically used on a LAN and they're diff --git a/docs/doxygen/config.doxyfile b/docs/doxygen/config.doxyfile index 7d4821e1f1..d19f0d7b41 100644 --- a/docs/doxygen/config.doxyfile +++ b/docs/doxygen/config.doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.8.20 +# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -32,13 +32,13 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "FreeRTOS-Plus-TCP" +PROJECT_NAME = FreeRTOS-Plus-TCP # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.3.2" +PROJECT_NUMBER = V2.3.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -323,7 +323,10 @@ OPTIMIZE_OUTPUT_SLICE = NO # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. EXTENSION_MAPPING = @@ -468,7 +471,7 @@ LOOKUP_CACHE_SIZE = 0 # DOT_NUM_THREADS setting. # Minimum value: 0, maximum value: 32, default value: 1. -# NUM_PROC_THREADS = 1 +NUM_PROC_THREADS = 1 #--------------------------------------------------------------------------- # Build related configuration options @@ -533,6 +536,13 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation @@ -570,11 +580,18 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES, upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# (including Cygwin) and Mac users are advised to set this option to NO. +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. # The default value is: system dependent. CASE_SENSE_NAMES = NO @@ -813,7 +830,10 @@ WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when -# a warning is encountered. +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO @@ -844,7 +864,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ./ \ +INPUT = ./ \ ./docs/doxygen \ ./include \ ./portable \ @@ -861,8 +881,8 @@ INPUT = ./ \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: https://www.gnu.org/software/libiconv/) for the list of -# possible encodings. +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 @@ -875,13 +895,15 @@ INPUT_ENCODING = UTF-8 # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen -# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, -# *.vhdl, *.ucf, *.qsf and *.ice. +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.h \ @@ -1098,15 +1120,21 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the -# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the -# cost of reduced performance. This can be particularly helpful with template -# rich C++ code for which doxygen's built-in parser lacks the necessary type -# information. +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. -# CLANG_ASSISTED_PARSING = NO +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that @@ -1114,20 +1142,20 @@ VERBATIM_HEADERS = YES # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. -# CLANG_OPTIONS = +CLANG_OPTIONS = # If clang assisted parsing is enabled you can provide the clang parser with the # path to the directory containing a file called compile_commands.json. This # file is the compilation database (see: # http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the # options used when the source files were built. This is equivalent to -# specifying the "-p" option to a clang tool, such as clang-check. These options +# specifying the -p option to a clang tool, such as clang-check. These options # will then be passed to the parser. Any options specified with CLANG_OPTIONS # will be added as well. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse_libclang=ON option for CMake. -# CLANG_DATABASE_PATH = +CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index @@ -1140,13 +1168,6 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 5 - # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored @@ -1317,10 +1338,11 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: https://developer.apple.com/xcode/), introduced with OSX -# 10.5 (Leopard). To create a documentation set, doxygen will generate a -# Makefile in the HTML output directory. Running make will produce the docset in -# that directory and running make install will install the docset in +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy # genXcode/_index.html for more information. @@ -1362,8 +1384,8 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on -# Windows. +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML @@ -1438,7 +1460,8 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1446,8 +1469,8 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- -# folders). +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1455,16 +1478,16 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- -# filters). +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = @@ -1476,9 +1499,9 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = -# The QHG_LOCATION tag can be used to specify the location of Qt's -# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the -# generated .qhp file. +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = @@ -1564,7 +1587,7 @@ EXT_LINKS_IN_WINDOW = NO # The default value is: png. # This tag requires that the tag GENERATE_HTML is set to YES. -# HTML_FORMULA_FORMAT = png +HTML_FORMULA_FORMAT = png # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful @@ -1590,7 +1613,7 @@ FORMULA_TRANSPARENT = YES # to create new LaTeX commands to be used in formulas as building blocks. See # the section "Including formulas" for details. -# FORMULA_MACROFILE = +FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering @@ -1605,7 +1628,7 @@ USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/latest/output.html) for more details. +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. @@ -1635,7 +1658,8 @@ MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site -# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1682,7 +1706,8 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). +# Xapian (see: +# https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1695,8 +1720,9 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: https://xapian.org/). See the section "External Indexing and -# Searching" for details. +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. # This tag requires that the tag SEARCHENGINE is set to YES. SEARCHENGINE_URL = @@ -2198,15 +2224,15 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = "DOXYGEN=1" \ - "ipconfigUSE_DHCP=1" \ - "ipconfigUSE_DNS=1" \ - "ipconfigUSE_LLMNR=1" \ - "ipconfigUSE_NBNS=1" \ - "ipconfigDNS_USE_CALLBACKS=1" \ - "ipconfigSUPPORT_SELECT_FUNCTION=1" \ - "ipconfigUSE_TCP=1" \ - "ipconfigUSE_TCP_WIN=1" +PREDEFINED = DOXYGEN=1 \ + ipconfigUSE_DHCP=1 \ + ipconfigUSE_DNS=1 \ + ipconfigUSE_LLMNR=1 \ + ipconfigUSE_NBNS=1 \ + ipconfigDNS_USE_CALLBACKS=1 \ + ipconfigSUPPORT_SELECT_FUNCTION=1 \ + ipconfigUSE_TCP=1 \ + ipconfigUSE_TCP_WIN=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2383,10 +2409,32 @@ UML_LOOK = NO # but if the number exceeds 15, the total amount of fields shown is limited to # 10. # Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag HAVE_DOT is set to YES. +# This tag requires that the tag UML_LOOK is set to YES. UML_LIMIT_NUM_FIELDS = 10 +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2576,17 +2624,11 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc and +# plantuml temporary files. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES - -# Aliases - -ALIASES += transportcallback="@ingroup mqtt_callback_types" -ALIASES += transportstruct="@ingroup mqtt_struct_types" -ALIASES += transportpage="@page mqtt_transport_interface Transport Interface" -ALIASES += transportsectionimplementation="@section mqtt_transport_interface_implementation Implementing the Transport Interface" -ALIASES += transportsectionoverview="@section mqtt_transport_interface_overview Transport Interface Overview" diff --git a/include/FreeRTOSIPConfigDefaults.h b/include/FreeRTOSIPConfigDefaults.h index bbbab54da5..dcbabb2159 100644 --- a/include/FreeRTOSIPConfigDefaults.h +++ b/include/FreeRTOSIPConfigDefaults.h @@ -336,6 +336,18 @@ #define ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS 1 #endif +/* Configuration to control whether all outgoing IP datagrams get their + * "don't fragment" flag set. + * If set to 1, the stack will set the "don't fragment" flag on all outgoing IP + * packets. If a packet needs to be fragmented somewhere along it's path, it will get + * discarded instead of fragmented. + * If set to 0, the stack will clear the "don't fragment" flag an all outgoing IP + * packets therefore allowing fragmentation if it is needed. + */ +#ifndef ipconfigFORCE_IP_DONT_FRAGMENT + #define ipconfigFORCE_IP_DONT_FRAGMENT 0 +#endif + /* Configuration to control whether UDP packets with * checksum value of zero should be passed up the software * stack OR should be dropped. diff --git a/include/FreeRTOS_IP.h b/include/FreeRTOS_IP.h index 3354d6ae4f..665da6e119 100644 --- a/include/FreeRTOS_IP.h +++ b/include/FreeRTOS_IP.h @@ -198,75 +198,18 @@ #define FreeRTOS_ntohs( x ) FreeRTOS_htons( x ) #define FreeRTOS_ntohl( x ) FreeRTOS_htonl( x ) - #if ( ipconfigHAS_INLINE_FUNCTIONS == 1 ) - - static portINLINE int32_t FreeRTOS_max_int32( int32_t a, - int32_t b ); - static portINLINE uint32_t FreeRTOS_max_uint32( uint32_t a, - uint32_t b ); - static portINLINE int32_t FreeRTOS_min_int32( int32_t a, - int32_t b ); - static portINLINE uint32_t FreeRTOS_min_uint32( uint32_t a, - uint32_t b ); - static portINLINE uint32_t FreeRTOS_round_up( uint32_t a, - uint32_t d ); - static portINLINE uint32_t FreeRTOS_round_down( uint32_t a, - uint32_t d ); - static portINLINE BaseType_t FreeRTOS_min_BaseType( BaseType_t a, - BaseType_t b ); - - static portINLINE int32_t FreeRTOS_max_int32( int32_t a, - int32_t b ) - { - return ( a >= b ) ? a : b; - } - static portINLINE uint32_t FreeRTOS_max_uint32( uint32_t a, - uint32_t b ) - { - return ( a >= b ) ? a : b; - } - static portINLINE int32_t FreeRTOS_min_int32( int32_t a, - int32_t b ) - { - return ( a <= b ) ? a : b; - } - static portINLINE uint32_t FreeRTOS_min_uint32( uint32_t a, - uint32_t b ) - { - return ( a <= b ) ? a : b; - } - static portINLINE uint32_t FreeRTOS_round_up( uint32_t a, - uint32_t d ) - { - return d * ( ( a + d - 1U ) / d ); - } - static portINLINE uint32_t FreeRTOS_round_down( uint32_t a, - uint32_t d ) - { - return d * ( a / d ); - } - - static portINLINE BaseType_t FreeRTOS_min_BaseType( BaseType_t a, - BaseType_t b ) - { - return ( a <= b ) ? a : b; - } - - #else /* if ( ipconfigHAS_INLINE_FUNCTIONS == 1 ) */ - - #define FreeRTOS_max_int32( a, b ) ( ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) ) - #define FreeRTOS_max_uint32( a, b ) ( ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) ) - - #define FreeRTOS_min_int32( a, b ) ( ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) ) - #define FreeRTOS_min_uint32( a, b ) ( ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) ) - -/* Round-up: divide a by d and round=up the result. */ - #define FreeRTOS_round_up( a, d ) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) ) - #define FreeRTOS_round_down( a, d ) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) ) - - #define FreeRTOS_min_BaseType( a, b ) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) ) - - #endif /* ipconfigHAS_INLINE_FUNCTIONS */ + int32_t FreeRTOS_max_int32( int32_t a, + int32_t b ); + uint32_t FreeRTOS_max_uint32( uint32_t a, + uint32_t b ); + int32_t FreeRTOS_min_int32( int32_t a, + int32_t b ); + uint32_t FreeRTOS_min_uint32( uint32_t a, + uint32_t b ); + uint32_t FreeRTOS_round_up( uint32_t a, + uint32_t d ); + uint32_t FreeRTOS_round_down( uint32_t a, + uint32_t d ); #define ipMS_TO_MIN_TICKS( xTimeInMs ) ( ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1U ) ) ? ( ( TickType_t ) 1U ) : pdMS_TO_TICKS( ( xTimeInMs ) ) ) @@ -330,6 +273,8 @@ uint32_t FreeRTOS_GetGatewayAddress( void ); uint32_t FreeRTOS_GetDNSServerAddress( void ); uint32_t FreeRTOS_GetNetmask( void ); + BaseType_t xARPWaitResolution( uint32_t ulIPAddress, + TickType_t uxTicksToWait ); void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress ); BaseType_t FreeRTOS_IsNetworkUp( void ); diff --git a/include/FreeRTOS_IP_Private.h b/include/FreeRTOS_IP_Private.h index c800441889..e065de1d28 100644 --- a/include/FreeRTOS_IP_Private.h +++ b/include/FreeRTOS_IP_Private.h @@ -88,15 +88,8 @@ #include "pack_struct_end.h" typedef struct xETH_HEADER EthernetHeader_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ) - { - return ( EthernetHeader_t * ) pvArgument; - } - - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ) - { - return ( const EthernetHeader_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( EthernetHeader_t ); #include "pack_struct_start.h" @@ -132,14 +125,8 @@ #include "pack_struct_end.h" typedef struct xIP_HEADER IPHeader_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPHeader_t ) - { - return ( IPHeader_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPHeader_t ) - { - return ( const IPHeader_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPHeader_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPHeader_t ); #include "pack_struct_start.h" @@ -154,14 +141,8 @@ #include "pack_struct_end.h" typedef struct xICMP_HEADER ICMPHeader_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ) - { - return ( ICMPHeader_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ) - { - return ( const ICMPHeader_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ICMPHeader_t ); #include "pack_struct_start.h" @@ -208,14 +189,8 @@ #include "pack_struct_end.h" typedef struct xARP_PACKET ARPPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) - { - return ( ARPPacket_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) - { - return ( const ARPPacket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( ARPPacket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ARPPacket_t ); #include "pack_struct_start.h" @@ -227,14 +202,8 @@ #include "pack_struct_end.h" typedef struct xIP_PACKET IPPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPPacket_t ) - { - return ( IPPacket_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPPacket_t ) - { - return ( const IPPacket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPPacket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( IPPacket_t ); #include "pack_struct_start.h" @@ -247,11 +216,7 @@ #include "pack_struct_end.h" typedef struct xICMP_PACKET ICMPPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPPacket_t ) - { - return ( ICMPPacket_t * ) pvArgument; - } - + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( ICMPPacket_t ); #include "pack_struct_start.h" struct xUDP_PACKET @@ -263,14 +228,8 @@ #include "pack_struct_end.h" typedef struct xUDP_PACKET UDPPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( UDPPacket_t ) - { - return ( UDPPacket_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( UDPPacket_t ) - { - return ( const UDPPacket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( UDPPacket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( UDPPacket_t ); #include "pack_struct_start.h" struct xTCP_PACKET @@ -282,15 +241,8 @@ #include "pack_struct_end.h" typedef struct xTCP_PACKET TCPPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( TCPPacket_t ) - { - return ( TCPPacket_t * ) pvArgument; - } - - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( TCPPacket_t ) - { - return ( const TCPPacket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( TCPPacket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( TCPPacket_t ); /** @@ -305,14 +257,8 @@ ICMPPacket_t xICMPPacket; /**< Union member: ICMP packet struct */ } ProtocolPacket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ) - { - return ( ProtocolPacket_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ) - { - return ( const ProtocolPacket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolPacket_t ); /** * Union for protocol headers to save space (RAM). Any packet cannot have more than one of @@ -325,15 +271,8 @@ TCPHeader_t xTCPHeader; /**< Union member: TCP header */ } ProtocolHeaders_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ) - { - return ( ProtocolHeaders_t * ) pvArgument; - } - - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ) - { - return ( const ProtocolHeaders_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( ProtocolHeaders_t ); /* The maximum UDP payload length. */ #define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER ) @@ -382,9 +321,6 @@ #define ipFRAGMENTATION_PARAMETERS_OFFSET ( 6 ) #define ipSOCKET_OPTIONS_OFFSET ( 6 ) -/* Only used when outgoing fragmentation is being used (FreeRTOSIPConfig.h - * setting. */ - #define ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT( usFragmentOffset ) ( ( ( usFragmentOffset ) == 0 ) ? ipUDP_PAYLOAD_OFFSET_IPv4 : ipIP_PAYLOAD_OFFSET ) /* The offset into a UDP packet at which the UDP data (payload) starts. */ #define ipUDP_PAYLOAD_OFFSET_IPv4 ( sizeof( UDPPacket_t ) ) @@ -418,6 +354,27 @@ #endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */ + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) + #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) + /* The bits in the two byte IP header field that make up the fragment offset value. */ + #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff1fU ) + /* The bits in the two byte IP header field that make up the flags value. */ + #define ipFRAGMENT_FLAGS_BIT_MASK ( ( uint16_t ) 0x00e0U ) + /* Don't Fragment Flag */ + #define ipFRAGMENT_FLAGS_DONT_FRAGMENT ( ( uint16_t ) 0x0040U ) + /* More Fragments Flag */ + #define ipFRAGMENT_FLAGS_MORE_FRAGMENTS ( ( uint16_t ) 0x0020U ) + #else + /* The bits in the two byte IP header field that make up the fragment offset value. */ + #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x1fffU ) + /* The bits in the two byte IP header field that make up the flags value. */ + #define ipFRAGMENT_FLAGS_BIT_MASK ( ( uint16_t ) 0xe000U ) + /* Don't Fragment Flag */ + #define ipFRAGMENT_FLAGS_DONT_FRAGMENT ( ( uint16_t ) 0x4000U ) + /* More Fragments Flag */ + #define ipFRAGMENT_FLAGS_MORE_FRAGMENTS ( ( uint16_t ) 0x2000U ) + #endif /* ipconfigBYTE_ORDER */ + #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ /* For convenience, a MAC address of all zeros and another of all 0xffs are * defined const for quick reference. */ @@ -797,14 +754,8 @@ } u; /**< Union of TCP/UDP socket */ } FreeRTOS_Socket_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ) - { - return ( FreeRTOS_Socket_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ) - { - return ( const FreeRTOS_Socket_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( FreeRTOS_Socket_t ); #if ( ipconfigUSE_TCP == 1 ) @@ -882,22 +833,9 @@ * if they are not being used anywhere. But their use depends on the * application and hence these functions are defined unconditionally. */ - static portINLINE uint32_t ulChar2u32( const uint8_t * apChr ); - static portINLINE uint32_t ulChar2u32( const uint8_t * apChr ) - { - return ( ( ( uint32_t ) apChr[ 0 ] ) << 24 ) | - ( ( ( uint32_t ) apChr[ 1 ] ) << 16 ) | - ( ( ( uint32_t ) apChr[ 2 ] ) << 8 ) | - ( ( ( uint32_t ) apChr[ 3 ] ) ); - } + extern uint32_t ulChar2u32( const uint8_t * pucPtr ); - static portINLINE uint16_t usChar2u16( const uint8_t * apChr ); - static portINLINE uint16_t usChar2u16( const uint8_t * apChr ) - { - return ( uint16_t ) - ( ( ( ( uint32_t ) apChr[ 0 ] ) << 8 ) | - ( ( ( uint32_t ) apChr[ 1 ] ) ) ); - } + extern uint16_t usChar2u16( const uint8_t * pucPtr ); /* Check a single socket for retransmissions and timeouts */ BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t * pxSocket ); @@ -962,14 +900,8 @@ EventGroupHandle_t xSelectGroup; } SocketSelect_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelect_t ) - { - return ( SocketSelect_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelect_t ) - { - return ( const SocketSelect_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelect_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelect_t ); extern void vSocketSelect( SocketSelect_t * pxSocketSet ); @@ -980,14 +912,8 @@ SocketSelect_t * pxSocketSet; /**< The event group for the socket select functionality. */ } SocketSelectMessage_t; - static portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ) - { - return ( SocketSelectMessage_t * ) pvArgument; - } - static portINLINE ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ) - { - return ( const SocketSelectMessage_t * ) pvArgument; - } + extern ipDECL_CAST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ); + extern ipDECL_CAST_CONST_PTR_FUNC_FOR_TYPE( SocketSelectMessage_t ); #endif /* ipconfigSUPPORT_SELECT_FUNCTION */ diff --git a/include/FreeRTOS_Sockets.h b/include/FreeRTOS_Sockets.h index ac5218cbec..2bcad8a5d5 100644 --- a/include/FreeRTOS_Sockets.h +++ b/include/FreeRTOS_Sockets.h @@ -219,24 +219,7 @@ typedef struct xSOCKET * Socket_t; typedef struct xSOCKET const * ConstSocket_t; - static portINLINE BaseType_t xSocketValid( Socket_t xSocket ) - { - BaseType_t xReturnValue = pdFALSE; - - /* - * There are two values which can indicate an invalid socket: - * FREERTOS_INVALID_SOCKET and NULL. In order to compare against - * both values, the code cannot be compliant with rule 11.4, - * hence the Coverity suppression statement below. - */ - /* coverity[misra_c_2012_rule_11_4_violation] */ - if( ( xSocket != FREERTOS_INVALID_SOCKET ) && ( xSocket != NULL ) ) - { - xReturnValue = pdTRUE; - } - - return xReturnValue; - } + extern BaseType_t xSocketValid( Socket_t xSocket ); #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) diff --git a/include/FreeRTOS_Stream_Buffer.h b/include/FreeRTOS_Stream_Buffer.h index c2f814b32d..224fb65aed 100644 --- a/include/FreeRTOS_Stream_Buffer.h +++ b/include/FreeRTOS_Stream_Buffer.h @@ -53,182 +53,42 @@ uint8_t ucArray[ sizeof( size_t ) ]; /**< array big enough to store any pointer address */ } StreamBuffer_t; - static portINLINE void vStreamBufferClear( StreamBuffer_t * pxBuffer ); - static portINLINE void vStreamBufferClear( StreamBuffer_t * pxBuffer ) - { - /* Make the circular buffer empty */ - pxBuffer->uxHead = 0U; - pxBuffer->uxTail = 0U; - pxBuffer->uxFront = 0U; - pxBuffer->uxMid = 0U; - } - + void vStreamBufferClear( StreamBuffer_t * pxBuffer ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer, - const size_t uxLower, - const size_t uxUpper ); - static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer, - const size_t uxLower, - const size_t uxUpper ) - { -/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */ - size_t uxCount; - - uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1U; - - if( uxCount >= pxBuffer->LENGTH ) - { - uxCount -= pxBuffer->LENGTH; - } - - return uxCount; - } + size_t uxStreamBufferSpace( const StreamBuffer_t * pxBuffer, + const size_t uxLower, + const size_t uxUpper ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer, - const size_t uxLower, - const size_t uxUpper ); - static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer, - const size_t uxLower, - const size_t uxUpper ) - { -/* Returns the distance between uxLower and uxUpper */ - size_t uxCount; - - uxCount = pxBuffer->LENGTH + uxUpper - uxLower; - - if( uxCount >= pxBuffer->LENGTH ) - { - uxCount -= pxBuffer->LENGTH; - } - - return uxCount; - } + size_t uxStreamBufferDistance( const StreamBuffer_t * pxBuffer, + const size_t uxLower, + const size_t uxUpper ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer ); - static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer ) - { -/* Returns the number of items which can still be added to uxHead - * before hitting on uxTail */ - size_t uxHead = pxBuffer->uxHead; - size_t uxTail = pxBuffer->uxTail; - - return uxStreamBufferSpace( pxBuffer, uxHead, uxTail ); - } + size_t uxStreamBufferGetSpace( const StreamBuffer_t * pxBuffer ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer ); - static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer ) - { -/* Distance between uxFront and uxTail - * or the number of items which can still be added to uxFront, - * before hitting on uxTail */ - - size_t uxFront = pxBuffer->uxFront; - size_t uxTail = pxBuffer->uxTail; - - return uxStreamBufferSpace( pxBuffer, uxFront, uxTail ); - } + size_t uxStreamBufferFrontSpace( const StreamBuffer_t * pxBuffer ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer ); - static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer ) - { -/* Returns the number of items which can be read from uxTail - * before reaching uxHead */ - size_t uxHead = pxBuffer->uxHead; - size_t uxTail = pxBuffer->uxTail; - - return uxStreamBufferDistance( pxBuffer, uxTail, uxHead ); - } + size_t uxStreamBufferGetSize( const StreamBuffer_t * pxBuffer ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer ); - static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer ) - { -/* Returns the distance between uxHead and uxMid */ - size_t uxHead = pxBuffer->uxHead; - size_t uxMid = pxBuffer->uxMid; - - return uxStreamBufferDistance( pxBuffer, uxMid, uxHead ); - } + size_t uxStreamBufferMidSpace( const StreamBuffer_t * pxBuffer ); /*-----------------------------------------------------------*/ - static portINLINE void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer, - size_t uxCount ); - static portINLINE void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer, - size_t uxCount ) - { -/* Increment uxMid, but no further than uxHead */ - size_t uxSize = uxStreamBufferMidSpace( pxBuffer ); - size_t uxMoveCount = uxCount; - - if( uxMoveCount > uxSize ) - { - uxMoveCount = uxSize; - } - - pxBuffer->uxMid += uxMoveCount; - - if( pxBuffer->uxMid >= pxBuffer->LENGTH ) - { - pxBuffer->uxMid -= pxBuffer->LENGTH; - } - } + void vStreamBufferMoveMid( StreamBuffer_t * pxBuffer, + size_t uxCount ); /*-----------------------------------------------------------*/ - static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer, - const size_t uxLeft, - const size_t uxRight ); - static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer, - const size_t uxLeft, - const size_t uxRight ) - { - BaseType_t xReturn; - size_t uxTail = pxBuffer->uxTail; - - /* Returns true if ( uxLeft < uxRight ) */ - if( ( ( ( uxLeft < uxTail ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U ) - { - if( uxRight < uxTail ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - else - { - if( uxLeft <= uxRight ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - - return xReturn; - } + BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t * pxBuffer, + const size_t uxLeft, + const size_t uxRight ); /*-----------------------------------------------------------*/ - static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer, - uint8_t ** ppucData ); - static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer, - uint8_t ** ppucData ) - { - size_t uxNextTail = pxBuffer->uxTail; - size_t uxSize = uxStreamBufferGetSize( pxBuffer ); - - *ppucData = pxBuffer->ucArray + uxNextTail; - - return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail ); - } + size_t uxStreamBufferGetPtr( StreamBuffer_t * pxBuffer, + uint8_t ** ppucData ); /* * Add bytes to a stream buffer. diff --git a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c index c3169fc205..1cfa0ef74d 100644 --- a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c +++ b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c @@ -72,7 +72,6 @@ #define niMAX_TX_ATTEMPTS ( 5 ) - /* ============================= Static Prototypes ========================= */ static void rx_task( void * pvParameters ); @@ -96,15 +95,13 @@ static struct smsc9220_eth_dev_t SMSC9220_ETH_DEV = static void print_hex( unsigned const char * const bin_data, size_t len ); - /* ============================= Extern Variables ========================== */ /* defined in main_networking.c */ extern uint8_t ucMACAddress[ SMSC9220_HWADDR_SIZE ]; /* 6 bytes */ - /* ============================= Static Variables ========================== */ static TaskHandle_t xRxHanderTask = NULL; - +static SemaphoreHandle_t xSemaphore = NULL; /* ============================= Static Functions ========================== */ @@ -168,10 +165,31 @@ static void set_mac( const uint8_t * addr ) } } +void EthernetISR( void ) +{ + const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + configASSERT( xRxHanderTask ); + + if( smsc9220_get_interrupt( dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ) ) + { + configASSERT( xSemaphore ); + xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); + + smsc9220_disable_interrupt( dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); + smsc9220_clear_interrupt( dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); + } + + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + /** - * @brief function to poll the netwrok card(qemu emulation) as we faced some - * problems with the network interrupt being fired for no reason at - * a very high rate which made the program not progress + * @brief function to wait on a semaphore from the interrupt handler of the + * network card when data is available */ static void rx_task( void * pvParameters ) { @@ -184,20 +202,13 @@ static void rx_task( void * pvParameters ) for( ; ; ) { - if( ( smsc9220_get_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ) ) ) - { /* data received */ - smsc9220_clear_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - xResult = pdPASS; - } - else - { - vTaskDelay( xBlockTime ); - continue; - } + configASSERT( xSemaphore ); + xSemaphoreTake( xSemaphore, + portMAX_DELAY ); packet_rx(); + smsc9220_clear_interrupt( dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); } } @@ -210,9 +221,8 @@ static void packet_rx() uint32_t data_read; FreeRTOS_debug_printf( ( "Enter\n" ) ); - data_read = low_level_input( &pxNetworkBuffer ); - if( data_read > 0 ) + while( ( data_read = low_level_input( &pxNetworkBuffer ) ) ) { xRxEvent.pvData = ( void * ) pxNetworkBuffer; @@ -234,7 +244,7 @@ static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer ) FreeRTOS_debug_printf( ( "Enter\n" ) ); - message_length = smsc9220_peek_next_packet_size( dev ); + message_length = smsc9220_peek_next_packet_size2( dev ); if( message_length != 0 ) { @@ -245,11 +255,11 @@ static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer ) { ( *pxNetworkBuffer )->xDataLength = message_length; - received_bytes = smsc9220_receive_by_chunks( dev, - ( *pxNetworkBuffer )->pucEthernetBuffer, - message_length ); /* not used */ + received_bytes = smsc9220_receive_by_chunks2( dev, + ( *pxNetworkBuffer )->pucEthernetBuffer, + message_length ); /* not used */ ( *pxNetworkBuffer )->xDataLength = received_bytes; - FreeRTOS_debug_printf( ( "incoming data < < < < < < < < < < read: %d length: %d\n", + FreeRTOS_debug_printf( ( "Incoming data < < < < < < < < < < read: %d length: %d\n", received_bytes, message_length ) ); print_hex( ( *pxNetworkBuffer )->pucEthernetBuffer, @@ -273,6 +283,8 @@ BaseType_t xNetworkInterfaceInitialise( void ) enum smsc9220_error_t err; FreeRTOS_debug_printf( ( "Enter\n" ) ); + xSemaphore = xSemaphoreCreateBinary(); + configASSERT( xSemaphore ); if( xRxHanderTask == NULL ) { @@ -283,6 +295,7 @@ BaseType_t xNetworkInterfaceInitialise( void ) configMAX_PRIORITIES - 4, &xRxHanderTask ); configASSERT( xReturn != 0 ); + configASSERT( xRxHanderTask ); } err = smsc9220_init( dev, wait_ms_function ); @@ -307,6 +320,7 @@ BaseType_t xNetworkInterfaceInitialise( void ) set_mac( ucMACAddress ); NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY ); smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); + NVIC_EnableIRQ( ETHERNET_IRQn ); } FreeRTOS_debug_printf( ( "Exit\n" ) ); diff --git a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c index 8a8305b1a3..5980d791eb 100644 --- a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c +++ b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c @@ -219,7 +219,9 @@ enum rx_fifo_status_bits_t */ enum irq_cfg_bits_t { - IRQ_CFG_IRQ_EN_INDEX = 8U + IRQ_CFG_IRQ_TYPE = 0U, + IRQ_CFG_IRQ_POL = 4U, + IRQ_CFG_IRQ_EN_INDEX = 8U, }; #define IRQ_CFG_INT_DEAS_MASK 0xFFU @@ -718,6 +720,8 @@ void smsc9220_init_irqs( const struct smsc9220_eth_dev_t * dev ) IRQ_CFG_INT_DEAS_POS, IRQ_CFG_INT_DEAS_10US ); /* enable interrupts */ + SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_TYPE ); + SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_POL ); SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_EN_INDEX ); } @@ -1198,6 +1202,55 @@ uint32_t smsc9220_receive_by_chunks( const struct smsc9220_eth_dev_t * dev, return packet_length_byte; } +/*! + * @brief second version to circumvent a bug + * in quemu where the peeked message + * size is different than the actual message size + */ +uint32_t smsc9220_receive_by_chunks2( const struct smsc9220_eth_dev_t * dev, + char * data, + uint32_t dlen ) +{ + uint32_t rxfifo_inf = 0; + uint32_t rxfifo_stat = 0; + /*uint32_t packet_length_byte = 0; */ + struct smsc9220_eth_reg_map_t * register_map = + ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; + + if( !data ) + { + return 0; /* Invalid input parameter, cannot read */ + } + + dev->data->current_rx_size_words = dlen; + + empty_rx_fifo( dev, ( uint8_t * ) data, dlen ); + dev->data->current_rx_size_words = 0; + return dlen; +} + +/*! + * @brief second version to circumvent a bug + * in quemu where the peeked message + * size is different than the actual message size + */ +uint32_t smsc9220_peek_next_packet_size2( const struct + smsc9220_eth_dev_t * dev ) +{ + uint32_t packet_size = 0; + struct smsc9220_eth_reg_map_t * register_map = + ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; + + if( smsc9220_get_rxfifo_data_used_space( dev ) ) + { + packet_size = GET_BIT_FIELD( register_map->rx_status_port, + RX_FIFO_STATUS_PKT_LENGTH_MASK, + RX_FIFO_STATUS_PKT_LENGTH_POS ); + } + + return packet_size; +} + uint32_t smsc9220_peek_next_packet_size( const struct smsc9220_eth_dev_t * dev ) { diff --git a/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/portable/NetworkInterface/STM32Fxx/NetworkInterface.c index b483fc158a..6f262127af 100644 --- a/portable/NetworkInterface/STM32Fxx/NetworkInterface.c +++ b/portable/NetworkInterface/STM32Fxx/NetworkInterface.c @@ -900,9 +900,6 @@ static void prvPassEthMessages( NetworkBufferDescriptor_t * pxDescriptor ) static BaseType_t prvNetworkInterfaceInput( void ) { - NetworkBufferDescriptor_t * pxCurDescriptor; - NetworkBufferDescriptor_t * pxNewDescriptor = NULL; - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) NetworkBufferDescriptor_t * pxFirstDescriptor = NULL; NetworkBufferDescriptor_t * pxLastDescriptor = NULL; @@ -916,7 +913,10 @@ static BaseType_t prvNetworkInterfaceInput( void ) while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u ) { + NetworkBufferDescriptor_t * pxCurDescriptor; + NetworkBufferDescriptor_t * pxNewDescriptor = NULL; BaseType_t xAccepted = pdTRUE; + /* Get the Frame Length of the received packet: subtract 4 bytes of the CRC */ xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4; diff --git a/portable/NetworkInterface/STM32Hxx/readme.md b/portable/NetworkInterface/STM32Hxx/readme.md index ef3bc343df..6ea5356337 100644 --- a/portable/NetworkInterface/STM32Hxx/readme.md +++ b/portable/NetworkInterface/STM32Hxx/readme.md @@ -54,18 +54,16 @@ Here is an example of the changes to the linker file: } >AXI_RAM Here is a table of 3 types of STH32H7 : -/** - * RAM area H747 H743 H742 Location - * ------------------------------------------------ - * DTCM 128k 128k 128k 0x20000000 - * AXI-SRAM 511k 511k 384k 0x24000000 - * - * SRAM1 128k 128k 32k 0x30000000 - * SRAM2 128k 128k 16k 0x30020000 - * SRAM3 32k 32k - 0x30040000 - * SRAM4 64k 64k 64k 0x38000000 - * Backup SRAM 4k 4k 4k 0x38800000 - */ + +|RAM area |H747|H743|H742|Location | +|-----------|----|----|----|----------| +|DTCM |128k|128k|128k|0x20000000| +|AXI-SRAM |511k|511k|384k|0x24000000| +|SRAM1 |128k|128k|32k |0x30000000| +|SRAM2 |128k|128k|16k |0x30020000| +|SRAM3 |32k | 32k| - |0x30040000| +|SRAM4 |64k |64k |64k |0x38000000| +|Backup SRAM|4k |4k |4k |0x38800000| Please make sure that the addresses and lengths are correct for your model of STM32H7xx. diff --git a/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c b/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c index 8107a55b22..2a918d9dac 100644 --- a/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c +++ b/portable/NetworkInterface/pic32mzef/NetworkInterface_eth.c @@ -195,15 +195,11 @@ static int _Command_NetInfo( SYS_CMD_DEVICE_NODE * pCmdIO, int argc, char ** argv ); - static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO, - int argc, - char ** argv ); static const SYS_CMD_DESCRIPTOR macCmdTbl[] = { { "macinfo", _Command_MacInfo, ": Check MAC statistics" }, { "netinfo", _Command_NetInfo, ": Net info" }, - { "version", _Command_Version, ": Version info" }, }; #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */ @@ -877,15 +873,5 @@ return true; } - #include "aws_application_version.h" - - static int _Command_Version( SYS_CMD_DEVICE_NODE * pCmdIO, - int argc, - char ** argv ) - { - configPRINTF( ( "App version - maj: %d, min: %d, build: %d\r\n", xAppFirmwareVersion.u.x.ucMajor, xAppFirmwareVersion.u.x.ucMinor, xAppFirmwareVersion.u.x.usBuild ) ); - return 0; - } - #endif /* (PIC32_MAC_DEBUG_COMMANDS != 0) */ #endif /* #ifdef PIC32_USE_ETHERNET */ diff --git a/test/Coverity/CMakeLists.txt b/test/Coverity/CMakeLists.txt new file mode 100644 index 0000000000..e423334534 --- /dev/null +++ b/test/Coverity/CMakeLists.txt @@ -0,0 +1,61 @@ +# Minimum required version of CMake +cmake_minimum_required ( VERSION 3.13.0 ) + +# Name of the project +project ( "FreeRTOS+TCP Static analysis" + VERSION 1.0.0 + LANGUAGES C ) + +# Allow the project to be organized into folders. +set_property( GLOBAL PROPERTY USE_FOLDERS ON ) + +# Use C90. +set( CMAKE_C_STANDARD 90 ) +set( CMAKE_C_STANDARD_REQUIRED ON ) + +# Do not allow in-source build. +if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} ) + message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." ) +endif() + +# Set global path variables. +get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) +set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "FreeRTOS-Plus-TCP repository root." ) + +# Set the kernel directory +set( KERNEL_DIRECTORY ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel ) + +# If the kernel is not submoduled, download it. +if( NOT EXISTS ${KERNEL_DIRECTORY}/include ) + # Inform the user of the actions + message( STATUS "FreeRTOS-Kernel is required for this build. Submoduling it..." ) + execute_process( COMMAND git submodule update --init --checkout ${KERNEL_DIRECTORY} + WORKING_DIRECTORY ${MODULE_ROOT_DIR} ) +endif() + +# Add kernel sources to a list +file( GLOB KERNEL_SOURCES + ${KERNEL_DIRECTORY}/*.c ) + +# Add TCP sources to a list +file( GLOB TCP_SOURCES + ${MODULE_ROOT_DIR}/*.c ) + +# A better way would be to create a library such that all other dependencies are +# ignored by the static analysis tool. But, since +TCP is very closely linked +# with the FreeRTOS-Kernel, an executable had to be created. + +# Add the executable for static analysis +add_executable( StaticAnalysis ${TCP_SOURCES} + ${KERNEL_SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/Portable.c + ${MODULE_ROOT_DIR}/portable/BufferManagement/BufferAllocation_2.c ) + +# Link the include directories with the target +target_include_directories( StaticAnalysis + PUBLIC "${KERNEL_DIRECTORY}/include" + PUBLIC "${MODULE_ROOT_DIR}/test/Coverity/ConfigFiles" + PUBLIC "${MODULE_ROOT_DIR}/include" ) + +# Uncomment the below line if the desired platform is 32-bit +# set_target_properties( StaticAnalysis PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32" ) diff --git a/test/Coverity/ConfigFiles/FreeRTOSConfig.h b/test/Coverity/ConfigFiles/FreeRTOSConfig.h new file mode 100644 index 0000000000..ac5afdbe8b --- /dev/null +++ b/test/Coverity/ConfigFiles/FreeRTOSConfig.h @@ -0,0 +1,119 @@ +/* + * FreeRTOS Kernel V10.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- +* Application specific definitions. +* +* These definitions should be adjusted for your particular hardware and +* application requirements. +* +* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE +* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See +* http://www.freertos.org/a00110.html +*----------------------------------------------------------*/ + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) /* 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 ) ( 52 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 20 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configINITIAL_TICK_COUNT ( ( TickType_t ) 0 ) + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 7 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ +#define configGENERATE_RUN_TIME_STATS 1 +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 1 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* 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. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero + * to exclude the API function. In most cases the linker will remove unused + * functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 + +/* Config assert should be defined while developing. For the static analysis + * though this should be left undefined. */ +#define configASSERT( x ) + +#define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 + +#endif /* FREERTOS_CONFIG_H */ diff --git a/test/Coverity/ConfigFiles/FreeRTOSIPConfig.h b/test/Coverity/ConfigFiles/FreeRTOSIPConfig.h new file mode 100644 index 0000000000..f0dad0cb82 --- /dev/null +++ b/test/Coverity/ConfigFiles/FreeRTOSIPConfig.h @@ -0,0 +1,310 @@ +/* + * FreeRTOS Kernel V10.2.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + + +/***************************************************************************** +* +* See the following URL for configuration information. +* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html +* +*****************************************************************************/ + +#ifndef FREERTOS_IP_CONFIG_H +#define FREERTOS_IP_CONFIG_H + +#define _static + +#define ipconfigUSE_ARP_REMOVE_ENTRY 1 +#define ipconfigUSE_ARP_REVERSED_LOOKUP 1 + +/* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to + * 1 then FreeRTOS_debug_printf should be defined to the function used to print + * out the debugging messages. */ +#define ipconfigHAS_DEBUG_PRINTF 0 +#if ( ipconfigHAS_DEBUG_PRINTF == 1 ) + #define FreeRTOS_debug_printf( X ) configPRINTF( X ) +#endif + +/* Set to 1 to print out non debugging messages, for example the output of the + * FreeRTOS_netstat() command, and ping replies. If ipconfigHAS_PRINTF is set to 1 + * then FreeRTOS_printf should be set to the function used to print out the + * messages. */ +#define ipconfigHAS_PRINTF 0 +#if ( ipconfigHAS_PRINTF == 1 ) + #define FreeRTOS_printf( X ) configPRINTF( X ) +#endif + +/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing + * on). Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */ +#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN + +/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums) + * then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software + * stack repeating the checksum calculations. */ +#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1 + +/* Several API's will block until the result is known, or the action has been + * performed, for example FreeRTOS_send() and FreeRTOS_recv(). The timeouts can be + * set per socket, using setsockopt(). If not set, the times below will be + * used as defaults. */ +#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME ( 5000 ) +#define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME ( 5000 ) + +/* Include support for DNS caching. For TCP, having a small DNS cache is very + * useful. When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low + * and also DNS may use small timeouts. If a DNS reply comes in after the DNS + * socket has been destroyed, the result will be stored into the cache. The next + * call to FreeRTOS_gethostbyname() will return immediately, without even creating + * a socket. + */ +#define ipconfigUSE_DNS_CACHE ( 1 ) +#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 6 ) +#define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) + +/* The IP stack executes it its own task (although any application task can make + * use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY + * sets the priority of the task that executes the IP stack. The priority is a + * standard FreeRTOS task priority so can take any value from 0 (the lowest + * priority) to (configMAX_PRIORITIES - 1) (the highest priority). + * configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in + * FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to + * the priority assigned to the task executing the IP stack relative to the + * priority assigned to tasks that use the IP stack. */ +#define ipconfigIP_TASK_PRIORITY ( configMAX_PRIORITIES - 2 ) + +/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP + * task. This setting is less important when the FreeRTOS Win32 simulator is used + * as the Win32 simulator only stores a fixed amount of information on the task + * stack. FreeRTOS includes optional stack overflow detection, see: + * http://www.freertos.org/Stacks-and-stack-overflow-checking.html. */ +#define ipconfigIP_TASK_STACK_SIZE_WORDS ( configMINIMAL_STACK_SIZE * 5 ) + +/* ipconfigRAND32() is called by the IP stack to generate random numbers for + * things such as a DHCP transaction number or initial sequence number. Random + * number generation is performed via this macro to allow applications to use their + * own random number generation method. For example, it might be possible to + * generate a random number by sampling noise on an analogue input. */ +extern uint32_t ulRand(); +#define ipconfigRAND32() ulRand() + +/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the + * network event hook at the appropriate times. If ipconfigUSE_NETWORK_EVENT_HOOK + * is not set to 1 then the network event hook will never be called. See: + * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml. + */ +#define ipconfigUSE_NETWORK_EVENT_HOOK 1 + +/* Sockets have a send block time attribute. If FreeRTOS_sendto() is called but + * a network buffer cannot be obtained then the calling task is held in the Blocked + * state (so other tasks can continue to executed) until either a network buffer + * becomes available or the send block time expires. If the send block time expires + * then the send operation is aborted. The maximum allowable send block time is + * capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS. Capping the + * maximum allowable send block time prevents prevents a deadlock occurring when + * all the network buffers are in use and the tasks that process (and subsequently + * free) the network buffers are themselves blocked waiting for a network buffer. + * ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks. A time in + * milliseconds can be converted to a time in ticks by dividing the time in + * milliseconds by portTICK_PERIOD_MS. */ +#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000U / portTICK_PERIOD_MS ) + +/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP + * address, netmask, DNS server address and gateway address from a DHCP server. If + * ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address. The + * stack will revert to using the static IP address even when ipconfigUSE_DHCP is + * set to 1 if a valid configuration cannot be obtained from a DHCP server for any + * reason. The static configuration used is that passed into the stack by the + * FreeRTOS_IPInit() function call. */ +#define ipconfigUSE_DHCP 1 +#define ipconfigDHCP_REGISTER_HOSTNAME 1 +#define ipconfigDHCP_USES_UNICAST 1 + +/* If ipconfigDHCP_USES_USER_HOOK is set to 1 then the application writer must + * provide an implementation of the DHCP callback function, + * xApplicationDHCPUserHook(). */ +#define ipconfigUSE_DHCP_HOOK 0 + +/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at + * increasing time intervals until either a reply is received from a DHCP server + * and accepted, or the interval between transmissions reaches + * ipconfigMAXIMUM_DISCOVER_TX_PERIOD. The IP stack will revert to using the + * static IP address passed as a parameter to FreeRTOS_IPInit() if the + * re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without + * a DHCP reply being received. */ +#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD \ + ( 120000U / portTICK_PERIOD_MS ) + +/* The ARP cache is a table that maps IP addresses to MAC addresses. The IP + * stack can only send a UDP message to a remove IP address if it knowns the MAC + * address associated with the IP address, or the MAC address of the router used to + * contact the remote IP address. When a UDP message is received from a remote IP + * address the MAC address and IP address are added to the ARP cache. When a UDP + * message is sent to a remote IP address that does not already appear in the ARP + * cache then the UDP message is replaced by a ARP message that solicits the + * required MAC address information. ipconfigARP_CACHE_ENTRIES defines the maximum + * number of entries that can exist in the ARP table at any one time. */ +#define ipconfigARP_CACHE_ENTRIES 6 + +/* ARP requests that do not result in an ARP response will be re-transmitted a + * maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is + * aborted. */ +#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 ) + +/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP + * table being created or refreshed and the entry being removed because it is stale. + * New ARP requests are sent for ARP cache entries that are nearing their maximum + * age. ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is + * equal to 1500 seconds (or 25 minutes). */ +#define ipconfigMAX_ARP_AGE 150 + +/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling + * routines, which are relatively large. To save code space the full + * FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster + * alternative called FreeRTOS_inet_addr_quick() is provided. FreeRTOS_inet_addr() + * takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter. + * FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets + * (for example, 192, 168, 0, 1) as its parameters. If + * ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and + * FreeRTOS_indet_addr_quick() are available. If ipconfigINCLUDE_FULL_INET_ADDR is + * not set to 1 then only FreeRTOS_indet_addr_quick() is available. */ +#define ipconfigINCLUDE_FULL_INET_ADDR 1 + +/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that + * are available to the IP stack. The total number of network buffers is limited + * to ensure the total amount of RAM that can be consumed by the IP stack is capped + * to a pre-determinable value. */ +#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 60 + +/* A FreeRTOS queue is used to send events from application tasks to the IP + * stack. ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can + * be queued for processing at any one time. The event queue must be a minimum of + * 5 greater than the total number of network buffers. */ +#define ipconfigEVENT_QUEUE_LENGTH \ + ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) + +/* The address of a socket is the combination of its IP address and its port + * number. FreeRTOS_bind() is used to manually allocate a port number to a socket + * (to 'bind' the socket to a port), but manual binding is not normally necessary + * for client sockets (those sockets that initiate outgoing connections rather than + * wait for incoming connections on a known port number). If + * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling + * FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP + * stack automatically binding the socket to a port number from the range + * socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff. If + * ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto() + * on a socket that has not yet been bound will result in the send operation being + * aborted. */ +#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1 + +/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */ +#define ipconfigUDP_TIME_TO_LIVE 128 +/* Also defined in FreeRTOSIPConfigDefaults.h. */ +#define ipconfigTCP_TIME_TO_LIVE 128 + +/* USE_TCP: Use TCP and all its features. */ +#define ipconfigUSE_TCP ( 1 ) + +/* USE_WIN: Let TCP use windowing mechanism. */ +#define ipconfigUSE_TCP_WIN ( 1 ) + +/* The MTU is the maximum number of bytes the payload of a network frame can + * contain. For normal Ethernet V2 frames the maximum MTU is 1500. Setting a + * lower value can save RAM, depending on the buffer management scheme used. If + * ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must + * be divisible by 8. */ +#define ipconfigNETWORK_MTU 1200U + +/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver. DNS is used + * through the FreeRTOS_gethostbyname() API function. */ +#define ipconfigUSE_DNS 1 + +/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will + * generate replies to incoming ICMP echo (ping) requests. */ +#define ipconfigREPLY_TO_INCOMING_PINGS 1 + +/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the + * FreeRTOS_SendPingRequest() API function is available. */ +#define ipconfigSUPPORT_OUTGOING_PINGS 0 + +/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select() + * (and associated) API function is available. */ +#define ipconfigSUPPORT_SELECT_FUNCTION 1 + +/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames + * that are not in Ethernet II format will be dropped. This option is included for + * potential future IP stack developments. */ +#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1 + +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the + * responsibility of the Ethernet interface to filter out packets that are of no + * interest. If the Ethernet interface does not implement this functionality, then + * set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack + * perform the filtering instead (it is much less efficient for the stack to do it + * because the packet will already have been passed into the stack). If the + * Ethernet driver does all the necessary filtering in hardware then software + * filtering can be removed by using a value other than 1 or 0. */ +#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 + +/* The windows simulator cannot really simulate MAC interrupts, and needs to + * block occasionally to allow other tasks to run. */ +#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS ) + +/* Advanced only: in order to access 32-bit fields in the IP packets with + * 32-bit memory instructions, all packets will be stored 32-bit-aligned, + * plus 16-bits. This has to do with the contents of the IP-packets: all + * 32-bit fields are 32-bit-aligned, plus 16-bit. */ +#define ipconfigPACKET_FILLER_SIZE 2U + +/* Define the size of the pool of TCP window descriptors. On the average, each + * TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6 + * outstanding packets (for Rx and Tx). When using up to 10 TP sockets + * simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */ +#define ipconfigTCP_WIN_SEG_COUNT 240 + +/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed + * maximum size. Define the size of Rx buffer for TCP sockets. */ +#define ipconfigTCP_RX_BUFFER_LENGTH ( 10000 ) + +/* Define the size of Tx buffer for TCP sockets. */ +#define ipconfigTCP_TX_BUFFER_LENGTH ( 10000 ) + +/* When using call-back handlers, the driver may check if the handler points to + * real program memory (RAM or flash) or just has a random non-zero value. */ +#define ipconfigIS_VALID_PROG_ADDRESS( x ) ( ( x ) != NULL ) + +/* Include support for TCP keep-alive messages. */ +#define ipconfigTCP_KEEP_ALIVE ( 1 ) +#define ipconfigTCP_KEEP_ALIVE_INTERVAL ( 20 ) /* Seconds. */ + +/* The socket semaphore is used to unblock the MQTT task. */ +#define ipconfigSOCKET_HAS_USER_SEMAPHORE ( 0 ) + +#define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK ( 1 ) +#define ipconfigUSE_CALLBACKS ( 0 ) + + +#define portINLINE + +void vApplicationMQTTGetKeys( const char ** ppcRootCA, + const char ** ppcClientCert, + const char ** ppcClientPrivateKey ); + +#endif /* FREERTOS_IP_CONFIG_H */ diff --git a/test/Coverity/ConfigFiles/pack_struct_end.h b/test/Coverity/ConfigFiles/pack_struct_end.h new file mode 100644 index 0000000000..584f3dcdfc --- /dev/null +++ b/test/Coverity/ConfigFiles/pack_struct_end.h @@ -0,0 +1,35 @@ +/* + * FreeRTOS+TCP V2.3.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/***************************************************************************** +* +* See the following URL for an explanation of this file: +* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html +* +*****************************************************************************/ + +/* Keyword required to appear after any structure which has packed + * placement in memory. */ +__attribute__( ( packed ) ); diff --git a/test/Coverity/ConfigFiles/pack_struct_start.h b/test/Coverity/ConfigFiles/pack_struct_start.h new file mode 100644 index 0000000000..9b71fcb38a --- /dev/null +++ b/test/Coverity/ConfigFiles/pack_struct_start.h @@ -0,0 +1,33 @@ +/* + * FreeRTOS+TCP V2.3.2 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/***************************************************************************** +* +* See the following URL for an explanation of this file: +* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html +* +*****************************************************************************/ + +/* Nothing to do here. */ diff --git a/test/Coverity/ConfigFiles/portmacro.h b/test/Coverity/ConfigFiles/portmacro.h new file mode 100644 index 0000000000..30ac3e6040 --- /dev/null +++ b/test/Coverity/ConfigFiles/portmacro.h @@ -0,0 +1,161 @@ +/* + * FreeRTOS Kernel V10.3.0 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +/****************************************************************************** +* Defines +******************************************************************************/ +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE size_t +#define portBASE_TYPE long +#define portPOINTER_SIZE_TYPE size_t + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + + +#if ( configUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#else + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +/* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick + * count do not need to be guarded with a critical section. */ + #define portTICK_TYPE_IS_ATOMIC 1 +#endif + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portINLINE + +#if defined( __x86_64__ ) || defined( _M_X64 ) + #define portBYTE_ALIGNMENT 8 +#else + #define portBYTE_ALIGNMENT 4 +#endif + +#define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD ) + + +extern volatile BaseType_t xInsideInterrupt; +#define portSOFTWARE_BARRIER() while( xInsideInterrupt != pdFALSE ) + + +/* Simulated interrupts return pdFALSE if no context switch should be performed, + * or a non-zero number if a context switch should be performed. */ +#define portYIELD_FROM_ISR( x ) ( void ) x +#define portEND_SWITCHING_ISR( x ) portYIELD_FROM_ISR( ( x ) ) + +void vPortCloseRunningThread( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ); +void vPortDeleteThread( void * pvThreadToDelete ); +#define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB ) +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) ) +#define portDISABLE_INTERRUPTS() vPortEnterCritical() +#define portENABLE_INTERRUPTS() vPortExitCritical() + +/* Critical section handling. */ +void vPortEnterCritical( void ); +void vPortExitCritical( void ); + +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + +/* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + +/* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + +/*-----------------------------------------------------------*/ + + #ifdef __GNUC__ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ + __asm volatile ( "bsr %1, %0\n\t" \ + : "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" ) + #else + +/* BitScanReverse returns the bit position of the most significant '1' + * in the word. */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) + #endif /* __GNUC__ */ + +#endif /* taskRECORD_READY_PRIORITY */ + +#ifndef __GNUC__ + __pragma( warning( disable: 4211 ) ) /* Nonstandard extension used, as extern is only nonstandard to MSVC. */ +#endif + + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) + +#define portINTERRUPT_YIELD ( 0UL ) +#define portINTERRUPT_TICK ( 1UL ) + +/* + * Raise a simulated interrupt represented by the bit mask in ulInterruptMask. + * Each bit can be used to represent an individual interrupt - with the first + * two bits being used for the Yield and Tick interrupts respectively. + */ +void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ); + +/* + * Install an interrupt handler to be called by the simulated interrupt handler + * thread. The interrupt number must be above any used by the kernel itself + * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2 + * as defined above). The number must also be lower than 32. + * + * Interrupt handler functions must return a non-zero value if executing the + * handler resulted in a task switch being required. + */ +void vPortSetInterruptHandler( uint32_t ulInterruptNumber, + uint32_t ( * pvHandler )( void ) ); + +#endif /* ifndef PORTMACRO_H */ diff --git a/test/Coverity/Portable.c b/test/Coverity/Portable.c new file mode 100644 index 0000000000..d35ae29adb --- /dev/null +++ b/test/Coverity/Portable.c @@ -0,0 +1,112 @@ +/* Include standard libraries */ +#include +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "list.h" + +#include "FreeRTOS_IP.h" + +volatile BaseType_t xInsideInterrupt = pdFALSE; + +/* Provide a main function for the build to succeed. */ +int main() +{ + return 0; +} + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return 0; +} + +const char * pcApplicationHostnameHook( void ) +{ +} +uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress, + uint16_t usSourcePort, + uint32_t ulDestinationAddress, + uint16_t usDestinationPort ) +{ +} +BaseType_t xNetworkInterfaceInitialise( void ) +{ +} +void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) +{ +} +BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber ) +{ +} +void vApplicationDaemonTaskStartupHook( void ) +{ +} +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) +{ +} +void vPortDeleteThread( void * pvTaskToDelete ) +{ +} +void vApplicationIdleHook( void ) +{ +} +void vApplicationTickHook( void ) +{ +} +unsigned long ulGetRunTimeCounterValue( void ) +{ +} +void vPortEndScheduler( void ) +{ +} +BaseType_t xPortStartScheduler( void ) +{ +} +void vPortEnterCritical( void ) +{ +} +void vPortExitCritical( void ) +{ +} + +void * pvPortMalloc( size_t xWantedSize ) +{ + return malloc( xWantedSize ); +} + +void vPortFree( void * pv ) +{ + free( pv ); +} + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) +{ +} +void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ) +{ +} +void vPortCloseRunningThread( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ) +{ +} +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ +} +void vConfigureTimerForRunTimeStats( void ) +{ +} + + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) +{ + return pdPASS; +} +/*-----------------------------------------------------------*/ diff --git a/test/cbmc/proofs/ARP/ARPAgeCache/Makefile.json b/test/cbmc/proofs/ARP/ARPAgeCache/Makefile.json index 8d1438c828..b096b3160b 100644 --- a/test/cbmc/proofs/ARP/ARPAgeCache/Makefile.json +++ b/test/cbmc/proofs/ARP/ARPAgeCache/Makefile.json @@ -9,6 +9,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_ARP.goto", "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/tasks.goto" ], diff --git a/test/cbmc/proofs/ARP/ARPGenerateRequestPacket/Makefile.json b/test/cbmc/proofs/ARP/ARPGenerateRequestPacket/Makefile.json index 3c588741cb..5a8c65f71d 100644 --- a/test/cbmc/proofs/ARP/ARPGenerateRequestPacket/Makefile.json +++ b/test/cbmc/proofs/ARP/ARPGenerateRequestPacket/Makefile.json @@ -7,6 +7,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_ARP.goto" ], "DEF": diff --git a/test/cbmc/proofs/ARP/ARP_FreeRTOS_OutputARPRequest/Configurations.json b/test/cbmc/proofs/ARP/ARP_FreeRTOS_OutputARPRequest/Configurations.json index b0c93322ad..e8b71ca0f8 100644 --- a/test/cbmc/proofs/ARP/ARP_FreeRTOS_OutputARPRequest/Configurations.json +++ b/test/cbmc/proofs/ARP/ARP_FreeRTOS_OutputARPRequest/Configurations.json @@ -35,6 +35,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_ARP.goto" ], #That is the minimal required size for an ARPPacket_t plus offset in the buffer. diff --git a/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc1/Configurations.json b/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc1/Configurations.json index 8cbf156395..988257c86f 100644 --- a/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc1/Configurations.json +++ b/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc1/Configurations.json @@ -9,6 +9,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_ARP.goto", "$(FREERTOS_PLUS_TCP)/portable/BufferManagement/BufferAllocation_1.goto", "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto", diff --git a/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc2/Configurations.json b/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc2/Configurations.json index b995601a24..e82d297bde 100644 --- a/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc2/Configurations.json +++ b/test/cbmc/proofs/ARP/ARP_OutputARPRequest_buffer_alloc2/Configurations.json @@ -10,6 +10,7 @@ [ "$(ENTRY)_harness.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_ARP.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/portable/BufferManagement/BufferAllocation_2.goto", "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto", "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/queue.goto" diff --git a/test/cbmc/proofs/CheckOptions/Makefile.json b/test/cbmc/proofs/CheckOptions/Makefile.json index 1f90c77e8b..b57a8e6fd2 100644 --- a/test/cbmc/proofs/CheckOptions/Makefile.json +++ b/test/cbmc/proofs/CheckOptions/Makefile.json @@ -4,6 +4,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_WIN.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_Stream_Buffer.goto", diff --git a/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json b/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json index 61cd679916..6243308854 100644 --- a/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json +++ b/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json @@ -39,7 +39,8 @@ "OBJS": [ "$(ENTRY)_harness.goto", - "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto" + "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto" ], "DEF": [ diff --git a/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json b/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json index 2ba001dfb7..241279ab30 100644 --- a/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json +++ b/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json @@ -36,6 +36,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto" ], "DEF": diff --git a/test/cbmc/proofs/TCP/prvTCPReturnPacket/Makefile.json b/test/cbmc/proofs/TCP/prvTCPReturnPacket/Makefile.json index 47e58ab237..4b09d607c3 100644 --- a/test/cbmc/proofs/TCP/prvTCPReturnPacket/Makefile.json +++ b/test/cbmc/proofs/TCP/prvTCPReturnPacket/Makefile.json @@ -37,6 +37,8 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_Stream_Buffer.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto" ], "DEF": diff --git a/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c b/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c index 5b16730f7f..d938bbeb94 100644 --- a/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c +++ b/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c @@ -45,8 +45,8 @@ void publicTCPReturnPacket( FreeRTOS_Socket_t * pxSocket, BaseType_t xReleaseAfterSend ); /* Abstraction of pxDuplicateNetworkBufferWithDescriptor*/ -NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t xNewLength ) +NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer, + size_t xNewLength ) { NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated(); @@ -59,6 +59,28 @@ NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( NetworkBuffe return pxNetworkBuffer; } +uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, + size_t uxBufferLength, + BaseType_t xOutgoingPacket ) +{ + __CPROVER_assert( pucEthernetBuffer != NULL, "The ethernet buffer cannot be NULL" ); + __CPROVER_r_ok( pucEthernetBuffer, uxBufferLength ); + + uint16_t usReturn; + return usReturn; +} + +uint16_t usGenerateChecksum( uint16_t usSum, + const uint8_t * pucNextData, + size_t uxByteCount ) +{ + __CPROVER_assert( pucNextData != NULL, "The next data pointer cannot be NULL" ); + __CPROVER_r_ok( pucNextData, uxByteCount ); + + uint16_t usReturn; + return usReturn; +} + void harness() { FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated(); diff --git a/test/cbmc/proofs/UDP/vProcessGeneratedUDPPacket/Makefile.json b/test/cbmc/proofs/UDP/vProcessGeneratedUDPPacket/Makefile.json index f39ff8ca5b..4baf82b1f3 100644 --- a/test/cbmc/proofs/UDP/vProcessGeneratedUDPPacket/Makefile.json +++ b/test/cbmc/proofs/UDP/vProcessGeneratedUDPPacket/Makefile.json @@ -6,6 +6,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_UDP_IP.goto" ], "INSTFLAGS": diff --git a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/Makefile.json b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/Makefile.json index 04a390c42c..9d2fa86c13 100644 --- a/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/Makefile.json +++ b/test/cbmc/proofs/parsing/ProcessReceivedTCPPacket/Makefile.json @@ -9,6 +9,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/FreeRTOS_TCP_IP.goto" ], "INSTFLAGS": diff --git a/test/litani b/test/litani index fcc583c4a5..3fc5e02bc1 160000 --- a/test/litani +++ b/test/litani @@ -1 +1 @@ -Subproject commit fcc583c4a5d5b9bebbefce5626256283fab1edda +Subproject commit 3fc5e02bc17483352546ac4c81078fde64cab674 diff --git a/test/unit-test/FreeRTOS_TCP_Unit_test.c b/test/unit-test/FreeRTOS_TCP_Unit_test.c index a5782caf62..49afa38ec1 100644 --- a/test/unit-test/FreeRTOS_TCP_Unit_test.c +++ b/test/unit-test/FreeRTOS_TCP_Unit_test.c @@ -4,6 +4,10 @@ /* Include standard libraries */ #include #include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "list.h" /* Include header file(s) which have declaration * of functions under test */ diff --git a/test/unit-test/TCPFilePaths.cmake b/test/unit-test/TCPFilePaths.cmake index 266959efe3..ac1b42fdb2 100644 --- a/test/unit-test/TCPFilePaths.cmake +++ b/test/unit-test/TCPFilePaths.cmake @@ -21,3 +21,11 @@ set( TCP_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../../portable/Compiler/MSVC" "${CMAKE_CURRENT_LIST_DIR}/stubs" ) +set( KERNEL_SOURCES + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/croutine.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/event_groups.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/list.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/queue.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/stream_buffer.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/tasks.c" + "${CMAKE_CURRENT_LIST_DIR}/../FreeRTOS-Kernel/timers.c" ) diff --git a/test/unit-test/stubs/FreeRTOS_ARP_stubs.c b/test/unit-test/stubs/FreeRTOS_ARP_stubs.c index 7b4b0b3b84..032dcbbebb 100644 --- a/test/unit-test/stubs/FreeRTOS_ARP_stubs.c +++ b/test/unit-test/stubs/FreeRTOS_ARP_stubs.c @@ -1,122 +1,109 @@ -/* IPv4 multi-cast addresses range from 224.0.0.0.0 to 240.0.0.0. */ -#define ipFIRST_MULTI_CAST_IPv4 0xE0000000UL -#define ipLAST_MULTI_CAST_IPv4 0xF0000000UL +/* Include Unity header */ +#include -/* For convenience, a MAC address of all 0xffs is defined const for quick - * reference. */ -const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; +/* Include standard libraries */ +#include +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "list.h" -/* Structure that stores the netmask, gateway address and DNS server addresses. */ -NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 }; +#include "FreeRTOS_IP.h" -/* The expected IP version and header length coded into the IP header itself. */ -#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 ) +volatile BaseType_t xInsideInterrupt = pdFALSE; -BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress ) +size_t xPortGetMinimumEverFreeHeapSize( void ) { - BaseType_t xReturn; - uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress ); - - if( ( ulIP >= ipFIRST_MULTI_CAST_IPv4 ) && ( ulIP < ipLAST_MULTI_CAST_IPv4 ) ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; + return 0; } -/*-----------------------------------------------------------*/ -void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress, - MACAddress_t * pxMACAddress ) +const char * pcApplicationHostnameHook( void ) { - uint32_t ulIP = FreeRTOS_ntohl( ulIPAddress ); - - pxMACAddress->ucBytes[ 0 ] = ( uint8_t ) 0x01U; - pxMACAddress->ucBytes[ 1 ] = ( uint8_t ) 0x00U; - pxMACAddress->ucBytes[ 2 ] = ( uint8_t ) 0x5EU; - pxMACAddress->ucBytes[ 3 ] = ( uint8_t ) ( ( ulIP >> 16 ) & 0x7fU ); /* Use 7 bits. */ - pxMACAddress->ucBytes[ 4 ] = ( uint8_t ) ( ( ulIP >> 8 ) & 0xffU ); /* Use 8 bits. */ - pxMACAddress->ucBytes[ 5 ] = ( uint8_t ) ( ( ulIP ) & 0xffU ); /* Use 8 bits. */ } -/*-----------------------------------------------------------*/ - -TickType_t xTaskGetTickCount( void ) +uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress, + uint16_t usSourcePort, + uint32_t ulDestinationAddress, + uint16_t usDestinationPort ) { - TickType_t xTicks; - - return xTicks; } - -BaseType_t xSendEventToIPTask( eIPEvent_t eEvent ) +BaseType_t xNetworkInterfaceInitialise( void ) { - return 0; } -/*-----------------------------------------------------------*/ - -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, - BaseType_t bReleaseAfterSend ) +void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) { - return pdPASS; } -/*-----------------------------------------------------------*/ - -NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, - TickType_t xBlockTimeTicks ) +BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber ) { - return NULL; } -/*-----------------------------------------------------------*/ - -BaseType_t xIsCallingFromIPTask( void ) +void vApplicationDaemonTaskStartupHook( void ) { - BaseType_t xReturn = 0; - - return xReturn; } -/*-----------------------------------------------------------*/ - -void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer ) +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) { } -/*-----------------------------------------------------------*/ - -BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent, - TickType_t uxTimeout ) +void vPortDeleteThread( void * pvTaskToDelete ) +{ +} +void vApplicationIdleHook( void ) +{ +} +void vApplicationTickHook( void ) +{ +} +unsigned long ulGetRunTimeCounterValue( void ) +{ +} +void vPortEndScheduler( void ) +{ +} +BaseType_t xPortStartScheduler( void ) +{ +} +void vPortEnterCritical( void ) { - BaseType_t xReturn; +} +void vPortExitCritical( void ) +{ +} - return xReturn; +void * pvPortMalloc( size_t xWantedSize ) +{ + return malloc( xWantedSize ); } -/*-----------------------------------------------------------*/ -NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer, - size_t uxNewLength ) +void vPortFree( void * pv ) { - NetworkBufferDescriptor_t * pxNewBuffer; + free( pv ); +} - return pxNewBuffer; +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) +{ +} +void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ) +{ +} +void vPortCloseRunningThread( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ) +{ +} +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ +} +void vConfigureTimerForRunTimeStats( void ) +{ } -/*-----------------------------------------------------------*/ -UDPPacketHeader_t xDefaultPartUDPPacketHeader = -{ - /* .ucBytes : */ - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source MAC address. */ - 0x08, 0x00, /* Ethernet frame type. */ - ipIP_VERSION_AND_HEADER_LENGTH_BYTE, /* ucVersionHeaderLength. */ - 0x00, /* ucDifferentiatedServicesCode. */ - 0x00, 0x00, /* usLength. */ - 0x00, 0x00, /* usIdentification. */ - 0x00, 0x00, /* usFragmentOffset. */ - ipconfigUDP_TIME_TO_LIVE, /* ucTimeToLive */ - ipPROTOCOL_UDP, /* ucProtocol. */ - 0x00, 0x00, /* usHeaderChecksum. */ - 0x00, 0x00, 0x00, 0x00 /* Source IP address. */ - } -}; +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) +{ + return pdPASS; +} +/*-----------------------------------------------------------*/ diff --git a/test/unit-test/unit_test_build.cmake b/test/unit-test/unit_test_build.cmake index bf5f334c88..48cdc14720 100644 --- a/test/unit-test/unit_test_build.cmake +++ b/test/unit-test/unit_test_build.cmake @@ -28,6 +28,9 @@ list(APPEND mock_define_list # list the files you would like to test here list(APPEND real_source_files ${TCP_SOURCES} + ${KERNEL_SOURCES} + ${MODULE_ROOT_DIR}/test/unit-test/stubs/FreeRTOS_ARP_stubs.c + ${MODULE_ROOT_DIR}/portable/BufferManagement/BufferAllocation_2.c ) # list the directories the module under test includes list(APPEND real_include_directories diff --git a/tools/tcp_utilities/tcp_mem_stats.c b/tools/tcp_utilities/tcp_mem_stats.c index 6a426339d1..b3aa87c54e 100644 --- a/tools/tcp_utilities/tcp_mem_stats.c +++ b/tools/tcp_utilities/tcp_mem_stats.c @@ -49,7 +49,7 @@ #ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u -// #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" + #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" #endif #if ( ipconfigUSE_TCP_MEM_STATS != 0 ) From 9de49b589e06219c58cafbe8a19c85d78dc5d6d0 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed, 21 Apr 2021 10:58:37 -0700 Subject: [PATCH 03/11] Remove unused file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include ICMP while calculating IP header checksum (#198) * Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify * Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update litani submodule (#147) Co-authored-by: Mark R. Tuttle * Fix doxygen check (#149) * Update doxygen version * update the config file * TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes * Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. * Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> * Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment * Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify * Include ICMP checksum * Uncrustify * Update ci.yml * Spell check Co-authored-by: Hein Tibosch Co-authored-by: Hein Tibosch Co-authored-by: Mark Tuttle Co-authored-by: Mark R. Tuttle Co-authored-by: Thomas Pedersen Co-authored-by: Thomas Pedersen Co-authored-by: Hartmut Schaefer Co-authored-by: evpopov Co-authored-by: Emil Popov Co-authored-by: shrewmouse1 <34042878+shrewmouse1@users.noreply.github.com> Co-authored-by: Paul Bartell Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> Add comment to CI.yml fix compiler warnings about casting to format string (#197) * fix compiler warnings about casting to format string Fix various warnings like: /FreeRTOS-Plus-TCP/FreeRTOS_IP.c: In function 'FreeRTOS_strerror_r': /FreeRTOS-Plus-TCP/FreeRTOS_IP.c:3395:60: error: format '%d' expects argument of type 'int', but argument 4 has type 'long int' [-Werror=format=] ( void ) snprintf( pcBuffer, uxLength, "Errno %d", ( int32_t ) xErrnum ); ~^ ~~~~~~~~~~~~~~~~~~~ %ld * explicitly cast arguments to format string This should hopefully make the format string compatible with all architectures. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere Added git-secrets check to Github actions (#201) Add header file to socket.h so that it can be compiled on its own (#204) * Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify * Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update litani submodule (#147) Co-authored-by: Mark R. Tuttle * Fix doxygen check (#149) * Update doxygen version * update the config file * TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes * Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. * Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> * Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment * Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify * Create uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Add header in the socket file * Remove unwanted file * remove unwanted changes Co-authored-by: Hein Tibosch Co-authored-by: Hein Tibosch Co-authored-by: Mark Tuttle Co-authored-by: Mark R. Tuttle Co-authored-by: Thomas Pedersen Co-authored-by: Thomas Pedersen Co-authored-by: Hartmut Schaefer Co-authored-by: evpopov Co-authored-by: Emil Popov Co-authored-by: shrewmouse1 <34042878+shrewmouse1@users.noreply.github.com> Co-authored-by: Paul Bartell Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> User hook function for handling unsupported Ethernet frames (#200) * Adds an optional user hook that gets called for all unhandled Ethernet frames. * re-wording * Fix spell check Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Limit the number of attempts to resolve an address in xARPWaitResolution() (#206) Co-authored-by: Hein Tibosch Update litani submodule to version 1.6.0 (#210) [CBMC] Add assert with readability check (#214) * Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify * Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update litani submodule (#147) Co-authored-by: Mark R. Tuttle * Fix doxygen check (#149) * Update doxygen version * update the config file * TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes * Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. * Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> * Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment * Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify * Create uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update proof to use assert with readability check * Revert ci.yml changes * Remove unwanted changes * Null check * Fix adding NULL checks * Uncrustify Co-authored-by: Hein Tibosch Co-authored-by: Hein Tibosch Co-authored-by: Mark Tuttle Co-authored-by: Mark R. Tuttle Co-authored-by: Thomas Pedersen Co-authored-by: Thomas Pedersen Co-authored-by: Hartmut Schaefer Co-authored-by: evpopov Co-authored-by: Emil Popov Co-authored-by: shrewmouse1 <34042878+shrewmouse1@users.noreply.github.com> Co-authored-by: Paul Bartell Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> Add unit-tests for FreeRTOS_ARP.c (#209) * Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify * Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update litani submodule (#147) Co-authored-by: Mark R. Tuttle * Fix doxygen check (#149) * Update doxygen version * update the config file * TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes * Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. * Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> * Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment * Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify * Create uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Add header in the socket file * Remove unwanted file * remove unwanted changes * First commit * Cleanup * Update: working version * Coverage of eARPGetCacheEntry * Update * Unit-test and clenaup * 100% line and function coverage * Uncrustify and update * 100% all coverage * Move files to correct location * Fix tests * uncrustified * Update ci.yml * Update * uncrustify and update after Hein's comments * Empty commit * Clenaup after @yanjos-dev's review * Update CI * Cleanup - pass 1 * Remove gdb * Uncrustify * Remove litani changes * Clean up * Uncrustify Co-authored-by: Hein Tibosch Co-authored-by: Hein Tibosch Co-authored-by: Mark Tuttle Co-authored-by: Mark R. Tuttle Co-authored-by: Thomas Pedersen Co-authored-by: Thomas Pedersen Co-authored-by: Hartmut Schaefer Co-authored-by: evpopov Co-authored-by: Emil Popov Co-authored-by: shrewmouse1 <34042878+shrewmouse1@users.noreply.github.com> Co-authored-by: Paul Bartell Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> DHCP unit test (#211) Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Repair buffer leak when replying to NBNS requests (#215) * Repair buffer leak when replying to NBNS requests * Applied Uncrustify * Variable 'pxNewBuffer' was out of scope Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Static allocation, if configSUPPORT_STATIC_ALLOCATION == 1 (#208) (#217) * Static allocation of tasks and queues, if configSUPPORT_STATIC_ALLOCATION == 1 (#208) Is not added to any ported network interfaced. * Build-check fix * Uncrustify * Uncrustify v2 * Update FreeRTOS_IP.c Co-authored-by: Christian Jensen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Add a method to obtain the handle of the FreeRTOS+TCP IP task (#222) * Add a method to obtain the handle of the FreeRTOS+TCP IP task * Added the modified FreeRTOS_IP.c * Update lexicon.txt Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Code changes for unit-testing (#223) * Fix compiler warnings when the TCP Window is not used (#124) * Fix warnings when TCP window is not used * Uncrustify * Move local variables to inner loop in prvNetworkInterfaceInput() (#144) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update litani submodule (#147) Co-authored-by: Mark R. Tuttle * Fix doxygen check (#149) * Update doxygen version * update the config file * TCP_WIN: fix compile warning on x86_64 (#148) * TCP_WIN: fix compile warning on x86_64 Fix the following warning when building for 64 bit: warning: conversion from ‘long unsigned int’ to ‘uint32_t’ {aka ‘unsigned int’} changes value from ‘18446744073709551615’ to ‘4294967295’ [-Woverflow] uint32_t ulReturn = ~0UL; ^ * Update FreeRTOS_TCP_WIN.c Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix deprecated volatile compound assignment (#152) * fixed deprecated volatile compound assignment C++20 deprecates some undefined or unclear use cases of 'volatile' like compound assignments and compliant compilers warn about those deprecated operations. In vStreamBufferMoveMid the deprecated compound assignment and other direct accesses to volatile 'StreamBuffer_t->uxMid' is replaced using a local variable stored back when done. * Uncrustify Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * FreeRTOS_ARP.c : store local addresses only (#120) * FreeRTOS_ARP.c : store local addresses only * Added the function xARPWaitResolution() * Added an entry to lexicon.txt. * Ran Uncrustify * Update unit test file * Update * Declared xARPWaitResolution() in FreeRTOS_IP.h * Compare the result of xIsCallingFromIPTask() with pdFALSE in stead of 0 Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Co-authored-by: Aniruddha Kanhere * Remove unnecessary #ifndef (#186) * Add entropy * remove warning * Remove unnecessary ifndef * Remove unwanted changes * Don't Fragment Flags patch. (#179) * Moves all IP flag defines in FreeRTOS_IP_Private.h so that they are accessible to all protocols Adds definitions for the IP fragmentation flags Modifies the fragmentation check for incoming frames to drop both the first and later fragments. Sets the "don't fragment" flag for all outgoing IP frames ( ICMP, DNS, UDP, TCP ) Removes ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT as it appears obsolete. The stack never outputs fragments. * Uncrustified * Uncrustify * Fixes the fragment offset and fragmentation flags masks ( 0x0FFF and 0xF000 -> 0x1FFF and 0xE000 ) Adds a configuration define ( ipconfigADVERTISE_DONT_FRAGMENT_FLAG ) as suggested by htibosch with a default value of zero for backwards compatibility Updates the comment that explains the discarding of incoming fragments as discussed with Aniruddha Kanhere * Adds the 'U' qualifier as requested by hs2gh fixes a typo in FreeRTOSIPConfigDefaults.h * Shortens the comment in FreeRTOSIPConfigDefaults as per htibosch's suggestion. * Renames ipconfigADVERTISE_DONT_FRAGMENT to ipconfigFORCE_IP_DONT_FRAGMENT * same as last commit, simply forgot to save this before pushing. Co-authored-by: Emil Popov Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * fix IP buffer padding check on 64bit (#146) * fix IP buffer padding check on 64bit On 64 bit systems, FreeRTOS_IPInit() would assert ipconfigBUFFER_PADDING was equal to 14 to "make sure there is enough space in pucEthernetBuffer to store a pointer." This prevents the driver from requesting additional padding, so make the assert greater than or equal to 14. Also use the final ipBUFFER_PADDING value instead of ipconfigBUFFER_PADDING, which is probably what was intended? * Update after comments Co-authored-by: Thomas Pedersen Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update readme.md (#189) Just fixing the "table of 3 types of STH32H7" so that it renders in github webpage. I had a tough time reading that table until I looked at the md source. You could also just put code fences around it: ~~~ /** * RAM area H747 H743 H742 Location * ------------------------------------------------ * DTCM 128k 128k 128k 0x20000000 * AXI-SRAM 511k 511k 384k 0x24000000 * * SRAM1 128k 128k 32k 0x30000000 * SRAM2 128k 128k 16k 0x30020000 * SRAM3 32k 32k - 0x30040000 * SRAM4 64k 64k 64k 0x38000000 * Backup SRAM 4k 4k 4k 0x38800000 */ ~~~ Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Update files referencing aws_application_version.h to use iot_application_version.h (#188) * Update files referencing aws_application_version.h to use iot_application_version.h * Remove pic32 ethernet _Command_Version function to remove dependency on iot_application_version.h from amazon-freertos repository. * Remove function defs from header files (#190) * Add entropy * remove warning * Remove function defs from headers * Some corrections * More fixes and uncrustify * Remove the BaseType min function * Doxygen * Fix one CBMC proof * More cbmc proof fixes * More cbmc fixes * Some doxygen additions * Update last CBMC proof * Doxygen comments * Doxygen updates * Doxygen and spell check * Spell check and unit-test * Unit test fix * Update after comments * Update 2 after comments * Move function around * Uncrustify * Update after comments Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> * Do not release a network buffer if it equals to NULL (#191) Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> * Circumvent Qemu MPS2 networking bug (#142) * Add support for MPS2 networking with lan9118/lan9220 * Fix uncrustify errors * Enable network interrupt handling * Add network interrupt support to Qemu MPS2 AN385 * Fix function comment * Fix Uncrustify errors * Fix Uncrustify errors * Fix Uncrustify Errors * Fix typo * Cirumvent Qemu MPS2 network bug * Remove commented code, add doxygen comment * Add a project for static analysis (#195) * Add entropy * remove warning * Remove unwanted changes * Update tcp_mem_stats.c * Add Coverity * Remove unused files * Add some features * clean up * More clean up * Unwanted additions removal * Clean up * Add 32-bit compile option * Update after comments * Uncrustify * Create uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Update uncrustify.yml * Make some code changes as a precursor for unit-testing * remove unused file * Fixed failing checks * Fixed CBMC proof Co-authored-by: Hein Tibosch Co-authored-by: Hein Tibosch Co-authored-by: Mark Tuttle Co-authored-by: Mark R. Tuttle Co-authored-by: Thomas Pedersen Co-authored-by: Thomas Pedersen Co-authored-by: Hartmut Schaefer Co-authored-by: evpopov Co-authored-by: Emil Popov Co-authored-by: shrewmouse1 <34042878+shrewmouse1@users.noreply.github.com> Co-authored-by: Paul Bartell Co-authored-by: Gary Wicker <14828980+gkwicker@users.noreply.github.com> Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> Use an infinite timeout in FreeRTOS_closesocket when called from a user task (#226) Reformat MPS2_AN385 network driver (#224) * Update the MPS2_AN385 network driver so it conforms to the +TCP coding and style guide. * Update smsc9220_eth_drv.c Remove #warning message erroneously left in. Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com> Uncrustify. Uncrustify again. Before sending a challenge ACK, check the sequence number more properly (#225) * Before sending a challenge ACK, check the sequence number more properly * Make xSequenceLessThan and xSequenceGreaterThan public functions * Extended comments on two public functions. * Fix Spell check * Although no changes were made to MPS2_AN385, some formatting changes to that driver Co-authored-by: Hein Tibosch Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> --- .github/lexicon.txt | 26 + .github/workflows/ci.yml | 37 +- .github/workflows/uncrustify.yml | 45 - FreeRTOS_ARP.c | 3 + FreeRTOS_DHCP.c | 138 +- FreeRTOS_DNS.c | 210 +- FreeRTOS_IP.c | 92 +- FreeRTOS_Sockets.c | 23 +- FreeRTOS_TCP_IP.c | 6 +- FreeRTOS_TCP_WIN.c | 76 +- include/FreeRTOSIPConfigDefaults.h | 16 +- include/FreeRTOS_DHCP.h | 122 + include/FreeRTOS_DNS.h | 175 + include/FreeRTOS_IP.h | 2 + include/FreeRTOS_Sockets.h | 4 + include/FreeRTOS_TCP_WIN.h | 25 + .../BufferManagement/BufferAllocation_1.c | 15 +- .../BufferManagement/BufferAllocation_2.c | 15 +- .../MPS2_AN385/NetworkInterface.c | 409 +- .../MPS2_AN385/ether_lan9118/SMM_MPS2.h | 615 +++ .../ether_lan9118/smsc9220_eth_drv.c | 159 +- .../AllDisable/FreeRTOSIPConfig.h | 2 +- .../DNSHandlePacket/DNShandlePacket_harness.c | 12 - .../TCPReturnPacket_harness.c | 40 +- test/litani | 2 +- test/unit-test/CMakeLists.txt | 115 +- test/unit-test/ConfigFiles/FreeRTOSConfig.h | 11 +- test/unit-test/ConfigFiles/FreeRTOSIPConfig.h | 24 +- .../ConfigFiles/FreeRTOSIPConfigDefaults.h | 6 +- test/unit-test/ConfigFiles/portmacro.h | 164 - .../FreeRTOS_ARP_stubs.c | 63 +- .../FreeRTOS_ARP/FreeRTOS_ARP_utest.c | 1049 +++++ .../ut.cmake} | 22 +- .../FreeRTOS_DHCP/FreeRTOS_DHCP_mock.h | 4 + .../FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c | 180 + .../FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c | 3672 +++++++++++++++++ test/unit-test/FreeRTOS_DHCP/ut.cmake | 93 + test/unit-test/FreeRTOS_TCP_Unit_test.c | 116 - test/unit-test/catch_assert.h | 77 + test/unit-test/cmock/coverage.cmake | 33 + test/unit-test/cmock/create_test.cmake | 3 +- test/unit-test/cmock/project.yml | 11 +- 42 files changed, 6802 insertions(+), 1110 deletions(-) delete mode 100644 .github/workflows/uncrustify.yml create mode 100644 portable/NetworkInterface/MPS2_AN385/ether_lan9118/SMM_MPS2.h delete mode 100644 test/unit-test/ConfigFiles/portmacro.h rename test/unit-test/{stubs => FreeRTOS_ARP}/FreeRTOS_ARP_stubs.c (55%) create mode 100644 test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_utest.c rename test/unit-test/{unit_test_build.cmake => FreeRTOS_ARP/ut.cmake} (76%) create mode 100644 test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_mock.h create mode 100644 test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c create mode 100644 test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c create mode 100644 test/unit-test/FreeRTOS_DHCP/ut.cmake delete mode 100644 test/unit-test/FreeRTOS_TCP_Unit_test.c create mode 100644 test/unit-test/catch_assert.h diff --git a/.github/lexicon.txt b/.github/lexicon.txt index 98538a49fe..c2fa1c8518 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -89,6 +89,7 @@ bwinscaling bytecount callbacklist calloc +cambridge camen carriersense castingmacrofunctions @@ -155,6 +156,7 @@ dff dhcp dhcpbroadcast dhcpcookie +dhcpserveraddress didn dm dma @@ -181,8 +183,10 @@ dw dword dzpq eagain +eapplicationprocesscustomframehook earpcachehit earpcachemiss +earpgetcacheentry earptimerevent ec ecantsendpacket @@ -318,8 +322,10 @@ github gmac gmacpins gmacsa +gnw gpio gpl +greaterthan grr gswutr hal @@ -386,6 +392,7 @@ isdhcpsocket isn isp isr +isrs iss itemvalue jd @@ -411,6 +418,7 @@ ldistance leds len lendofframe +lessthan linkcurr linklayer linkmd @@ -426,6 +434,7 @@ lmaxlength lminlength lnetlength loffset +longjmp loopback loopbackmode loptionname @@ -580,6 +589,7 @@ pcipaddress pcmessage pcname pcnetworkbuffer +pcrequestedname pcs pcsource pcto @@ -659,6 +669,8 @@ prvreadnamefield prvreadsackoption prvrxcallback prvsenddata +prvsenddhcpdiscover +prvsenddhcprequest prvsetoptions prvsetsynackoptions prvsinglesteptcpheaderoptions @@ -742,6 +754,7 @@ pxdestinationaddress pxdnsmessageheader pxduplicatenetworkbufferwithdescriptor pxevent +pxgetnetworkbuffer pxgetnetworkbufferwithdescriptor pxhandleconnected pxhandlereceive @@ -821,6 +834,7 @@ regist regvalue reinit renesas +releaseudppayloadbuffer reqlength resetpins retrytransmission @@ -834,6 +848,7 @@ richard rle rlex rmii +rng ro rollover roreg @@ -916,6 +931,7 @@ srdbl srtt ss starttx +stderr stmicroelectronics strcmp streambuffer @@ -1007,6 +1023,7 @@ uclen uclength uclinklayeripaddress ucmacaddress +ucmessagetype ucmywinscalefactor ucname ucnamecode @@ -1033,6 +1050,7 @@ uctcpoffset uctcpstate uctimetolive uctransmitcount +ucserveridentifier uctypeofmessage uctypeofservice ucvalid @@ -1052,6 +1070,7 @@ ulbytecount ulchecktime ulconnected ulcount +ulclientipaddress ulcurrentsequencenumber ulcurrentspistatus uldefaultipaddress @@ -1060,6 +1079,7 @@ uldestinationaddress uldestinationipaddress uldhcpcookie uldhcpserveraddress +uldnsserver uldnsserveraddress uldonemask ulfifolength @@ -1068,6 +1088,7 @@ ulfirst ulfirstsequencenumber ulflag ulflags +ulgateway ulgatewayaddress ulgetruntimecountervalue ulhighestrxallowed @@ -1117,6 +1138,7 @@ ulsize ulsourceipaddress ulspace ulstatus +ulsubnetmask ulsum ultargetprotocoladdress ultcpwindowtxack @@ -1139,6 +1161,7 @@ unhandled unicast unicastframesfilter unicastpauseframedetect +uninitialised unsetmacaddr urg url @@ -1374,6 +1397,7 @@ xilinx xinternal xipheader xipheadersize +xiptaskhandle xiptaskinitialised xisbound xisforrx @@ -1457,6 +1481,7 @@ xstream xsum xtargethardwareaddress xtaskcheckfortimeout +xtaskgettickcount xtaskhandle xtaskresumeall xtcp @@ -1471,6 +1496,7 @@ xtcpwindowrxconfirm xtcpwindowtxdone xtime xtimeout +xtotallength xtransmittimer xtxcallback xtxdescriptorsemaphore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1021c26fec..d9aab19978 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,10 +22,8 @@ jobs: git submodule update --init vendor/unity cd ../.. sudo apt-get install -y lcov - cmake -S test/unit-test -B test/unit-test/build/ \ - -G "Unix Makefiles" \ - -DCMAKE_BUILD_TYPE=Debug \ - -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -DNDEBUG' + sudo apt-get install -y unifdef + cmake -S test/unit-test -B test/unit-test/build/ make -C test/unit-test/build/ all - name: Test run: | @@ -35,11 +33,7 @@ jobs: - name: Coverage run: | make -C test/unit-test/build/ coverage - lcov --rc lcov_branch_coverage=1 --remove test/unit-test/build/coverage.info '*test*' --output-file test/unit-test/build/coverage.info - lcov --rc lcov_branch_coverage=1 --remove test/unit-test/build/coverage.info '*CMakeCCompilerId*' --output-file test/unit-test/build/coverage.info - lcov --rc lcov_branch_coverage=1 --remove test/unit-test/build/coverage.info '*third-party*' --output-file test/unit-test/build/coverage.info - lcov --rc lcov_branch_coverage=1 --remove test/unit-test/build/coverage.info '*mocks*' --output-file test/unit-test/build/coverage.info - lcov --list test/unit-test/build/coverage.info + lcov --list --rc lcov_branch_coverage=1 test/unit-test/build/coverage.info spell-check: runs-on: ubuntu-latest @@ -71,7 +65,9 @@ jobs: fi formatting: - runs-on: ubuntu-latest + # Use only 18.04 since we want the uncrustify version to + # be 0.66.1_f to ensure proper formatting. + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 - name: Install Uncrustify @@ -79,7 +75,7 @@ jobs: - name: Run Uncrustify run: | uncrustify --version - find . -iname "*.[hc]" -exec uncrustify --check -c tools/uncrustify.cfg {} + + find . -not -path '.*catch_assert.h' -iname "*.[hc]" -exec uncrustify --check -c tools/uncrustify.cfg {} + - name: Check For Trailing Whitespace run: | set +e @@ -131,3 +127,22 @@ jobs: run: | find . -iname '*.c' |\ xargs complexity --scores --threshold=0 --horrid-threshold=55 + + git-secrets: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Checkout awslabs/git-secrets + uses: actions/checkout@v2 + with: + repository: awslabs/git-secrets + ref: master + path: git-secrets + - name: Install git-secrets + run: cd git-secrets && sudo make install && cd .. + - name: Run git-secrets + run: | + git-secrets --register-aws + git-secrets --scan diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml deleted file mode 100644 index f6eb973f4a..0000000000 --- a/.github/workflows/uncrustify.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Uncrustify the source code - -on: - issue_comment: - types: [created] - -jobs: - Uncrustify: - name: Run_Uncrustify - if: ${{ github.event.issue.pull_request }} - # && contains(github.event.comment.body, 'confirm Uncrustify') - runs-on: ubuntu-18.04 - steps: - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - name: get pullrequest url - run: | - echo ${{ github.event.issue.pull_request.url }} - - name: get upstream branch - id: upstreambranch - run: | - echo "::set-output name=branchname::$(curl -v -H "Accept: application/vnd.github.sailor-v-preview+json" --url ${{ secrets.PAT }} ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')" - - name: echo upstream branch - run: | - echo ${{ steps.upstreambranch.outputs }} - - name: Checkout upstream repo - uses: actions/checkout@v2 - with: - ref: ${{ steps.upstreambranch.outputs.branchname }} - - name: Install Uncrustify - run: sudo apt-get install uncrustify - - name: Run Uncrustify - run: | - uncrustify --version - find . -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + - echo "hello there" > hello.txt - - name: GitHub Action for committing changes to a repository - run: | - git config --global user.name 'Aniruddha Kanhere' - git config --global user.email '60444055+AniruddhaKanhere@users.noreply.github.com' - git add -A - git commit -m "test" - git push diff --git a/FreeRTOS_ARP.c b/FreeRTOS_ARP.c index 9295f126ed..88666f7579 100644 --- a/FreeRTOS_ARP.c +++ b/FreeRTOS_ARP.c @@ -807,6 +807,9 @@ BaseType_t xARPWaitResolution( uint32_t ulIPAddress, { break; } + + /* Decrement the count. */ + uxSendCount--; } } diff --git a/FreeRTOS_DHCP.c b/FreeRTOS_DHCP.c index a9d3380fb5..86440ddd1c 100644 --- a/FreeRTOS_DHCP.c +++ b/FreeRTOS_DHCP.c @@ -44,130 +44,13 @@ #include "FreeRTOS_DHCP.h" #include "FreeRTOS_ARP.h" + /* Exclude the entire file if DHCP is not enabled. */ #if ( ipconfigUSE_DHCP != 0 ) #include "NetworkInterface.h" #include "NetworkBufferManagement.h" - #if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586U ) - -/* DHCP must be able to receive an options field of 312 bytes, the fixed - * part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */ - #error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP - #endif - -/* Parameter widths in the DHCP packet. */ - #define dhcpCLIENT_HARDWARE_ADDRESS_LENGTH 16 /**< Client hardware address length.*/ - #define dhcpSERVER_HOST_NAME_LENGTH 64 /**< Server host name length. */ - #define dhcpBOOT_FILE_NAME_LENGTH 128 /**< Boot file name length. */ - -/* Timer parameters */ - #ifndef dhcpINITIAL_TIMER_PERIOD - /** @brief The interval at which the DHCP state handler is called. */ - #define dhcpINITIAL_TIMER_PERIOD ( pdMS_TO_TICKS( 250U ) ) - #endif - - #ifndef dhcpINITIAL_DHCP_TX_PERIOD - -/** @brief The initial amount of time to wait for a DHCP reply. When repeating an - * unanswered request, this time-out shall be multiplied by 2. */ - #define dhcpINITIAL_DHCP_TX_PERIOD ( pdMS_TO_TICKS( 5000U ) ) - #endif - -/* Codes of interest found in the DHCP options field. */ - #define dhcpIPv4_ZERO_PAD_OPTION_CODE ( 0U ) /**< Used to pad other options to make them aligned. See RFC 2132. */ - #define dhcpIPv4_SUBNET_MASK_OPTION_CODE ( 1U ) /**< Subnet mask. See RFC 2132. */ - #define dhcpIPv4_GATEWAY_OPTION_CODE ( 3U ) /**< Available routers. See RFC 2132. */ - #define dhcpIPv4_DNS_SERVER_OPTIONS_CODE ( 6U ) /**< Domain name server. See RFC 2132. */ - #define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE ( 12U ) /**< Host name. See RFC 2132. */ - #define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE ( 50U ) /**< Requested IP-address. See RFC 2132. */ - #define dhcpIPv4_LEASE_TIME_OPTION_CODE ( 51U ) /**< IP-address lease time. See RFC 2132. */ - #define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE ( 53U ) /**< DHCP message type. See RFC 2132. */ - #define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE ( 54U ) /**< Server Identifier. See RFC 2132. */ - #define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE ( 55U ) /**< Parameter Request list. See RFC 2132. */ - #define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE ( 61U ) /**< Client Identifier. See RFC 2132. */ - -/* The four DHCP message types of interest. */ - #define dhcpMESSAGE_TYPE_DISCOVER ( 1 ) /**< DHCP discover message. */ - #define dhcpMESSAGE_TYPE_OFFER ( 2 ) /**< DHCP offer message. */ - #define dhcpMESSAGE_TYPE_REQUEST ( 3 ) /**< DHCP request message. */ - #define dhcpMESSAGE_TYPE_ACK ( 5 ) /**< DHCP acknowledgement. */ - #define dhcpMESSAGE_TYPE_NACK ( 6 ) /**< DHCP NACK. (Negative acknowledgement) */ - -/* Offsets into the transmitted DHCP options fields at which various parameters - * are located. */ - #define dhcpCLIENT_IDENTIFIER_OFFSET ( 6U ) /**< Offset for the client ID option. */ - #define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 14U ) /**< Offset for the requested IP-address option. */ - #define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 20U ) /**< Offset for the server IP-address option. */ - -/* Values used in the DHCP packets. */ - #define dhcpREQUEST_OPCODE ( 1U ) /**< DHCP request opcode. */ - #define dhcpREPLY_OPCODE ( 2U ) /**< DHCP reply opcode. */ - #define dhcpADDRESS_TYPE_ETHERNET ( 1U ) /**< Address type: ethernet opcode. */ - #define dhcpETHERNET_ADDRESS_LENGTH ( 6U ) /**< Ethernet address length opcode. */ - -/* The following define is temporary and serves to make the /single source - * code more similar to the /multi version. */ - - #define EP_DHCPData xDHCPData /**< Temporary define to make /single source similar to /multi version. */ - #define EP_IPv4_SETTINGS xNetworkAddressing /**< Temporary define to make /single source similar to /multi version. */ - -/** @brief If a lease time is not received, use the default of two days (48 hours in ticks). - * Can not use pdMS_TO_TICKS() as integer overflow can occur. */ - #define dhcpDEFAULT_LEASE_TIME ( ( 48UL * 60UL * 60UL ) * configTICK_RATE_HZ ) - -/** @brief Don't allow the lease time to be too short. */ - #define dhcpMINIMUM_LEASE_TIME ( pdMS_TO_TICKS( 60000UL ) ) /* 60 seconds in ticks. */ - -/** @brief Marks the end of the variable length options field in the DHCP packet. */ - #define dhcpOPTION_END_BYTE 0xffu - -/** @brief Offset into a DHCP message at which the first byte of the options is - * located. */ - #define dhcpFIRST_OPTION_BYTE_OFFSET ( 0xf0U ) - -/* Standard DHCP port numbers and magic cookie value. - * DHCPv4 uses UDP port number 68 for clients and port number 67 for servers. - */ - #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) - #define dhcpCLIENT_PORT_IPv4 0x4400U /**< Little endian representation of port 68. */ - #define dhcpSERVER_PORT_IPv4 0x4300U /**< Little endian representation of port 67. */ - #define dhcpCOOKIE 0x63538263UL /**< Little endian representation of magic cookie. */ - #define dhcpBROADCAST 0x0080U /**< Little endian representation of broadcast flag. */ - #else - #define dhcpCLIENT_PORT_IPv4 0x0044U /**< Big endian representation of port 68. */ - #define dhcpSERVER_PORT_IPv4 0x0043U /**< Big endian representation of port 68. */ - #define dhcpCOOKIE 0x63825363UL /**< Big endian representation of magic cookie. */ - #define dhcpBROADCAST 0x8000U /**< Big endian representation of broadcast flag. */ - #endif /* ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) */ - - #include "pack_struct_start.h" - struct xDHCPMessage_IPv4 - { - uint8_t ucOpcode; /**< Operation Code: Specifies the general type of message. */ - uint8_t ucAddressType; /**< Hardware type used on the local network. */ - uint8_t ucAddressLength; /**< Hardware Address Length: Specifies how long hardware - * addresses are in this message. */ - uint8_t ucHops; /**< Hops. */ - uint32_t ulTransactionID; /**< A 32-bit identification field generated by the client, - * to allow it to match up the request with replies received - * from DHCP servers. */ - uint16_t usElapsedTime; /**< Number of seconds elapsed since a client began an attempt to acquire or renew a lease. */ - uint16_t usFlags; /**< Just one bit used to indicate broadcast. */ - uint32_t ulClientIPAddress_ciaddr; /**< Client's IP address if it has one or 0 is put in this field. */ - uint32_t ulYourIPAddress_yiaddr; /**< The IP address that the server is assigning to the client. */ - uint32_t ulServerIPAddress_siaddr; /**< The DHCP server address that the client should use. */ - uint32_t ulRelayAgentIPAddress_giaddr; /**< Gateway IP address in case the server client are on different subnets. */ - uint8_t ucClientHardwareAddress[ dhcpCLIENT_HARDWARE_ADDRESS_LENGTH ]; /**< The client hardware address. */ - uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ]; /**< Server's hostname. */ - uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ]; /**< Boot file full directory path. */ - uint32_t ulDHCPCookie; /**< Magic cookie option. */ - /* Option bytes from here on. */ - } - #include "pack_struct_end.h" - typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t; - /** * @brief Function to cast pointers to DHCPMessage_IPv4_t. */ @@ -965,10 +848,15 @@ case dhcpIPv4_DNS_SERVER_OPTIONS_CODE: - /* ulProcessed is not incremented in this case - * because the DNS server is not essential. Only the - * first DNS server address is taken. */ - EP_IPv4_SETTINGS.ulDNSServerAddress = ulParameter; + /* The DHCP server may send more than 1 DNS server addresses. */ + if( uxLength >= sizeof( uint32_t ) ) + { + /* ulProcessed is not incremented in this case + * because the DNS server is not essential. Only the + * first DNS server address is taken. */ + EP_IPv4_SETTINGS.ulDNSServerAddress = ulParameter; + } + break; case dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE: @@ -1259,8 +1147,10 @@ * returned to the stack. */ FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); } - - xResult = pdTRUE; + else + { + xResult = pdTRUE; + } } return xResult; diff --git a/FreeRTOS_DNS.c b/FreeRTOS_DNS.c index c6f36457f2..d3d56d102c 100644 --- a/FreeRTOS_DNS.c +++ b/FreeRTOS_DNS.c @@ -50,76 +50,6 @@ /* Exclude the entire file if DNS is not enabled. */ #if ( ipconfigUSE_DNS != 0 ) - #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) - #define dnsDNS_PORT 0x3500U /**< Little endian: Port used for DNS. */ - #define dnsONE_QUESTION 0x0100U /**< Little endian representation of a DNS question.*/ - #define dnsOUTGOING_FLAGS 0x0001U /**< Little endian representation of standard query. */ - #define dnsRX_FLAGS_MASK 0x0f80U /**< Little endian: The bits of interest in the flags field of incoming DNS messages. */ - #define dnsEXPECTED_RX_FLAGS 0x0080U /**< Little Endian: Should be a response, without any errors. */ - #else - #define dnsDNS_PORT 0x0035U /**< Big endian: Port used for DNS. */ - #define dnsONE_QUESTION 0x0001U /**< Big endian representation of a DNS question.*/ - #define dnsOUTGOING_FLAGS 0x0100U /**< Big endian representation of standard query. */ - #define dnsRX_FLAGS_MASK 0x800fU /**< Big endian: The bits of interest in the flags field of incoming DNS messages. */ - #define dnsEXPECTED_RX_FLAGS 0x8000U /**< Big endian: Should be a response, without any errors. */ - - #endif /* ipconfigBYTE_ORDER */ - -/** @brief The maximum number of times a DNS request should be sent out if a response - * is not received, before giving up. */ - #ifndef ipconfigDNS_REQUEST_ATTEMPTS - #define ipconfigDNS_REQUEST_ATTEMPTS 5 - #endif - -/** @brief If the top two bits in the first character of a name field are set then the - * name field is an offset to the string, rather than the string itself. */ - #define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 ) - -/* NBNS flags. */ - #if ( ipconfigUSE_NBNS == 1 ) - #define dnsNBNS_FLAGS_RESPONSE 0x8000U /**< NBNS response flag. */ - #define dnsNBNS_FLAGS_OPCODE_MASK 0x7800U /**< NBNS opcode bitmask. */ - #define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000U /**< NBNS opcode query. */ - #endif /* ( ipconfigUSE_NBNS == 1 ) */ - -/* Host types. */ - #define dnsTYPE_A_HOST 0x01U /**< DNS type A host. */ - #define dnsCLASS_IN 0x01U /**< DNS class IN (Internet). */ - - #ifndef _lint - /* LLMNR constants. */ - #define dnsLLMNR_TTL_VALUE 300000UL /**< LLMNR time to live value. */ - #define dnsLLMNR_FLAGS_IS_REPONSE 0x8000U /**< LLMNR flag value for response. */ - #endif /* _lint */ - -/* NBNS constants. */ - #if ( ipconfigUSE_NBNS != 0 ) - #define dnsNBNS_TTL_VALUE 3600UL /**< NBNS TTL: 1 hour valid. */ - #define dnsNBNS_TYPE_NET_BIOS 0x0020U /**< NBNS Type: NetBIOS. */ - #define dnsNBNS_CLASS_IN 0x01U /**< NBNS Class: IN (Internet). */ - #define dnsNBNS_NAME_FLAGS 0x6000U /**< NBNS name flags. */ - #define dnsNBNS_ENCODED_NAME_LENGTH 32 /**< NBNS encoded name length. */ - -/** @brief If the queried NBNS name matches with the device's name, - * the query will be responded to with these flags: */ - #define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500U ) - #endif /* ( ipconfigUSE_NBNS != 0 ) */ - -/** @brief Flag DNS parsing errors in situations where an IPv4 address is the return - * type. */ - #define dnsPARSE_ERROR 0UL - - #ifndef _lint - #if ( ipconfigUSE_DNS_CACHE == 0 ) - #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY != 1 ) - #error When DNS caching is disabled, please make ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY equal to 1. - #endif - #endif - #endif - -/** @brief Define the ASCII value of '.' (Period/Full-stop). */ - #define ASCII_BASELINE_DOT 46U - /* * Create a socket and bind it to the standard DNS port number. Return the * the created socket - or NULL if the socket could not be created or bound. @@ -211,19 +141,7 @@ uint32_t ulTTL, BaseType_t xLookUp ); - typedef struct xDNS_CACHE_TABLE_ROW - { - uint32_t ulIPAddresses[ ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ]; /* The IP address(es) of an ARP cache entry. */ - char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /* The name of the host */ - uint32_t ulTTL; /* Time-to-Live (in seconds) from the DNS server. */ - uint32_t ulTimeWhenAddedInSeconds; - #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) - uint8_t ucNumIPAddresses; - uint8_t ucCurrentIPAddress; - #endif - } DNSCacheRow_t; - - static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ]; + _static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ]; /* Utility function: Clear DNS cache by calling this function. */ void FreeRTOS_dnsclear( void ) @@ -239,21 +157,6 @@ /*-----------------------------------------------------------*/ -/* Below #include just tells the compiler to pack the structure. - * It is included in to make the code more readable */ - #include "pack_struct_start.h" - struct xDNSMessage - { - uint16_t usIdentifier; /**< Query identifier. Used to match up replies to outstanding queries. */ - uint16_t usFlags; /**< Flags. */ - uint16_t usQuestions; /**< Number of questions asked in this query. */ - uint16_t usAnswers; /**< Number of answers being provided in this query. */ - uint16_t usAuthorityRRs; /**< Authoritative name server resource records. */ - uint16_t usAdditionalRRs; /**< Additional resource records.*/ - } - #include "pack_struct_end.h" - typedef struct xDNSMessage DNSMessage_t; - /** * @brief Utility function to cast pointer of a type to pointer of type DNSMessage_t. * @@ -297,18 +200,6 @@ return ( DNSTail_t * ) pvArgument; } -/* DNS answer record header. */ - #include "pack_struct_start.h" - struct xDNSAnswerRecord - { - uint16_t usType; /**< Type of DNS answer record. */ - uint16_t usClass; /**< Class of DNS answer record. */ - uint32_t ulTTL; /**< Number of seconds the result can be cached. */ - uint16_t usDataLength; /**< Length of the data field. */ - } - #include "pack_struct_end.h" - typedef struct xDNSAnswerRecord DNSAnswerRecord_t; - /** * @brief Utility function to cast pointer of a type to pointer of type DNSAnswerRecord_t. * @@ -319,21 +210,8 @@ return ( DNSAnswerRecord_t * ) pvArgument; } - #if ( ipconfigUSE_LLMNR == 1 ) - #include "pack_struct_start.h" - struct xLLMNRAnswer - { - uint8_t ucNameCode; /**< Name type. */ - uint8_t ucNameOffset; /**< The name is not repeated in the answer, only the offset is given with "0xc0 " */ - uint16_t usType; /**< Type of the Resource record. */ - uint16_t usClass; /**< Class of the Resource record. */ - uint32_t ulTTL; /**< Seconds till this entry can be cached. */ - uint16_t usDataLength; /**< Length of the address in this record. */ - uint32_t ulIPAddress; /**< The IP-address. */ - } - #include "pack_struct_end.h" - typedef struct xLLMNRAnswer LLMNRAnswer_t; + #if ( ipconfigUSE_LLMNR == 1 ) /** * @brief Utility function to cast pointer of a type to pointer of type LLMNRAnswer_t. @@ -350,37 +228,6 @@ #if ( ipconfigUSE_NBNS == 1 ) - #include "pack_struct_start.h" - struct xNBNSRequest - { - uint16_t usRequestId; /**< NBNS request ID. */ - uint16_t usFlags; /**< Flags of the DNS message. */ - uint16_t ulRequestCount; /**< The number of requests/questions in this query. */ - uint16_t usAnswerRSS; /**< The number of answers in this query. */ - uint16_t usAuthRSS; /**< Number of authoritative resource records. */ - uint16_t usAdditionalRSS; /**< Number of additional resource records. */ - uint8_t ucNameSpace; /**< Length of name. */ - uint8_t ucName[ dnsNBNS_ENCODED_NAME_LENGTH ]; /**< The domain name. */ - uint8_t ucNameZero; /**< Terminator of the name. */ - uint16_t usType; /**< Type of NBNS record. */ - uint16_t usClass; /**< Class of NBNS request. */ - } - #include "pack_struct_end.h" - typedef struct xNBNSRequest NBNSRequest_t; - - #include "pack_struct_start.h" - struct xNBNSAnswer - { - uint16_t usType; /**< Type of NBNS answer. */ - uint16_t usClass; /**< Class of NBNS answer. */ - uint32_t ulTTL; /**< Time in seconds for which the answer can be cached. */ - uint16_t usDataLength; /**< Data length. */ - uint16_t usNbFlags; /**< NetBIOS flags 0x6000 : IP-address, big-endian. */ - uint32_t ulIPAddress; /**< The IPv4 address. */ - } - #include "pack_struct_end.h" - typedef struct xNBNSAnswer NBNSAnswer_t; - /** * @brief Utility function to cast pointer of a type to pointer of type NBNSAnswer_t. * @@ -408,18 +255,6 @@ #if ( ipconfigDNS_USE_CALLBACKS == 1 ) -/** @brief The structure to hold information for a DNS callback. */ - typedef struct xDNS_Callback - { - TickType_t uxRemaningTime; /**< Timeout in ms */ - FOnDNSEvent pCallbackFunction; /**< Function to be called when the address has been found or when a timeout has been reached */ - TimeOut_t uxTimeoutState; /**< Timeout state. */ - void * pvSearchID; /**< Search ID of the callback function. */ - struct xLIST_ITEM xListItem; /**< List struct. */ - char pcName[ 1 ]; /**< 1 character name. */ - } DNSCallback_t; - - /** * @brief Utility function to cast pointer of a type to pointer of type DNSCallback_t. * @@ -431,7 +266,7 @@ } /** @brief The list of all callback structures. */ - static List_t xCallbackList; + _static List_t xCallbackList; /** * @brief Define FreeRTOS_gethostbyname() as a normal blocking call. @@ -1137,7 +972,7 @@ break; } - while( ( uxCount-- != 0U ) && ( uxIndex < uxSourceLen ) ) + while( uxCount-- != 0U ) { if( uxNameLen >= uxDestLen ) { @@ -1157,7 +992,14 @@ /* Confirm that a fully formed name was found. */ if( uxIndex > 0U ) { - if( ( uxNameLen < uxDestLen ) && ( uxIndex < uxSourceLen ) && ( pucByte[ uxIndex ] == 0U ) ) + /* Here, there is no need to check for pucByte[ uxindex ] == 0 because: + * When we break out of the above while loop, uxIndex is made 0 thereby + * failing above check. Whenever we exit the loop otherwise, either + * pucByte[ uxIndex ] == 0 (which makes the check here unnecessary) or + * uxIndex >= uxSourceLen (which makes sure that we do not go in the 'if' + * case). + */ + if( ( uxNameLen < uxDestLen ) && ( uxIndex < uxSourceLen ) ) { pcName[ uxNameLen ] = '\0'; uxIndex++; @@ -1614,7 +1456,11 @@ } #if ( ipconfigUSE_LLMNR == 1 ) - else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) && ( pcRequestedName != NULL ) ) + + /* No need to check that pcRequestedName != NULL since is usQuestions != 0, then + * pcRequestedName is assigned with this statement + * "pcRequestedName = ( char * ) pucByte;" */ + else if( ( usQuestions != ( uint16_t ) 0U ) && ( usType == dnsTYPE_A_HOST ) && ( usClass == dnsCLASS_IN ) ) { /* If this is not a reply to our DNS request, it might an LLMNR * request. */ @@ -1813,6 +1659,7 @@ uint16_t usLength; DNSMessage_t * pxMessage; NBNSAnswer_t * pxAnswer; + NetworkBufferDescriptor_t * pxNewBuffer = NULL; /* Someone is looking for a device with ucNBNSName, * prepare a positive reply. */ @@ -1820,8 +1667,6 @@ if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { - NetworkBufferDescriptor_t * pxNewBuffer; - /* The field xDataLength was set to the total length of the UDP packet, * i.e. the payload size plus sizeof( UDPPacket_t ). */ pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, pxNetworkBuffer->xDataLength + sizeof( NBNSAnswer_t ) ); @@ -1871,6 +1716,11 @@ usLength = ( uint16_t ) ( sizeof( NBNSAnswer_t ) + ( size_t ) offsetof( NBNSRequest_t, usType ) ); prvReplyDNSMessage( pxNetworkBuffer, ( BaseType_t ) usLength ); + + if( pxNewBuffer != NULL ) + { + vReleaseNetworkBufferAndDescriptor( pxNewBuffer ); + } } } } @@ -2007,12 +1857,15 @@ { BaseType_t x; BaseType_t xFound = pdFALSE; - uint32_t ulCurrentTimeSeconds = ( xTaskGetTickCount() / portTICK_PERIOD_MS ) / 1000UL; + TickType_t xCurrentTickCount = xTaskGetTickCount(); + uint32_t ulCurrentTimeSeconds; uint32_t ulIPAddressIndex = 0; static BaseType_t xFreeEntry = 0; configASSERT( ( pcName != NULL ) ); + ulCurrentTimeSeconds = ( xCurrentTickCount / portTICK_PERIOD_MS ) / 1000UL; + /* For each entry in the DNS cache table. */ for( x = 0; x < ipconfigDNS_CACHE_ENTRIES; x++ ) { @@ -2031,17 +1884,26 @@ { #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) uint8_t ucIndex; + /* The ucCurrentIPAddress value increments without bound and will rollover, */ /* modulo it by the number of IP addresses to keep it in range. */ /* Also perform a final modulo by the max number of IP addresses */ /* per DNS cache entry to prevent out-of-bounds access in the event */ /* that ucNumIPAddresses has been corrupted. */ + if( xDNSCache[ x ].ucNumIPAddresses == 0 ) + { + /* Trying lookup before cache is updated with the number of IP + * addressed? Maybe an accident. Break out of the loop. */ + break; + } + ucIndex = xDNSCache[ x ].ucCurrentIPAddress % xDNSCache[ x ].ucNumIPAddresses; ucIndex = ucIndex % ( uint8_t ) ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY; ulIPAddressIndex = ucIndex; xDNSCache[ x ].ucCurrentIPAddress++; #endif /* if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) */ + *pulIP = xDNSCache[ x ].ulIPAddresses[ ulIPAddressIndex ]; } else diff --git a/FreeRTOS_IP.c b/FreeRTOS_IP.c index 05c4be25be..68549035b8 100644 --- a/FreeRTOS_IP.c +++ b/FreeRTOS_IP.c @@ -191,6 +191,21 @@ static void prvIPTask( void * pvParameters ); */ static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer ); +#if ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 ) + +/* + * The stack will call this user hook for all Ethernet frames that it + * does not support, i.e. other than IPv4, IPv6 and ARP ( for the moment ) + * If this hook returns eReleaseBuffer or eProcessBuffer, the stack will + * release and reuse the network buffer. If this hook returns + * eReturnEthernetFrame, that means user code has reused the network buffer + * to generate a response and the stack will send that response out. + * If this hook returns eFrameConsumed, the user code has ownership of the + * network buffer and has to release it when it’s done. + */ + extern eFrameProcessingResult_t eApplicationProcessCustomFrameHook( NetworkBufferDescriptor_t * const pxNetworkBuffer ); +#endif /* ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 ) */ + /* * Process incoming IP packets. */ @@ -623,6 +638,18 @@ BaseType_t xIsCallingFromIPTask( void ) } /*-----------------------------------------------------------*/ +/** + * @brief The variable 'xIPTaskHandle' is declared static. This function + * gives read-only access to it. + * + * @return The handle of the IP-task. + */ +TaskHandle_t FreeRTOS_GetIPTaskHandle( void ) +{ + return xIPTaskHandle; +} +/*-----------------------------------------------------------*/ + /** * @brief Handle the incoming Ethernet packets. * @@ -1156,8 +1183,18 @@ BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE ); /* Attempt to create the queue used to communicate with the IP task. */ - xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); - configASSERT( xNetworkEventQueue != NULL ); + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + static StaticQueue_t xNetworkEventStaticQueue; + static uint8_t ucNetworkEventQueueStorageArea[ ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t ) ]; + xNetworkEventQueue = xQueueCreateStatic( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ), ucNetworkEventQueueStorageArea, &xNetworkEventStaticQueue ); + } + #else + { + xNetworkEventQueue = xQueueCreate( ipconfigEVENT_QUEUE_LENGTH, sizeof( IPStackEvent_t ) ); + configASSERT( xNetworkEventQueue != NULL ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ if( xNetworkEventQueue != NULL ) { @@ -1208,12 +1245,28 @@ BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES vNetworkSocketsInit(); /* Create the task that processes Ethernet and stack events. */ - xReturn = xTaskCreate( prvIPTask, - "IP-task", - ipconfigIP_TASK_STACK_SIZE_WORDS, - NULL, - ipconfigIP_TASK_PRIORITY, - &( xIPTaskHandle ) ); + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + static StaticTask_t xIPTaskBuffer; + static StackType_t xIPTaskStack[ ipconfigIP_TASK_STACK_SIZE_WORDS ]; + xIPTaskHandle = xTaskCreateStatic( prvIPTask, + "IP-Task", + ipconfigIP_TASK_STACK_SIZE_WORDS, + NULL, + ipconfigIP_TASK_PRIORITY, + xIPTaskStack, + &xIPTaskBuffer ); + } + #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ + { + xReturn = xTaskCreate( prvIPTask, + "IP-task", + ipconfigIP_TASK_STACK_SIZE_WORDS, + NULL, + ipconfigIP_TASK_PRIORITY, + &( xIPTaskHandle ) ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ } else { @@ -1727,8 +1780,13 @@ static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetwor break; default: - /* No other packet types are handled. Nothing to do. */ - eReturned = eReleaseBuffer; + #if ( ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES != 0 ) + /* Custom frame handler. */ + eReturned = eApplicationProcessCustomFrameHook( pxNetworkBuffer ); + #else + /* No other packet types are handled. Nothing to do. */ + eReturned = eReleaseBuffer; + #endif break; } } @@ -1890,9 +1948,15 @@ static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPP * define, so that the checksum won't be checked again here */ if( eReturn == eProcessBuffer ) { - /* Is the IP header checksum correct? */ - if( ( pxIPHeader->ucProtocol != ( uint8_t ) ipPROTOCOL_ICMP ) && - ( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) ) + /* Is the IP header checksum correct? + * + * NOTE: When the checksum of IP header is calculated while not omitting + * the checksum field, the resulting value of the checksum always is 0xffff + * which is denoted by ipCORRECT_CRC. See this wiki for more information: + * https://en.wikipedia.org/wiki/IPv4_header_checksum#Verifying_the_IPv4_header_checksum + * and this RFC: https://tools.ietf.org/html/rfc1624#page-4 + */ + if( usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) { /* Check sum in IP-header not correct. */ eReturn = eReleaseBuffer; @@ -3392,7 +3456,7 @@ const char * FreeRTOS_strerror_r( BaseType_t xErrnum, default: /* Using function "snprintf". */ - ( void ) snprintf( pcBuffer, uxLength, "Errno %d", ( int32_t ) xErrnum ); + ( void ) snprintf( pcBuffer, uxLength, "Errno %d", ( int ) xErrnum ); pcName = NULL; break; } diff --git a/FreeRTOS_Sockets.c b/FreeRTOS_Sockets.c index c854bf460d..b70068f639 100644 --- a/FreeRTOS_Sockets.c +++ b/FreeRTOS_Sockets.c @@ -1451,10 +1451,11 @@ BaseType_t FreeRTOS_closesocket( Socket_t xSocket ) /* Let the IP task close the socket to keep it synchronised with the * packet handling. */ - /* Note when changing the time-out value below, it must be checked who is calling - * this function. If it is called by the IP-task, a deadlock could occur. - * The IP-task would only call it in case of a user call-back */ - if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL ) + /* The timeout value below is only used if this function is called from + * a user task. If this function is called by the IP-task, it may fail + * to close the socket when the event queue is full. + * This should only happen in case of a user call-back. */ + if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL ) { FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) ); xResult = -1; @@ -3977,13 +3978,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) if( xResult != ( int32_t ) ulByteCount ) { FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %u: %d/%u bytes (tail %u head %u space %u front %u)\n", - ( UBaseType_t ) uxOffset, - ( BaseType_t ) xResult, - ( UBaseType_t ) ulByteCount, - ( UBaseType_t ) pxStream->uxTail, - ( UBaseType_t ) pxStream->uxHead, - ( UBaseType_t ) uxStreamBufferFrontSpace( pxStream ), - ( UBaseType_t ) pxStream->uxFront ) ); + ( unsigned int ) uxOffset, + ( int ) xResult, + ( unsigned int ) ulByteCount, + ( unsigned int ) pxStream->uxTail, + ( unsigned int ) pxStream->uxHead, + ( unsigned int ) uxStreamBufferFrontSpace( pxStream ), + ( unsigned int ) pxStream->uxFront ) ); } } #endif /* ipconfigHAS_DEBUG_PRINTF */ diff --git a/FreeRTOS_TCP_IP.c b/FreeRTOS_TCP_IP.c index bd51860cf3..338bebc99d 100644 --- a/FreeRTOS_TCP_IP.c +++ b/FreeRTOS_TCP_IP.c @@ -3583,9 +3583,9 @@ vTCPStateChange( pxSocket, eCLOSED ); } /* Otherwise, check whether the packet is within the receive window. */ - else if( ( ulSequenceNumber > pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) && - ( ulSequenceNumber < ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber + - pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) ) ) + else if( ( xSequenceGreaterThan( ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) ) && + ( xSequenceLessThan( ulSequenceNumber, ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber + + pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) ) ) ) { /* Send a challenge ACK. */ ( void ) prvTCPSendChallengeAck( pxNetworkBuffer ); diff --git a/FreeRTOS_TCP_WIN.c b/FreeRTOS_TCP_WIN.c index adff6b0d50..2b6e9eff67 100644 --- a/FreeRTOS_TCP_WIN.c +++ b/FreeRTOS_TCP_WIN.c @@ -269,10 +269,6 @@ #endif /* ipconfigUSE_TCP_WIN */ /*-----------------------------------------------------------*/ - #if ( ipconfigUSE_TCP_WIN == 1 ) - static portINLINE BaseType_t xSequenceLessThan( uint32_t a, - uint32_t b ); - /** * @brief Check if a < b. * @@ -281,30 +277,25 @@ * * @return pdTRUE when "( b - ( a + 1 ) ) < 0x80000000", else pdFALSE. */ - static portINLINE BaseType_t xSequenceLessThan( uint32_t a, - uint32_t b ) - { - BaseType_t xResult; - - /* Test if a < b */ - if( ( ( b - ( a + 1UL ) ) & 0x80000000UL ) == 0UL ) - { - xResult = pdTRUE; - } - else - { - xResult = pdFALSE; - } + BaseType_t xSequenceLessThan( uint32_t a, + uint32_t b ) + { + BaseType_t xResult; - return xResult; + /* Test if a < b */ + if( ( ( b - ( a + 1UL ) ) & 0x80000000UL ) == 0UL ) + { + xResult = pdTRUE; + } + else + { + xResult = pdFALSE; } - #endif /* ipconfigUSE_TCP_WIN */ -/*-----------------------------------------------------------*/ + return xResult; + } - #if ( ipconfigUSE_TCP_WIN == 1 ) - static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, - uint32_t b ); +/*-----------------------------------------------------------*/ /** * @brief Check if a > b. @@ -314,25 +305,24 @@ * * @return pdTRUE when "( a - b ) < 0x80000000", else pdFALSE. */ - static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, - uint32_t b ) - { - BaseType_t xResult; - - /* Test if a > b */ - if( ( ( a - ( b + 1UL ) ) & 0x80000000UL ) == 0UL ) - { - xResult = pdTRUE; - } - else - { - xResult = pdFALSE; - } + BaseType_t xSequenceGreaterThan( uint32_t a, + uint32_t b ) + { + BaseType_t xResult; - return xResult; + /* Test if a > b */ + if( ( ( a - ( b + 1UL ) ) & 0x80000000UL ) == 0UL ) + { + xResult = pdTRUE; + } + else + { + xResult = pdFALSE; } - #endif /* ipconfigUSE_TCP_WIN */ + return xResult; + } + /*-----------------------------------------------------------*/ static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, @@ -1183,9 +1173,9 @@ FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %u exp %u (dist %d) SACK to %u\n", ( int ) pxWindow->usPeerPortNumber, ( int ) pxWindow->usOurPortNumber, - ( unsigned ) ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber, - ( unsigned ) ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber, - ( unsigned ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */ + ( unsigned ) ( ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ), + ( unsigned ) ( ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ), + ( int ) ( ulSequenceNumber - ulCurrentSequenceNumber ), ( unsigned ) ( ulLast - pxWindow->rx.ulFirstSequenceNumber ) ) ); } diff --git a/include/FreeRTOSIPConfigDefaults.h b/include/FreeRTOSIPConfigDefaults.h index dcbabb2159..effb8e8af7 100644 --- a/include/FreeRTOSIPConfigDefaults.h +++ b/include/FreeRTOSIPConfigDefaults.h @@ -396,7 +396,13 @@ #endif #if ( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 ) - #define ipconfigARP_USE_CLASH_DETECTION 1 + #ifndef ipconfigARP_USE_CLASH_DETECTION + #define ipconfigARP_USE_CLASH_DETECTION 1 + #else + #if ( ipconfigARP_USE_CLASH_DETECTION != 1 ) + #error ipconfigARP_USE_CLASH_DETECTION should be defined as 1 when AUTO_IP is used. + #endif + #endif #endif #ifndef ipconfigARP_USE_CLASH_DETECTION @@ -633,4 +639,12 @@ #define ipconfigSELECT_USES_NOTIFY 0 #endif +/* Set to 1 if you plan on processing custom Ethernet protocols or protocols + * that are not yet supported by the FreeRTOS+TCP stack. If set to 1, + * the user must define eFrameProcessingResult_t eApplicationProcessCustomFrameHook( NetworkBufferDescriptor_t * const pxNetworkBuffer ) + * which will be called by the stack for any frame with an unsupported EtherType. */ +#ifndef ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES + #define ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES 0 +#endif + #endif /* FREERTOS_DEFAULT_IP_CONFIG_H */ diff --git a/include/FreeRTOS_DHCP.h b/include/FreeRTOS_DHCP.h index 3dd43ea1c8..f0a569e185 100644 --- a/include/FreeRTOS_DHCP.h +++ b/include/FreeRTOS_DHCP.h @@ -34,6 +34,128 @@ #include "FreeRTOSIPConfig.h" #include "IPTraceMacroDefaults.h" + #include "FreeRTOS_Sockets.h" + + + #if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586U ) + +/* DHCP must be able to receive an options field of 312 bytes, the fixed + * part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */ + #error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP + #endif + +/* Parameter widths in the DHCP packet. */ + #define dhcpCLIENT_HARDWARE_ADDRESS_LENGTH 16 /**< Client hardware address length.*/ + #define dhcpSERVER_HOST_NAME_LENGTH 64 /**< Server host name length. */ + #define dhcpBOOT_FILE_NAME_LENGTH 128 /**< Boot file name length. */ + +/* Timer parameters */ + #ifndef dhcpINITIAL_TIMER_PERIOD + /** @brief The interval at which the DHCP state handler is called. */ + #define dhcpINITIAL_TIMER_PERIOD ( pdMS_TO_TICKS( 250U ) ) + #endif + + #ifndef dhcpINITIAL_DHCP_TX_PERIOD + +/** @brief The initial amount of time to wait for a DHCP reply. When repeating an + * unanswered request, this time-out shall be multiplied by 2. */ + #define dhcpINITIAL_DHCP_TX_PERIOD ( pdMS_TO_TICKS( 5000U ) ) + #endif + +/* Codes of interest found in the DHCP options field. */ + #define dhcpIPv4_ZERO_PAD_OPTION_CODE ( 0U ) /**< Used to pad other options to make them aligned. See RFC 2132. */ + #define dhcpIPv4_SUBNET_MASK_OPTION_CODE ( 1U ) /**< Subnet mask. See RFC 2132. */ + #define dhcpIPv4_GATEWAY_OPTION_CODE ( 3U ) /**< Available routers. See RFC 2132. */ + #define dhcpIPv4_DNS_SERVER_OPTIONS_CODE ( 6U ) /**< Domain name server. See RFC 2132. */ + #define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE ( 12U ) /**< Host name. See RFC 2132. */ + #define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE ( 50U ) /**< Requested IP-address. See RFC 2132. */ + #define dhcpIPv4_LEASE_TIME_OPTION_CODE ( 51U ) /**< IP-address lease time. See RFC 2132. */ + #define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE ( 53U ) /**< DHCP message type. See RFC 2132. */ + #define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE ( 54U ) /**< Server Identifier. See RFC 2132. */ + #define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE ( 55U ) /**< Parameter Request list. See RFC 2132. */ + #define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE ( 61U ) /**< Client Identifier. See RFC 2132. */ + +/* The four DHCP message types of interest. */ + #define dhcpMESSAGE_TYPE_DISCOVER ( 1 ) /**< DHCP discover message. */ + #define dhcpMESSAGE_TYPE_OFFER ( 2 ) /**< DHCP offer message. */ + #define dhcpMESSAGE_TYPE_REQUEST ( 3 ) /**< DHCP request message. */ + #define dhcpMESSAGE_TYPE_ACK ( 5 ) /**< DHCP acknowledgement. */ + #define dhcpMESSAGE_TYPE_NACK ( 6 ) /**< DHCP NACK. (Negative acknowledgement) */ + +/* Offsets into the transmitted DHCP options fields at which various parameters + * are located. */ + #define dhcpCLIENT_IDENTIFIER_OFFSET ( 6U ) /**< Offset for the client ID option. */ + #define dhcpREQUESTED_IP_ADDRESS_OFFSET ( 14U ) /**< Offset for the requested IP-address option. */ + #define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ( 20U ) /**< Offset for the server IP-address option. */ + +/* Values used in the DHCP packets. */ + #define dhcpREQUEST_OPCODE ( 1U ) /**< DHCP request opcode. */ + #define dhcpREPLY_OPCODE ( 2U ) /**< DHCP reply opcode. */ + #define dhcpADDRESS_TYPE_ETHERNET ( 1U ) /**< Address type: ethernet opcode. */ + #define dhcpETHERNET_ADDRESS_LENGTH ( 6U ) /**< Ethernet address length opcode. */ + +/* The following define is temporary and serves to make the /single source + * code more similar to the /multi version. */ + + #define EP_DHCPData xDHCPData /**< Temporary define to make /single source similar to /multi version. */ + #define EP_IPv4_SETTINGS xNetworkAddressing /**< Temporary define to make /single source similar to /multi version. */ + +/** @brief If a lease time is not received, use the default of two days (48 hours in ticks). + * Can not use pdMS_TO_TICKS() as integer overflow can occur. */ + #define dhcpDEFAULT_LEASE_TIME ( ( 48UL * 60UL * 60UL ) * configTICK_RATE_HZ ) + +/** @brief Don't allow the lease time to be too short. */ + #define dhcpMINIMUM_LEASE_TIME ( pdMS_TO_TICKS( 60000UL ) ) /* 60 seconds in ticks. */ + +/** @brief Marks the end of the variable length options field in the DHCP packet. */ + #define dhcpOPTION_END_BYTE 0xffu + +/** @brief Offset into a DHCP message at which the first byte of the options is + * located. */ + #define dhcpFIRST_OPTION_BYTE_OFFSET ( 0xf0U ) + +/* Standard DHCP port numbers and magic cookie value. + * DHCPv4 uses UDP port number 68 for clients and port number 67 for servers. + */ + #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) + #define dhcpCLIENT_PORT_IPv4 0x4400U /**< Little endian representation of port 68. */ + #define dhcpSERVER_PORT_IPv4 0x4300U /**< Little endian representation of port 67. */ + #define dhcpCOOKIE 0x63538263UL /**< Little endian representation of magic cookie. */ + #define dhcpBROADCAST 0x0080U /**< Little endian representation of broadcast flag. */ + #else + #define dhcpCLIENT_PORT_IPv4 0x0044U /**< Big endian representation of port 68. */ + #define dhcpSERVER_PORT_IPv4 0x0043U /**< Big endian representation of port 68. */ + #define dhcpCOOKIE 0x63825363UL /**< Big endian representation of magic cookie. */ + #define dhcpBROADCAST 0x8000U /**< Big endian representation of broadcast flag. */ + #endif /* ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) */ + + #include "pack_struct_start.h" + struct xDHCPMessage_IPv4 + { + uint8_t ucOpcode; /**< Operation Code: Specifies the general type of message. */ + uint8_t ucAddressType; /**< Hardware type used on the local network. */ + uint8_t ucAddressLength; /**< Hardware Address Length: Specifies how long hardware + * addresses are in this message. */ + uint8_t ucHops; /**< Hops. */ + uint32_t ulTransactionID; /**< A 32-bit identification field generated by the client, + * to allow it to match up the request with replies received + * from DHCP servers. */ + uint16_t usElapsedTime; /**< Number of seconds elapsed since a client began an attempt to acquire or renew a lease. */ + uint16_t usFlags; /**< Just one bit used to indicate broadcast. */ + uint32_t ulClientIPAddress_ciaddr; /**< Client's IP address if it has one or 0 is put in this field. */ + uint32_t ulYourIPAddress_yiaddr; /**< The IP address that the server is assigning to the client. */ + uint32_t ulServerIPAddress_siaddr; /**< The DHCP server address that the client should use. */ + uint32_t ulRelayAgentIPAddress_giaddr; /**< Gateway IP address in case the server client are on different subnets. */ + uint8_t ucClientHardwareAddress[ dhcpCLIENT_HARDWARE_ADDRESS_LENGTH ]; /**< The client hardware address. */ + uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ]; /**< Server's hostname. */ + uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ]; /**< Boot file full directory path. */ + uint32_t ulDHCPCookie; /**< Magic cookie option. */ + /* Option bytes from here on. */ + } + #include "pack_struct_end.h" + typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t; + + #if ( ipconfigUSE_DHCP_HOOK != 0 ) /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */ typedef enum eDHCP_PHASE diff --git a/include/FreeRTOS_DNS.h b/include/FreeRTOS_DNS.h index f89a199614..2b7aea06dd 100644 --- a/include/FreeRTOS_DNS.h +++ b/include/FreeRTOS_DNS.h @@ -32,9 +32,80 @@ /* Application level configuration options. */ #include "FreeRTOSIPConfig.h" + #include "FreeRTOSIPConfigDefaults.h" #include "IPTraceMacroDefaults.h" + #if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) + #define dnsDNS_PORT 0x3500U /**< Little endian: Port used for DNS. */ + #define dnsONE_QUESTION 0x0100U /**< Little endian representation of a DNS question.*/ + #define dnsOUTGOING_FLAGS 0x0001U /**< Little endian representation of standard query. */ + #define dnsRX_FLAGS_MASK 0x0f80U /**< Little endian: The bits of interest in the flags field of incoming DNS messages. */ + #define dnsEXPECTED_RX_FLAGS 0x0080U /**< Little Endian: Should be a response, without any errors. */ + #else + #define dnsDNS_PORT 0x0035U /**< Big endian: Port used for DNS. */ + #define dnsONE_QUESTION 0x0001U /**< Big endian representation of a DNS question.*/ + #define dnsOUTGOING_FLAGS 0x0100U /**< Big endian representation of standard query. */ + #define dnsRX_FLAGS_MASK 0x800fU /**< Big endian: The bits of interest in the flags field of incoming DNS messages. */ + #define dnsEXPECTED_RX_FLAGS 0x8000U /**< Big endian: Should be a response, without any errors. */ + + #endif /* ipconfigBYTE_ORDER */ + +/** @brief The maximum number of times a DNS request should be sent out if a response + * is not received, before giving up. */ + #ifndef ipconfigDNS_REQUEST_ATTEMPTS + #define ipconfigDNS_REQUEST_ATTEMPTS 5 + #endif + +/** @brief If the top two bits in the first character of a name field are set then the + * name field is an offset to the string, rather than the string itself. */ + #define dnsNAME_IS_OFFSET ( ( uint8_t ) 0xc0 ) + +/* NBNS flags. */ + #if ( ipconfigUSE_NBNS == 1 ) + #define dnsNBNS_FLAGS_RESPONSE 0x8000U /**< NBNS response flag. */ + #define dnsNBNS_FLAGS_OPCODE_MASK 0x7800U /**< NBNS opcode bitmask. */ + #define dnsNBNS_FLAGS_OPCODE_QUERY 0x0000U /**< NBNS opcode query. */ + #endif /* ( ipconfigUSE_NBNS == 1 ) */ + +/* Host types. */ + #define dnsTYPE_A_HOST 0x01U /**< DNS type A host. */ + #define dnsCLASS_IN 0x01U /**< DNS class IN (Internet). */ + + #ifndef _lint + /* LLMNR constants. */ + #define dnsLLMNR_TTL_VALUE 300000UL /**< LLMNR time to live value. */ + #define dnsLLMNR_FLAGS_IS_REPONSE 0x8000U /**< LLMNR flag value for response. */ + #endif /* _lint */ + +/* NBNS constants. */ + #if ( ipconfigUSE_NBNS != 0 ) + #define dnsNBNS_TTL_VALUE 3600UL /**< NBNS TTL: 1 hour valid. */ + #define dnsNBNS_TYPE_NET_BIOS 0x0020U /**< NBNS Type: NetBIOS. */ + #define dnsNBNS_CLASS_IN 0x01U /**< NBNS Class: IN (Internet). */ + #define dnsNBNS_NAME_FLAGS 0x6000U /**< NBNS name flags. */ + #define dnsNBNS_ENCODED_NAME_LENGTH 32 /**< NBNS encoded name length. */ + +/** @brief If the queried NBNS name matches with the device's name, + * the query will be responded to with these flags: */ + #define dnsNBNS_QUERY_RESPONSE_FLAGS ( 0x8500U ) + #endif /* ( ipconfigUSE_NBNS != 0 ) */ + +/** @brief Flag DNS parsing errors in situations where an IPv4 address is the return + * type. */ + #define dnsPARSE_ERROR 0UL + + #ifndef _lint + #if ( ipconfigUSE_DNS_CACHE == 0 ) + #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY != 1 ) + #error When DNS caching is disabled, please make ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY equal to 1. + #endif + #endif + #endif + +/** @brief Define the ASCII value of '.' (Period/Full-stop). */ + #define ASCII_BASELINE_DOT 46U + /* The Link-local Multicast Name Resolution (LLMNR) * is included. * Note that a special MAC address is required in addition to the NIC's actual @@ -55,6 +126,99 @@ #define ipNBNS_PORT 137 /* NetBIOS Name Service. */ #define ipNBDGM_PORT 138 /* Datagram Service, not included. */ +/* DNS answer record header. */ + #include "pack_struct_start.h" + struct xDNSAnswerRecord + { + uint16_t usType; /**< Type of DNS answer record. */ + uint16_t usClass; /**< Class of DNS answer record. */ + uint32_t ulTTL; /**< Number of seconds the result can be cached. */ + uint16_t usDataLength; /**< Length of the data field. */ + } + #include "pack_struct_end.h" + typedef struct xDNSAnswerRecord DNSAnswerRecord_t; + + + #if ( ipconfigUSE_DNS_CACHE == 1 ) + typedef struct xDNS_CACHE_TABLE_ROW + { + uint32_t ulIPAddresses[ ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ]; /* The IP address(es) of an ARP cache entry. */ + char pcName[ ipconfigDNS_CACHE_NAME_LENGTH ]; /* The name of the host */ + uint32_t ulTTL; /* Time-to-Live (in seconds) from the DNS server. */ + uint32_t ulTimeWhenAddedInSeconds; + #if ( ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY > 1 ) + uint8_t ucNumIPAddresses; + uint8_t ucCurrentIPAddress; + #endif + } DNSCacheRow_t; + #endif /* if ( ipconfigUSE_DNS_CACHE == 1 ) */ + +/* Below #include just tells the compiler to pack the structure. + * It is included in to make the code more readable */ + #include "pack_struct_start.h" + struct xDNSMessage + { + uint16_t usIdentifier; /**< Query identifier. Used to match up replies to outstanding queries. */ + uint16_t usFlags; /**< Flags. */ + uint16_t usQuestions; /**< Number of questions asked in this query. */ + uint16_t usAnswers; /**< Number of answers being provided in this query. */ + uint16_t usAuthorityRRs; /**< Authoritative name server resource records. */ + uint16_t usAdditionalRRs; /**< Additional resource records.*/ + } + #include "pack_struct_end.h" + typedef struct xDNSMessage DNSMessage_t; + + #if ( ipconfigUSE_LLMNR == 1 ) + + #include "pack_struct_start.h" + struct xLLMNRAnswer + { + uint8_t ucNameCode; /**< Name type. */ + uint8_t ucNameOffset; /**< The name is not repeated in the answer, only the offset is given with "0xc0 " */ + uint16_t usType; /**< Type of the Resource record. */ + uint16_t usClass; /**< Class of the Resource record. */ + uint32_t ulTTL; /**< Seconds till this entry can be cached. */ + uint16_t usDataLength; /**< Length of the address in this record. */ + uint32_t ulIPAddress; /**< The IP-address. */ + } + #include "pack_struct_end.h" + typedef struct xLLMNRAnswer LLMNRAnswer_t; + #endif /* if ( ipconfigUSE_LLMNR == 1 ) */ + + #if ( ipconfigUSE_NBNS == 1 ) + + #include "pack_struct_start.h" + struct xNBNSRequest + { + uint16_t usRequestId; /**< NBNS request ID. */ + uint16_t usFlags; /**< Flags of the DNS message. */ + uint16_t ulRequestCount; /**< The number of requests/questions in this query. */ + uint16_t usAnswerRSS; /**< The number of answers in this query. */ + uint16_t usAuthRSS; /**< Number of authoritative resource records. */ + uint16_t usAdditionalRSS; /**< Number of additional resource records. */ + uint8_t ucNameSpace; /**< Length of name. */ + uint8_t ucName[ dnsNBNS_ENCODED_NAME_LENGTH ]; /**< The domain name. */ + uint8_t ucNameZero; /**< Terminator of the name. */ + uint16_t usType; /**< Type of NBNS record. */ + uint16_t usClass; /**< Class of NBNS request. */ + } + #include "pack_struct_end.h" + typedef struct xNBNSRequest NBNSRequest_t; + + #include "pack_struct_start.h" + struct xNBNSAnswer + { + uint16_t usType; /**< Type of NBNS answer. */ + uint16_t usClass; /**< Class of NBNS answer. */ + uint32_t ulTTL; /**< Time in seconds for which the answer can be cached. */ + uint16_t usDataLength; /**< Data length. */ + uint16_t usNbFlags; /**< NetBIOS flags 0x6000 : IP-address, big-endian. */ + uint32_t ulIPAddress; /**< The IPv4 address. */ + } + #include "pack_struct_end.h" + typedef struct xNBNSAnswer NBNSAnswer_t; + #endif /* if ( ipconfigUSE_NBNS == 1 ) */ + #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) /* @@ -117,6 +281,17 @@ TickType_t uxTimeout ); void FreeRTOS_gethostbyname_cancel( void * pvSearchID ); +/** @brief The structure to hold information for a DNS callback. */ + typedef struct xDNS_Callback + { + TickType_t uxRemaningTime; /**< Timeout in ms */ + FOnDNSEvent pCallbackFunction; /**< Function to be called when the address has been found or when a timeout has been reached */ + TimeOut_t uxTimeoutState; /**< Timeout state. */ + void * pvSearchID; /**< Search ID of the callback function. */ + struct xLIST_ITEM xListItem; /**< List struct. */ + char pcName[ 1 ]; /**< 1 character name. */ + } DNSCallback_t; + #endif /* if ( ipconfigDNS_USE_CALLBACKS != 0 ) */ /* diff --git a/include/FreeRTOS_IP.h b/include/FreeRTOS_IP.h index 665da6e119..f36fc7d9be 100644 --- a/include/FreeRTOS_IP.h +++ b/include/FreeRTOS_IP.h @@ -237,6 +237,8 @@ const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] ); + TaskHandle_t FreeRTOS_GetIPTaskHandle( void ); + void * FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes, TickType_t uxBlockTimeTicks ); void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress, diff --git a/include/FreeRTOS_Sockets.h b/include/FreeRTOS_Sockets.h index 2bcad8a5d5..cf141b0235 100644 --- a/include/FreeRTOS_Sockets.h +++ b/include/FreeRTOS_Sockets.h @@ -33,6 +33,10 @@ /* Standard includes. */ #include +/* FreeRTOS includes. */ + #include "FreeRTOS.h" + #include "task.h" + /* Application level configuration options. */ #include "FreeRTOSIPConfig.h" diff --git a/include/FreeRTOS_TCP_WIN.h b/include/FreeRTOS_TCP_WIN.h index 00f154e810..6a8d5f4987 100644 --- a/include/FreeRTOS_TCP_WIN.h +++ b/include/FreeRTOS_TCP_WIN.h @@ -229,6 +229,31 @@ uint32_t ulFirst, uint32_t ulLast ); +/** + * @brief Check if a > b, where a and b are rolling counters. + * + * @param[in] a: The value on the left-hand side. + * @param[in] b: The value on the right-hand side. + * + * @return pdTRUE if a > b, otherwise pdFALSE. + * + * @note GreaterThan is calculated as "( a - ( b + 1U ) ) < 0x80000000". + */ + BaseType_t xSequenceGreaterThan( uint32_t a, + uint32_t b ); + +/** + * @brief Check if a < b, where a and b are rolling counters. + * + * @param[in] a: The value on the left-hand side. + * @param[in] b: The value on the right-hand side. + * + * @return pdTRUE if a < b, otherwise pdFALSE. + * + * @note LessThan is implemented as "( b - ( a + 1 ) ) < 0x80000000". + */ + BaseType_t xSequenceLessThan( uint32_t a, + uint32_t b ); #ifdef __cplusplus } /* extern "C" */ diff --git a/portable/BufferManagement/BufferAllocation_1.c b/portable/BufferManagement/BufferAllocation_1.c index 905cbdbf9b..283ca0d2b6 100644 --- a/portable/BufferManagement/BufferAllocation_1.c +++ b/portable/BufferManagement/BufferAllocation_1.c @@ -176,7 +176,20 @@ BaseType_t xNetworkBuffersInitialise( void ) * here */ ipconfigBUFFER_ALLOC_INIT(); - xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + static StaticSemaphore_t xNetworkBufferSemaphoreBuffer; + xNetworkBufferSemaphore = xSemaphoreCreateCountingStatic( + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + &xNetworkBufferSemaphoreBuffer ); + } + #else + { + xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + configASSERT( xNetworkBufferSemaphore != NULL ); if( xNetworkBufferSemaphore != NULL ) diff --git a/portable/BufferManagement/BufferAllocation_2.c b/portable/BufferManagement/BufferAllocation_2.c index 765db4ac83..b7fbed5954 100644 --- a/portable/BufferManagement/BufferAllocation_2.c +++ b/portable/BufferManagement/BufferAllocation_2.c @@ -102,7 +102,20 @@ BaseType_t xNetworkBuffersInitialise( void ) * have not been initialised before. */ if( xNetworkBufferSemaphore == NULL ) { - xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); + #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + static StaticSemaphore_t xNetworkBufferSemaphoreBuffer; + xNetworkBufferSemaphore = xSemaphoreCreateCountingStatic( + ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + &xNetworkBufferSemaphoreBuffer ); + } + #else + { + xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + configASSERT( xNetworkBufferSemaphore != NULL ); if( xNetworkBufferSemaphore != NULL ) diff --git a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c index 1cfa0ef74d..2c05b04fdc 100644 --- a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c +++ b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c @@ -29,327 +29,287 @@ #include "task.h" #include "semphr.h" -/* standard library definitions */ +/* Standard library definitions */ #include #include /* FreeRTOS+TCP includes. */ #include #include +#include +#include -#include "NetworkBufferManagement.h" - -#include "CMSIS/SMM_MPS2.h" +/* PHY includes. */ +#include "SMM_MPS2.h" #include "ether_lan9118/smsc9220_eth_drv.h" #include "ether_lan9118/smsc9220_emac_config.h" -#include -#include "NetworkInterface.h" - -/* =============================== Function Macros ========================== */ - -/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet - * driver will filter incoming packets and only pass the stack those packets it - * considers need processing. */ -#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer -#else - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +/* Sets the size of the stack (in words, not bytes) of the task that reads bytes + * from the network. */ +#ifndef nwRX_TASK_STACK_SIZE + #define nwRX_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) #endif - -/* ============================= Variable Definitions ======================= */ -#ifndef configNUM_TX_DESCRIPTORS - #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h +#ifndef nwETHERNET_RX_HANDLER_TASK_PRIORITY + #define nwETHERNET_RX_HANDLER_TASK_PRIORITY ( configMAX_PRIORITIES - 3 ) #endif -#ifndef PHY_LS_LOW_CHECK_TIME_MS - /* Check if the LinkSStatus in the PHY is still low every second. */ - #define PHY_LS_LOW_CHECK_TIME_MS 1000 -#endif +/* The number of attempts to get a successful call to smsc9220_send_by_chunks() + * when transmitting a packet before giving up. */ +#define niMAX_TX_ATTEMPTS ( 5 ) -#define nwRX_TASK_STACK_SIZE 140 +/* Address of ISER and ICER registers in the Cortex-M NVIC. */ +#define nwNVIC_ISER ( *( ( volatile uint32_t * ) 0xE000E100UL ) ) +#define nwNVIC_ICER ( *( ( volatile uint32_t * ) 0xE000E180UL ) ) -#define niMAX_TX_ATTEMPTS ( 5 ) +/*-----------------------------------------------------------*/ -/* ============================= Static Prototypes ========================= */ -static void rx_task( void * pvParameters ); +/* + * The task that processes incoming Ethernet packets. It is unblocked by the + * Ethernet Rx interrupt. + */ +static void prvRxTask( void * pvParameters ); -static void packet_rx(); +/* + * Performs low level reads to obtain data from the Ethernet hardware. + */ +static uint32_t prvLowLevelInput( NetworkBufferDescriptor_t ** pxNetworkBuffer ); -static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer ); +static void prvWait_ms( uint32_t ulSleep_ms ); +static void prvSetMACAddress( void ); + +/*-----------------------------------------------------------*/ static const struct smsc9220_eth_dev_cfg_t SMSC9220_ETH_DEV_CFG = { .base = SMSC9220_BASE }; -static struct smsc9220_eth_dev_data_t SMSC9220_ETH_DEV_DATA = { .state = 0 }; +static struct smsc9220_eth_dev_data_t SMSC9220_ETH_DEV_DATA = +{ + .state = 0 +}; -static struct smsc9220_eth_dev_t SMSC9220_ETH_DEV = +static const struct smsc9220_eth_dev_t SMSC9220_ETH_DEV = { &( SMSC9220_ETH_DEV_CFG ), &( SMSC9220_ETH_DEV_DATA ) }; -static void print_hex( unsigned const char * const bin_data, - size_t len ); - -/* ============================= Extern Variables ========================== */ -/* defined in main_networking.c */ extern uint8_t ucMACAddress[ SMSC9220_HWADDR_SIZE ]; /* 6 bytes */ +static TaskHandle_t xRxTaskHandle = NULL; -/* ============================= Static Variables ========================== */ -static TaskHandle_t xRxHanderTask = NULL; -static SemaphoreHandle_t xSemaphore = NULL; - -/* ============================= Static Functions ========================== */ - -/*! - * @brief print binary packet in hex - * @param [in] bin_daa data to print - * @param [in] len length of the data - */ -#if ( ipconfigHAS_DEBUG_PRINTF == 1 ) - static void print_hex( unsigned const char * const bin_data, - size_t len ) - { - size_t i; - - for( i = 0; i < len; ++i ) - { - printf( "%.2X ", bin_data[ i ] ); - - if( ( ( i + 1 ) % 16 ) == 0 ) - { - printf( "\n" ); - } - } - - printf( "\n" ); - } -#else /* if ( ipconfigHAS_DEBUG_PRINTF == 1 ) */ - #define print_hex ( void * ) 0; -#endif /* if ( ipconfigHAS_DEBUG_PRINTF == 1 ) */ +/*-----------------------------------------------------------*/ -static void wait_ms_function( uint32_t sleep_ms ) +static void prvWait_ms( uint32_t ulSleep_ms ) { - vTaskDelay( pdMS_TO_TICKS( sleep_ms ) ); + vTaskDelay( pdMS_TO_TICKS( ulSleep_ms ) ); } +/*-----------------------------------------------------------*/ -static void set_mac( const uint8_t * addr ) +static void prvSetMACAddress( void ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - uint8_t _hwaddr[ SMSC9220_HWADDR_SIZE ]; - - if( !addr ) - { - return; - } + uint32_t ucMACLow = 0; + uint32_t ucMACHigh = 0; - memcpy( _hwaddr, addr, sizeof _hwaddr ); - uint32_t mac_low = 0; - uint32_t mac_high = 0; - /* Using local variables to make sure the right alignment is used */ - memcpy( ( void * ) &mac_low, ( void * ) addr, 4 ); - memcpy( ( void * ) &mac_high, ( void * ) ( addr + 4 ), 2 ); + /* Using local variables to make sure the right alignment is used. The MAC + * address is 6 bytes, hence the copy of 4 bytes followed by 2 bytes. */ + memcpy( ( void * ) &ucMACLow, ( void * ) ucMACAddress, 4 ); + memcpy( ( void * ) &ucMACHigh, ( void * ) ( ucMACAddress + 4 ), 2 ); - if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_ADDRL, mac_low ) ) + if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_ADDRL, ucMACLow ) != 0 ) { - return; - } - - if( smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_ADDRH, mac_high ) ) - { - return; + smsc9220_mac_regwrite( dev, SMSC9220_MAC_REG_OFFSET_ADDRH, ucMACHigh ); } } +/*-----------------------------------------------------------*/ -void EthernetISR( void ) +static void prvRxTask( void * pvParameters ) { + const TickType_t xBlockTime = pdMS_TO_TICKS( 1500UL ); const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - BaseType_t xHigherPriorityTaskWoken = pdFALSE; + IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; + NetworkBufferDescriptor_t * pxNetworkBuffer = NULL; + uint32_t ulDataRead; - configASSERT( xRxHanderTask ); + ( void ) pvParameters; - if( smsc9220_get_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ) ) + for( ; ; ) { - configASSERT( xSemaphore ); - xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); + /* Wait for the Ethernet ISR to receive a packet. */ + ulTaskNotifyTake( pdFALSE, xBlockTime ); - smsc9220_disable_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - smsc9220_clear_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - } - - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -} - -/** - * @brief function to wait on a semaphore from the interrupt handler of the - * network card when data is available - */ -static void rx_task( void * pvParameters ) -{ - BaseType_t xResult = 0; - uint32_t ulNotifiedValue; - const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - const TickType_t xBlockTime = pdMS_TO_TICKS( 50ul ); + while( ( ulDataRead = prvLowLevelInput( &pxNetworkBuffer ) ) != 0UL ) + { + xRxEvent.pvData = ( void * ) pxNetworkBuffer; - FreeRTOS_debug_printf( ( "Enter\n" ) ); + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) + { + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + } + } - for( ; ; ) - { - configASSERT( xSemaphore ); - xSemaphoreTake( xSemaphore, - portMAX_DELAY ); - - packet_rx(); - smsc9220_clear_interrupt( dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); /*_RB_ Can this move up. */ } } +/*-----------------------------------------------------------*/ -static void packet_rx() +static uint32_t prvLowLevelInput( NetworkBufferDescriptor_t ** pxNetworkBuffer ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; - NetworkBufferDescriptor_t * pxNetworkBuffer = NULL; - uint32_t data_read; + const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250UL ); + uint32_t ulMessageLength = 0, ulReceivedBytes = 0; - FreeRTOS_debug_printf( ( "Enter\n" ) ); + ulMessageLength = smsc9220_peek_next_packet_size( dev ); - while( ( data_read = low_level_input( &pxNetworkBuffer ) ) ) + if( ulMessageLength != 0 ) { - xRxEvent.pvData = ( void * ) pxNetworkBuffer; + *pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ulMessageLength, + xDescriptorWaitTime ); + + if( *pxNetworkBuffer != NULL ) + { + ( *pxNetworkBuffer )->xDataLength = ulMessageLength; - if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) + ulReceivedBytes = smsc9220_receive_by_chunks( dev, + ( char * ) ( ( *pxNetworkBuffer )->pucEthernetBuffer ), + ulMessageLength ); /* not used */ + ( *pxNetworkBuffer )->xDataLength = ulReceivedBytes; + } + else { - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + FreeRTOS_printf( ( "pxNetworkBuffer = NULL\n" ) ); } } - FreeRTOS_debug_printf( ( "Exit\n" ) ); + return ulReceivedBytes; } +/*-----------------------------------------------------------*/ -static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer ) +void EthernetISR( void ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); - uint32_t message_length = 0; - uint32_t received_bytes = 0; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + uint32_t ulIRQStatus; + const uint32_t ulRXFifoStatusIRQBit = 1UL << SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL; + extern uint32_t get_irq_status( const struct smsc9220_eth_dev_t * dev ); - FreeRTOS_debug_printf( ( "Enter\n" ) ); + /* Should not enable this interrupt until after the handler task has been + * created. */ + configASSERT( xRxTaskHandle ); - message_length = smsc9220_peek_next_packet_size2( dev ); + ulIRQStatus = get_irq_status( dev ); - if( message_length != 0 ) + if( ( ulIRQStatus & ulRXFifoStatusIRQBit ) != 0 ) { - *pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( message_length, - xDescriptorWaitTime ); + /* Unblock the task that will process this interrupt. */ + vTaskNotifyGiveFromISR( xRxTaskHandle, &xHigherPriorityTaskWoken ); + smsc9220_clear_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - if( *pxNetworkBuffer != NULL ) - { - ( *pxNetworkBuffer )->xDataLength = message_length; - - received_bytes = smsc9220_receive_by_chunks2( dev, - ( *pxNetworkBuffer )->pucEthernetBuffer, - message_length ); /* not used */ - ( *pxNetworkBuffer )->xDataLength = received_bytes; - FreeRTOS_debug_printf( ( "Incoming data < < < < < < < < < < read: %d length: %d\n", - received_bytes, - message_length ) ); - print_hex( ( *pxNetworkBuffer )->pucEthernetBuffer, - received_bytes ); - } - else - { - FreeRTOS_printf( ( "pxNetworkBuffer = NULL\n" ) ); - } + /* Re-enabled by the task that handles the incoming packet. */ /*_RB_ Is this necessary? */ + smsc9220_disable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); } - FreeRTOS_debug_printf( ( "Exit\n" ) ); - return received_bytes; + smsc9220_clear_all_interrupts( dev ); + + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } +/*-----------------------------------------------------------*/ -/* =============================== API Functions ============================ */ BaseType_t xNetworkInterfaceInitialise( void ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - BaseType_t xReturn = pdPASS; + const uint32_t ulEthernetIRQ = 13UL; + BaseType_t xReturn = pdFAIL; enum smsc9220_error_t err; - FreeRTOS_debug_printf( ( "Enter\n" ) ); - xSemaphore = xSemaphoreCreateBinary(); - configASSERT( xSemaphore ); - - if( xRxHanderTask == NULL ) + if( xRxTaskHandle == NULL ) { - xReturn = xTaskCreate( rx_task, + /* Task has not been created before. */ + xReturn = xTaskCreate( prvRxTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, - configMAX_PRIORITIES - 4, - &xRxHanderTask ); - configASSERT( xReturn != 0 ); - configASSERT( xRxHanderTask ); + nwETHERNET_RX_HANDLER_TASK_PRIORITY, + &xRxTaskHandle ); + configASSERT( xReturn != pdFALSE ); } - err = smsc9220_init( dev, wait_ms_function ); - - if( err != SMSC9220_ERROR_NONE ) + if( xReturn == pdPASS ) { - FreeRTOS_debug_printf( ( "%s: %d\n", "smsc9220_init failed", err ) ); - xReturn = pdFAIL; - } - else - { - NVIC_DisableIRQ( ETHERNET_IRQn ); - smsc9220_disable_all_interrupts( dev ); - smsc9220_clear_all_interrupts( dev ); - - smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN ); - smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN ); - smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX ); - set_mac( ucMACAddress ); - NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY ); - smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); - NVIC_EnableIRQ( ETHERNET_IRQn ); + err = smsc9220_init( dev, prvWait_ms ); + + if( err != SMSC9220_ERROR_NONE ) + { + FreeRTOS_debug_printf( ( "%s: %d\n", "smsc9220_init failed", err ) ); + xReturn = pdFAIL; + } + else + { + /* Disable the Ethernet interrupt in the NVIC. */ + nwNVIC_ICER = ( uint32_t ) ( 1UL << ( ulEthernetIRQ & 0x1FUL ) ); + + smsc9220_disable_all_interrupts( dev ); + smsc9220_clear_all_interrupts( dev ); + + smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN ); + smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN ); + smsc9220_set_fifo_level_irq( dev, SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX ); + prvSetMACAddress(); + + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_GPIO0 ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_GPIO1 ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_GPIO2 ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_DROPPED_FRAME ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_ERROR ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_ERROR ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_PHY ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_GP_TIMER ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_DMA ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_IOC ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STOPPED ); + smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_TX_STOPPED ); + + /* Enable the Ethernet interrupt in the NVIC. */ + nwNVIC_ISER = ( uint32_t ) ( 1UL << ( ulEthernetIRQ & 0x1FUL ) ); + + xReturn = pdPASS; + } } - FreeRTOS_debug_printf( ( "Exit\n" ) ); return xReturn; } +/*-----------------------------------------------------------*/ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 ); enum smsc9220_error_t error = SMSC9220_ERROR_NONE; - BaseType_t xReturn = pdFAIL; - int x; - - FreeRTOS_debug_printf( ( "Enter\n" ) ); + BaseType_t xReturn = pdFAIL, x; for( x = 0; x < niMAX_TX_ATTEMPTS; x++ ) { if( pxNetworkBuffer->xDataLength < SMSC9220_ETH_MAX_FRAME_SIZE ) - { /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */ - FreeRTOS_debug_printf( ( "outgoing data > > > > > > > > > > > > length: %d\n", - pxNetworkBuffer->xDataLength ) ); - print_hex( pxNetworkBuffer->pucEthernetBuffer, - pxNetworkBuffer->xDataLength ); + { error = smsc9220_send_by_chunks( dev, pxNetworkBuffer->xDataLength, true, - pxNetworkBuffer->pucEthernetBuffer, + ( char * ) ( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength ); if( error == SMSC9220_ERROR_NONE ) @@ -378,25 +338,32 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkB vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); } - FreeRTOS_debug_printf( ( "Exit\n" ) ); return xReturn; } +/*-----------------------------------------------------------*/ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - /* FIX ME. */ + /* FIX ME if you want to use BufferAllocation_1.c, which uses statically + * allocated network buffers. */ + + /* Hard force an assert as this driver cannot be used with BufferAllocation_1.c + * without implementing this function. */ + configASSERT( xRxTaskHandle == ( TaskHandle_t ) 1 ); + ( void ) pxNetworkBuffers; } +/*-----------------------------------------------------------*/ BaseType_t xGetPhyLinkStatus( void ) { const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV; - uint32_t phy_basic_status_reg_value = 0; - bool current_link_status_up = pdFALSE; + uint32_t ulPHYBasicStatusValue; + BaseType_t xLinkStatusUp; /* Get current status */ smsc9220_phy_regread( dev, SMSC9220_PHY_REG_OFFSET_BSTATUS, - &phy_basic_status_reg_value ); - current_link_status_up = ( bool ) ( phy_basic_status_reg_value & - ( 1ul << ( PHY_REG_BSTATUS_LINK_STATUS_INDEX ) ) ); - return current_link_status_up; + &ulPHYBasicStatusValue ); + xLinkStatusUp = ( bool ) ( ulPHYBasicStatusValue & + ( 1ul << ( PHY_REG_BSTATUS_LINK_STATUS_INDEX ) ) ); + return xLinkStatusUp; } diff --git a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/SMM_MPS2.h b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/SMM_MPS2.h new file mode 100644 index 0000000000..25857c4d98 --- /dev/null +++ b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/SMM_MPS2.h @@ -0,0 +1,615 @@ +/* + * copyright (c) 2006-2016 ARM Limited + * SPDX-License-Identifier: BSD-3-Clause + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + * File: smm_mps2.h + * Release: Version 1.1 + *******************************************************************************/ + +#ifndef __SMM_MPS2_H +#define __SMM_MPS2_H + +#if defined( __CC_ARM ) + #pragma anon_unions +#endif + + + +/******************************************************************************/ +/* FPGA System Register declaration */ +/******************************************************************************/ + +typedef struct +{ + volatile uint32_t LED; /* Offset: 0x000 (R/W) LED connections */ + /* [31:2] : Reserved */ + /* [1:0] : LEDs */ + uint32_t RESERVED1[ 1 ]; + volatile uint32_t BUTTON; /* Offset: 0x008 (R/W) Buttons */ + /* [31:2] : Reserved */ + /* [1:0] : Buttons */ + uint32_t RESERVED2[ 1 ]; + volatile uint32_t CLK1HZ; /* Offset: 0x010 (R/W) 1Hz up counter */ + volatile uint32_t CLK100HZ; /* Offset: 0x014 (R/W) 100Hz up counter */ + volatile uint32_t COUNTER; /* Offset: 0x018 (R/W) Cycle Up Counter */ + /* Increments when 32-bit prescale counter reach zero */ + uint32_t RESERVED3[ 1 ]; + volatile uint32_t PRESCALE; /* Offset: 0x020 (R/W) Prescaler */ + /* Bit[31:0] : reload value for prescale counter */ + volatile uint32_t PSCNTR; /* Offset: 0x024 (R/W) 32-bit Prescale counter */ + /* current value of the pre-scaler counter */ + /* The Cycle Up Counter increment when the prescale down counter reach 0 */ + /* The pre-scaler counter is reloaded with PRESCALE after reaching 0. */ + uint32_t RESERVED4[ 9 ]; + volatile uint32_t MISC; /* Offset: 0x04C (R/W) Misc control * / */ + /* [31:10] : Reserved */ + /* [9] : SHIELD_1_SPI_nCS */ + /* [8] : SHIELD_0_SPI_nCS */ + /* [7] : ADC_SPI_nCS */ + /* [6] : CLCD_BL_CTRL */ + /* [5] : CLCD_RD */ + /* [4] : CLCD_RS */ + /* [3] : CLCD_RESET */ + /* [2] : RESERVED */ + /* [1] : SPI_nSS */ + /* [0] : CLCD_CS */ +} MPS2_FPGAIO_TypeDef; + +/* MISC register bit definitions */ + +#define CLCD_CS_Pos 0 +#define CLCD_CS_Msk ( 1UL << CLCD_CS_Pos ) +#define SPI_nSS_Pos 1 +#define SPI_nSS_Msk ( 1UL << SPI_nSS_Pos ) +#define CLCD_RESET_Pos 3 +#define CLCD_RESET_Msk ( 1UL << CLCD_RESET_Pos ) +#define CLCD_RS_Pos 4 +#define CLCD_RS_Msk ( 1UL << CLCD_RS_Pos ) +#define CLCD_RD_Pos 5 +#define CLCD_RD_Msk ( 1UL << CLCD_RD_Pos ) +#define CLCD_BL_Pos 6 +#define CLCD_BL_Msk ( 1UL << CLCD_BL_Pos ) +#define ADC_nCS_Pos 7 +#define ADC_nCS_Msk ( 1UL << ADC_nCS_Pos ) +#define SHIELD_0_nCS_Pos 8 +#define SHIELD_0_nCS_Msk ( 1UL << SHIELD_0_nCS_Pos ) +#define SHIELD_1_nCS_Pos 9 +#define SHIELD_1_nCS_Msk ( 1UL << SHIELD_1_nCS_Pos ) + +/******************************************************************************/ +/* SCC Register declaration */ +/******************************************************************************/ + +typedef struct /* */ +{ + volatile uint32_t CFG_REG0; /* Offset: 0x000 (R/W) Remaps block RAM to ZBT */ + /* [31:1] : Reserved */ + /* [0] 1 : REMAP BlockRam to ZBT */ + volatile uint32_t LEDS; /* Offset: 0x004 (R/W) Controls the MCC user LEDs */ + /* [31:8] : Reserved */ + /* [7:0] : MCC LEDs */ + uint32_t RESERVED0[ 1 ]; + volatile uint32_t SWITCHES; /* Offset: 0x00C (R/ ) Denotes the state of the MCC user switches */ + /* [31:8] : Reserved */ + /* [7:0] : These bits indicate state of the MCC switches */ + volatile uint32_t CFG_REG4; /* Offset: 0x010 (R/ ) Denotes the board revision */ + /* [31:4] : Reserved */ + /* [3:0] : Used by the MCC to pass PCB revision. 0 = A 1 = B */ + uint32_t RESERVED1[ 35 ]; + volatile uint32_t SYS_CFGDATA_RTN; /* Offset: 0x0A0 (R/W) User data register */ + /* [31:0] : Data */ + volatile uint32_t SYS_CFGDATA_OUT; /* Offset: 0x0A4 (R/W) User data register */ + /* [31:0] : Data */ + volatile uint32_t SYS_CFGCTRL; /* Offset: 0x0A8 (R/W) Control register */ + /* [31] : Start (generates interrupt on write to this bit) */ + /* [30] : R/W access */ + /* [29:26] : Reserved */ + /* [25:20] : Function value */ + /* [19:12] : Reserved */ + /* [11:0] : Device (value of 0/1/2 for supported clocks) */ + volatile uint32_t SYS_CFGSTAT; /* Offset: 0x0AC (R/W) Contains status information */ + /* [31:2] : Reserved */ + /* [1] : Error */ + /* [0] : Complete */ + volatile uint32_t RESERVED2[ 20 ]; + volatile uint32_t SCC_DLL; /* Offset: 0x100 (R/W) DLL Lock Register */ + /* [31:24] : DLL LOCK MASK[7:0] - Indicate if the DLL locked is masked */ + /* [23:16] : DLL LOCK MASK[7:0] - Indicate if the DLLs are locked or unlocked */ + /* [15:1] : Reserved */ + /* [0] : This bit indicates if all enabled DLLs are locked */ + uint32_t RESERVED3[ 957 ]; + volatile uint32_t SCC_AID; /* Offset: 0xFF8 (R/ ) SCC AID Register */ + /* [31:24] : FPGA build number */ + /* [23:20] : V2M-MPS2 target board revision (A = 0, B = 1) */ + /* [19:11] : Reserved */ + /* [10] : if “1” SCC_SW register has been implemented */ + /* [9] : if “1” SCC_LED register has been implemented */ + /* [8] : if “1” DLL lock register has been implemented */ + /* [7:0] : number of SCC configuration register */ + volatile uint32_t SCC_ID; /* Offset: 0xFFC (R/ ) Contains information about the FPGA image */ + /* [31:24] : Implementer ID: 0x41 = ARM */ + /* [23:20] : Application note IP variant number */ + /* [19:16] : IP Architecture: 0x4 =AHB */ + /* [15:4] : Primary part number: 386 = AN386 */ + /* [3:0] : Application note IP revision number */ +} MPS2_SCC_TypeDef; + + +/******************************************************************************/ +/* SSP Peripheral declaration */ +/******************************************************************************/ + +typedef struct /* Document DDI0194G_ssp_pl022_r1p3_trm.pdf */ +{ + volatile uint32_t CR0; /* Offset: 0x000 (R/W) Control register 0 */ + /* [31:16] : Reserved */ + /* [15:8] : Serial clock rate */ + /* [7] : SSPCLKOUT phase, applicable to Motorola SPI frame format only */ + /* [6] : SSPCLKOUT polarity, applicable to Motorola SPI frame format only */ + /* [5:4] : Frame format */ + /* [3:0] : Data Size Select */ + volatile uint32_t CR1; /* Offset: 0x004 (R/W) Control register 1 */ + /* [31:4] : Reserved */ + /* [3] : Slave-mode output disable */ + /* [2] : Master or slave mode select */ + /* [1] : Synchronous serial port enable */ + /* [0] : Loop back mode */ + volatile uint32_t DR; /* Offset: 0x008 (R/W) Data register */ + /* [31:16] : Reserved */ + /* [15:0] : Transmit/Receive FIFO */ + volatile uint32_t SR; /* Offset: 0x00C (R/ ) Status register */ + /* [31:5] : Reserved */ + /* [4] : PrimeCell SSP busy flag */ + /* [3] : Receive FIFO full */ + /* [2] : Receive FIFO not empty */ + /* [1] : Transmit FIFO not full */ + /* [0] : Transmit FIFO empty */ + volatile uint32_t CPSR; /* Offset: 0x010 (R/W) Clock prescale register */ + /* [31:8] : Reserved */ + /* [8:0] : Clock prescale divisor */ + volatile uint32_t IMSC; /* Offset: 0x014 (R/W) Interrupt mask set or clear register */ + /* [31:4] : Reserved */ + /* [3] : Transmit FIFO interrupt mask */ + /* [2] : Receive FIFO interrupt mask */ + /* [1] : Receive timeout interrupt mask */ + /* [0] : Receive overrun interrupt mask */ + volatile uint32_t RIS; /* Offset: 0x018 (R/ ) Raw interrupt status register */ + /* [31:4] : Reserved */ + /* [3] : raw interrupt state, prior to masking, of the SSPTXINTR interrupt */ + /* [2] : raw interrupt state, prior to masking, of the SSPRXINTR interrupt */ + /* [1] : raw interrupt state, prior to masking, of the SSPRTINTR interrupt */ + /* [0] : raw interrupt state, prior to masking, of the SSPRORINTR interrupt */ + volatile uint32_t MIS; /* Offset: 0x01C (R/ ) Masked interrupt status register */ + /* [31:4] : Reserved */ + /* [3] : transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt */ + /* [2] : receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt */ + /* [1] : receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt */ + /* [0] : receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt */ + volatile uint32_t ICR; /* Offset: 0x020 ( /W) Interrupt clear register */ + /* [31:2] : Reserved */ + /* [1] : Clears the SSPRTINTR interrupt */ + /* [0] : Clears the SSPRORINTR interrupt */ + volatile uint32_t DMACR; /* Offset: 0x024 (R/W) DMA control register */ + /* [31:2] : Reserved */ + /* [1] : Transmit DMA Enable */ + /* [0] : Receive DMA Enable */ +} MPS2_SSP_TypeDef; + + +/* SSP_CR0 Control register 0 */ +#define SSP_CR0_DSS_Pos 0 /* Data Size Select */ +#define SSP_CR0_DSS_Msk ( 0xF << SSP_CR0_DSS_Pos ) +#define SSP_CR0_FRF_Pos 4 /* Frame Format Select */ +#define SSP_CR0_FRF_Msk ( 3UL << SSP_CR0_FRM_Pos ) +#define SSP_CR0_SPO_Pos 6 /* SSPCLKOUT polarity */ +#define SSP_CR0_SPO_Msk ( 1UL << SSP_CR0_SPO_Pos ) +#define SSP_CR0_SPH_Pos 7 /* SSPCLKOUT phase */ +#define SSP_CR0_SPH_Msk ( 1UL << SSP_CR0_SPH_Pos ) +#define SSP_CR0_SCR_Pos 8 /* Serial Clock Rate (divide) */ +#define SSP_CR0_SCR_Msk ( 0xFF << SSP_CR0_SCR_Pos ) + +#define SSP_CR0_SCR_DFLT 0x0300 /* Serial Clock Rate (divide), default set at 3 */ +#define SSP_CR0_FRF_MOT 0x0000 /* Frame format, Motorola */ +#define SSP_CR0_DSS_8 0x0007 /* Data packet size, 8bits */ +#define SSP_CR0_DSS_16 0x000F /* Data packet size, 16bits */ + +/* SSP_CR1 Control register 1 */ +#define SSP_CR1_LBM_Pos 0 /* Loop Back Mode */ +#define SSP_CR1_LBM_Msk ( 1UL << SSP_CR1_LBM_Pos ) +#define SSP_CR1_SSE_Pos 1 /* Serial port enable */ +#define SSP_CR1_SSE_Msk ( 1UL << SSP_CR1_SSE_Pos ) +#define SSP_CR1_MS_Pos 2 /* Master or Slave mode */ +#define SSP_CR1_MS_Msk ( 1UL << SSP_CR1_MS_Pos ) +#define SSP_CR1_SOD_Pos 3 /* Slave Output mode Disable */ +#define SSP_CR1_SOD_Msk ( 1UL << SSP_CR1_SOD_Pos ) + +/* SSP_SR Status register */ +#define SSP_SR_TFE_Pos 0 /* Transmit FIFO empty */ +#define SSP_SR_TFE_Msk ( 1UL << SSP_SR_TFE_Pos ) +#define SSP_SR_TNF_Pos 1 /* Transmit FIFO not full */ +#define SSP_SR_TNF_Msk ( 1UL << SSP_SR_TNF_Pos ) +#define SSP_SR_RNE_Pos 2 /* Receive FIFO not empty */ +#define SSP_SR_RNE_Msk ( 1UL << SSP_SR_RNE_Pos ) +#define SSP_SR_RFF_Pos 3 /* Receive FIFO full */ +#define SSP_SR_RFF_Msk ( 1UL << SSP_SR_RFF_Pos ) +#define SSP_SR_BSY_Pos 4 /* Busy */ +#define SSP_SR_BSY_Msk ( 1UL << SSP_SR_BSY_Pos ) + +/* SSP_CPSR Clock prescale register */ +#define SSP_CPSR_CPD_Pos 0 /* Clock prescale divisor */ +#define SSP_CPSR_CPD_Msk ( 0xFF << SSP_CPSR_CDP_Pos ) + +#define SSP_CPSR_DFLT 0x0008 /* Clock prescale (use with SCR), default set at 8 */ + +/* SSPIMSC Interrupt mask set and clear register */ +#define SSP_IMSC_RORIM_Pos 0 /* Receive overrun not Masked */ +#define SSP_IMSC_RORIM_Msk ( 1UL << SSP_IMSC_RORIM_Pos ) +#define SSP_IMSC_RTIM_Pos 1 /* Receive timeout not Masked */ +#define SSP_IMSC_RTIM_Msk ( 1UL << SSP_IMSC_RTIM_Pos ) +#define SSP_IMSC_RXIM_Pos 2 /* Receive FIFO not Masked */ +#define SSP_IMSC_RXIM_Msk ( 1UL << SSP_IMSC_RXIM_Pos ) +#define SSP_IMSC_TXIM_Pos 3 /* Transmit FIFO not Masked */ +#define SSP_IMSC_TXIM_Msk ( 1UL << SSP_IMSC_TXIM_Pos ) + +/* SSPRIS Raw interrupt status register */ +#define SSP_RIS_RORRIS_Pos 0 /* Raw Overrun interrupt flag */ +#define SSP_RIS_RORRIS_Msk ( 1UL << SSP_RIS_RORRIS_Pos ) +#define SSP_RIS_RTRIS_Pos 1 /* Raw Timemout interrupt flag */ +#define SSP_RIS_RTRIS_Msk ( 1UL << SSP_RIS_RTRIS_Pos ) +#define SSP_RIS_RXRIS_Pos 2 /* Raw Receive interrupt flag */ +#define SSP_RIS_RXRIS_Msk ( 1UL << SSP_RIS_RXRIS_Pos ) +#define SSP_RIS_TXRIS_Pos 3 /* Raw Transmit interrupt flag */ +#define SSP_RIS_TXRIS_Msk ( 1UL << SSP_RIS_TXRIS_Pos ) + +/* SSPMIS Masked interrupt status register */ +#define SSP_MIS_RORMIS_Pos 0 /* Masked Overrun interrupt flag */ +#define SSP_MIS_RORMIS_Msk ( 1UL << SSP_MIS_RORMIS_Pos ) +#define SSP_MIS_RTMIS_Pos 1 /* Masked Timemout interrupt flag */ +#define SSP_MIS_RTMIS_Msk ( 1UL << SSP_MIS_RTMIS_Pos ) +#define SSP_MIS_RXMIS_Pos 2 /* Masked Receive interrupt flag */ +#define SSP_MIS_RXMIS_Msk ( 1UL << SSP_MIS_RXMIS_Pos ) +#define SSP_MIS_TXMIS_Pos 3 /* Masked Transmit interrupt flag */ +#define SSP_MIS_TXMIS_Msk ( 1UL << SSP_MIS_TXMIS_Pos ) + +/* SSPICR Interrupt clear register */ +#define SSP_ICR_RORIC_Pos 0 /* Clears Overrun interrupt flag */ +#define SSP_ICR_RORIC_Msk ( 1UL << SSP_ICR_RORIC_Pos ) +#define SSP_ICR_RTIC_Pos 1 /* Clears Timemout interrupt flag */ +#define SSP_ICR_RTIC_Msk ( 1UL << SSP_ICR_RTIC_Pos ) + +/* SSPDMACR DMA control register */ +#define SSP_DMACR_RXDMAE_Pos 0 /* Enable Receive FIFO DMA */ +#define SSP_DMACR_RXDMAE_Msk ( 1UL << SSP_DMACR_RXDMAE_Pos ) +#define SSP_DMACR_TXDMAE_Pos 1 /* Enable Transmit FIFO DMA */ +#define SSP_DMACR_TXDMAE_Msk ( 1UL << SSP_DMACR_TXDMAE_Pos ) + +/******************************************************************************/ +/* Audio and Touch Screen (I2C) Peripheral declaration */ +/******************************************************************************/ + +typedef struct +{ + union + { + volatile uint32_t CONTROLS; /* Offset: 0x000 CONTROL Set Register ( /W) */ + volatile uint32_t CONTROL; /* Offset: 0x000 CONTROL Status Register (R/ ) */ + }; + volatile uint32_t CONTROLC; /* Offset: 0x004 CONTROL Clear Register ( /W) */ +} MPS2_I2C_TypeDef; + +#define SDA 1 << 1 +#define SCL 1 << 0 + + +/******************************************************************************/ +/* Audio I2S Peripheral declaration */ +/******************************************************************************/ + +typedef struct +{ + /*!< Offset: 0x000 CONTROL Register (R/W) */ + volatile uint32_t CONTROL; /* CONTROL */ + /* TX Enable */ + /* <0=> TX disabled */ + /* <1=> TX enabled */ + /* TX IRQ Enable */ + /* <0=> TX IRQ disabled */ + /* <1=> TX IRQ enabled */ + /* RX Enable */ + /* <0=> RX disabled */ + /* <1=> RX enabled */ + /* RX IRQ Enable */ + /* <0=> RX IRQ disabled */ + /* <1=> RX IRQ enabled */ + /* TX Buffer Water Level */ + /* <0=> / IRQ triggers when any space available */ + /* <1=> / IRQ triggers when more than 1 space available */ + /* <2=> / IRQ triggers when more than 2 space available */ + /* <3=> / IRQ triggers when more than 3 space available */ + /* <4=> Undefined! */ + /* <5=> Undefined! */ + /* <6=> Undefined! */ + /* <7=> Undefined! */ + /* RX Buffer Water Level */ + /* <0=> Undefined! */ + /* <1=> / IRQ triggers when less than 1 space available */ + /* <2=> / IRQ triggers when less than 2 space available */ + /* <3=> / IRQ triggers when less than 3 space available */ + /* <4=> / IRQ triggers when less than 4 space available */ + /* <5=> Undefined! */ + /* <6=> Undefined! */ + /* <7=> Undefined! */ + /* FIFO reset */ + /* <0=> Normal operation */ + /* <1=> FIFO reset */ + /* Audio Codec reset */ + /* <0=> Normal operation */ + /* <1=> Assert audio Codec reset */ + /*!< Offset: 0x004 STATUS Register (R/ ) */ + volatile uint32_t STATUS; /* STATUS */ + /* TX Buffer alert */ + /* <0=> TX buffer don't need service yet */ + /* <1=> TX buffer need service */ + /* RX Buffer alert */ + /* <0=> RX buffer don't need service yet */ + /* <1=> RX buffer need service */ + /* TX Buffer Empty */ + /* <0=> TX buffer have data */ + /* <1=> TX buffer empty */ + /* TX Buffer Full */ + /* <0=> TX buffer not full */ + /* <1=> TX buffer full */ + /* RX Buffer Empty */ + /* <0=> RX buffer have data */ + /* <1=> RX buffer empty */ + /* RX Buffer Full */ + /* <0=> RX buffer not full */ + /* <1=> RX buffer full */ + union + { + /*!< Offset: 0x008 Error Status Register (R/ ) */ + volatile uint32_t ERROR; /* ERROR */ + /* TX error */ + /* <0=> Okay */ + /* <1=> TX overrun/underrun */ + /* RX error */ + /* <0=> Okay */ + /* <1=> RX overrun/underrun */ + /*!< Offset: 0x008 Error Clear Register ( /W) */ + volatile uint32_t ERRORCLR; /* ERRORCLR */ + /* TX error */ + /* <0=> Okay */ + /* <1=> Clear TX error */ + /* RX error */ + /* <0=> Okay */ + /* <1=> Clear RX error */ + }; + /*!< Offset: 0x00C Divide ratio Register (R/W) */ + volatile uint32_t DIVIDE; /* Divide ratio for Left/Right clock */ + /* TX error (default 0x80) */ + /*!< Offset: 0x010 Transmit Buffer ( /W) */ + volatile uint32_t TXBUF; /* Transmit buffer */ + /* Right channel */ + /* Left channel */ + /*!< Offset: 0x014 Receive Buffer (R/ ) */ + volatile uint32_t RXBUF; /* Receive buffer */ + /* Right channel */ + /* Left channel */ + uint32_t RESERVED1[ 186 ]; + volatile uint32_t ITCR; /* Integration Test Control Register */ + /* ITEN */ + /* <0=> Normal operation */ + /* <1=> Integration Test mode enable */ + volatile uint32_t ITIP1; /* Integration Test Input Register 1 */ + /* SDIN */ + volatile uint32_t ITOP1; /* Integration Test Output Register 1 */ + /* SDOUT */ + /* SCLK */ + /* LRCK */ + /* IRQOUT */ +} MPS2_I2S_TypeDef; + +#define I2S_CONTROL_TXEN_Pos 0 +#define I2S_CONTROL_TXEN_Msk ( 1UL << I2S_CONTROL_TXEN_Pos ) + +#define I2S_CONTROL_TXIRQEN_Pos 1 +#define I2S_CONTROL_TXIRQEN_Msk ( 1UL << I2S_CONTROL_TXIRQEN_Pos ) + +#define I2S_CONTROL_RXEN_Pos 2 +#define I2S_CONTROL_RXEN_Msk ( 1UL << I2S_CONTROL_RXEN_Pos ) + +#define I2S_CONTROL_RXIRQEN_Pos 3 +#define I2S_CONTROL_RXIRQEN_Msk ( 1UL << I2S_CONTROL_RXIRQEN_Pos ) + +#define I2S_CONTROL_TXWLVL_Pos 8 +#define I2S_CONTROL_TXWLVL_Msk ( 7UL << I2S_CONTROL_TXWLVL_Pos ) + +#define I2S_CONTROL_RXWLVL_Pos 12 +#define I2S_CONTROL_RXWLVL_Msk ( 7UL << I2S_CONTROL_RXWLVL_Pos ) +/* FIFO reset*/ +#define I2S_CONTROL_FIFORST_Pos 16 +#define I2S_CONTROL_FIFORST_Msk ( 1UL << I2S_CONTROL_FIFORST_Pos ) +/* Codec reset*/ +#define I2S_CONTROL_CODECRST_Pos 17 +#define I2S_CONTROL_CODECRST_Msk ( 1UL << I2S_CONTROL_CODECRST_Pos ) + +#define I2S_STATUS_TXIRQ_Pos 0 +#define I2S_STATUS_TXIRQ_Msk ( 1UL << I2S_STATUS_TXIRQ_Pos ) + +#define I2S_STATUS_RXIRQ_Pos 1 +#define I2S_STATUS_RXIRQ_Msk ( 1UL << I2S_STATUS_RXIRQ_Pos ) + +#define I2S_STATUS_TXEmpty_Pos 2 +#define I2S_STATUS_TXEmpty_Msk ( 1UL << I2S_STATUS_TXEmpty_Pos ) + +#define I2S_STATUS_TXFull_Pos 3 +#define I2S_STATUS_TXFull_Msk ( 1UL << I2S_STATUS_TXFull_Pos ) + +#define I2S_STATUS_RXEmpty_Pos 4 +#define I2S_STATUS_RXEmpty_Msk ( 1UL << I2S_STATUS_RXEmpty_Pos ) + +#define I2S_STATUS_RXFull_Pos 5 +#define I2S_STATUS_RXFull_Msk ( 1UL << I2S_STATUS_RXFull_Pos ) + +#define I2S_ERROR_TXERR_Pos 0 +#define I2S_ERROR_TXERR_Msk ( 1UL << I2S_ERROR_TXERR_Pos ) + +#define I2S_ERROR_RXERR_Pos 1 +#define I2S_ERROR_RXERR_Msk ( 1UL << I2S_ERROR_RXERR_Pos ) + +/******************************************************************************/ +/* SMSC9220 Register Definitions */ +/******************************************************************************/ + +typedef struct /* SMSC LAN9220 */ +{ + volatile uint32_t RX_DATA_PORT; /* Receive FIFO Ports (offset 0x0) */ + uint32_t RESERVED1[ 0x7 ]; + volatile uint32_t TX_DATA_PORT; /* Transmit FIFO Ports (offset 0x20) */ + uint32_t RESERVED2[ 0x7 ]; + + volatile uint32_t RX_STAT_PORT; /* Receive FIFO status port (offset 0x40) */ + volatile uint32_t RX_STAT_PEEK; /* Receive FIFO status peek (offset 0x44) */ + volatile uint32_t TX_STAT_PORT; /* Transmit FIFO status port (offset 0x48) */ + volatile uint32_t TX_STAT_PEEK; /* Transmit FIFO status peek (offset 0x4C) */ + + volatile uint32_t ID_REV; /* Chip ID and Revision (offset 0x50) */ + volatile uint32_t IRQ_CFG; /* Main Interrupt Configuration (offset 0x54) */ + volatile uint32_t INT_STS; /* Interrupt Status (offset 0x58) */ + volatile uint32_t INT_EN; /* Interrupt Enable Register (offset 0x5C) */ + uint32_t RESERVED3; /* Reserved for future use (offset 0x60) */ + volatile uint32_t BYTE_TEST; /* Read-only byte order testing register 87654321h (offset 0x64) */ + volatile uint32_t FIFO_INT; /* FIFO Level Interrupts (offset 0x68) */ + volatile uint32_t RX_CFG; /* Receive Configuration (offset 0x6C) */ + volatile uint32_t TX_CFG; /* Transmit Configuration (offset 0x70) */ + volatile uint32_t HW_CFG; /* Hardware Configuration (offset 0x74) */ + volatile uint32_t RX_DP_CTL; /* RX Datapath Control (offset 0x78) */ + volatile uint32_t RX_FIFO_INF; /* Receive FIFO Information (offset 0x7C) */ + volatile uint32_t TX_FIFO_INF; /* Transmit FIFO Information (offset 0x80) */ + volatile uint32_t PMT_CTRL; /* Power Management Control (offset 0x84) */ + volatile uint32_t GPIO_CFG; /* General Purpose IO Configuration (offset 0x88) */ + volatile uint32_t GPT_CFG; /* General Purpose Timer Configuration (offset 0x8C) */ + volatile uint32_t GPT_CNT; /* General Purpose Timer Count (offset 0x90) */ + uint32_t RESERVED4; /* Reserved for future use (offset 0x94) */ + volatile uint32_t ENDIAN; /* WORD SWAP Register (offset 0x98) */ + volatile uint32_t FREE_RUN; /* Free Run Counter (offset 0x9C) */ + volatile uint32_t RX_DROP; /* RX Dropped Frames Counter (offset 0xA0) */ + volatile uint32_t MAC_CSR_CMD; /* MAC CSR Synchronizer Command (offset 0xA4) */ + volatile uint32_t MAC_CSR_DATA; /* MAC CSR Synchronizer Data (offset 0xA8) */ + volatile uint32_t AFC_CFG; /* Automatic Flow Control Configuration (offset 0xAC) */ + volatile uint32_t E2P_CMD; /* EEPROM Command (offset 0xB0) */ + volatile uint32_t E2P_DATA; /* EEPROM Data (offset 0xB4) */ +} SMSC9220_TypeDef; + +/* SMSC9220 MAC Registers Indices */ +#define SMSC9220_MAC_CR 0x1 +#define SMSC9220_MAC_ADDRH 0x2 +#define SMSC9220_MAC_ADDRL 0x3 +#define SMSC9220_MAC_HASHH 0x4 +#define SMSC9220_MAC_HASHL 0x5 +#define SMSC9220_MAC_MII_ACC 0x6 +#define SMSC9220_MAC_MII_DATA 0x7 +#define SMSC9220_MAC_FLOW 0x8 +#define SMSC9220_MAC_VLAN1 0x9 +#define SMSC9220_MAC_VLAN2 0xA +#define SMSC9220_MAC_WUFF 0xB +#define SMSC9220_MAC_WUCSR 0xC + +/* SMSC9220 PHY Registers Indices */ +#define SMSC9220_PHY_BCONTROL 0x0 +#define SMSC9220_PHY_BSTATUS 0x1 +#define SMSC9220_PHY_ID1 0x2 +#define SMSC9220_PHY_ID2 0x3 +#define SMSC9220_PHY_ANEG_ADV 0x4 +#define SMSC9220_PHY_ANEG_LPA 0x5 +#define SMSC9220_PHY_ANEG_EXP 0x6 +#define SMSC9220_PHY_MCONTROL 0x17 +#define SMSC9220_PHY_MSTATUS 0x18 +#define SMSC9220_PHY_CSINDICATE 0x27 +#define SMSC9220_PHY_INTSRC 0x29 +#define SMSC9220_PHY_INTMASK 0x30 +#define SMSC9220_PHY_CS 0x31 + +/******************************************************************************/ +/* Peripheral memory map */ +/******************************************************************************/ + +#define MPS2_SSP1_BASE ( 0x40020000ul ) /* User SSP Base Address */ +#define MPS2_SSP0_BASE ( 0x40021000ul ) /* CLCD SSP Base Address */ +#define MPS2_TSC_I2C_BASE ( 0x40022000ul ) /* Touch Screen I2C Base Address */ +#define MPS2_AAIC_I2C_BASE ( 0x40023000ul ) /* Audio Interface I2C Base Address */ +#define MPS2_AAIC_I2S_BASE ( 0x40024000ul ) /* Audio Interface I2S Base Address */ +#define MPS2_SSP2_BASE ( 0x40025000ul ) /* adc SSP Base Address */ +#define MPS2_SSP3_BASE ( 0x40026000ul ) /* Shield 0 SSP Base Address */ +#define MPS2_SSP4_BASE ( 0x40027000ul ) /* Shield 1 SSP Base Address */ +#define MPS2_FPGAIO_BASE ( 0x40028000ul ) /* FPGAIO Base Address */ +#define MPS2_SHIELD0_I2C_BASE ( 0x40029000ul ) /* Shield 0 I2C Base Address */ +#define MPS2_SHIELD1_I2C_BASE ( 0x4002A000ul ) /* Shield 1 I2C Base Address */ +#define MPS2_SCC_BASE ( 0x4002F000ul ) /* SCC Base Address */ + +#ifdef CORTEX_M7 + #define SMSC9220_BASE ( 0xA0000000ul ) /* Ethernet SMSC9220 Base Address */ +#else + #define SMSC9220_BASE ( 0x40200000ul ) /* Ethernet SMSC9220 Base Address */ +#endif + +#define MPS2_VGA_TEXT_BUFFER ( 0x41000000ul ) /* VGA Text Buffer Address */ +#define MPS2_VGA_BUFFER ( 0x41100000ul ) /* VGA Buffer Base Address */ + +/******************************************************************************/ +/* Peripheral declaration */ +/******************************************************************************/ + +#define SMSC9220 ( ( SMSC9220_TypeDef * ) SMSC9220_BASE ) +#define MPS2_TS_I2C ( ( MPS2_I2C_TypeDef * ) MPS2_TSC_I2C_BASE ) +#define MPS2_AAIC_I2C ( ( MPS2_I2C_TypeDef * ) MPS2_AAIC_I2C_BASE ) +#define MPS2_SHIELD0_I2C ( ( MPS2_I2C_TypeDef * ) MPS2_SHIELD0_I2C_BASE ) +#define MPS2_SHIELD1_I2C ( ( MPS2_I2C_TypeDef * ) MPS2_SHIELD1_I2C_BASE ) +#define MPS2_AAIC_I2S ( ( MPS2_I2S_TypeDef * ) MPS2_AAIC_I2S_BASE ) +#define MPS2_FPGAIO ( ( MPS2_FPGAIO_TypeDef * ) MPS2_FPGAIO_BASE ) +#define MPS2_SCC ( ( MPS2_SCC_TypeDef * ) MPS2_SCC_BASE ) +#define MPS2_SSP0 ( ( MPS2_SSP_TypeDef * ) MPS2_SSP0_BASE ) +#define MPS2_SSP1 ( ( MPS2_SSP_TypeDef * ) MPS2_SSP1_BASE ) +#define MPS2_SSP2 ( ( MPS2_SSP_TypeDef * ) MPS2_SSP2_BASE ) +#define MPS2_SSP3 ( ( MPS2_SSP_TypeDef * ) MPS2_SSP3_BASE ) +#define MPS2_SSP4 ( ( MPS2_SSP_TypeDef * ) MPS2_SSP4_BASE ) + +/******************************************************************************/ +/* General Function Definitions */ +/******************************************************************************/ + + +/******************************************************************************/ +/* General MACRO Definitions */ +/******************************************************************************/ + + + +#endif /* __SMM_MPS2_H */ diff --git a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c index 5980d791eb..ca96b97081 100644 --- a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c +++ b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "cmsis.h" + #include "smsc9220_eth_drv.h" /*#include "CMSIS/SMM_MPS2.h" */ @@ -46,42 +46,42 @@ struct smsc9220_eth_reg_map_t { - __I uint32_t rx_data_port; /**< Receive FIFO Ports (offset 0x0) */ + volatile uint32_t rx_data_port; /**< Receive FIFO Ports (offset 0x0) */ uint32_t reserved1[ 0x7 ]; - __O uint32_t tx_data_port; /**< Transmit FIFO Ports (offset 0x20) */ + volatile uint32_t tx_data_port; /**< Transmit FIFO Ports (offset 0x20) */ uint32_t reserved2[ 0x7 ]; - __I uint32_t rx_status_port; /**< Receive FIFO status port (offset 0x40) */ - __I uint32_t rx_status_peek; /**< Receive FIFO status peek (offset 0x44) */ - __I uint32_t tx_status_port; /**< Transmit FIFO status port (offset 0x48) */ - __I uint32_t tx_status_peek; /**< Transmit FIFO status peek (offset 0x4C) */ - - __I uint32_t id_revision; /**< Chip ID and Revision (offset 0x50) */ - __IO uint32_t irq_cfg; /**< Main Interrupt Config (offset 0x54) */ - __IO uint32_t irq_status; /**< Interrupt Status (offset 0x58) */ - __IO uint32_t irq_enable; /**< Interrupt Enable Register (offset 0x5C) */ - uint32_t reserved3; /**< Reserved for future use (offset 0x60) */ - __I uint32_t byte_test; /**< Byte order test 87654321h (offset 0x64) */ - __IO uint32_t fifo_level_irq; /**< FIFO Level Interrupts (offset 0x68) */ - __IO uint32_t rx_cfg; /**< Receive Configuration (offset 0x6C) */ - __IO uint32_t tx_cfg; /**< Transmit Configuration (offset 0x70) */ - __IO uint32_t hw_cfg; /**< Hardware Configuration (offset 0x74) */ - __IO uint32_t rx_datapath_ctrl; /**< RX Datapath Control (offset 0x78) */ - __I uint32_t rx_fifo_inf; /**< Receive FIFO Information (offset 0x7C) */ - __I uint32_t tx_fifo_inf; /**< Transmit FIFO Information (offset 0x80) */ - __IO uint32_t pmt_ctrl; /**< Power Management Control (offset 0x84) */ - __IO uint32_t gpio_cfg; /**< GPIO Configuration (offset 0x88) */ - __IO uint32_t gptimer_cfg; /**< GP Timer Configuration (offset 0x8C) */ - __I uint32_t gptimer_count; /**< GP Timer Count (offset 0x90) */ - uint32_t reserved4; /**< Reserved for future use (offset 0x94) */ - __IO uint32_t word_swap; /**< WORD SWAP Register (offset 0x98) */ - __I uint32_t free_run_counter; /**< Free Run Counter (offset 0x9C) */ - __I uint32_t rx_dropped_frames; /**< RX Dropped Frames Counter (offset 0xA0) */ - __IO uint32_t mac_csr_cmd; /**< MAC CSR Synchronizer Cmd (offset 0xA4) */ - __IO uint32_t mac_csr_data; /**< MAC CSR Synchronizer Data (offset 0xA8) */ - __IO uint32_t afc_cfg; /**< AutomaticFlow Ctrl Config (offset 0xAC) */ - __IO uint32_t eeprom_cmd; /**< EEPROM Command (offset 0xB0) */ - __IO uint32_t eeprom_data; /**< EEPROM Data (offset 0xB4) */ + volatile uint32_t rx_status_port; /**< Receive FIFO status port (offset 0x40) */ + volatile uint32_t rx_status_peek; /**< Receive FIFO status peek (offset 0x44) */ + volatile uint32_t tx_status_port; /**< Transmit FIFO status port (offset 0x48) */ + volatile uint32_t tx_status_peek; /**< Transmit FIFO status peek (offset 0x4C) */ + + volatile uint32_t id_revision; /**< Chip ID and Revision (offset 0x50) */ + volatile uint32_t irq_cfg; /**< Main Interrupt Config (offset 0x54) */ + volatile uint32_t irq_status; /**< Interrupt Status (offset 0x58) */ + volatile uint32_t irq_enable; /**< Interrupt Enable Register (offset 0x5C) */ + uint32_t reserved3; /**< Reserved for future use (offset 0x60) */ + volatile uint32_t byte_test; /**< Byte order test 87654321h (offset 0x64) */ + volatile uint32_t fifo_level_irq; /**< FIFO Level Interrupts (offset 0x68) */ + volatile uint32_t rx_cfg; /**< Receive Configuration (offset 0x6C) */ + volatile uint32_t tx_cfg; /**< Transmit Configuration (offset 0x70) */ + volatile uint32_t hw_cfg; /**< Hardware Configuration (offset 0x74) */ + volatile uint32_t rx_datapath_ctrl; /**< RX Datapath Control (offset 0x78) */ + volatile uint32_t rx_fifo_inf; /**< Receive FIFO Information (offset 0x7C) */ + volatile uint32_t tx_fifo_inf; /**< Transmit FIFO Information (offset 0x80) */ + volatile uint32_t pmt_ctrl; /**< Power Management Control (offset 0x84) */ + volatile uint32_t gpio_cfg; /**< GPIO Configuration (offset 0x88) */ + volatile uint32_t gptimer_cfg; /**< GP Timer Configuration (offset 0x8C) */ + volatile uint32_t gptimer_count; /**< GP Timer Count (offset 0x90) */ + uint32_t reserved4; /**< Reserved for future use (offset 0x94) */ + volatile uint32_t word_swap; /**< WORD SWAP Register (offset 0x98) */ + volatile uint32_t free_run_counter; /**< Free Run Counter (offset 0x9C) */ + volatile uint32_t rx_dropped_frames; /**< RX Dropped Frames Counter (offset 0xA0) */ + volatile uint32_t mac_csr_cmd; /**< MAC CSR Synchronizer Cmd (offset 0xA4) */ + volatile uint32_t mac_csr_data; /**< MAC CSR Synchronizer Data (offset 0xA8) */ + volatile uint32_t afc_cfg; /**< AutomaticFlow Ctrl Config (offset 0xAC) */ + volatile uint32_t eeprom_cmd; /**< EEPROM Command (offset 0xB0) */ + volatile uint32_t eeprom_data; /**< EEPROM Data (offset 0xB4) */ }; /** @@ -221,7 +221,7 @@ enum irq_cfg_bits_t { IRQ_CFG_IRQ_TYPE = 0U, IRQ_CFG_IRQ_POL = 4U, - IRQ_CFG_IRQ_EN_INDEX = 8U, + IRQ_CFG_IRQ_EN_INDEX = 8U }; #define IRQ_CFG_INT_DEAS_MASK 0xFFU @@ -886,6 +886,15 @@ void smsc9220_clear_interrupt( const struct smsc9220_eth_dev_t * dev, SET_BIT( register_map->irq_status, source ); } +uint32_t get_irq_status( const struct smsc9220_eth_dev_t * dev ) +{ + struct smsc9220_eth_reg_map_t * register_map = + ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; + + return register_map->irq_status; +} + + void smsc9220_clear_all_interrupts( const struct smsc9220_eth_dev_t * dev ) { struct smsc9220_eth_reg_map_t * register_map = @@ -1171,99 +1180,43 @@ uint32_t smsc9220_receive_by_chunks( const struct smsc9220_eth_dev_t * dev, char * data, uint32_t dlen ) { - uint32_t rxfifo_inf = 0; - uint32_t rxfifo_stat = 0; uint32_t packet_length_byte = 0; - struct smsc9220_eth_reg_map_t * register_map = - ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; if( !data ) { return 0; /* Invalid input parameter, cannot read */ } - rxfifo_inf = register_map->rx_fifo_inf; - - if( rxfifo_inf & 0xFFFF ) /* If there's data */ - { - rxfifo_stat = register_map->rx_status_port; - - if( rxfifo_stat != 0 ) /* Fetch status of this packet */ - { /* Ethernet controller is padding to 32bit aligned data */ - packet_length_byte = GET_BIT_FIELD( rxfifo_stat, - RX_FIFO_STATUS_PKT_LENGTH_MASK, - RX_FIFO_STATUS_PKT_LENGTH_POS ); - dev->data->current_rx_size_words = packet_length_byte; - } - } + packet_length_byte = dlen; /*_RB_ Hard set to length read from peek register. */ + dev->data->current_rx_size_words = packet_length_byte; empty_rx_fifo( dev, ( uint8_t * ) data, packet_length_byte ); dev->data->current_rx_size_words = 0; return packet_length_byte; } -/*! - * @brief second version to circumvent a bug - * in quemu where the peeked message - * size is different than the actual message size - */ -uint32_t smsc9220_receive_by_chunks2( const struct smsc9220_eth_dev_t * dev, - char * data, - uint32_t dlen ) -{ - uint32_t rxfifo_inf = 0; - uint32_t rxfifo_stat = 0; - /*uint32_t packet_length_byte = 0; */ - struct smsc9220_eth_reg_map_t * register_map = - ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; - - if( !data ) - { - return 0; /* Invalid input parameter, cannot read */ - } - - dev->data->current_rx_size_words = dlen; - - empty_rx_fifo( dev, ( uint8_t * ) data, dlen ); - dev->data->current_rx_size_words = 0; - return dlen; -} - -/*! - * @brief second version to circumvent a bug - * in quemu where the peeked message - * size is different than the actual message size - */ -uint32_t smsc9220_peek_next_packet_size2( const struct - smsc9220_eth_dev_t * dev ) -{ - uint32_t packet_size = 0; - struct smsc9220_eth_reg_map_t * register_map = - ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; - - if( smsc9220_get_rxfifo_data_used_space( dev ) ) - { - packet_size = GET_BIT_FIELD( register_map->rx_status_port, - RX_FIFO_STATUS_PKT_LENGTH_MASK, - RX_FIFO_STATUS_PKT_LENGTH_POS ); - } - - return packet_size; -} - uint32_t smsc9220_peek_next_packet_size( const struct smsc9220_eth_dev_t * dev ) { uint32_t packet_size = 0; struct smsc9220_eth_reg_map_t * register_map = ( struct smsc9220_eth_reg_map_t * ) dev->cfg->base; + volatile uint32_t rx_status_from_peek = 0; if( smsc9220_get_rxfifo_data_used_space( dev ) ) { - packet_size = GET_BIT_FIELD( register_map->rx_status_peek, + rx_status_from_peek = register_map->rx_status_peek; + /* Warning: try reading from port as peek is often zero. */ + rx_status_from_peek = register_map->rx_status_port; + + packet_size = GET_BIT_FIELD( rx_status_from_peek, RX_FIFO_STATUS_PKT_LENGTH_MASK, RX_FIFO_STATUS_PKT_LENGTH_POS ); } + else + { + rx_status_from_peek = -1; + } return packet_size; } diff --git a/test/build-combination/AllDisable/FreeRTOSIPConfig.h b/test/build-combination/AllDisable/FreeRTOSIPConfig.h index f2994e6441..88007df0ac 100644 --- a/test/build-combination/AllDisable/FreeRTOSIPConfig.h +++ b/test/build-combination/AllDisable/FreeRTOSIPConfig.h @@ -75,7 +75,7 @@ * a socket. */ #define ipconfigUSE_DNS_CACHE ( 0 ) -#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 6 ) +#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY ( 1 ) #define ipconfigDNS_REQUEST_ATTEMPTS ( 2 ) /* The IP stack executes it its own task (although any application task can make diff --git a/test/cbmc/proofs/DNS/DNSHandlePacket/DNShandlePacket_harness.c b/test/cbmc/proofs/DNS/DNSHandlePacket/DNShandlePacket_harness.c index f557c94198..36b19cfce7 100644 --- a/test/cbmc/proofs/DNS/DNSHandlePacket/DNShandlePacket_harness.c +++ b/test/cbmc/proofs/DNS/DNSHandlePacket/DNShandlePacket_harness.c @@ -15,18 +15,6 @@ uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer, { } -struct xDNSMessage -{ - uint16_t usIdentifier; - uint16_t usFlags; - uint16_t usQuestions; - uint16_t usAnswers; - uint16_t usAuthorityRRs; - uint16_t usAdditionalRRs; -}; - -typedef struct xDNSMessage DNSMessage_t; - void harness() { NetworkBufferDescriptor_t xNetworkBuffer; diff --git a/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c b/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c index d938bbeb94..446121eec8 100644 --- a/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c +++ b/test/cbmc/proofs/TCP/prvTCPReturnPacket/TCPReturnPacket_harness.c @@ -37,8 +37,9 @@ #include "../../utility/memory_assignments.c" -/* This proof assumes that pxDuplicateNetworkBufferWithDescriptor is implemented correctly. */ +#include "cbmc.h" +/* This proof assumes that pxDuplicateNetworkBufferWithDescriptor is implemented correctly. */ void publicTCPReturnPacket( FreeRTOS_Socket_t * pxSocket, NetworkBufferDescriptor_t * pxNetworkBuffer, uint32_t ulLen, @@ -59,12 +60,23 @@ NetworkBufferDescriptor_t * pxDuplicateNetworkBufferWithDescriptor( const Networ return pxNetworkBuffer; } +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * pxDescriptor, + BaseType_t xReleaseAfterSend ) +{ + BaseType_t xReturn; + + __CPROVER_assert( pxDescriptor != NULL, "The descriptor cannot be NULL" ); + __CPROVER_assert( pxDescriptor->pucEthernetBuffer != NULL, "The ethernet buffer cannot be NULL" ); + + return xReturn; +} + uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength, BaseType_t xOutgoingPacket ) { __CPROVER_assert( pucEthernetBuffer != NULL, "The ethernet buffer cannot be NULL" ); - __CPROVER_r_ok( pucEthernetBuffer, uxBufferLength ); + __CPROVER_assert( __CPROVER_r_ok( pucEthernetBuffer, uxBufferLength ), "pucEthernetBuffer should be readable." ); uint16_t usReturn; return usReturn; @@ -75,7 +87,7 @@ uint16_t usGenerateChecksum( uint16_t usSum, size_t uxByteCount ) { __CPROVER_assert( pucNextData != NULL, "The next data pointer cannot be NULL" ); - __CPROVER_r_ok( pucNextData, uxByteCount ); + __CPROVER_assert( __CPROVER_r_ok( pucNextData, uxByteCount ), "The pucNextData should be readable." ); uint16_t usReturn; return usReturn; @@ -86,16 +98,30 @@ void harness() FreeRTOS_Socket_t * pxSocket = ensure_FreeRTOS_Socket_t_is_allocated(); NetworkBufferDescriptor_t * pxNetworkBuffer = ensure_FreeRTOS_NetworkBuffer_is_allocated(); + /* The code does not expect both of these to be equal to NULL at the same time. */ + __CPROVER_assume( pxSocket != NULL || pxNetworkBuffer != NULL ); + + uint32_t ulLen; + + /* If network buffer is properly created. */ if( ensure_memory_is_valid( pxNetworkBuffer, sizeof( *pxNetworkBuffer ) ) ) { - pxNetworkBuffer->pucEthernetBuffer = safeMalloc( sizeof( TCPPacket_t ) ); + /* Assume that the length is proper. */ + __CPROVER_assume( ( ulLen >= sizeof( TCPPacket_t ) ) && ( ulLen < ipconfigNETWORK_MTU ) ); + pxNetworkBuffer->pucEthernetBuffer = safeMalloc( ulLen + ipSIZE_OF_ETH_HEADER ); __CPROVER_assume( pxNetworkBuffer->pucEthernetBuffer ); } + /* If not. */ + else + { + /* Assume that the length is proper. The length should be between this range. It + * is made so by the functions up the call tree. Essentially, this is equal to a + * TCP packet header with and without TCP options. */ + __CPROVER_assume( ( ulLen >= ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) && + ( ulLen <= ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 40 /* Maximum option bytes. */ ) ); + } - uint32_t ulLen; BaseType_t xReleaseAfterSend; - /* The code does not expect both of these to be equal to NULL at the same time. */ - __CPROVER_assume( pxSocket != NULL || pxNetworkBuffer != NULL ); publicTCPReturnPacket( pxSocket, pxNetworkBuffer, ulLen, xReleaseAfterSend ); } diff --git a/test/litani b/test/litani index 3fc5e02bc1..b652295078 160000 --- a/test/litani +++ b/test/litani @@ -1 +1 @@ -Subproject commit 3fc5e02bc17483352546ac4c81078fde64cab674 +Subproject commit b652295078e26f8444c72ee3088f6a1230624827 diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index ae48f7d3f3..2b2cbb7d27 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -1,13 +1,16 @@ -cmake_minimum_required ( VERSION 3.13.0 ) -project ( "FreeRTOS-Plus-TCP test" - VERSION 1.0.0 - LANGUAGES C ) +# Set the required version. +cmake_minimum_required( VERSION 3.13.0 ) + +# Set the unit-test project. +project( "FreeRTOS-Plus-TCP test" + VERSION 1.0.0 + LANGUAGES C ) # Allow the project to be organized into folders. set_property( GLOBAL PROPERTY USE_FOLDERS ON ) # Use C90. -set( CMAKE_C_STANDARD 90 ) +set( CMAKE_C_STANDARD 99 ) set( CMAKE_C_STANDARD_REQUIRED ON ) # Do not allow in-source build. @@ -16,8 +19,26 @@ if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} ) endif() # Set global path variables. -get_filename_component(__MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) -set(MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "FreeRTOS-Plus-TCP repository root.") +get_filename_component( __MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE ) +set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "FreeRTOS-Plus-TCP repository root." ) + +# Set the unit-test directory. +set( UNIT_TEST_DIR ${MODULE_ROOT_DIR}/test/unit-test CACHE INTERNAL "Unit-test directory." ) + +set( KERNEL_DIRECTORY ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel ) + +# See if FreRTOS-Kernel is submoduled +if( NOT EXISTS ${KERNEL_DIRECTORY}/include ) + # Inform the user of the actions + message( STATUS "FreeRTOS-Kernel is required for this build. Submoduling it..." ) + execute_process( COMMAND git submodule update --init --checkout ${KERNEL_DIRECTORY} + WORKING_DIRECTORY ${MODULE_ROOT_DIR} ) +endif() + +# Set the include directories +string( APPEND GLOBAL_INCLUDES "-I ${MODULE_ROOT_DIR}/include ") +string( APPEND GLOBAL_INCLUDES "-I ${UNIT_TEST_DIR}/ConfigFiles " ) +string( APPEND GLOBAL_INCLUDES "-I ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include " ) # Configure options to always show in CMake GUI. option( BUILD_CLONE_SUBMODULES @@ -29,17 +50,73 @@ set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) -# ===================================== Coverity Analysis Configuration ================================================= -# Include filepaths for source and include. -include( ${MODULE_ROOT_DIR}/test/unit-test/TCPFilePaths.cmake ) +# Set TCP includes. +set( TCP_INCLUDES "${MODULE_ROOT_DIR}/include/FreeRTOS_IP.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_ARP.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_Sockets.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_IP_Private.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_UDP_IP.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_DHCP.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_DNS.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_TCP_IP.h" + "${MODULE_ROOT_DIR}/include/FreeRTOS_TCP_WIN.h" + "${MODULE_ROOT_DIR}/include/NetworkBufferManagement.h" + "${MODULE_ROOT_DIR}/include/NetworkInterface.h" ) + +# Create a directory for the modified files +file( MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Annexed_TCP ) +# =========================================================================== + +# =========================================================================== +# Preprocess the TCP include files as they will be mocked later. +foreach( file ${TCP_INCLUDES} ) + get_filename_component( MODIFIED_FILE ${file} NAME_WLE ) + + string(TOUPPER ${MODIFIED_FILE} Guard) + + if(${MODIFIED_FILE} STREQUAL "NetworkBufferManagement" ) + set( Guard "NETWORK_BUFFER_MANAGEMENT_H" ) + else() + set( Guard ${Guard}_H ) + endif() + + # Remove IPConfigDefaults from the file + execute_process( COMMAND sed "s,#include \"FreeRTOSIPConfigDefaults.h\",,g" ${file} + OUTPUT_FILE ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}_tmp1.h ) + + # Add the FreeRTOSIPConfig file to each directory + execute_process( COMMAND sed "1 i\#include \"FreeRTOSIPConfig.h\"" ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}_tmp1.h + OUTPUT_FILE ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}_tmp.h ) -# Target for Coverity analysis that builds the library. -#add_library( coverity_analysis -# ${MQTT_SOURCES} -# ${MQTT_SERIALIZER_SOURCES} ) + # Use this tool to process all conditional declarations. + execute_process( COMMAND unifdefall -U${Guard} -I ${MODULE_ROOT_DIR}/tools/CMock/vendor/unity/src + -I ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include + -I ${UNIT_TEST_DIR}/ConfigFiles + -I ${MODULE_ROOT_DIR}/include + -I ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix + ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}_tmp.h + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + OUTPUT_FILE ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}.h + OUTPUT_QUIET ) -# ==================================== Test Configuration ======================================== + # Add the guards back to the files + execute_process( COMMAND sed -i "1 i\#ifndef ${Guard}" ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}.h ) + execute_process( COMMAND sed -i -e "$ a\#endif" ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}.h ) + + execute_process( COMMAND sed -i -E "s,[ ]*extern ipDECL_CAST_.*,,g" ${CMAKE_BINARY_DIR}/Annexed_TCP/${MODIFIED_FILE}.h ) + +endforeach() +# =========================================================================== + + + +# ===================================== Include the cmake configurations ================================================= + +# Include filepaths for source and include. +include( ${UNIT_TEST_DIR}/TCPFilePaths.cmake ) + +# ==================================== Test Configuration ======================================== # Define a CMock resource path. set( CMOCK_DIR ${MODULE_ROOT_DIR}/tools/CMock CACHE INTERNAL "CMock library source directory." ) @@ -71,15 +148,17 @@ add_cmock_targets() # Add function to enable CMock based tests and coverage. include( ${MODULE_ROOT_DIR}/test/unit-test/cmock/create_test.cmake ) +set(FILE_UNDER_TEST FreeRTOS_ARP) + # Include unit-test build configuration -include( unit_test_build.cmake ) +include( ${UNIT_TEST_DIR}/FreeRTOS_ARP/ut.cmake ) +include( ${UNIT_TEST_DIR}/FreeRTOS_DHCP/ut.cmake ) # ==================================== Coverage Analysis configuration ======================================== # Add a target for running coverage on tests. add_custom_target( coverage COMMAND ${CMAKE_COMMAND} -P ${MODULE_ROOT_DIR}/test/unit-test/cmock/coverage.cmake - DEPENDS cmock unity FreeRTOS_TCP_Unit_test + DEPENDS cmock unity FreeRTOS_ARP_utest FreeRTOS_DHCP_utest WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) - diff --git a/test/unit-test/ConfigFiles/FreeRTOSConfig.h b/test/unit-test/ConfigFiles/FreeRTOSConfig.h index 6c6e358e62..d9ce1a123f 100644 --- a/test/unit-test/ConfigFiles/FreeRTOSConfig.h +++ b/test/unit-test/ConfigFiles/FreeRTOSConfig.h @@ -29,7 +29,7 @@ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H -#include +#include /*----------------------------------------------------------- * Application specific definitions. @@ -77,11 +77,8 @@ #define configMAX_PRIORITIES ( 7 ) /* Run time stats gathering configuration options. */ -unsigned long ulGetRunTimeCounterValue( void ); /* Prototype of function that returns run time counter. */ -void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that initialises the run time counter. */ -#define configGENERATE_RUN_TIME_STATS 1 -#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() -#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() + +#define configGENERATE_RUN_TIME_STATS 1 /* Co-routine related configuration options. */ #define configUSE_CO_ROUTINES 1 @@ -117,7 +114,7 @@ void vConfigureTimerForRunTimeStats( void ); /* Prototype of function that in * uses the same semantics as the standard C assert() macro. */ extern void vAssertCalled( unsigned long ulLine, const char * const pcFileName ); -#define configASSERT( x ) if( x == 0 ) TEST_ABORT() +#define configASSERT( x ) assert( x ) #define configINCLUDE_MESSAGE_BUFFER_AMP_DEMO 0 #if ( configINCLUDE_MESSAGE_BUFFER_AMP_DEMO == 1 ) diff --git a/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h b/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h index ce2855fe8a..29a0960464 100644 --- a/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h +++ b/test/unit-test/ConfigFiles/FreeRTOSIPConfig.h @@ -32,13 +32,10 @@ #define _static -#define ipconfigUSE_ARP_REMOVE_ENTRY 1 -#define ipconfigUSE_ARP_REVERSED_LOOKUP 1 - /* Set to 1 to print out debug messages. If ipconfigHAS_DEBUG_PRINTF is set to * 1 then FreeRTOS_debug_printf should be defined to the function used to print * out the debugging messages. */ -#define ipconfigHAS_DEBUG_PRINTF 0 +#define ipconfigHAS_DEBUG_PRINTF 0 #if ( ipconfigHAS_DEBUG_PRINTF == 1 ) #define FreeRTOS_debug_printf( X ) configPRINTF( X ) #endif @@ -140,7 +137,7 @@ extern uint32_t ulRand(); /* If ipconfigDHCP_USES_USER_HOOK is set to 1 then the application writer must * provide an implementation of the DHCP callback function, * xApplicationDHCPUserHook(). */ -#define ipconfigUSE_DHCP_HOOK 0 +#define ipconfigUSE_DHCP_HOOK 1 /* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at * increasing time intervals until either a reply is received from a DHCP server @@ -300,11 +297,20 @@ extern uint32_t ulRand(); #define ipconfigSOCKET_HAS_USER_WAKE_CALLBACK ( 1 ) #define ipconfigUSE_CALLBACKS ( 0 ) +#define ipconfigUSE_NBNS ( 1 ) + +#define ipconfigUSE_LLMNR ( 1 ) + +#define ipconfigDNS_USE_CALLBACKS 1 +#define ipconfigUSE_ARP_REMOVE_ENTRY 1 +#define ipconfigUSE_ARP_REVERSED_LOOKUP 1 + +#define ipconfigETHERNET_MINIMUM_PACKET_BYTES ( 200 ) + +#define ipconfigARP_STORES_REMOTE_ADDRESSES ( 1 ) -#define portINLINE +#define ipconfigARP_USE_CLASH_DETECTION ( 1 ) -void vApplicationMQTTGetKeys( const char ** ppcRootCA, - const char ** ppcClientCert, - const char ** ppcClientPrivateKey ); +#define ipconfigDHCP_FALL_BACK_AUTO_IP ( 1 ) #endif /* FREERTOS_IP_CONFIG_H */ diff --git a/test/unit-test/ConfigFiles/FreeRTOSIPConfigDefaults.h b/test/unit-test/ConfigFiles/FreeRTOSIPConfigDefaults.h index cdd56deca3..1aa2e90426 100644 --- a/test/unit-test/ConfigFiles/FreeRTOSIPConfigDefaults.h +++ b/test/unit-test/ConfigFiles/FreeRTOSIPConfigDefaults.h @@ -350,11 +350,7 @@ * If no DHCP server responds, use "Auto-IP" : the * device will allocate a random LinkLayer IP address. */ - #define ipconfigDHCP_FALL_BACK_AUTO_IP ( 0 ) -#endif - -#if ( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 ) - #define ipconfigARP_USE_CLASH_DETECTION 1 + #define ipconfigDHCP_FALL_BACK_AUTO_IP ( 1 ) #endif #ifndef ipconfigARP_USE_CLASH_DETECTION diff --git a/test/unit-test/ConfigFiles/portmacro.h b/test/unit-test/ConfigFiles/portmacro.h deleted file mode 100644 index 8cae05cdf2..0000000000 --- a/test/unit-test/ConfigFiles/portmacro.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * FreeRTOS Kernel V10.3.0 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#ifndef PORTMACRO_H -#define PORTMACRO_H - -#include -#include - -/****************************************************************************** -* Defines -******************************************************************************/ -/* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE size_t -#define portBASE_TYPE long -#define portPOINTER_SIZE_TYPE size_t - -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - - -#if ( configUSE_16_BIT_TICKS == 1 ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff -#else - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL - -/* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick - * count do not need to be guarded with a critical section. */ - #define portTICK_TYPE_IS_ATOMIC 1 -#endif - -/* Hardware specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portINLINE - -#if defined( __x86_64__ ) || defined( _M_X64 ) - #define portBYTE_ALIGNMENT 8 -#else - #define portBYTE_ALIGNMENT 4 -#endif - -#define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD ) - - -extern volatile BaseType_t xInsideInterrupt; -#define portSOFTWARE_BARRIER() while( xInsideInterrupt != pdFALSE ) - - -/* Simulated interrupts return pdFALSE if no context switch should be performed, - * or a non-zero number if a context switch should be performed. */ -#define portYIELD_FROM_ISR( x ) ( void ) x -#define portEND_SWITCHING_ISR( x ) portYIELD_FROM_ISR( ( x ) ) - -void vPortCloseRunningThread( void * pvTaskToDelete, - volatile BaseType_t * pxPendYield ); -void vPortDeleteThread( void * pvThreadToDelete ); -#define portCLEAN_UP_TCB( pxTCB ) vPortDeleteThread( pxTCB ) -#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) ) -#define portDISABLE_INTERRUPTS() vPortEnterCritical() -#define portENABLE_INTERRUPTS() vPortExitCritical() - -/* Critical section handling. */ -void vPortEnterCritical( void ); -void vPortExitCritical( void ); - -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() - -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif - -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - -/* Check the configuration. */ - #if ( configMAX_PRIORITIES > 32 ) - #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. - #endif - -/* Store/clear the ready priorities in a bit map. */ - #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) - #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) - - -/*-----------------------------------------------------------*/ - - #ifdef __GNUC__ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ - __asm volatile ( "bsr %1, %0\n\t" \ - : "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" ) - #else - -/* BitScanReverse returns the bit position of the most significant '1' - * in the word. */ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) - #endif /* __GNUC__ */ - -#endif /* taskRECORD_READY_PRIORITY */ - -#ifndef __GNUC__ - __pragma( warning( disable: 4211 ) ) /* Nonstandard extension used, as extern is only nonstandard to MSVC. */ -#endif - - -/* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) - -#define portINTERRUPT_YIELD ( 0UL ) -#define portINTERRUPT_TICK ( 1UL ) - -/* - * Raise a simulated interrupt represented by the bit mask in ulInterruptMask. - * Each bit can be used to represent an individual interrupt - with the first - * two bits being used for the Yield and Tick interrupts respectively. - */ -void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ); - -/* - * Install an interrupt handler to be called by the simulated interrupt handler - * thread. The interrupt number must be above any used by the kernel itself - * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2 - * as defined above). The number must also be lower than 32. - * - * Interrupt handler functions must return a non-zero value if executing the - * handler resulted in a task switch being required. - */ -void vPortSetInterruptHandler( uint32_t ulInterruptNumber, - uint32_t ( * pvHandler )( void ) ); - -#endif /* ifndef PORTMACRO_H */ diff --git a/test/unit-test/stubs/FreeRTOS_ARP_stubs.c b/test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_stubs.c similarity index 55% rename from test/unit-test/stubs/FreeRTOS_ARP_stubs.c rename to test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_stubs.c index 032dcbbebb..ffe1041319 100644 --- a/test/unit-test/stubs/FreeRTOS_ARP_stubs.c +++ b/test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_stubs.c @@ -10,14 +10,72 @@ #include "list.h" #include "FreeRTOS_IP.h" +#include "FreeRTOS_IP_Private.h" volatile BaseType_t xInsideInterrupt = pdFALSE; +/** @brief The expected IP version and header length coded into the IP header itself. */ +#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 ) + +UDPPacketHeader_t xDefaultPartUDPPacketHeader = +{ + /* .ucBytes : */ + { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, /* Ethernet source MAC address. */ + 0x08, 0x00, /* Ethernet frame type. */ + ipIP_VERSION_AND_HEADER_LENGTH_BYTE, /* ucVersionHeaderLength. */ + 0x00, /* ucDifferentiatedServicesCode. */ + 0x00, 0x00, /* usLength. */ + 0x00, 0x00, /* usIdentification. */ + 0x00, 0x00, /* usFragmentOffset. */ + ipconfigUDP_TIME_TO_LIVE, /* ucTimeToLive */ + ipPROTOCOL_UDP, /* ucProtocol. */ + 0x00, 0x00, /* usHeaderChecksum. */ + 0x00, 0x00, 0x00, 0x00 /* Source IP address. */ + } +}; + +portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) +{ + return ( ARPPacket_t * ) pvArgument; +} + +portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPPacket_t ) +{ + return ( IPPacket_t * ) pvArgument; +} + +/** @brief For convenience, a MAC address of all 0xffs is defined const for quick + * reference. */ +const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; + +/** @brief Structure that stores the netmask, gateway address and DNS server addresses. */ +NetworkAddressingParameters_t xNetworkAddressing = +{ + 0xC0C0C0C0, /* 192.192.192.192 - Default IP address. */ + 0xFFFFFF00, /* 255.255.255.0 - Netmask. */ + 0xC0C0C001, /* 192.192.192.1 - Gateway Address. */ + 0x01020304, /* 1.2.3.4 - DNS server address. */ + 0xC0C0C0FF +}; /* 192.192.192.255 - Broadcast address. */ + size_t xPortGetMinimumEverFreeHeapSize( void ) { return 0; } + +BaseType_t xApplicationDNSQueryHook( const char * pcName ) +{ +} + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) +{ +} + const char * pcApplicationHostnameHook( void ) { } @@ -79,11 +137,6 @@ void vPortFree( void * pv ) free( pv ); } -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) -{ -} void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ) { } diff --git a/test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_utest.c b/test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_utest.c new file mode 100644 index 0000000000..91f4e247f5 --- /dev/null +++ b/test/unit-test/FreeRTOS_ARP/FreeRTOS_ARP_utest.c @@ -0,0 +1,1049 @@ +/* Include Unity header */ +#include "unity.h" + +/* Include standard libraries */ +#include +#include +#include + +#include "mock_FreeRTOS_IP.h" +#include "mock_FreeRTOS_IP_Private.h" +#include "mock_task.h" +#include "mock_NetworkBufferManagement.h" + +#include "FreeRTOS_ARP.h" + +#include "FreeRTOS_ARP_stubs.c" +#include "catch_assert.h" + +#include "FreeRTOSIPConfig.h" + +extern ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ]; + +void test_xCheckLoopback_IncorrectFrameType( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( IPPacket_t ) + ipBUFFER_PADDING ]; + BaseType_t xResult; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( IPPacket_t ); + + IPPacket_t * pxIPPacket = ( IPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); + + /* =================================================== */ + /* Let the frame-type be anything else than IPv4. */ + pxIPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE + 1; + /* bReleaseAfterSend parameter doesn't matter here. */ + xResult = xCheckLoopback( pxNetworkBuffer, pdFALSE ); + TEST_ASSERT_EQUAL( pdFALSE, xResult ); + /* =================================================== */ +} + +void test_xCheckLoopback_IncorrectMACAddress( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( IPPacket_t ) + ipBUFFER_PADDING ]; + BaseType_t xResult; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( IPPacket_t ); + + IPPacket_t * pxIPPacket = ( IPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); + + /* =================================================== */ + /* Let the frame-type be IPv4. */ + pxIPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE; + /* But let the MAC address be different. */ + memset( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, 0xAA, ipMAC_ADDRESS_LENGTH_BYTES ); + /* bReleaseAfterSend parameter doesn't matter here. */ + xResult = xCheckLoopback( pxNetworkBuffer, pdFALSE ); + TEST_ASSERT_EQUAL( pdFALSE, xResult ); + /* =================================================== */ +} + +void test_xCheckLoopback_HappyCase( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( IPPacket_t ) + ipBUFFER_PADDING ]; + BaseType_t xResult; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( IPPacket_t ); + + IPPacket_t * pxIPPacket = ( IPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); + + /* =================================================== */ + /* Let the frame-type be IPv4. */ + pxIPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE; + /* Make the MAC address same. */ + memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ); + pxDuplicateNetworkBufferWithDescriptor_ExpectAndReturn( pxNetworkBuffer, pxNetworkBuffer->xDataLength, pxNetworkBuffer ); + xSendEventStructToIPTask_IgnoreAndReturn( pdTRUE ); + + xResult = xCheckLoopback( pxNetworkBuffer, pdFALSE ); + TEST_ASSERT_EQUAL( pdTRUE, xResult ); + /* =================================================== */ +} + +void test_xCheckLoopback_DuplicationFails( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( IPPacket_t ) + ipBUFFER_PADDING ]; + BaseType_t xResult; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( IPPacket_t ); + + IPPacket_t * pxIPPacket = ( IPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); + + /* =================================================== */ + /* Let the frame-type be IPv4. */ + pxIPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE; + /* Make the MAC address same. */ + memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ); + /* Make buffer duplication fail. */ + pxDuplicateNetworkBufferWithDescriptor_ExpectAndReturn( pxNetworkBuffer, pxNetworkBuffer->xDataLength, NULL ); + xResult = xCheckLoopback( pxNetworkBuffer, pdFALSE ); + TEST_ASSERT_EQUAL( pdTRUE, xResult ); + /* =================================================== */ +} + + +void test_xCheckLoopback_SendEventToIPTaskFails( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( IPPacket_t ) + ipBUFFER_PADDING ]; + BaseType_t xResult; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( IPPacket_t ); + + IPPacket_t * pxIPPacket = ( IPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer ); + + + /* =================================================== */ + /* Let the frame-type be IPv4. */ + pxIPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE; + /* Make the MAC address same. */ + memcpy( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ); + + xSendEventStructToIPTask_IgnoreAndReturn( pdFALSE ); + vReleaseNetworkBufferAndDescriptor_Expect( pxNetworkBuffer ); + + xResult = xCheckLoopback( pxNetworkBuffer, pdTRUE ); + TEST_ASSERT_EQUAL( pdTRUE, xResult ); + /* =================================================== */ +} + + +void test_eARPProcessPacket_LocalIPisZero( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* When the local IP address is 0, we should not process any ARP Packets. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0UL; + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); + /* =================================================== */ +} + +void test_eARPProcessPacket_InvalidOperation( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* What is some invalid option is sent in the ARP Packet? */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Add invalid operation */ + xARPFrame.xARPHeader.usOperation = ipARP_REQUEST | ipARP_REPLY; + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); +} + +void test_eARPProcessPacket_Request_DifferentIP( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* Process an ARP request, but not meant for this node. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Fill in the request option. */ + xARPFrame.xARPHeader.usOperation = ipARP_REQUEST; + xARPFrame.xARPHeader.ulTargetProtocolAddress = *ipLOCAL_IP_ADDRESS_POINTER + 0x11; + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); + /* =================================================== */ +} + +void test_eARPProcessPacket_Request_SenderAndTargetDifferent( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* Process an ARP request - meant for this node with target and source different. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Fill in the request option. */ + xARPFrame.xARPHeader.usOperation = ipARP_REQUEST; + xARPFrame.xARPHeader.ulTargetProtocolAddress = *ipLOCAL_IP_ADDRESS_POINTER; + memcpy( xARPFrame.xARPHeader.ucSenderProtocolAddress, &( xARPFrame.xARPHeader.ulTargetProtocolAddress ), sizeof( xARPFrame.xARPHeader.ulTargetProtocolAddress ) ); + /* Make sure the the destination and source IP addresses are different. */ + xARPFrame.xARPHeader.ucSenderProtocolAddress[ 0 ]++; + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReturnEthernetFrame, eResult ); + /* =================================================== */ +} + +void test_eARPProcessPacket_Request_SenderAndTargetSame( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* Process an ARP request - meant for this node with target and source same. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Fill in the request option. */ + xARPFrame.xARPHeader.usOperation = ipARP_REQUEST; + xARPFrame.xARPHeader.ulTargetProtocolAddress = *ipLOCAL_IP_ADDRESS_POINTER; + memcpy( xARPFrame.xARPHeader.ucSenderProtocolAddress, &( xARPFrame.xARPHeader.ulTargetProtocolAddress ), sizeof( xARPFrame.xARPHeader.ulTargetProtocolAddress ) ); + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReturnEthernetFrame, eResult ); + /* =================================================== */ +} + +void test_eARPProcessPacket_Reply_SenderAndTargetSame( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* Process an ARP reply - meant for this node with target and source same. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Fill in the request option. */ + xARPFrame.xARPHeader.usOperation = ipARP_REPLY; + xARPFrame.xARPHeader.ulTargetProtocolAddress = 0xAABBCCDD; + memcpy( xARPFrame.xARPHeader.ucSenderProtocolAddress, &( xARPFrame.xARPHeader.ulTargetProtocolAddress ), sizeof( xARPFrame.xARPHeader.ulTargetProtocolAddress ) ); + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); + /* =================================================== */ +} + +void test_eARPProcessPacket_Reply_DifferentIP( void ) +{ + ARPPacket_t xARPFrame; + eFrameProcessingResult_t eResult; + + /* =================================================== */ + /* Process an ARP reply - not meant for this node. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCDD; + /* Fill in the request option. */ + xARPFrame.xARPHeader.usOperation = ipARP_REPLY; + xARPFrame.xARPHeader.ulTargetProtocolAddress = *ipLOCAL_IP_ADDRESS_POINTER + 0x11; + memcpy( xARPFrame.xARPHeader.ucSenderProtocolAddress, &( xARPFrame.xARPHeader.ulTargetProtocolAddress ), sizeof( xARPFrame.xARPHeader.ulTargetProtocolAddress ) ); + eResult = eARPProcessPacket( &xARPFrame ); + TEST_ASSERT_EQUAL( eReleaseBuffer, eResult ); + /* =================================================== */ +} + +void test_ulARPRemoveCacheEntryByMac_NoMatch( void ) +{ + uint32_t ulResult; + const MACAddress_t xMACAddress = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; + int i; + BaseType_t xEntryToCheck; + uint8_t ucBuffer[ sizeof( xARPCache[ 0 ] ) ]; + + /* Catch some asserts. */ + catch_assert( ulARPRemoveCacheEntryByMac( NULL ) ); + + /* =================================================== */ + /* Make sure no entry matches. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + } + + ulResult = ulARPRemoveCacheEntryByMac( &xMACAddress ); + TEST_ASSERT_EQUAL( 0, ulResult ); + /* =================================================== */ +} + +void test_ulARPRemoveCacheEntryByMac_OneMatchingEntry( void ) +{ + uint32_t ulResult; + const MACAddress_t xMACAddress = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; + int i; + BaseType_t xEntryToCheck; + uint8_t ucBuffer[ sizeof( xARPCache[ 0 ] ) ]; + + /* =================================================== */ + /* Make sure only one entry matches. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + } + + xEntryToCheck = 1; + xARPCache[ xEntryToCheck ].ulIPAddress = 0xAABBCCEE; + memset( xARPCache[ xEntryToCheck ].xMACAddress.ucBytes, 0xAA, sizeof( xMACAddress.ucBytes ) ); + memset( ucBuffer, 0, sizeof( xARPCache[ 0 ] ) ); + ulResult = ulARPRemoveCacheEntryByMac( &xMACAddress ); + TEST_ASSERT_EQUAL( 0xAABBCCEE, ulResult ); + TEST_ASSERT_EQUAL( 0, memcmp( ucBuffer, &xARPCache[ xEntryToCheck ], sizeof( xARPCache[ 0 ] ) ) ); +} + +void test_vARPRefreshCacheEntry_NULLMAC_NoMatchingEntry( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = 255; + xARPCache[ i ].ucValid = pdTRUE; + } + + ulIPAddress = 0x00; + /* Pass a NULL MAC Address and an IP address which will not match. */ + vARPRefreshCacheEntry( NULL, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL( xARPCache[ 0 ].ucAge, ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS ); + TEST_ASSERT_EQUAL( xARPCache[ 0 ].ucValid, ( uint8_t ) pdFALSE ); + /* =================================================== */ +} + +void test_vARPRefreshCacheEntry_NULLMAC_MatchingEntry( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + /* =================================================== */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = 255; + xARPCache[ i ].ucValid = pdTRUE; + } + + xARPCache[ 1 ].ulIPAddress = 0xAABBCCEE; + + ulIPAddress = 0xAABBCCEE; + /* Pass a NULL MAC Address and an IP address which will match. */ + vARPRefreshCacheEntry( NULL, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL( xARPCache[ 1 ].ucAge, 255 ); + TEST_ASSERT_EQUAL( xARPCache[ 1 ].ucValid, ( uint8_t ) pdTRUE ); + /* =================================================== */ +} + +void test_vARPRefreshCacheEntry_MACWontMatch_IPWillMatch( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + /* =================================================== */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = 255; + xARPCache[ i ].ucValid = pdTRUE; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x34, sizeof( xMACAddress.ucBytes ) ); + } + + xUseEntry = 1; + xARPCache[ xUseEntry ].ulIPAddress = 0xAABBCCEE; + + ulIPAddress = 0xAABBCCEE; + memset( xMACAddress.ucBytes, 0x11, ipMAC_ADDRESS_LENGTH_BYTES ); + /* Pass a MAC Address which won't match and an IP address which will match. */ + vARPRefreshCacheEntry( &xMACAddress, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL_MESSAGE( ipconfigMAX_ARP_AGE, xARPCache[ xUseEntry ].ucAge, "Test 3" ); + TEST_ASSERT_EQUAL( ( uint8_t ) pdTRUE, xARPCache[ xUseEntry ].ucValid ); + TEST_ASSERT_EQUAL_MEMORY( xMACAddress.ucBytes, xARPCache[ xUseEntry ].xMACAddress.ucBytes, sizeof( xMACAddress.ucBytes ) ); + /* =================================================== */ +} + +void test_vARPRefreshCacheEntry_MACAndIPWillMatch( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + /* =================================================== */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = 255; + xARPCache[ i ].ucValid = pdFALSE; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x34, sizeof( xMACAddress.ucBytes ) ); + } + + xUseEntry = 1; + xARPCache[ xUseEntry ].ulIPAddress = 0xAABBCCEE; + /* Set a MAC address which will match */ + memset( xARPCache[ xUseEntry ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + + ulIPAddress = 0xAABBCCEE; + memset( xMACAddress.ucBytes, 0x11, ipMAC_ADDRESS_LENGTH_BYTES ); + /* Pass a MAC Address which will match and an IP address which will match too. */ + vARPRefreshCacheEntry( &xMACAddress, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL_MESSAGE( ipconfigMAX_ARP_AGE, xARPCache[ xUseEntry ].ucAge, "Test 4" ); + TEST_ASSERT_EQUAL( ( uint8_t ) pdTRUE, xARPCache[ xUseEntry ].ucValid ); + TEST_ASSERT_EQUAL_MEMORY( xMACAddress.ucBytes, xARPCache[ xUseEntry ].xMACAddress.ucBytes, sizeof( xMACAddress.ucBytes ) ); + /* =================================================== */ +} + + +void test_vARPRefreshCacheEntry_IPOnADifferentSubnet( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + /* =================================================== */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = 255; + xARPCache[ i ].ucValid = pdFALSE; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x34, sizeof( xMACAddress.ucBytes ) ); + } + + xUseEntry = 1; + xARPCache[ xUseEntry ].ulIPAddress = 0xAABBCCEE; + /* Set a MAC address which will match */ + memset( xARPCache[ xUseEntry ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + /* Set a local IP address */ + *ipLOCAL_IP_ADDRESS_POINTER = 0xAABBCCEF; + + /* The IP address being passed should not be on the same subnet. */ + ulIPAddress = 0x00BBCCEE; + memset( xMACAddress.ucBytes, 0x11, ipMAC_ADDRESS_LENGTH_BYTES ); + /* Pass a MAC Address which will match and an IP address which will match too. */ + vARPRefreshCacheEntry( &xMACAddress, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL_MESSAGE( ipconfigMAX_ARP_AGE, xARPCache[ 0 ].ucAge, "Test 5" ); + TEST_ASSERT_EQUAL( ( uint8_t ) pdTRUE, xARPCache[ 0 ].ucValid ); + TEST_ASSERT_EQUAL_MEMORY( xMACAddress.ucBytes, xARPCache[ 0 ].xMACAddress.ucBytes, sizeof( xMACAddress.ucBytes ) ); + /* =================================================== */ +} + +void test_vARPRefreshCacheEntry_IPAndMACInDifferentLocations( void ) +{ + MACAddress_t xMACAddress; + uint32_t ulIPAddress; + int i; + BaseType_t xUseEntry; + + /* =================================================== */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + xARPCache[ i ].ucAge = i + 1; + xARPCache[ i ].ucValid = pdFALSE; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x34, sizeof( xMACAddress.ucBytes ) ); + } + + xUseEntry = 0; + + /* Make sure an entry matches. */ + xARPCache[ xUseEntry ].ulIPAddress = 0xAABBCCEE; + ulIPAddress = 0xAABBCCEE; + + /* Also make sure that a MAC address matches. But a different one. */ + memset( xARPCache[ xUseEntry + 1 ].xMACAddress.ucBytes, 0x22, sizeof( xMACAddress.ucBytes ) ); + memset( xMACAddress.ucBytes, 0x22, ipMAC_ADDRESS_LENGTH_BYTES ); + + /* Pass a MAC and IP Address which won't match, but age is now a factor. */ + vARPRefreshCacheEntry( &xMACAddress, ulIPAddress ); + + /* Since no matching entry will be found with smallest age (i.e. oldest), 0th entry will be updated to have the below details. */ + TEST_ASSERT_EQUAL( xARPCache[ xUseEntry + 1 ].ulIPAddress, ulIPAddress ); + TEST_ASSERT_EQUAL_MESSAGE( ipconfigMAX_ARP_AGE, xARPCache[ xUseEntry + 1 ].ucAge, "Test 9" ); + TEST_ASSERT_EQUAL( ( uint8_t ) pdTRUE, xARPCache[ xUseEntry + 1 ].ucValid ); + + uint8_t MemoryCompare[ sizeof( ARPCacheRow_t ) ]; + memset( MemoryCompare, 0, sizeof( ARPCacheRow_t ) ); + TEST_ASSERT_EQUAL_MEMORY( MemoryCompare, &xARPCache[ xUseEntry ], sizeof( ARPCacheRow_t ) ); + /* =================================================== */ +} + +void test_eARPGetCacheEntryByMac_NoMatchingEntries( void ) +{ + uint32_t ulIPAddress = 0x12345678, ulEntryToTest; + eARPLookupResult_t eResult; + MACAddress_t xMACAddress = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }; + int i; + + /* Hit some asserts */ + catch_assert( eARPGetCacheEntryByMac( NULL, &ulIPAddress ) ); + catch_assert( eARPGetCacheEntryByMac( &xMACAddress, NULL ) ); + + /* =================================================== */ + /* Make sure no entry matches. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + } + + eResult = eARPGetCacheEntryByMac( &xMACAddress, &ulIPAddress ); + TEST_ASSERT_EQUAL( eARPCacheMiss, eResult ); + TEST_ASSERT_EQUAL( 0x12345678, ulIPAddress ); + /* =================================================== */ +} + +void test_eARPGetCacheEntryByMac_OneMatchingEntry( void ) +{ + uint32_t ulIPAddress = 0x12345678, ulEntryToTest; + eARPLookupResult_t eResult; + MACAddress_t xMACAddress = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }; + int i; + + /* =================================================== */ + /* Make sure one entry matches. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAABBCCDD; + memset( xARPCache[ i ].xMACAddress.ucBytes, 0x11, sizeof( xMACAddress.ucBytes ) ); + } + + ulEntryToTest = 1; + memset( xARPCache[ ulEntryToTest ].xMACAddress.ucBytes, 0x22, sizeof( xMACAddress.ucBytes ) ); + xARPCache[ ulEntryToTest ].ulIPAddress = 0xAABBCCEE; + eResult = eARPGetCacheEntryByMac( &xMACAddress, &ulIPAddress ); + TEST_ASSERT_EQUAL( eARPCacheHit, eResult ); + TEST_ASSERT_EQUAL( xARPCache[ ulEntryToTest ].ulIPAddress, ulIPAddress ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_IPMatchesBroadcastAddr( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + ulIPAddress = xNetworkAddressing.ulBroadcastAddress; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eARPCacheHit, eResult, "Test 3" ); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE( &xBroadcastMACAddress, &xMACAddress, sizeof( xMACAddress ), "Test 3" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_IPMatchesOtherBroadcastAddr( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + ulIPAddress = ipBROADCAST_IP_ADDRESS; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eARPCacheHit, eResult, "Test 3" ); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE( &xBroadcastMACAddress, &xMACAddress, sizeof( xMACAddress ), "Test 3" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_LocalIPIsZero( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + ulIPAddress = 0x1234; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eCantSendPacket, eResult, "Test 4" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_LocalIPMatchesReceivedIP( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x1234; + ulIPAddress = *ipLOCAL_IP_ADDRESS_POINTER; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eARPCacheHit, eResult, "Test 5" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_MatchingInvalidEntry( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + ulIPAddress = 0x4321; + /* Make both values (IP address and local IP pointer) different. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x1234; + /* Add the IP address in the cache so that we'll have a cache hit. */ + xARPCache[ 1 ].ulIPAddress = xNetworkAddressing.ulGatewayAddress; + /* But reset the valid bit. */ + xARPCache[ 1 ].ucValid = pdFALSE; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eCantSendPacket, eResult, "Test 6" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_MatchingValidEntry( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + ulIPAddress = 0x4321; + /* Make both values (IP address and local IP pointer) different. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x1234; + /* Add the IP address in the cache so that we'll have a cache hit. */ + xARPCache[ 1 ].ulIPAddress = xNetworkAddressing.ulGatewayAddress; + /* Now try with a set valid bit. */ + xARPCache[ 1 ].ucValid = pdTRUE; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eARPCacheHit, eResult, "Test 7" ); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE( &xARPCache[ 1 ].xMACAddress, &xMACAddress, sizeof( xMACAddress ), "Test 7" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_GatewayAddressZero( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + for( int i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ucValid = ( uint8_t ) pdFALSE; + } + + ulSavedGatewayAddress = xNetworkAddressing.ulGatewayAddress; + xNetworkAddressing.ulGatewayAddress = 0; + ulIPAddress = 0x4321; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + xNetworkAddressing.ulGatewayAddress = ulSavedGatewayAddress; + TEST_ASSERT_EQUAL_MESSAGE( eARPCacheMiss, eResult, "Test 9" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_AddressNotOnLocalAddress( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + ulIPAddress = 0; + /* Make both values (IP address and local IP pointer) different. */ + /* Get any address on the same netmask. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x00000034; + + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + TEST_ASSERT_EQUAL_MESSAGE( eCantSendPacket, eResult, "Test 11" ); + /* =================================================== */ +} + +void test_eARPGetCacheEntry_NoCacheHit( void ) +{ + uint32_t ulIPAddress; + MACAddress_t xMACAddress; + eARPLookupResult_t eResult; + uint32_t ulSavedGatewayAddress; + + /* =================================================== */ + for( int i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0; + xARPCache[ i ].ucValid = ( uint8_t ) pdTRUE; + } + + ulSavedGatewayAddress = xNetworkAddressing.ulGatewayAddress; + xNetworkAddressing.ulGatewayAddress = 0; + /* Make IP address param == 0 */ + ulIPAddress = 0; + + /* Make both values (IP address and local IP pointer) different + * and on different net masks. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x1234; + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + eResult = eARPGetCacheEntry( &ulIPAddress, &xMACAddress ); + xNetworkAddressing.ulGatewayAddress = ulSavedGatewayAddress; + TEST_ASSERT_EQUAL( eARPCacheHit, eResult ); + /* =================================================== */ +} + +void test_vARPAgeCache( void ) +{ + /* Invalidate the first cache entry. */ + for( int i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ucAge = 0; + } + + uint8_t ucEntryToCheck = 1; + + /* =================================================== */ + /* Make second entry invalid but with age > 1. */ + xARPCache[ ucEntryToCheck ].ucAge = 1; + xARPCache[ ucEntryToCheck ].ucValid = pdFALSE; + /* Set an IP address */ + xARPCache[ ucEntryToCheck ].ulIPAddress = 0xAAAAAAAA; + + /* The function which calls 'pxGetNetworkBufferWithDescriptor' is 'FreeRTOS_OutputARPRequest'. + * It doesn't return anything and will be tested separately. */ + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + + /* Let the value returned first time be 100. */ + xTaskGetTickCount_IgnoreAndReturn( 100 ); + vARPAgeCache(); + /* =================================================== */ + + /* =================================================== */ + /* Make second entry invalid but with age > 1. */ + xARPCache[ ucEntryToCheck ].ucAge = 1; + xARPCache[ ucEntryToCheck ].ucValid = pdTRUE; + /* Set an IP address */ + xARPCache[ ucEntryToCheck ].ulIPAddress = 0xAAAAAAAA; + + /* The function which calls 'pxGetNetworkBufferWithDescriptor' is 'FreeRTOS_OutputARPRequest'. + * It doesn't return anything and will be tested separately. */ + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + + /* Let the value returned second time be 100. */ + xTaskGetTickCount_IgnoreAndReturn( 100 ); + vARPAgeCache(); + /* =================================================== */ + + /* =================================================== */ + /* Make second entry invalid but with age > 1. */ + xARPCache[ ucEntryToCheck ].ucAge = 100; + xARPCache[ ucEntryToCheck ].ucValid = pdTRUE; + /* Set an IP address */ + xARPCache[ ucEntryToCheck ].ulIPAddress = 0xAAAAAAAA; + + /* This time the pxGetNetworkBuffer will be called. */ + /* Let the value returned third time be 100000. */ + xTaskGetTickCount_IgnoreAndReturn( 100000 ); + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vARPAgeCache(); + /* =================================================== */ +} + +void test_vARPSendGratuitous( void ) +{ + /* The output is ignored. But we should check the input though. */ + xSendEventToIPTask_ExpectAndReturn( eARPTimerEvent, 0 ); + vARPSendGratuitous(); +} + +void test_FreeRTOS_OutputARPRequest( void ) +{ + uint8_t ucBuffer[ sizeof( ARPPacket_t ) + ipBUFFER_PADDING + ipconfigETHERNET_MINIMUM_PACKET_BYTES ]; + NetworkBufferDescriptor_t xNetworkBuffer; + uint32_t ulIPAddress = 0xAAAAAAAA; + + xNetworkBuffer.pucEthernetBuffer = ucBuffer; + xNetworkBuffer.xDataLength = sizeof( ARPPacket_t ); + + /* =================================================== */ + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, &xNetworkBuffer ); + xIsCallingFromIPTask_IgnoreAndReturn( pdTRUE ); + FreeRTOS_OutputARPRequest( ulIPAddress ); + /* =================================================== */ + + /* =================================================== */ + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, &xNetworkBuffer ); + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + xSendEventStructToIPTask_IgnoreAndReturn( pdFALSE ); + vReleaseNetworkBufferAndDescriptor_Expect( &xNetworkBuffer ); + FreeRTOS_OutputARPRequest( ulIPAddress ); + /* =================================================== */ + + /* =================================================== */ + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, &xNetworkBuffer ); + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + xSendEventStructToIPTask_IgnoreAndReturn( pdPASS ); + FreeRTOS_OutputARPRequest( ulIPAddress ); + /* =================================================== */ +} + + +void vStoreTimeValue( TimeOut_t * const timeout, + int32_t callbacks ) +{ + timeout->xOverflowCount = 0; + timeout->xTimeOnEntering = 100; +} + +void test_xARPWaitResolution_PrivateFunctionReturnsHit( void ) +{ + uint32_t ulIPAddress = 0xAAAAAAAA; + BaseType_t xResult; + int i; + + /* Catch the assertion for calling from IP task. */ + /* =================================================== */ + /* Assertion on calling from IP-task */ + xIsCallingFromIPTask_IgnoreAndReturn( pdTRUE ); + catch_assert( xARPWaitResolution( ulIPAddress, 0 ) ); + /* =================================================== */ + + + /* Make the resolution pass without any attempt by making + * eARPGetCacheEntry return eARPCacheHit. */ + /* =================================================== */ + /* Assertion on calling from IP-task */ + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 1UL ); + vSetMultiCastIPv4MacAddress_Ignore(); + xResult = xARPWaitResolution( ulIPAddress, 0 ); + TEST_ASSERT_EQUAL( xResult, 0 ); + /* =================================================== */ +} + +void test_xARPWaitResolution_GNWFailsNoTimeout( void ) +{ + uint32_t ulIPAddress = 0xAAAAAAAA; + BaseType_t xResult; + int i; + + /* Make the resolution fail with maximum tryouts. */ + /* =================================================== */ + /* Make sure that no address matches the IP address. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAAAAAAAA; + } + + ulIPAddress = 0x00000031; + /* Make both values (IP address and local IP pointer) different. */ + /* Get any address on the same netmask. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x00000034; + + /* Assertion on calling from IP-task */ + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + + vTaskSetTimeOutState_Stub( vStoreTimeValue ); + + /* Make sure that there are enough stubs for all the repetitive calls. */ + for( i = 0; i < ipconfigMAX_ARP_RETRANSMISSIONS; i++ ) + { + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vTaskDelay_Expect( pdMS_TO_TICKS( 250U ) ); + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + xTaskCheckForTimeOut_IgnoreAndReturn( pdFALSE ); + } + + xResult = xARPWaitResolution( ulIPAddress, 0 ); + TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EADDRNOTAVAIL, xResult ); + /* =================================================== */ +} + +void test_xARPWaitResolution( void ) +{ + uint32_t ulIPAddress = 0xAAAAAAAA; + BaseType_t xResult; + int i; + + /* Make the resolution fail after some attempts due to timeout. */ + /* =================================================== */ + /* Make sure that no address matches the IP address. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAAAAAAAA; + } + + ulIPAddress = 0x00000031; + /* Make both values (IP address and local IP pointer) different. */ + /* Get any address on the same netmask. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x00000034; + + /* Assertion on calling from IP-task */ + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + /* Make eARPGetCacheEntry return a cache miss. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + + vTaskSetTimeOutState_Stub( vStoreTimeValue ); + + /* Make sure that there are enough stubs for all the repetitive calls. */ + for( i = 0; i < ( ipconfigMAX_ARP_RETRANSMISSIONS - 1 ); i++ ) + { + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vTaskDelay_Expect( pdMS_TO_TICKS( 250U ) ); + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + xTaskCheckForTimeOut_IgnoreAndReturn( pdFALSE ); + } + + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vTaskDelay_Expect( pdMS_TO_TICKS( 250U ) ); + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + xTaskCheckForTimeOut_IgnoreAndReturn( pdTRUE ); + + xResult = xARPWaitResolution( ulIPAddress, 0 ); + TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EADDRNOTAVAIL, xResult ); + /* =================================================== */ + + /* Make the resolution pass after some attempts. */ + /* =================================================== */ + /* Make sure that no address matches the IP address. */ + for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) + { + xARPCache[ i ].ulIPAddress = 0xAAAAAAAA; + } + + ulIPAddress = 0x00000031; + /* Make both values (IP address and local IP pointer) different. */ + /* Get any address on the same netmask. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0x00000034; + + /* Assertion on calling from IP-task */ + xIsCallingFromIPTask_IgnoreAndReturn( pdFALSE ); + /* Not worried about what these functions do. */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + + vTaskSetTimeOutState_Stub( vStoreTimeValue ); + + /* Make sure that there are enough stubs for all the repetitive calls. */ + for( i = 0; i < ( ipconfigMAX_ARP_RETRANSMISSIONS - 2 ); i++ ) + { + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vTaskDelay_Expect( pdMS_TO_TICKS( 250U ) ); + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 0UL ); + xTaskCheckForTimeOut_IgnoreAndReturn( pdFALSE ); + } + + pxGetNetworkBufferWithDescriptor_ExpectAndReturn( sizeof( ARPPacket_t ), 0, NULL ); + vTaskDelay_Expect( pdMS_TO_TICKS( 250U ) ); + /* Make eARPGetCacheEntry succeed. That is - make it return eARPCacheHit */ + xIsIPv4Multicast_ExpectAndReturn( ulIPAddress, 1UL ); + vSetMultiCastIPv4MacAddress_Ignore(); + + /* Make sure that there is no timeout. */ + xTaskCheckForTimeOut_IgnoreAndReturn( pdFALSE ); + + xResult = xARPWaitResolution( ulIPAddress, 0 ); + TEST_ASSERT_EQUAL( 0, xResult ); + /* =================================================== */ +} + +void test_vARPGenerateRequestPacket( void ) +{ + NetworkBufferDescriptor_t xNetworkBuffer; + NetworkBufferDescriptor_t * const pxNetworkBuffer = &xNetworkBuffer; + uint8_t ucBuffer[ sizeof( ARPPacket_t ) + ipBUFFER_PADDING ]; + + pxNetworkBuffer->pucEthernetBuffer = ucBuffer; + pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t ); + + /* Catch some asserts. */ + catch_assert( vARPGenerateRequestPacket( NULL ) ); + + pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t ) - 10; + catch_assert( vARPGenerateRequestPacket( pxNetworkBuffer ) ); + + pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t ); + vARPGenerateRequestPacket( pxNetworkBuffer ); +} + + +void test_FreeRTOS_ClearARP( void ) +{ + uint8_t ucArray[ sizeof( xARPCache ) ]; + + memset( ucArray, 0, sizeof( xARPCache ) ); + + FreeRTOS_ClearARP(); + TEST_ASSERT_EQUAL_MEMORY( ucArray, xARPCache, sizeof( xARPCache ) ); +} + + + +void test_FreeRTOS_PrintARPCache( void ) +{ + int x; + + for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) + { + /* Anything except 0. */ + xARPCache[ x ].ulIPAddress = 0xAA; + /* Anything except 0. */ + xARPCache[ x ].ucAge = x; + } + + /* Nothing to actually unit-test here. */ + FreeRTOS_PrintARPCache(); + + for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) + { + /* Anything except 0. */ + xARPCache[ x ].ulIPAddress = 0x00; + /* Anything except 0. */ + xARPCache[ x ].ucAge = x; + } + + /* Nothing to actually unit-test here. */ + FreeRTOS_PrintARPCache(); +} diff --git a/test/unit-test/unit_test_build.cmake b/test/unit-test/FreeRTOS_ARP/ut.cmake similarity index 76% rename from test/unit-test/unit_test_build.cmake rename to test/unit-test/FreeRTOS_ARP/ut.cmake index 48cdc14720..ad39bf639f 100644 --- a/test/unit-test/unit_test_build.cmake +++ b/test/unit-test/FreeRTOS_ARP/ut.cmake @@ -2,19 +2,25 @@ include( ${MODULE_ROOT_DIR}/test/unit-test/TCPFilePaths.cmake ) # ==================== Define your project name (edit) ======================== -set(project_name "FreeRTOS_TCP_Unit") +message( STATUS "${FILE_UNDER_TEST}" ) + +set( project_name "FreeRTOS_ARP" ) # ===================== Create your mock here (edit) ======================== # list the files to mock here list(APPEND mock_list - "${MODULE_ROOT_DIR}/include/FreeRTOS_ARP.h" + "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/task.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Private.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/NetworkBufferManagement.h" ) # list the directories your mocks need list(APPEND mock_include_list . ${TCP_INCLUDE_DIRS} ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include + ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix ${MODULE_ROOT_DIR}/test/unit-test/ConfigFiles ) @@ -27,10 +33,7 @@ list(APPEND mock_define_list # list the files you would like to test here list(APPEND real_source_files - ${TCP_SOURCES} - ${KERNEL_SOURCES} - ${MODULE_ROOT_DIR}/test/unit-test/stubs/FreeRTOS_ARP_stubs.c - ${MODULE_ROOT_DIR}/portable/BufferManagement/BufferAllocation_2.c + ${MODULE_ROOT_DIR}/FreeRTOS_ARP.c ) # list the directories the module under test includes list(APPEND real_include_directories @@ -38,6 +41,7 @@ list(APPEND real_include_directories ${TCP_INCLUDE_DIRS} ${MODULE_ROOT_DIR}/test/unit-test/ConfigFiles ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include + ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix ${CMOCK_DIR}/vendor/unity/src ) @@ -46,6 +50,7 @@ list(APPEND real_include_directories # list the directories your test needs to include list(APPEND test_include_directories . + ${CMOCK_DIR}/vendor/unity/src ${TCP_INCLUDE_DIRS} ) @@ -76,8 +81,9 @@ list(APPEND utest_dep_list ${real_name} ) -set(utest_name "${project_name}_test") -set(utest_source "${project_name}_test.c") +set(utest_name "${project_name}_utest") +set(utest_source "${project_name}/${project_name}_utest.c") + create_test(${utest_name} ${utest_source} "${utest_link_list}" diff --git a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_mock.h b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_mock.h new file mode 100644 index 0000000000..9a5a05618f --- /dev/null +++ b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_mock.h @@ -0,0 +1,4 @@ +#include "FreeRTOS_DHCP.h" + +eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, + uint32_t ulIPAddress ); diff --git a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c new file mode 100644 index 0000000000..759ede2dd7 --- /dev/null +++ b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_stubs.c @@ -0,0 +1,180 @@ +/* Include Unity header */ +#include + +/* Include standard libraries */ +#include +#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "list.h" + +#include "FreeRTOS_IP.h" +#include "FreeRTOS_IP_Private.h" + +volatile BaseType_t xInsideInterrupt = pdFALSE; + +/** @brief The expected IP version and header length coded into the IP header itself. */ +#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 ) + +UDPPacketHeader_t xDefaultPartUDPPacketHeader = +{ + /* .ucBytes : */ + { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, /* Ethernet source MAC address. */ + 0x08, 0x00, /* Ethernet frame type. */ + ipIP_VERSION_AND_HEADER_LENGTH_BYTE, /* ucVersionHeaderLength. */ + 0x00, /* ucDifferentiatedServicesCode. */ + 0x00, 0x00, /* usLength. */ + 0x00, 0x00, /* usIdentification. */ + 0x00, 0x00, /* usFragmentOffset. */ + ipconfigUDP_TIME_TO_LIVE, /* ucTimeToLive */ + ipPROTOCOL_UDP, /* ucProtocol. */ + 0x00, 0x00, /* usHeaderChecksum. */ + 0x00, 0x00, 0x00, 0x00 /* Source IP address. */ + } +}; + + +/* + * IP-clash detection is currently only used internally. When DHCP doesn't respond, the + * driver can try out a random LinkLayer IP address (169.254.x.x). It will send out a + * gratuitous ARP message and, after a period of time, check the variables here below: + */ +#if ( ipconfigARP_USE_CLASH_DETECTION != 0 ) + /* Becomes non-zero if another device responded to a gratuitous ARP message. */ + BaseType_t xARPHadIPClash; + /* MAC-address of the other device containing the same IP-address. */ + MACAddress_t xARPClashMacAddress; +#endif /* ipconfigARP_USE_CLASH_DETECTION */ + + +portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( ARPPacket_t ) +{ + return ( ARPPacket_t * ) pvArgument; +} + +portINLINE ipDECL_CAST_PTR_FUNC_FOR_TYPE( IPPacket_t ) +{ + return ( IPPacket_t * ) pvArgument; +} + +/** @brief For convenience, a MAC address of all 0xffs is defined const for quick + * reference. */ +const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; + +/** @brief Structure that stores the netmask, gateway address and DNS server addresses. */ +NetworkAddressingParameters_t xNetworkAddressing = +{ + 0xC0C0C0C0, /* 192.192.192.192 - Default IP address. */ + 0xFFFFFF00, /* 255.255.255.0 - Netmask. */ + 0xC0C0C001, /* 192.192.192.1 - Gateway Address. */ + 0x01020304, /* 1.2.3.4 - DNS server address. */ + 0xC0C0C0FF +}; /* 192.192.192.255 - Broadcast address. */ + +/** @brief Structure that stores the netmask, gateway address and DNS server addresses. */ +NetworkAddressingParameters_t xDefaultAddressing = +{ + 0xC0C0C0C0, /* 192.192.192.192 - Default IP address. */ + 0xFFFFFF00, /* 255.255.255.0 - Netmask. */ + 0xC0C0C001, /* 192.192.192.1 - Gateway Address. */ + 0x01020304, /* 1.2.3.4 - DNS server address. */ + 0xC0C0C0FF +}; + +size_t xPortGetMinimumEverFreeHeapSize( void ) +{ + return 0; +} + + +BaseType_t xApplicationDNSQueryHook( const char * pcName ) +{ +} + +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) +{ +} + +uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress, + uint16_t usSourcePort, + uint32_t ulDestinationAddress, + uint16_t usDestinationPort ) +{ +} +BaseType_t xNetworkInterfaceInitialise( void ) +{ +} +void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ) +{ +} +void vApplicationDaemonTaskStartupHook( void ) +{ +} +void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, + StackType_t ** ppxTimerTaskStackBuffer, + uint32_t * pulTimerTaskStackSize ) +{ +} +void vPortDeleteThread( void * pvTaskToDelete ) +{ +} +void vApplicationIdleHook( void ) +{ +} +void vApplicationTickHook( void ) +{ +} +unsigned long ulGetRunTimeCounterValue( void ) +{ +} +void vPortEndScheduler( void ) +{ +} +BaseType_t xPortStartScheduler( void ) +{ +} +void vPortEnterCritical( void ) +{ +} +void vPortExitCritical( void ) +{ +} + +void * pvPortMalloc( size_t xWantedSize ) +{ + return malloc( xWantedSize ); +} + +void vPortFree( void * pv ) +{ + free( pv ); +} + +void vPortGenerateSimulatedInterrupt( uint32_t ulInterruptNumber ) +{ +} +void vPortCloseRunningThread( void * pvTaskToDelete, + volatile BaseType_t * pxPendYield ) +{ +} +void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, + StackType_t ** ppxIdleTaskStackBuffer, + uint32_t * pulIdleTaskStackSize ) +{ +} +void vConfigureTimerForRunTimeStats( void ) +{ +} + + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t bReleaseAfterSend ) +{ + return pdPASS; +} +/*-----------------------------------------------------------*/ diff --git a/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c new file mode 100644 index 0000000000..fdb2935b18 --- /dev/null +++ b/test/unit-test/FreeRTOS_DHCP/FreeRTOS_DHCP_utest.c @@ -0,0 +1,3672 @@ +/* Include Unity header */ +#include "unity.h" + +/* Include standard libraries */ +#include +#include +#include + +#include "mock_FreeRTOS_IP.h" +#include "mock_FreeRTOS_Sockets.h" +#include "mock_FreeRTOS_IP_Private.h" +#include "mock_FreeRTOS_UDP_IP.h" +#include "mock_FreeRTOS_ARP.h" +#include "mock_task.h" +#include "mock_NetworkBufferManagement.h" +#include "mock_FreeRTOS_DHCP_mock.h" + +#include "FreeRTOS_DHCP.h" + +#include "FreeRTOS_DHCP_stubs.c" +#include "catch_assert.h" + +#include "FreeRTOSIPConfig.h" + +extern Socket_t xDHCPSocket; +extern DHCPData_t xDHCPData; + +static const char * pcHostName = "Unit-Test"; + +static NetworkBufferDescriptor_t * pxGlobalNetworkBuffer[ 10 ]; +static uint8_t GlobalBufferCounter = 0; +static NetworkBufferDescriptor_t * GetNetworkBuffer( size_t SizeOfEthBuf, + long unsigned int xTimeToBlock, + int callbacks ) +{ + NetworkBufferDescriptor_t * pxNetworkBuffer = malloc( sizeof( NetworkBufferDescriptor_t ) ); + + pxNetworkBuffer->pucEthernetBuffer = malloc( SizeOfEthBuf ); + + /* Ignore the callback count. */ + ( void ) callbacks; + /* Ignore the timeout. */ + ( void ) xTimeToBlock; + + /* Set the global network buffer so that memory can be freed later on. */ + pxGlobalNetworkBuffer[ GlobalBufferCounter++ ] = pxNetworkBuffer; + + return pxNetworkBuffer; +} + +static void ReleaseNetworkBuffer( void ) +{ + /* Free the ethernet buffer. */ + free( pxGlobalNetworkBuffer[ --GlobalBufferCounter ]->pucEthernetBuffer ); + /* Free the network buffer. */ + free( pxGlobalNetworkBuffer[ GlobalBufferCounter ] ); +} + +static void ReleaseUDPBuffer( const void * temp, + int callbacks ) +{ + /* Should just call network buffer. */ + ReleaseNetworkBuffer(); +} + +#define xSizeofUDPBuffer 300 +static uint8_t pucUDPBuffer[ xSizeofUDPBuffer ]; + +static int32_t RecvFromStub( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + switch( callbacks ) + { + case 0: + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + break; + + case 1: + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + /* Put incorrect DHCP opcode. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE + 10; + break; + } + + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + return xSizeofUDPBuffer; +} + +static uint8_t DHCP_header[] = +{ + dhcpREPLY_OPCODE, /**< Operation Code: Specifies the general type of message. */ + 0x01, /**< Hardware type used on the local network. */ + 0x06, /**< Hardware Address Length: Specifies how long hardware + * addresses are in this message. */ + 0x02, /**< Hops. */ + 0x01, 0xAB, 0xCD, 0xEF, /**< A 32-bit identification field generated by the client, + * to allow it to match up the request with replies received + * from DHCP servers. */ + 0x01, /**< Number of seconds elapsed since a client began an attempt to acquire or renew a lease. */ + 0x00, /**< Just one bit used to indicate broadcast. */ + 0xC0, 0xA8, 0x00, 0x0A, /**< Client's IP address if it has one or 0 is put in this field. */ + 0x00, 0xAA, 0xAA, 0xAA, /**< The IP address that the server is assigning to the client. */ + 0x00, 0xAA, 0xAA, 0xAA, /**< The DHCP server address that the client should use. */ + 0x00, 0xAA, 0xAA, 0xAA /**< Gateway IP address in case the server client are on different subnets. */ +}; + +static uint8_t * ucGenericPtr; +static int32_t ulGenericLength; +static int32_t FreeRTOS_recvfrom_Generic( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = ucGenericPtr; + } + + return ulGenericLength; +} + +static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromLessBytesNoTimeout( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + + return sizeof( DHCPMessage_IPv4_t ) - 1; +} + +static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + + return xSizeofUDPBuffer; +} + +static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + + return xSizeofUDPBuffer; +} + +static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + /* Put incorrect DHCP opcode. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + + return xSizeofUDPBuffer; +} + +static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccessCorrectTxID( Socket_t xSocket, + void * pvBuffer, + size_t uxBufferLength, + BaseType_t xFlags, + struct freertos_sockaddr * pxSourceAddress, + socklen_t * pxSourceAddressLength, + int callbacks ) +{ + if( xFlags == FREERTOS_ZERO_COPY ) + { + *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; + } + + memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); + /* Put in correct DHCP cookie. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; + /* Put in correct DHCP opcode. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; + /* Put in correct DHCP Tx ID. */ + ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); + + return xSizeofUDPBuffer; +} + + +void test_xIsDHCPSocket( void ) +{ + BaseType_t xReturn; + struct xSOCKET xTestSocket; + + xDHCPSocket = &xTestSocket; + + /************************************/ + /* Test by NOT giving DHCP socket. */ + xReturn = xIsDHCPSocket( NULL ); + TEST_ASSERT_EQUAL( pdFALSE, xReturn ); + + /************************************/ + /* Test by giving DHCP socket. */ + xReturn = xIsDHCPSocket( xDHCPSocket ); + TEST_ASSERT_EQUAL( pdTRUE, xReturn ); +} + +void test_eGetDHCPState( void ) +{ + DHCPData_t xTestData; + eDHCPState_t eReturn; + int i; + + for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) + { + /* Modify the global state. */ + xDHCPData.eDHCPState = i; + eReturn = eGetDHCPState(); + TEST_ASSERT_EQUAL( i, eReturn ); + } +} + +void test_vDHCPProcess_NotResetAndIncorrectState( void ) +{ + xDHCPData.eDHCPState = eSendDHCPRequest; + /*vIPReloadDHCPTimer_Ignore(); */ + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* Since the expected state is incorrect, the state + * should remain the same. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_ResetAndIncorrectStateWithRNGFail( void ) +{ + xDHCPData.eDHCPState = eSendDHCPRequest; + /* Make random number generation fail. */ + xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdFALSE ); + vDHCPProcess( pdTRUE, eWaitingSendFirstDiscover ); + + /* Expected state is incorrect, but we are trying to reset + * the DHCP the state machine. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketCreationFail( void ) +{ + /* Test all the valid and invalid entries. */ + for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) + { + /* This should get assigned to a given value. */ + xDHCPSocket = NULL; + /* Put any state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + /* This should be reset to 0. */ + xDHCPData.xUseBroadcast = 1; + /* This should be reset as well */ + xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; + /* And this too. */ + xDHCPData.ulDHCPServerAddress = 0xABABABAB; + + + /* Make random number generation pass. */ + xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); + /* return an invalid socket. */ + FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, FREERTOS_INVALID_SOCKET ); + /* See if the timer is reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + /* Try all kinds of states. */ + vDHCPProcess( pdTRUE, i ); + + /* Expected state is incorrect, but we are trying to reset + * the DHCP the state machine. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); + /* This should be reset as well */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); + /* And this too. */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); + } +} + +void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketBindFail( void ) +{ + struct xSOCKET xTestSocket; + + /* Test all the valid and invalid entries. */ + for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) + { + /* This should get assigned to a given value. */ + xDHCPSocket = NULL; + /* Put any state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + /* This should be reset to 0. */ + xDHCPData.xUseBroadcast = 1; + /* This should be reset as well */ + xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; + /* And this too. */ + xDHCPData.ulDHCPServerAddress = 0xABABABAB; + + + /* Make random number generation pass. */ + xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); + /* Return a valid socket. */ + FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xTestSocket ); + /* Ignore the inputs to setting the socket options. */ + FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); + FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); + /* Make sure that binding fails. Return anything except zero. */ + vSocketBind_ExpectAnyArgsAndReturn( pdTRUE ); + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + /* See if the timer is reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + /* Try all kinds of states. */ + vDHCPProcess( pdTRUE, i ); + + /* Expected state is incorrect, but we are trying to reset + * the DHCP the state machine. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); + /* This should be reset as well */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); + /* And this too. */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); + } +} + +void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketSuccess( void ) +{ + struct xSOCKET xTestSocket; + + /* Test all the valid and invalid entries. */ + for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) + { + /* This should get assigned to a given value. */ + xDHCPSocket = NULL; + /* Put any state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + /* This should be reset to 0. */ + xDHCPData.xUseBroadcast = 1; + /* This should be reset as well */ + xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; + /* And this too. */ + xDHCPData.ulDHCPServerAddress = 0xABABABAB; + + + /* Make random number generation pass. */ + xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); + /* Return a valid socket. */ + FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xTestSocket ); + /* Ignore the inputs to setting the socket options. */ + FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); + FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); + /* Make sure that binding fails. Return anything except zero. */ + vSocketBind_ExpectAnyArgsAndReturn( 0 ); + /* See if the timer is reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + /* Try all kinds of states. */ + vDHCPProcess( pdTRUE, i ); + + /* Expected state is incorrect, but we are trying to reset + * the DHCP the state machine. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); + /* This should be reset as well */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); + /* And this too. */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); + } +} + +void test_vDHCPProcess_ResetAndIncorrectStateWithSocketAlreadyCreated( void ) +{ + struct xSOCKET xTestSocket; + + /* Test all the valid and invalid entries. */ + for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) + { + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put any state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + /* This should be reset to 0. */ + xDHCPData.xUseBroadcast = 1; + /* This should be reset as well */ + xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; + /* And this too. */ + xDHCPData.ulDHCPServerAddress = 0xABABABAB; + /* And this should be updated. */ + xDHCPData.xDHCPTxPeriod = 0; + + /* Make random number generation pass. */ + xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); + /* See if the timer is reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + /* Try all kinds of states. */ + vDHCPProcess( pdTRUE, i ); + + /* Expected state is incorrect, but we are trying to reset + * the DHCP the state machine. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( xDHCPSocket, &xTestSocket ); + TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); + /* This should be reset as well */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); + /* And this too. */ + TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); + /* This should be updated. */ + TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, xDHCPData.xDHCPTxPeriod ); + } +} + +void test_vDHCPProcess_CorrectStateDHCPHookFailsDHCPSocketNULL( void ) +{ + /* The DHCP socket is NULL. */ + xDHCPSocket = NULL; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Make sure that the local IP address is uninitialised. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + /* Put a verifiable value. */ + xNetworkAddressing.ulDefaultIPAddress = 0x12345678; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 2 ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + vIPNetworkUpCalls_Ignore(); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that we are not using leased address. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that the local IP address pointer indicates that. */ + TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookFailsDHCPSocketNonNULL( void ) +{ + struct xSOCKET xTestSocket; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Make sure that the local IP address is uninitialised. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + /* Put a verifiable value. */ + xNetworkAddressing.ulDefaultIPAddress = 0x12345678; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 2 ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + /* Ignore the call. */ + vIPNetworkUpCalls_Ignore(); + /* Expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that we are not using leased address. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that the local IP address pointer indicates that. */ + TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookDefaultReturn( void ) +{ + struct xSOCKET xTestSocket; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Make sure that the local IP address is uninitialised. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + /* Put a verifiable value. */ + memset( &xNetworkAddressing, 0xAA, sizeof( xNetworkAddressing ) ); + /* Put a verifiable value. */ + memset( &xDefaultAddressing, 0xBB, sizeof( xDefaultAddressing ) ); + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPUseDefaults ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + /* Ignore the call. */ + vIPNetworkUpCalls_Ignore(); + /* Expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that we are not using leased address. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that the network addressing struct is updated to show that. */ + TEST_ASSERT_EQUAL_MEMORY( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) ); + /* Make sure that the local IP address pointer indicates that. */ + TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); +} + +/* GNW = getNetworkBufferWithDescriptor */ +void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNotNULLButGNWFails( void ) +{ + struct xSOCKET xTestSocket; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); + xTaskGetTickCount_ExpectAndReturn( 100 ); + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning NULL will mean the prvSendDHCPDiscover fail. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we are not using leased address. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNULL( void ) +{ + /* This should remain unchanged. */ + xDHCPSocket = NULL; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + /* Ignore the call. */ + vIPNetworkUpCalls_Ignore(); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that we are not using leased address. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsNoBroadcast( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Not using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); + /* Return the time value. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Make the call to FreeRTOS_send fail. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); + /* Since the send failed, a call to release the buffer should be there. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + /* The time value should be as expected. */ + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsUseBroadCast( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Not using broadcast. */ + xDHCPData.xUseBroadcast = pdTRUE; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); + /* Return the time value. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Make the call to FreeRTOS_send fail. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); + /* Since the send failed, a call to release the buffer should be there. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); + /* The time value should be as expected. */ + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); +} + +void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendSucceedsUseBroadCast( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingSendFirstDiscover; + /* Using broadcast. */ + xDHCPData.xUseBroadcast = pdTRUE; + + /* Make sure that the user indicates anything else than the desired options. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); + /* Return the time value. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Make the call to FreeRTOS_send succeed. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + + vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); + /* The time value should be as expected. */ + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); + + /* Free the allocated memory. */ + ReleaseNetworkBuffer(); +} + +void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWFails( void ) +{ + struct xSOCKET xTestSocket; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Return NULL network buffer. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + vDHCPProcess( pdFALSE, eSendDHCPRequest ); + + /* DHCP socket should be NULL */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendFails( void ) +{ + struct xSOCKET xTestSocket; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Send fails. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); + /* ReleaseUDPPayloadBuffer will be called. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); + + vDHCPProcess( pdFALSE, eSendDHCPRequest ); + + /* DHCP socket should be still allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendSucceeds( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eSendDHCPRequest; + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Send succeeds. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + /* Return the time value. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + vDHCPProcess( pdFALSE, eSendDHCPRequest ); + + /* DHCP socket should be still allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); + TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, xDHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromFailsNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + xDHCPData.xDHCPTxPeriod = 100; + + /* Expect these arguments. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); + /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be still allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutGiveUp( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we exceed the period - and give up. */ + xDHCPData.xDHCPTxPeriod = ipconfigMAXIMUM_DISCOVER_TX_PERIOD; + + /* Expect these arguments. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); + /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + + /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference greater than the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + /* Time will be stored in DHCP state machine. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + /* Make all calls to the RNG succeed. */ + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + + + /* Closing the DHCP socket. */ + vSocketClose_ExpectAndReturn( xDHCPSocket, 0 ); + + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + + /* Ignore the call to this function. */ + vARPSendGratuitous_Ignore(); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eGetLinkLayerAddress, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGFail( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; + + /* Expect these arguments. Return a 0 to fail. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); + /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + + /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference greater than the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + /* Make all calls to the RNG fail. */ + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdFALSE ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); + /* make sure that the period is increased by a factor of two. */ + TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassUseBroadcast( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; + /* Using broadcast. */ + xDHCPData.xUseBroadcast = pdTRUE; + + /* Expect these arguments. Return a 0 to fail. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); + /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + + /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference greater than the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + /* Make all calls to the RNG succeed. */ + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Send succeeds. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); + /* make sure that the period is increased by a factor of two. */ + TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassNoBroadcast( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + + /* Expect these arguments. Return a 0 to fail. */ + FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); + /* Ignore the buffer argument though. */ + FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); + + /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference greater than the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + /* Make all calls to the RNG succeed. */ + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a NULL network buffer. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); + /* make sure that the period is increased by a factor of two. */ + TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + + + +void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which won't match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromLessBytesNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromLessBytesNoTimeout ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferRecvfromSuccessCorrectTxID( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccessCorrectTxID ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + + + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageWithoutOptionsNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + uint8_t DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageIncorrectOptionsNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 3U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Now add options which will be processed. */ + /* Add a closing flag at the end. */ + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageMissingLengthByteNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 1U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageIncorrectLengthByteNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add incorrect length. */ + DHCPOption[ 1 ] = 100; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageGetNACKNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_NACK; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageGetACKNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageOneOptionNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; + uint8_t DHCPMsg[ xTotalLength ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that we still in the state from where we started. */ + TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsSendFails( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + xDHCPData.ulOfferedIPAddress = DHCPServerAddress; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + /* Return continue. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPContinue ); + /* Make the hook return correct value. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning NULL will mean the prvSendDHCPRequest fails. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that sending failed. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsSendSucceeds( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + xDHCPData.ulOfferedIPAddress = DHCPServerAddress; + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + /* Return continue. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPContinue ); + /* Make the hook return correct value. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Make the call to FreeRTOS_send succeed. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* The state should indicate that sending failed. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); + /* The time should be updated. */ + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsDHCPHookReturnDefaultSendSucceeds( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + xDHCPData.ulOfferedIPAddress = DHCPServerAddress; + + /* Rest the network addressing values. */ + memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + /* Return continue. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPUseDefaults ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + vIPNetworkUpCalls_Ignore(); + /* Expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that sending failed. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( xDefaultAddressing ), sizeof( xNetworkAddressing ) ); +} + +void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsDHCPHookReturnErrorSendSucceeds( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + xDHCPData.ulOfferedIPAddress = DHCPServerAddress; + + /* Rest the network addressing values. */ + memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); + memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingOffer; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + /* Return continue. */ + xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 1 ); + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + vIPNetworkUpCalls_Ignore(); + /* Expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); + + vDHCPProcess( pdFALSE, eWaitingOffer ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* The state should indicate that sending failed. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); +} + + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerNoTimeout( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Rest the network addressing values. */ + memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); + memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put incorrect address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Still waiting on acknowledge. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); +} + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutGNBfails( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + /* Rest the network addressing values. */ + memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); + memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put incorrect address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + /* Return time second time which can be verified. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a NULL so that prvSendDHCPRequest fails. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Still waiting on acknowledge. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); + /* The time value should be stored in the state machine. */ + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); + TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); +} + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutGNBsucceeds( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put incorrect address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + /* Return time second time which can be verified. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Send succeeds. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Still waiting on acknowledge. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); +} + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutPeriodLess( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure we exceed the period - and thus, give up. */ + xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) + 1; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put incorrect address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Period exceeded. We should now be in initial state. */ + TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); + /* Period exceeded, should have initial value */ + TEST_ASSERT_EQUAL( 100, xDHCPData.xDHCPTxTime ); +} + + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsCorrectServerLeaseTimeZero( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + + /* Reset the lease time so that it will be set to default + * value later. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpDEFAULT_LEASE_TIME ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsCorrectServerLeaseTimeLessThanMinConfig( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + + /* Reset the lease time so that it will be set to minimum + * value later. */ + xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME - 10; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpMINIMUM_LEASE_TIME ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( dhcpMINIMUM_LEASE_TIME, xDHCPData.ulLeaseTime ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_TwoOptions_CorrectServer_AptLeaseTime( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time to an appropriate value. */ + xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME + 10; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( dhcpMINIMUM_LEASE_TIME + 10 ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( dhcpMINIMUM_LEASE_TIME + 10, xDHCPData.ulLeaseTime ); +} + +void test_vDHCPProcess_eWaitingAcknowledge_TwoOptions_NACK( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_NACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time to an appropriate value. */ + xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME + 10; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Should now be reset after NACK. */ + TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_AllOptionsCorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 6U /* DNS server */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + uint32_t ulDNSServer = 0xC0010101; /* 192.1.1.1 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_DNS_SERVER_OPTIONS_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulDNSServer; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ) ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ), xDHCPData.ulLeaseTime ); + TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulGatewayAddress, ulGateway ); + TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulNetMask, ulSubnetMask ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_DNSIncorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 6U /* DNS server */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + uint32_t ulDNSServer = 0xC0010101; /* 192.1.1.1 */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_DNS_SERVER_OPTIONS_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 3; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulDNSServer; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ) ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ), xDHCPData.ulLeaseTime ); + TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulGatewayAddress, ulGateway ); + TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulNetMask, ulSubnetMask ); +} + +void test_vDHCPProcess_eWaitingAcknowledge_IPv4ServerIncorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 3; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Ignore(); /*_Expect(configTICK_RATE_HZ*(FreeRTOS_ntohl(ulLeaseTime)>>1)); */ + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_SubnetMaskIncorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; + /* Add incorrect length. */ + DHCPOption[ 1 ] = 3; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Ignore(); /*_Expect(configTICK_RATE_HZ*(FreeRTOS_ntohl(ulLeaseTime)>>1)); */ + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); +} + +void test_vDHCPProcess_eWaitingAcknowledge_GatewayIncorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; + /* Add incorrect length. */ + DHCPOption[ 1 ] = 2; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Ignore(); /*_Expect(configTICK_RATE_HZ*(FreeRTOS_ntohl(ulLeaseTime)>>1)); */ + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_LeaseTimeIncorrectLength( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + + 3U /* DHCP offer */ + + 6U /* Server IP address */ + + 6U /* Subnet Mask */ + + 6U /* Gateway */ + + 6U /* Lease time */ + + 1U /* End */; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Leave one byte for the padding. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 1; + /* Add the offer byte. */ + DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; + + DHCPOption += 4; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 4; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; + + DHCPOption += 6; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; + /* Add incorrect length. */ + DHCPOption[ 1 ] = 3; + /* Add the offer byte. */ + *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; + + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Expect this function to be called since we now have + * successfully acquired an IP address. */ + vIPNetworkUpCalls_Expect(); + + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + + /* Expect ARP to begin. */ + vARPSendGratuitous_Expect(); + + /* Expect the timer to be reloaded. */ + vIPReloadDHCPTimer_Ignore(); /*_Expect(configTICK_RATE_HZ*(FreeRTOS_ntohl(ulLeaseTime)>>1)); */ + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be unallocated */ + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); + /* Should now be using leased address. */ + TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); + /* Make sure that this is not changed. */ + TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); +} + + +void test_vDHCPProcess_eWaitingAcknowledge_IncorrectLengthofpacket( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + /* Create a bit longer DHCP message but keep it empty. */ + const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 2U; + uint8_t DHCPMsg[ xTotalLength ]; + uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ + uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ + uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ + uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ + DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; + + DHCPMsg[ xTotalLength - 1U ] = 0xFF; + + + /* Set the header - or at least the start of DHCP message. */ + memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); + /* Copy the header here. */ + memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); + /* Make sure that the address matches. */ + memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); + /* Add the expected cookie. */ + pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; + + /* Set the client IP address. */ + pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; + + /* Get pointer to the end. */ + uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) ]; + /* Add Message type code. */ + DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; + /* Add length. */ + DHCPOption[ 1 ] = 0; + + /* Put the information in global variables to be returned by + * the FreeRTOS_recvrom. */ + ucGenericPtr = DHCPMsg; + ulGenericLength = sizeof( DHCPMsg ); + + /* This should remain unchanged. */ + xDHCPSocket = &xTestSocket; + /* Put the required state. */ + xDHCPData.eDHCPState = eWaitingAcknowledge; + /* Not Using broadcast. */ + xDHCPData.xUseBroadcast = pdFALSE; + /* Set the transaction ID which will match. */ + xDHCPData.ulTransactionId = 0x01ABCDEF; + /* Put correct address. */ + xDHCPData.ulDHCPServerAddress = DHCPServerAddress; + /* Reset the lease time. */ + xDHCPData.ulLeaseTime = 0; + /* Put some time values. */ + xDHCPData.xDHCPTxTime = 100; + /* Make sure that we don't exceed the period - and thus, don't give up. */ + xDHCPData.xDHCPTxPeriod = 100; + + /* Reset this value so that it can be verified later. */ + *ipLOCAL_IP_ADDRESS_POINTER = 0; + + /* Get a stub. */ + FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); + /* Release the UDP buffer. */ + FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); + + /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ + /* Return a value which makes the difference just equal to the period. */ + xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); + /* Return time second time which can be verified. */ + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + + /* Get the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Send succeeds. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + + vDHCPProcess( pdFALSE, eWaitingAcknowledge ); + + /* DHCP socket should be allocated */ + TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); + /* Should still be stuck in waiting for ack state. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eGetLinkLayerAddress_Timeout_NoARPIPClash( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + EP_DHCPData.xDHCPTxTime = 100; + EP_DHCPData.xDHCPTxPeriod = 100; + /* Put the required state. */ + xDHCPData.eDHCPState = eGetLinkLayerAddress; + + xARPHadIPClash = pdFALSE; + + xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime + 100 ); + + vIPNetworkUpCalls_Expect(); + + vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); + + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, EP_DHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eGetLinkLayerAddress_Timeout_ARPIPClash( void ) +{ + struct xSOCKET xTestSocket; + TickType_t xTimeValue = 1234; + + EP_DHCPData.xDHCPTxTime = 100; + EP_DHCPData.xDHCPTxPeriod = 100; + /* Put the required state. */ + xDHCPData.eDHCPState = eGetLinkLayerAddress; + /* This should be nullified. */ + xDHCPSocket = &xTestSocket; + + xARPHadIPClash = pdTRUE; + + xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime + 100 ); + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + /* Then expect the socket to be closed. */ + vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + vARPSendGratuitous_Expect(); + + vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); + + TEST_ASSERT_EQUAL( eGetLinkLayerAddress, EP_DHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); +} + +void test_vDHCPProcess_eGetLinkLayerAddress_NoTimeout( void ) +{ + EP_DHCPData.xDHCPTxTime = 100; + EP_DHCPData.xDHCPTxPeriod = 100; + /* Put the required state. */ + xDHCPData.eDHCPState = eGetLinkLayerAddress; + + xARPHadIPClash = pdTRUE; + + /* Make it so that there is no timeout. */ + xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime ); + + vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); + + TEST_ASSERT_EQUAL( eGetLinkLayerAddress, EP_DHCPData.eDHCPState ); +} + + +void test_vDHCPProcess_eLeasedAddress_NetworkDown( void ) +{ + /* Put the required state. */ + xDHCPData.eDHCPState = eLeasedAddress; + + /* The network is not up. */ + FreeRTOS_IsNetworkUp_ExpectAndReturn( 0 ); + /* Expect the DHCP timer to be reloaded. */ + vIPReloadDHCPTimer_Expect( pdMS_TO_TICKS( 5000U ) ); + + vDHCPProcess( pdFALSE, eLeasedAddress ); + + /* Still in this phase. */ + TEST_ASSERT_EQUAL( eLeasedAddress, EP_DHCPData.eDHCPState ); +} + +void test_vDHCPProcess_eLeasedAddress_NetworkUp_SokcetCreated_RNGPass_GNBfail( void ) +{ + struct xSOCKET xTestSocket; + BaseType_t xTimeValue = 300; + + /* Socket is already created. */ + xDHCPSocket = &xTestSocket; + + /* Put the required state. */ + xDHCPData.eDHCPState = eLeasedAddress; + + /* The network is up. */ + FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); + + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + /* Return the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning NULL will mean the prvSendDHCPDiscover fail. */ + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + + /* Expect the timer to be set. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + + vDHCPProcess( pdFALSE, eLeasedAddress ); + + /* Need to send DHCP request. */ + TEST_ASSERT_EQUAL( eSendDHCPRequest, EP_DHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( xTimeValue, EP_DHCPData.xDHCPTxTime ); + TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, EP_DHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eLeasedAddress_NetworkUp_SokcetCreated_RNGFail( void ) +{ + struct xSOCKET xTestSocket; + BaseType_t xTimeValue = 300; + + /* Socket is already created. */ + xDHCPSocket = &xTestSocket; + + /* Put the required state. */ + xDHCPData.eDHCPState = eLeasedAddress; + + /* The network is up. */ + FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); + + /* Make RNG fail. */ + xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdFALSE ); + xTaskGetTickCount_ExpectAndReturn( xTimeValue ); + /* Return the hostname. */ + pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); + /* Returning a proper network buffer. */ + pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); + /* Make the call to FreeRTOS_send succeed. */ + FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); + + /* Expect the timer to be set. */ + vIPReloadDHCPTimer_Expect( dhcpINITIAL_TIMER_PERIOD ); + + vDHCPProcess( pdFALSE, eLeasedAddress ); + + /* Sent DHCP request - waiting ACK. */ + TEST_ASSERT_EQUAL( eWaitingAcknowledge, EP_DHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( xTimeValue, EP_DHCPData.xDHCPTxTime ); + TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, EP_DHCPData.xDHCPTxPeriod ); +} + +void test_vDHCPProcess_eLeasedAddress_NetworkUp_SocketNotCreated_RNGPass_GNBfail( void ) +{ + /* Socket not created. */ + xDHCPSocket = NULL; + + /* Put the required state. */ + xDHCPData.eDHCPState = eLeasedAddress; + + /* The network is up. */ + FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); + + /* Return invalid socket. */ + FreeRTOS_socket_ExpectAnyArgsAndReturn( FREERTOS_INVALID_SOCKET ); + + vDHCPProcess( pdFALSE, eLeasedAddress ); + + /* Still here. */ + TEST_ASSERT_EQUAL( eLeasedAddress, EP_DHCPData.eDHCPState ); + TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); +} + +void test_vDHCPProcess_eNotUsingLeasedAddress( void ) +{ + /* Put the required state. */ + xDHCPData.eDHCPState = eNotUsingLeasedAddress; + + /* Expect the timer to be disabled. */ + vIPSetDHCPTimerEnableState_Expect( pdFALSE ); + + vDHCPProcess( pdFALSE, eNotUsingLeasedAddress ); + + /* Continue not using DHCP. */ + TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, EP_DHCPData.eDHCPState ); +} + +void test_vDHCPProcess_IncorrectState( void ) +{ + /* Put a non-existent state. */ + xDHCPData.eDHCPState = ( eNotUsingLeasedAddress << 1 ); + + vDHCPProcess( pdFALSE, ( eNotUsingLeasedAddress << 1 ) ); + + /* Continue not using DHCP. */ + TEST_ASSERT_EQUAL( ( eNotUsingLeasedAddress << 1 ), EP_DHCPData.eDHCPState ); +} diff --git a/test/unit-test/FreeRTOS_DHCP/ut.cmake b/test/unit-test/FreeRTOS_DHCP/ut.cmake new file mode 100644 index 0000000000..b1e06966e3 --- /dev/null +++ b/test/unit-test/FreeRTOS_DHCP/ut.cmake @@ -0,0 +1,93 @@ +# Include filepaths for source and include. +include( ${MODULE_ROOT_DIR}/test/unit-test/TCPFilePaths.cmake ) + +# ==================== Define your project name (edit) ======================== +set( project_name "FreeRTOS_DHCP" ) +message( STATUS "${project_name}" ) +# ===================== Create your mock here (edit) ======================== + +# list the files to mock here +list(APPEND mock_list + "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/task.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Sockets.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_UDP_IP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ARP.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Private.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/NetworkBufferManagement.h" + "${MODULE_ROOT_DIR}/test/unit-test/${project_name}/FreeRTOS_DHCP_mock.h" + ) +# list the directories your mocks need +list(APPEND mock_include_list + . + ${TCP_INCLUDE_DIRS} + ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include + ${MODULE_ROOT_DIR}/test/unit-test/ConfigFiles + ) + +#list the definitions of your mocks to control what to be included +list(APPEND mock_define_list + "" + ) + +# ================= Create the library under test here (edit) ================== + +# list the files you would like to test here +list(APPEND real_source_files + ${MODULE_ROOT_DIR}/FreeRTOS_DHCP.c + ) +# list the directories the module under test includes +list(APPEND real_include_directories + . + ${TCP_INCLUDE_DIRS} + ${MODULE_ROOT_DIR}/test/unit-test/ConfigFiles + ${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include + ${CMOCK_DIR}/vendor/unity/src + ) + +# ===================== Create UnitTest Code here (edit) ===================== + +# list the directories your test needs to include +list(APPEND test_include_directories + . + ${CMOCK_DIR}/vendor/unity/src + ${TCP_INCLUDE_DIRS} + ${MODULE_ROOT_DIR}/test/unit-test/${project_name} + ) + +# ============================= (end edit) =================================== + +set(mock_name "${project_name}_mock") +set(real_name "${project_name}_real") + +create_mock_list(${mock_name} + "${mock_list}" + "${MODULE_ROOT_DIR}/test/unit-test/cmock/project.yml" + "${mock_include_list}" + "${mock_define_list}" + ) + +create_real_library(${real_name} + "${real_source_files}" + "${real_include_directories}" + "${mock_name}" + ) + +list(APPEND utest_link_list + -l${mock_name} + lib${real_name}.a + ) + +list(APPEND utest_dep_list + ${real_name} + ) + +set(utest_name "${project_name}_utest") +set(utest_source "${project_name}/${project_name}_utest.c") + +create_test(${utest_name} + ${utest_source} + "${utest_link_list}" + "${utest_dep_list}" + "${test_include_directories}" + ) diff --git a/test/unit-test/FreeRTOS_TCP_Unit_test.c b/test/unit-test/FreeRTOS_TCP_Unit_test.c deleted file mode 100644 index 49afa38ec1..0000000000 --- a/test/unit-test/FreeRTOS_TCP_Unit_test.c +++ /dev/null @@ -1,116 +0,0 @@ -/* Include Unity header */ -#include - -/* Include standard libraries */ -#include -#include -#include -#include "FreeRTOS.h" -#include "task.h" -#include "list.h" - -/* Include header file(s) which have declaration - * of functions under test */ -#include "FreeRTOS_IP.h" -#include "mock_FreeRTOS_ARP.h" -#include "FreeRTOS_IP_Private.h" - -#include "FreeRTOSIPConfig.h" - -#include "FreeRTOS_ARP_stubs.c" - -#define ARPCacheEntryToCheck 2 - -#if ARPCacheEntryToCheck >= ipconfigARP_CACHE_ENTRIES - #error "ARPCacheEntryToCheck cannot be greater than ipconfigARP_CACHE_ENTRIES" -#endif - -extern ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ]; - -void FillARPCache( void ) -{ - int i, j; - - for( i = 0; i < ipconfigARP_CACHE_ENTRIES; i++ ) - { - for( j = 0; j < ipMAC_ADDRESS_LENGTH_BYTES; j++ ) - { - xARPCache[ i ].xMACAddress.ucBytes[ j ] = i * 10 + j; - } - - xARPCache[ i ].ulIPAddress = i; - } -} - -void test_ulARPRemoveCacheEntryByMac_RemoveNormalEntry( void ) -{ - int32_t lResult; - uint8_t offset = ARPCacheEntryToCheck * 10; - const MACAddress_t pxMACAddress = { offset + 0, offset + 1, offset + 2, offset + 3, offset + 4, offset + 5 }; - - FillARPCache(); - - lResult = ulARPRemoveCacheEntryByMac( &pxMACAddress ); - - TEST_ASSERT_EQUAL( lResult, ARPCacheEntryToCheck ); -} - -void test_ulARPRemoveCacheEntryByMac_RemoveAbsentEntry( void ) -{ - int32_t lResult; - uint8_t offset = ARPCacheEntryToCheck * 10; - const MACAddress_t pxMACAddress = { offset + 6, offset + 7, offset + 8, offset + 9, offset + 10, offset + 11 }; - - FillARPCache(); - - lResult = ulARPRemoveCacheEntryByMac( &pxMACAddress ); - - TEST_ASSERT_EQUAL( lResult, 0 ); -} - -void test_ulARPRemoveCacheEntryByMac_UseNULLPointer( void ) -{ - /* We expect this test to call ASSERT. */ - ulARPRemoveCacheEntryByMac( NULL ); -} - -void test_eARPGetCacheEntryByMac_GetNormalEntry( void ) -{ - uint32_t ulIPPointer = 12345; - eARPLookupResult_t xResult; - uint8_t offset = ARPCacheEntryToCheck * 10; - MACAddress_t xMACAddress = { offset + 0, offset + 1, offset + 2, offset + 3, offset + 4, offset + 5 }; - MACAddress_t * const pxMACAddress = &xMACAddress; - - FillARPCache(); - - xResult = eARPGetCacheEntryByMac( pxMACAddress, &ulIPPointer ); - - TEST_ASSERT_EQUAL( xResult, eARPCacheHit ); - TEST_ASSERT_EQUAL( ulIPPointer, ARPCacheEntryToCheck ); -} - -void test_eARPGetCacheEntryByMac_GetAbsentEntry( void ) -{ - uint32_t ulIPPointer = 12345; - eARPLookupResult_t xResult; - uint8_t offset = ARPCacheEntryToCheck * 10; - MACAddress_t xMACAddress = { offset + 5, offset + 4, offset + 3, offset + 2, offset + 1, offset + 0 }; - MACAddress_t * const pxMACAddress = &xMACAddress; - - FillARPCache(); - - xResult = eARPGetCacheEntryByMac( pxMACAddress, &ulIPPointer ); - - TEST_ASSERT_EQUAL( xResult, eARPCacheMiss ); - TEST_ASSERT_EQUAL( ulIPPointer, 12345 ); -} - -void test_eARPGetCacheEntryByMac_UseNULLPointer( void ) -{ - uint32_t * ulIPPointer = NULL; - MACAddress_t * const pxMACAddress = NULL; - - /* Expect this test to his an ASSERT. */ - eARPGetCacheEntryByMac( pxMACAddress, ulIPPointer ); -} diff --git a/test/unit-test/catch_assert.h b/test/unit-test/catch_assert.h new file mode 100644 index 0000000000..bce842fe3c --- /dev/null +++ b/test/unit-test/catch_assert.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * How to catch an assert: + * - save a jump buffer where execution will resume after the assert + * - setup a handler for the abort signal, call longjmp within + * - optional - close stderr ( fd 2 ) to discard the assert message + * + * Unity also does a longjmp within its TEST_ASSERT* macros, + * so the macro below restores stderr and the prior abort handler + * before calling the Unity macro. + */ + +#ifndef CATCH_ASSERT_H_ +#define CATCH_ASSERT_H_ + +#include +#include +#include + +#ifndef CATCH_JMPBUF + #define CATCH_JMPBUF waypoint_ +#endif + +jmp_buf CATCH_JMPBUF; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +static void catchHandler_( int signal ) +{ + longjmp( CATCH_JMPBUF, signal ); +} +#pragma GCC diagnostic pop + +#define catch_assert( x ) \ + do { \ + int try = 0, catch = 0; \ + int saveFd = dup( 2 ); \ + struct sigaction sa = { 0 }, saveSa; \ + sa.sa_handler = catchHandler_; \ + sigaction( SIGABRT, &sa, &saveSa ); \ + close( 2 ); \ + if( setjmp( CATCH_JMPBUF ) == 0 ) \ + { \ + try++; \ + x; \ + } \ + else \ + { \ + catch++; \ + } \ + sigaction( SIGABRT, &saveSa, NULL ); \ + dup2( saveFd, 2 ); \ + close( saveFd ); \ + TEST_ASSERT_EQUAL( try, catch ); \ + } while( 0 ) + +#endif /* ifndef CATCH_ASSERT_H_ */ diff --git a/test/unit-test/cmock/coverage.cmake b/test/unit-test/cmock/coverage.cmake index 94797b35d2..46ee7f984c 100644 --- a/test/unit-test/cmock/coverage.cmake +++ b/test/unit-test/cmock/coverage.cmake @@ -21,6 +21,7 @@ execute_process( COMMAND lcov --directory ${CMAKE_BINARY_DIR} --rc genhtml_branch_coverage=1 --output-file=${CMAKE_BINARY_DIR}/base_coverage.info ) + file(GLOB files "${CMAKE_BINARY_DIR}/bin/tests/*") set(REPORT_FILE ${CMAKE_BINARY_DIR}/utest_report.txt) @@ -56,6 +57,11 @@ execute_process( --output-file ${CMAKE_BINARY_DIR}/second_coverage.info ) +# Remove existing coverage file. +execute_process( + COMMAND rm -f ${CMAKE_BINARY_DIR}/coverage.info + ) + # combile baseline results (zeros) with the one after running the tests execute_process( COMMAND lcov --base-directory ${CMAKE_BINARY_DIR} @@ -66,6 +72,33 @@ execute_process( --no-external --rc lcov_branch_coverage=1 ) + +if(0) +# Remove kernel coverage +execute_process( + COMMAND lcov --rc lcov_branch_coverage=1 + --remove ${CMAKE_BINARY_DIR}/coverage.info + *FreeRTOS-Kernel* + --output-file ${CMAKE_BINARY_DIR}/coverage.info + ) + +# Remove portable coverage +execute_process( + COMMAND lcov --rc lcov_branch_coverage=1 + --remove ${CMAKE_BINARY_DIR}/coverage.info + *portable* + --output-file ${CMAKE_BINARY_DIR}/coverage.info + ) + +# Remove stubs coverage +execute_process( + COMMAND lcov --rc lcov_branch_coverage=1 + --remove ${CMAKE_BINARY_DIR}/coverage.info + *stubs* + --output-file ${CMAKE_BINARY_DIR}/coverage.info + ) +endif() + execute_process( COMMAND genhtml --rc lcov_branch_coverage=1 --branch-coverage diff --git a/test/unit-test/cmock/create_test.cmake b/test/unit-test/cmock/create_test.cmake index 8d66f8fc92..1d56cb6acc 100644 --- a/test/unit-test/cmock/create_test.cmake +++ b/test/unit-test/cmock/create_test.cmake @@ -132,6 +132,7 @@ function(create_mock_list mock_name set_target_properties(${mock_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib POSITION_INDEPENDENT_CODE ON + COMPILE_FLAG "-O0 -ggdb" ) target_compile_definitions(${mock_name} PUBLIC ${mock_define_list} @@ -151,7 +152,7 @@ function(create_real_library target ${real_include_list} ) set_target_properties(${target} PROPERTIES - COMPILE_FLAGS "-Wextra -Wpedantic \ + COMPILE_FLAGS "-O0 -Wextra -Wpedantic \ -fprofile-arcs -ftest-coverage -fprofile-generate \ -Wno-unused-but-set-variable" LINK_FLAGS "-fprofile-arcs -ftest-coverage \ diff --git a/test/unit-test/cmock/project.yml b/test/unit-test/cmock/project.yml index d741bec910..b66bc3ae19 100644 --- a/test/unit-test/cmock/project.yml +++ b/test/unit-test/cmock/project.yml @@ -22,10 +22,13 @@ - - - - - "FreeRTOS.h" - - "FreeRTOS_IP.h" - - "FreeRTOS_IP_Private.h" - - "FreeRTOS_UDP_IP.h" + - + - FreeRTOS.h + - FreeRTOS_IP.h :treat_externs: :exclude # Now the extern-ed functions will be mocked. :weak: __attribute__((weak)) :treat_externs: :include + :strippables: + - PRIVILEGED_FUNCTION + - portDONT_DISCARD + - portINLINE From 3c4db2dacb84bc49871d9e3bf408e8273f07b7a1 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:44:38 -0700 Subject: [PATCH 04/11] Fix Some warnings --- FreeRTOS_IP.c | 4 +--- tools/tcp_utilities/tcp_mem_stats.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/FreeRTOS_IP.c b/FreeRTOS_IP.c index 68549035b8..a0ab39e3b3 100644 --- a/FreeRTOS_IP.c +++ b/FreeRTOS_IP.c @@ -1997,13 +1997,11 @@ static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPP if( pxIPPacket->xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) { ProtocolPacket_t * pxProtPack; - const uint16_t * pusChecksum; /* pxProtPack will point to the offset were the protocols begin. */ pxProtPack = ipCAST_PTR_TO_TYPE_PTR( ProtocolPacket_t, &( pxNetworkBuffer->pucEthernetBuffer[ uxHeaderLength - ipSIZE_OF_IPv4_HEADER ] ) ); - pusChecksum = ( const uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) ); - if( *pusChecksum == ( uint16_t ) 0U ) + if( pxProtPack->xUDPPacket.xUDPHeader.usChecksum == ( uint16_t ) 0U ) { #if ( ipconfigHAS_PRINTF != 0 ) { diff --git a/tools/tcp_utilities/tcp_mem_stats.c b/tools/tcp_utilities/tcp_mem_stats.c index b3aa87c54e..4a2530e05d 100644 --- a/tools/tcp_utilities/tcp_mem_stats.c +++ b/tools/tcp_utilities/tcp_mem_stats.c @@ -49,7 +49,7 @@ #ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u - #pragma warning "ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?" + #pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?") #endif #if ( ipconfigUSE_TCP_MEM_STATS != 0 ) From d384db0ac8a3952005b8b7fbd7af09bb5ec6f8c6 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Wed, 9 Jun 2021 12:20:15 -0700 Subject: [PATCH 05/11] merge tcp_mem_stats --- tools/tcp_utilities/tcp_mem_stats.c | 39 +++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/tools/tcp_utilities/tcp_mem_stats.c b/tools/tcp_utilities/tcp_mem_stats.c index 4a2530e05d..4611dfd7f8 100644 --- a/tools/tcp_utilities/tcp_mem_stats.c +++ b/tools/tcp_utilities/tcp_mem_stats.c @@ -1,5 +1,5 @@ /* - * FreeRTOS+TCP V2.3.2 + * FreeRTOS+TCP V2.3.3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -47,13 +47,20 @@ #include "tcp_mem_stats.h" -#ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION - #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u - #pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?") -#endif - #if ( ipconfigUSE_TCP_MEM_STATS != 0 ) + #ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION + +/* Define the maximum number of objects ( memory allocations by + * the IP-stack ) that will be recorded. */ + #define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u + +/* If you don't want to see this pragma message, you can either + * remove it or define 'ipconfigTCP_MEM_STATS_MAX_ALLOCATION' in + * your freeRTOSIPConfig.h. */ + #pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?") + #endif + /* When a streambuffer is allocated, 4 extra bytes will be reserved. */ #define STREAM_BUFFER_ROUNDUP_BYTES 4 @@ -104,21 +111,21 @@ { /* Already added, strange. */ FreeRTOS_printf( ( "vAddAllocation: Pointer %p already added\n", pxObject ) ); - return; + break; } } - if( uxAllocationCount >= ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) + /* If the object has not been found, + * and if there is still space, add the object. */ + if( ( uxIndex == uxAllocationCount ) && + ( uxAllocationCount < ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) ) { - /* The table is full. */ - return; + xAllocations[ uxIndex ].pxObject = pxObject; + xAllocations[ uxIndex ].xMemType = xMemType; + xAllocations[ uxIndex ].uxSize = uxSize; + xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++; + uxAllocationCount++; } - - xAllocations[ uxIndex ].pxObject = pxObject; - xAllocations[ uxIndex ].xMemType = xMemType; - xAllocations[ uxIndex ].uxSize = uxSize; - xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++; - uxAllocationCount++; } xTaskResumeAll(); } From cae98675c219412de7fa9f4edd4f3061c8c34ed7 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere Date: Tue, 21 Dec 2021 13:54:40 -0800 Subject: [PATCH 06/11] Add automated uncrustify --- .github/workflows/uncrustify.yml | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/uncrustify.yml diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml new file mode 100644 index 0000000000..dccb734b0a --- /dev/null +++ b/.github/workflows/uncrustify.yml @@ -0,0 +1,50 @@ +name: Uncrustify the source code + +on: + issue_comment: + types: [created] + +jobs: + Uncrustify: + name: Run_Uncrustify + if: ${{ github.event.issue.pull_request && github.event.comment.body == '/bot run uncrustify' }} + runs-on: ubuntu-18.04 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - name: get pullrequest url + run: | + echo ${{ github.event.issue.pull_request.url }} + - name: get upstream repo + id: upstreamrepo + run: | + echo "::set-output name=RemoteRepo::$(curl -H "Accept: application/vnd.github.sailor-v-preview+json" --url ${{ github.event.issue.pull_request.url }} | jq '.head.repo.full_name' | sed 's/\"//g')" + - name: get upstream branch + id: upstreambranch + run: | + echo "::set-output name=branchname::$(curl -H "Accept: application/vnd.github.sailor-v-preview+json" --url ${{ github.event.issue.pull_request.url }} | jq '.head.ref' | sed 's/\"//g')" + - name: echo upstream repo:branch + run: | + echo ${{ steps.upstreamrepo.outputs.RemoteRepo }}:${{ steps.upstreambranch.outputs.branchname }} + - name: Checkout upstream repo + uses: actions/checkout@v2 + with: + #persist-credentials: false + token: ${{ secrets.PAT }} + repository: ${{ steps.upstreamrepo.outputs.RemoteRepo }} + ref: ${{ steps.upstreambranch.outputs.branchname }} + - name: Install Uncrustify + run: sudo apt-get install uncrustify + - name: Run Uncrustify + run: | + uncrustify --version + find . -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + + - name: Push changes to upstream repository + run: | + git config --global user.name 'Aniruddha Kanhere' + git config --global user.email '60444055+AniruddhaKanhere@users.noreply.github.com' + git add -A + git commit -m "Uncrustify: triggered by comment." + git push From 3e3b401a9ef70eb795042f84e9383ce28369e7a6 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com> Date: Tue, 21 Dec 2021 14:20:55 -0800 Subject: [PATCH 07/11] Un-uncrustify --- FreeRTOS_ARP.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/FreeRTOS_ARP.c b/FreeRTOS_ARP.c index 9d2a6a3fea..4722dbeedf 100644 --- a/FreeRTOS_ARP.c +++ b/FreeRTOS_ARP.c @@ -54,11 +54,11 @@ /** @brief When the age of an entry in the ARP table reaches this value (it counts down * to zero, so this is an old entry) an ARP request will be sent to see if the * entry is still valid and can therefore be refreshed. */ -#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 ) +#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 ) /** @brief The time between gratuitous ARPs. */ #ifndef arpGRATUITOUS_ARP_PERIOD - #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000U ) ) + #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS(20000U ) ) #endif /** @brief When there is another device which has the same IP address as the IP address @@ -79,12 +79,12 @@ /* * Lookup an MAC address in the ARP cache from the IP address. */ -static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, +static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress ); /*-----------------------------------------------------------*/ -static void vProcessARPPacketReply( ARPPacket_t * pxARPFrame, +static void vProcessARPPacketReply( ARPPacket_t*pxARPFrame, uint32_t ulSenderProtocolAddress ); /*-----------------------------------------------------------*/ @@ -94,7 +94,7 @@ _static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ]; /** @brief The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used * to ensure ARP tables are up to date and to detect IP address conflicts. */ -static TickType_t xLastGratuitousARPTime = 0U; +static TickType_t xLastGratuitousARPTime=0U; /* * IP-clash detection is currently only used internally. When DHCP doesn't respond, the @@ -103,18 +103,18 @@ static TickType_t xLastGratuitousARPTime = 0U; */ #if ( ipconfigARP_USE_CLASH_DETECTION != 0 ) /* Becomes non-zero if another device responded to a gratuitous ARP message. */ - BaseType_t xARPHadIPClash; + BaseType_t xARPHadIPClash ; /* MAC-address of the other device containing the same IP-address. */ - MACAddress_t xARPClashMacAddress; + MACAddress_t xARPClashMacAddress ; #endif /* ipconfigARP_USE_CLASH_DETECTION */ /** @brief This local variable is used to keep track of number of ARP requests sent and * also to limit the requests to arpIP_CLASH_MAX_RETRIES per arpIP_CLASH_RESET_TIMEOUT_MS * period. */ -static UBaseType_t uxARPClashCounter = 0U; +static UBaseType_t uxARPClashCounter=0U; /** @brief The time at which the last ARP clash was sent. */ -static TimeOut_t xARPClashTimeOut; + static TimeOut_t xARPClashTimeOut; /** @brief Next defensive request must not be sent for arpIP_CLASH_RESET_TIMEOUT_MS * period. */ From 2616a3fac8cb51083f3ec529244480fd757f0037 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere Date: Tue, 21 Dec 2021 14:26:18 -0800 Subject: [PATCH 08/11] Uncrustify - manually --- FreeRTOS_ARP.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/FreeRTOS_ARP.c b/FreeRTOS_ARP.c index 4722dbeedf..9d2a6a3fea 100644 --- a/FreeRTOS_ARP.c +++ b/FreeRTOS_ARP.c @@ -54,11 +54,11 @@ /** @brief When the age of an entry in the ARP table reaches this value (it counts down * to zero, so this is an old entry) an ARP request will be sent to see if the * entry is still valid and can therefore be refreshed. */ -#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 ) +#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 ) /** @brief The time between gratuitous ARPs. */ #ifndef arpGRATUITOUS_ARP_PERIOD - #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS(20000U ) ) + #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000U ) ) #endif /** @brief When there is another device which has the same IP address as the IP address @@ -79,12 +79,12 @@ /* * Lookup an MAC address in the ARP cache from the IP address. */ -static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, +static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress ); /*-----------------------------------------------------------*/ -static void vProcessARPPacketReply( ARPPacket_t*pxARPFrame, +static void vProcessARPPacketReply( ARPPacket_t * pxARPFrame, uint32_t ulSenderProtocolAddress ); /*-----------------------------------------------------------*/ @@ -94,7 +94,7 @@ _static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ]; /** @brief The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used * to ensure ARP tables are up to date and to detect IP address conflicts. */ -static TickType_t xLastGratuitousARPTime=0U; +static TickType_t xLastGratuitousARPTime = 0U; /* * IP-clash detection is currently only used internally. When DHCP doesn't respond, the @@ -103,18 +103,18 @@ static TickType_t xLastGratuitousARPTime=0U; */ #if ( ipconfigARP_USE_CLASH_DETECTION != 0 ) /* Becomes non-zero if another device responded to a gratuitous ARP message. */ - BaseType_t xARPHadIPClash ; + BaseType_t xARPHadIPClash; /* MAC-address of the other device containing the same IP-address. */ - MACAddress_t xARPClashMacAddress ; + MACAddress_t xARPClashMacAddress; #endif /* ipconfigARP_USE_CLASH_DETECTION */ /** @brief This local variable is used to keep track of number of ARP requests sent and * also to limit the requests to arpIP_CLASH_MAX_RETRIES per arpIP_CLASH_RESET_TIMEOUT_MS * period. */ -static UBaseType_t uxARPClashCounter=0U; +static UBaseType_t uxARPClashCounter = 0U; /** @brief The time at which the last ARP clash was sent. */ - static TimeOut_t xARPClashTimeOut; +static TimeOut_t xARPClashTimeOut; /** @brief Next defensive request must not be sent for arpIP_CLASH_RESET_TIMEOUT_MS * period. */ From c4a2f701c57743ed2f110eb90a48cc8b26f5098d Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere Date: Tue, 21 Dec 2021 14:36:16 -0800 Subject: [PATCH 09/11] Remove unused comment --- .github/workflows/uncrustify.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml index dccb734b0a..c945b3663e 100644 --- a/.github/workflows/uncrustify.yml +++ b/.github/workflows/uncrustify.yml @@ -31,7 +31,6 @@ jobs: - name: Checkout upstream repo uses: actions/checkout@v2 with: - #persist-credentials: false token: ${{ secrets.PAT }} repository: ${{ steps.upstreamrepo.outputs.RemoteRepo }} ref: ${{ steps.upstreambranch.outputs.branchname }} From 9936eeeda7a2d2161cf805cee378b4c60f190d06 Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere Date: Tue, 21 Dec 2021 15:44:24 -0800 Subject: [PATCH 10/11] Update user to be github action --- .github/workflows/uncrustify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml index c945b3663e..caa88af659 100644 --- a/.github/workflows/uncrustify.yml +++ b/.github/workflows/uncrustify.yml @@ -42,8 +42,8 @@ jobs: find . -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + - name: Push changes to upstream repository run: | - git config --global user.name 'Aniruddha Kanhere' - git config --global user.email '60444055+AniruddhaKanhere@users.noreply.github.com' + git config --global user.name 'GitHub Action' + git config --global user.email 'action@github.com' git add -A git commit -m "Uncrustify: triggered by comment." git push From adf8de2d5ceb3aa0528c1b767a629afad99d264c Mon Sep 17 00:00:00 2001 From: Aniruddha Kanhere Date: Tue, 21 Dec 2021 17:37:07 -0800 Subject: [PATCH 11/11] Remove catch_assert from uncrustify --- .github/workflows/uncrustify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/uncrustify.yml b/.github/workflows/uncrustify.yml index caa88af659..cfb3821062 100644 --- a/.github/workflows/uncrustify.yml +++ b/.github/workflows/uncrustify.yml @@ -39,7 +39,7 @@ jobs: - name: Run Uncrustify run: | uncrustify --version - find . -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + + find . -not -path '.*catch_assert.h' -iname "*.[hc]" -exec uncrustify -c tools/uncrustify.cfg --no-backup --replace {} + - name: Push changes to upstream repository run: | git config --global user.name 'GitHub Action'