1
0
mirror of https://github.com/FreeRTOS/FreeRTOS-Plus-TCP synced 2025-10-20 22:10:04 +08:00
Files
FreeRTOS-Plus-TCP/source/FreeRTOS_IP_Timers.c
Tony Josi 0e9628796c Fixing doxygen comments (#728)
* updating doxygen config

* fixing doxygen comments

* adding IPv6 files and fixing comments

* fix doxygen cfg and file names in comments

* wip doxygen v6 docs

* adding doxygen comments

* include RA src file to doxgendocs generation

* fix spell check issues

* Uncrustify: triggered by comment.

* fix minor build issue

* fix spell check issues

* Uncrustify: triggered by comment

* fix trailing white space

* Dev integration hein.v8 (#738)

* Updating tcp utilities

* Some more change in dev_integration_hein.v8

* In FreeRTOS_DNS_Parser.c : use 'ipUDP_PAYLOAD_OFFSET_IPv4' in stead of 'ipIP_PAYLOAD_OFFSET'

* And a few more corrections

* Changes to WinPCap network interface, removed debugging code

* After applying uncrustify

* Oops, I forgot the push changes in include files.

* Now removing it, hopefully

---------

Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com>
Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com>

* Fix CBMC proofs for DNS (#718)

* Use CBMC XML output to enable VSCode debugger (#673)

Prior to this commit, CBMC would emit logging information in plain text
format, which does not contain information required for the CBMC VSCode
debugger. This commit makes CBMC use XML instead of plain text.

Co-authored-by: Mark Tuttle <tuttle@acm.org>

* wip

* wip DNSgetHostByName

* wip DNSgetHostByName

* fixed cbmc proof for DNS_ReadNameField

* wip DNSgetHostByName_a_harness

* Fix CBMC prooff for DNSgetHostByName

* wip fix DNSgetHostByName_a CBMC proof

* fixed cbmc target func not called issue in DNSclear

* fixed cbmc target func not called issue in DNSlookup

* fix DNSgetHostByName_a CBMC proof

* update comments

* more asserts

* fixing formatting

* updating as per review comments

* fix dns after review comments

* adding more asserts

* adds more asserts

* minor fix

* fixing comments

* fixing comments

* fixing minor issue

* fixing DNS_ReadReply() signature

* making code more consistant

* adding more  asserts

* making code more consistent

---------

Co-authored-by: Kareem Khazem <karkhaz@amazon.com>
Co-authored-by: Mark Tuttle <tuttle@acm.org>

* Uncrustify: triggered by comment

* fixing formatting

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Hein Tibosch <hein_tibosch@yahoo.es>
Co-authored-by: Nikhil Kamath <110539926+amazonKamath@users.noreply.github.com>
Co-authored-by: Monika Singh <108652024+moninom1@users.noreply.github.com>
Co-authored-by: Kareem Khazem <karkhaz@amazon.com>
Co-authored-by: Mark Tuttle <tuttle@acm.org>
2023-02-24 13:58:53 +05:30

608 lines
18 KiB
C

/*
* FreeRTOS+TCP <DEVELOPMENT BRANCH>
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* 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
*/
/**
* @file FreeRTOS_IP_Timers.c
* @brief Implements the Internet Control Message Protocol for the FreeRTOS+TCP network stack.
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Timers.h"
#include "FreeRTOS_IP_Utils.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_ND.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_Routing.h"
#include "FreeRTOS_DNS.h"
/*-----------------------------------------------------------*/
/** @brief 'xAllNetworksUp' becomes pdTRUE as soon as all network interfaces have
* been initialised. */
/* MISRA Ref 8.9.1 [File scoped variables] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */
/* coverity[misra_c_2012_rule_8_9_violation] */
static BaseType_t xAllNetworksUp = pdFALSE;
/*-----------------------------------------------------------*/
/*
* Utility functions for the light weight IP timers.
*/
/**
* Start an IP timer. The IP-task has its own implementation of a timer
* called 'IPTimer_t', which is based on the FreeRTOS 'TimeOut_t'.
*/
static void prvIPTimerStart( IPTimer_t * pxTimer,
TickType_t xTime );
/**
* Check the IP timer to see whether an IP event should be processed or not.
*/
static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer );
/**
* Sets the reload time of an IP timer and restarts it.
*/
static void prvIPTimerReload( IPTimer_t * pxTimer,
TickType_t xTime );
/*-----------------------------------------------------------*/
/*
* A timer for each of the following processes, all of which need attention on a
* regular basis
*/
/** @brief Timer to limit the maximum time a packet should be stored while
* awaiting an ARP resolution. */
static IPTimer_t xARPResolutionTimer;
/** @brief ARP timer, to check its table entries. */
static IPTimer_t xARPTimer;
#if ( ipconfigUSE_TCP != 0 )
/** @brief TCP timer, to check for timeouts, resends. */
static IPTimer_t xTCPTimer;
#endif
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
/** @brief DNS timer, to check for timeouts when looking-up a domain. */
static IPTimer_t xDNSTimer;
#endif
/** @brief As long as not all networks are up, repeat initialisation by calling the
* xNetworkInterfaceInitialise() function of the interfaces that are not ready. */
/* MISRA Ref 8.9.1 [File scoped variables] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */
/* coverity[misra_c_2012_rule_8_9_violation] */
static IPTimer_t xNetworkTimer;
struct xNetworkEndpoint;
/*-----------------------------------------------------------*/
/**
* @brief Calculate the maximum sleep time remaining. It will go through all
* timers to see which timer will expire first. That will be the amount
* of time to block in the next call to xQueueReceive().
*
* @return The maximum sleep time or ipconfigMAX_IP_TASK_SLEEP_TIME,
* whichever is smaller.
*/
TickType_t xCalculateSleepTime( void )
{
TickType_t uxMaximumSleepTime;
/* Start with the maximum sleep time, then check this against the remaining
* time in any other timers that are active. */
uxMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME;
if( xARPTimer.bActive != pdFALSE_UNSIGNED )
{
if( xARPTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xARPTimer.ulRemainingTime;
}
}
#if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 )
{
const NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
while( pxEndPoint != NULL )
{
if( pxEndPoint->xDHCP_RATimer.bActive != pdFALSE_UNSIGNED )
{
if( pxEndPoint->xDHCP_RATimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = pxEndPoint->xDHCP_RATimer.ulRemainingTime;
}
}
pxEndPoint = pxEndPoint->pxNext;
}
}
#endif /* ipconfigUSE_DHCP */
#if ( ipconfigUSE_TCP == 1 )
{
if( xTCPTimer.bActive != pdFALSE_UNSIGNED )
{
if( xTCPTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xTCPTimer.ulRemainingTime;
}
}
}
#endif
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
{
if( xDNSTimer.bActive != pdFALSE_UNSIGNED )
{
if( xDNSTimer.ulRemainingTime < uxMaximumSleepTime )
{
uxMaximumSleepTime = xDNSTimer.ulRemainingTime;
}
}
}
#endif
return uxMaximumSleepTime;
}
/*-----------------------------------------------------------*/
/**
* @brief Check the network timers (ARP/DHCP/DNS/TCP) and if they are
* expired, send an event to the IP-Task.
*/
/* MISRA Ref 8.9.1 [File scoped variables] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */
/* coverity[misra_c_2012_rule_8_9_violation] */
/* coverity[single_use] */
void vCheckNetworkTimers( void )
{
NetworkInterface_t * pxInterface;
/* Is it time for ARP processing? */
if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
{
( void ) xSendEventToIPTask( eARPTimerEvent );
}
/* Is the ARP resolution timer expired? */
if( prvIPTimerCheck( &xARPResolutionTimer ) != pdFALSE )
{
if( pxARPWaitingNetworkBuffer != NULL )
{
/* Disable the ARP resolution timer. */
vIPSetARPResolutionTimerEnableState( pdFALSE );
/* We have waited long enough for the ARP response. Now, free the network
* buffer. */
vReleaseNetworkBufferAndDescriptor( pxARPWaitingNetworkBuffer );
/* Clear the pointer. */
pxARPWaitingNetworkBuffer = NULL;
iptraceDELAYED_ARP_TIMER_EXPIRED();
}
}
#if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 )
{
/* Is it time for DHCP processing? */
NetworkEndPoint_t * pxEndPoint = pxNetworkEndPoints;
while( pxEndPoint != NULL )
{
if( prvIPTimerCheck( &( pxEndPoint->xDHCP_RATimer ) ) != pdFALSE )
{
#if ( ipconfigUSE_DHCP == 1 )
if( END_POINT_USES_DHCP( pxEndPoint ) )
{
( void ) xSendDHCPEvent( pxEndPoint );
}
#endif /* ( ipconfigUSE_DHCP == 1 ) */
#if ( ipconfigUSE_RA != 0 )
if( END_POINT_USES_RA( pxEndPoint ) )
{
vRAProcess( pdFALSE, pxEndPoint );
}
#endif /* ( ipconfigUSE_RA != 0 ) */
}
pxEndPoint = pxEndPoint->pxNext;
}
}
#endif /* ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA != 0 ) */
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
{
/* Is it time for DNS processing? */
if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
{
vDNSCheckCallBack( NULL );
}
}
#endif /* ipconfigDNS_USE_CALLBACKS */
#if ( ipconfigUSE_TCP == 1 )
{
BaseType_t xWillSleep;
TickType_t xNextTime;
BaseType_t xCheckTCPSockets;
/* If the IP task has messages waiting to be processed then
* it will not sleep in any case. */
if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0U )
{
xWillSleep = pdTRUE;
}
else
{
xWillSleep = pdFALSE;
}
/* Sockets need to be checked if the TCP timer has expired. */
xCheckTCPSockets = prvIPTimerCheck( &xTCPTimer );
/* Sockets will also be checked if there are TCP messages but the
* message queue is empty (indicated by xWillSleep being true). */
/* if( ( xProcessedTCPMessage != pdFALSE ) && ( xWillSleep != pdFALSE ) ) */
if( xWillSleep != pdFALSE )
{
xCheckTCPSockets = pdTRUE;
}
if( xCheckTCPSockets != pdFALSE )
{
/* Attend to the sockets, returning the period after which the
* check must be repeated. */
xNextTime = xTCPTimerCheck( xWillSleep );
prvIPTimerStart( &xTCPTimer, xNextTime );
xProcessedTCPMessage = 0;
}
}
/* See if any socket was planned to be closed. */
vSocketCloseNextTime( NULL );
/* See if any reusable socket needs to go back to 'eTCP_LISTEN' state. */
vSocketListenNextTime( NULL );
#endif /* ipconfigUSE_TCP == 1 */
/* Is it time to trigger the repeated NetworkDown events? */
if( xAllNetworksUp == pdFALSE )
{
if( prvIPTimerCheck( &( xNetworkTimer ) ) != pdFALSE )
{
BaseType_t xUp = pdTRUE;
for( pxInterface = pxNetworkInterfaces; pxInterface != NULL; pxInterface = pxInterface->pxNext )
{
if( pxInterface->bits.bInterfaceUp == pdFALSE_UNSIGNED )
{
xUp = pdFALSE;
FreeRTOS_NetworkDown( pxInterface );
}
}
xAllNetworksUp = xUp;
}
}
}
/*-----------------------------------------------------------*/
/**
* @brief Start an IP timer. The IP-task has its own implementation of a timer
* called 'IPTimer_t', which is based on the FreeRTOS 'TimeOut_t'.
*
* @param[in] pxTimer: Pointer to the IP timer. When zero, the timer is marked
* as expired.
* @param[in] xTime: Time to be loaded into the IP timer.
*/
static void prvIPTimerStart( IPTimer_t * pxTimer,
TickType_t xTime )
{
vTaskSetTimeOutState( &pxTimer->xTimeOut );
pxTimer->ulRemainingTime = xTime;
if( xTime == ( TickType_t ) 0 )
{
pxTimer->bExpired = pdTRUE_UNSIGNED;
}
else
{
pxTimer->bExpired = pdFALSE_UNSIGNED;
}
pxTimer->bActive = pdTRUE_UNSIGNED;
}
/*-----------------------------------------------------------*/
/**
* @brief Start an ARP Resolution timer.
*
* @param[in] xTime: Time to be loaded into the ARP Resolution timer.
*/
void vIPTimerStartARPResolution( TickType_t xTime )
{
prvIPTimerStart( &( xARPResolutionTimer ), xTime );
}
/*-----------------------------------------------------------*/
/**
* @brief Sets the reload time of an IP timer and restarts it.
*
* @param[in] pxTimer: Pointer to the IP timer.
* @param[in] xTime: Time to be reloaded into the IP timer.
*/
static void prvIPTimerReload( IPTimer_t * pxTimer,
TickType_t xTime )
{
pxTimer->ulReloadTime = xTime;
prvIPTimerStart( pxTimer, xTime );
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_TCP == 1 )
/**
* @brief Sets the reload time of the TCP timer and restarts it.
*
* @param[in] xTime: Time to be reloaded into the TCP timer.
*/
void vTCPTimerReload( TickType_t xTime )
{
prvIPTimerReload( &xTCPTimer, xTime );
}
#endif
/*-----------------------------------------------------------*/
/**
* @brief Sets the reload time of the ARP timer and restarts it.
*
* @param[in] xTime: Time to be reloaded into the ARP timer.
*/
void vARPTimerReload( TickType_t xTime )
{
prvIPTimerReload( &xARPTimer, xTime );
}
/*-----------------------------------------------------------*/
#if ( ipconfigDNS_USE_CALLBACKS != 0 )
/**
* @brief Reload the DNS timer.
*
* @param[in] ulCheckTime: The reload value.
*/
void vDNSTimerReload( uint32_t ulCheckTime )
{
prvIPTimerReload( &xDNSTimer, ulCheckTime );
}
#endif /* ipconfigDNS_USE_CALLBACKS != 0 */
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 )
/**
* @brief Set the reload time of the DHCP/DHCPv6/RA timer.
*
* @param[in] pxEndPoint: The end-point that needs to acquire an IP-address.
* @param[in] uxClockTicks: The number of clock-ticks after which the timer should expire.
*/
void vDHCP_RATimerReload( NetworkEndPoint_t * pxEndPoint,
TickType_t uxClockTicks )
{
FreeRTOS_printf( ( "vDHCP_RATimerReload: %lu\n", uxClockTicks ) );
prvIPTimerReload( &( pxEndPoint->xDHCP_RATimer ), uxClockTicks );
}
#endif /* ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) */
/*-----------------------------------------------------------*/
/**
* @brief Reload the Network timer.
*
* @param[in] xTime: Time to be reloaded into the Network timer.
*/
void vNetworkTimerReload( TickType_t xTime )
{
prvIPTimerReload( &xNetworkTimer, xTime );
}
/*-----------------------------------------------------------*/
/**
* @brief Check the IP timer to see whether an IP event should be processed or not.
*
* @param[in] pxTimer: Pointer to the IP timer.
*
* @return If the timer is expired then pdTRUE is returned. Else pdFALSE.
*/
static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer )
{
BaseType_t xReturn;
if( pxTimer->bActive == pdFALSE_UNSIGNED )
{
/* The timer is not enabled. */
xReturn = pdFALSE;
}
else
{
/* The timer might have set the bExpired flag already, if not, check the
* value of xTimeOut against ulRemainingTime. */
if( pxTimer->bExpired == pdFALSE_UNSIGNED )
{
if( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE )
{
pxTimer->bExpired = pdTRUE_UNSIGNED;
}
}
if( pxTimer->bExpired != pdFALSE_UNSIGNED )
{
prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_TCP == 1 )
/**
* @brief Enable/disable the TCP timer.
*
* @param[in] xExpiredState: pdTRUE - set as expired; pdFALSE - set as non-expired.
*/
void vIPSetTCPTimerExpiredState( BaseType_t xExpiredState )
{
xTCPTimer.bActive = pdTRUE_UNSIGNED;
if( xExpiredState != pdFALSE )
{
xTCPTimer.bExpired = pdTRUE_UNSIGNED;
}
else
{
xTCPTimer.bExpired = pdFALSE_UNSIGNED;
}
}
#endif /* if ( ipconfigUSE_TCP == 1 ) */
/*-----------------------------------------------------------*/
/**
* @brief Enable/disable the ARP timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetARPTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xARPTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xARPTimer.bActive = pdFALSE_UNSIGNED;
}
}
/*-----------------------------------------------------------*/
/**
* @brief Enable or disable the ARP resolution timer.
*
* @param[in] xEnableState: pdTRUE if the timer must be enabled, pdFALSE otherwise.
*/
void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != pdFALSE )
{
xARPResolutionTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xARPResolutionTimer.bActive = pdFALSE_UNSIGNED;
}
}
/*-----------------------------------------------------------*/
#if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) || ( ipconfigUSE_DHCPv6 == 1 )
/**
* @brief Enable or disable the DHCP/DHCPv6/RA timer.
*
* @param[in] pxEndPoint: The end-point that needs to acquire an IP-address.
* @param[in] xEnableState: pdTRUE if the timer must be enabled, pdFALSE otherwise.
*/
void vIPSetDHCP_RATimerEnableState( NetworkEndPoint_t * pxEndPoint,
BaseType_t xEnableState )
{
FreeRTOS_printf( ( "vIPSetDHCP_RATimerEnableState: %s\n", ( xEnableState != 0 ) ? "On" : "Off" ) );
/* 'xDHCP_RATimer' is shared between DHCP (IPv4) and RA/SLAAC (IPv6). */
if( xEnableState != 0 )
{
pxEndPoint->xDHCP_RATimer.bActive = pdTRUE_UNSIGNED;
}
else
{
pxEndPoint->xDHCP_RATimer.bActive = pdFALSE_UNSIGNED;
}
}
#endif /* ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) */
/*-----------------------------------------------------------*/
#if ( ipconfigDNS_USE_CALLBACKS == 1 )
/**
* @brief Enable/disable the DNS timer.
*
* @param[in] xEnableState: pdTRUE - enable timer; pdFALSE - disable timer.
*/
void vIPSetDNSTimerEnableState( BaseType_t xEnableState )
{
if( xEnableState != 0 )
{
xDNSTimer.bActive = pdTRUE_UNSIGNED;
}
else
{
xDNSTimer.bActive = pdFALSE_UNSIGNED;
}
}
#endif /* ipconfigDNS_USE_CALLBACKS == 1 */
/*-----------------------------------------------------------*/