1
0
mirror of https://github.com/FreeRTOS/FreeRTOS-Plus-TCP synced 2025-10-23 18:38:33 +08:00
Files
FreeRTOS-Plus-TCP/source/include/FreeRTOS_Routing.h
ActoryOu 221d8b932d [IPv6] Add Unit Test for FreeRTOS_IP_Timers. (#863)
* Use endpoint's DHCP timer.

* Add test case description

* Remove useless check in MACRO

* Add test cases for xNetworkTimer and xCalculateSleepTime

* vCheckNetworkTimers

* Remove redundant header files

* full coverage

* Code beautify

* Fix spelling
2023-05-17 17:45:22 +08:00

351 lines
17 KiB
C

/*
* FreeRTOS+TCP V2.3.1
* 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
*/
#ifndef FREERTOS_ROUTING_H
#define FREERTOS_ROUTING_H
#ifdef __cplusplus
extern "C" {
#endif
#if ( ipconfigUSE_DHCP != 0 )
#include "FreeRTOS_DHCP.h"
#endif
#if ( ipconfigUSE_IPv6 != 0 )
#include "FreeRTOS_DHCPv6.h"
#endif
/* Every NetworkInterface needs a set of access functions: */
/* Forward declaration of 'struct xNetworkInterface'. */
struct xNetworkInterface;
/* Initialise the interface. */
typedef BaseType_t ( * NetworkInterfaceInitialiseFunction_t ) ( struct xNetworkInterface * pxDescriptor );
/* Send out an Ethernet packet. */
typedef BaseType_t ( * NetworkInterfaceOutputFunction_t ) ( struct xNetworkInterface * pxDescriptor,
NetworkBufferDescriptor_t * const pxNetworkBuffer,
BaseType_t xReleaseAfterSend );
/* Return true as long as the LinkStatus on the PHY is present. */
typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor );
/** @brief These NetworkInterface access functions are collected in a struct: */
typedef struct xNetworkInterface
{
const char * pcName; /**< Just for logging, debugging. */
void * pvArgument; /**< Will be passed to the access functions. */
NetworkInterfaceInitialiseFunction_t pfInitialise; /**< This function will be called upon initialisation and repeated until it returns pdPASS. */
NetworkInterfaceOutputFunction_t pfOutput; /**< This function is supposed to send out a packet. */
GetPhyLinkStatusFunction_t pfGetPhyLinkStatus; /**< This function will return pdTRUE as long as the PHY Link Status is high. */
struct
{
uint32_t
bInterfaceUp : 1, /**< Non-zero as soon as the interface is up. */
bCallDownEvent : 1; /**< The down-event must be called. */
} bits; /**< A collection of boolean flags. */
struct xNetworkEndPoint * pxEndPoint; /**< A list of end-points bound to this interface. */
struct xNetworkInterface * pxNext; /**< The next interface in a linked list. */
} NetworkInterface_t;
/*
* // As an example:
* NetworkInterface_t xZynqDescriptor = {
* .pcName = "Zynq-GEM",
* .pvArgument = ( void * )1,
* .pfInitialise = xZynqGEMInitialise,
* .pfOutput = xZynqGEMOutput,
* .pfGetPhyLinkStatus = xZynqGEMGetPhyLinkStatus,
* };
*/
/** @brief The network settings for IPv4. */
typedef struct xIPV4Parameters
{
uint32_t ulIPAddress; /**< The actual IPv4 address. Will be 0 as long as end-point is still down. */
uint32_t ulNetMask; /**< The netmask. */
uint32_t ulGatewayAddress; /**< The IP-address of the gateway. */
uint32_t ulDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ]; /**< IP-addresses of DNS servers. */
uint32_t ulBroadcastAddress; /**< The local broadcast address, e.g. '192.168.1.255'. */
uint8_t ucDNSIndex; /**< The index of the next DNS address to be used. */
} IPV4Parameters_t;
#if ( ipconfigUSE_IPv6 != 0 )
typedef struct xIPV6Parameters
{
IPv6_Address_t xIPAddress; /* The actual IPv4 address. Will be 0 as long as end-point is still down. */
size_t uxPrefixLength; /* Number of valid bytes in the network prefix. */
IPv6_Address_t xPrefix; /* The network prefix, e.g. fe80::/10 */
IPv6_Address_t xGatewayAddress; /* Gateway to the web. */
IPv6_Address_t xDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ];
uint8_t ucDNSIndex; /**< The index of the next DNS address to be used. */
} IPV6Parameters_t;
#endif
#if ( ipconfigUSE_RA != 0 )
/* Router Advertisement (RA). End-points can obtain their IP-address by asking for a RA. */
typedef enum xRAState
{
eRAStateApply, /* Send a Router Solicitation. */
eRAStateWait, /* Wait for a Router Advertisement. */
eRAStateIPTest, /* Take a random IP address, test if another device is using it already. */
eRAStateIPWait, /* Wait for a reply, if any */
eRAStatePreLease, /* The device is ready to go to the 'eRAStateLease' state. */
eRAStateLease, /* The device is up, repeat the RA-process when timer expires. */
eRAStateFailed,
} eRAState_t;
struct xRA_DATA
{
struct
{
uint32_t
bRouterReplied : 1,
bIPAddressInUse : 1;
}
bits;
TickType_t ulPreferredLifeTime;
UBaseType_t uxRetryCount;
/* Maintains the RA state machine state. */
eRAState_t eRAState;
};
typedef struct xRA_DATA RAData_t;
#endif /* ( ipconfigUSE_RA != 0 ) */
/** @brief The description of an end-point. */
typedef struct xNetworkEndPoint
{
union
{
struct
{
IPV4Parameters_t ipv4_settings; /**< Actual IPv4 settings used by the end-point. */
IPV4Parameters_t ipv4_defaults; /**< Use values form "ipv4_defaults" in case DHCP has failed. */
};
#if ( ipconfigUSE_IPv6 != 0 )
struct
{
IPV6Parameters_t ipv6_settings; /**< Actual IPv6 settings used by the end-point. */
IPV6Parameters_t ipv6_defaults; /**< Use values form "ipv6_defaults" in case DHCP has failed. */
};
#endif
};
MACAddress_t xMACAddress; /**< The MAC-address assigned to this end-point. */
struct
{
uint32_t
bIsDefault : 1, /**< This bit will be removed. */
#if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 )
bWantDHCP : 1, /**< This end-point wants to use DHCPv4 to obtain an IP-address. */
#endif /* ipconfigUSE_DHCP */
#if ( ipconfigUSE_RA != 0 )
bWantRA : 1, /**< This end-point wants to use RA/SLAAC to obtain an IP-address. */
#endif /* ipconfigUSE_RA */
bIPv6 : 1, /**< This end-point has an IP-address of type IPv6. */
#if ( ipconfigUSE_NETWORK_EVENT_HOOK != 0 )
bCallDownHook : 1, /**< The network down hook-must be called for this end-point. */
#endif /* ipconfigUSE_NETWORK_EVENT_HOOK */
bEndPointUp : 1; /**< The end-point is up. */
} bits; /**< A collection of boolean properties. */
uint8_t usDNSType; /**< A LLMNR/mDNS lookup is being done for an IPv6 address.
* This field is only valid while xApplicationDNSQueryHook() is called. */
#if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 )
IPTimer_t xDHCP_RATimer; /**< The timer used to call the DHCP/DHCPv6/RA state machine. */
#endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 ) */
#if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 )
DHCPData_t xDHCPData; /**< A description of the DHCP client state machine. */
#endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 ) */
#if ( ipconfigUSE_IPv6 != 0 )
DHCPMessage_IPv6_t * pxDHCPMessage; /**< A description of the DHCPv6 client state machine. */
#endif
#if ( ipconfigUSE_RA != 0 )
RAData_t xRAData; /**< A description of the Router Advertisement ( RA ) client state machine. */
#endif /* ( ipconfigUSE_RA != 0 ) */
NetworkInterface_t * pxNetworkInterface; /**< The network interface that owns this end-point. */
struct xNetworkEndPoint * pxNext; /**< The next end-point in the chain. */
} NetworkEndPoint_t;
#define END_POINT_USES_DHCP( pxEndPoint ) ( ( pxEndPoint )->bits.bWantDHCP != pdFALSE_UNSIGNED )
#define END_POINT_USES_RA( pxEndPoint ) ( ( ( pxEndPoint )->bits.bIPv6 != pdFALSE_UNSIGNED ) && ( ( pxEndPoint )->bits.bWantRA != pdFALSE_UNSIGNED ) )
#define ENDPOINT_IS_IPv4( pxEndPoint ) ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 == 0U ) )
#define ENDPOINT_IS_IPv6( pxEndPoint ) ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 != 0U ) )
/*
* Add a new physical Network Interface. The object pointed to by 'pxInterface'
* must continue to exist.
* Only the Network Interface function xx_FillInterfaceDescriptor() shall call this function.
*/
NetworkInterface_t * FreeRTOS_AddNetworkInterface( NetworkInterface_t * pxInterface );
/*
* Get the first Network Interface.
*/
NetworkInterface_t * FreeRTOS_FirstNetworkInterface( void );
/*
* Get the next Network Interface.
*/
NetworkInterface_t * FreeRTOS_NextNetworkInterface( const NetworkInterface_t * pxInterface );
/*
* Get the first end-point belonging to a given interface. When pxInterface is
* NULL, the very first end-point will be returned.
*/
NetworkEndPoint_t * FreeRTOS_FirstEndPoint( const NetworkInterface_t * pxInterface );
/*
* Get the next end-point. When pxInterface is null, all end-points can be
* iterated.
*/
NetworkEndPoint_t * FreeRTOS_NextEndPoint( const NetworkInterface_t * pxInterface,
NetworkEndPoint_t * pxEndPoint );
/*
* Find the end-point with given IP-address.
*/
NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv4( uint32_t ulIPAddress,
uint32_t ulWhere );
#if ( ipconfigUSE_IPv6 != 0 )
/* Find the end-point with given IP-address. */
NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv6( const IPv6_Address_t * pxIPAddress );
#endif /* ipconfigUSE_IPv6 */
/*
* Find the end-point with given MAC-address.
* The search can be limited by supplying a particular interface.
*/
NetworkEndPoint_t * FreeRTOS_FindEndPointOnMAC( const MACAddress_t * pxMACAddress,
const NetworkInterface_t * pxInterface );
/*
* Find the best fitting end-point to reach a given IP-address.
* Find an end-point whose IP-address is in the same network as the IP-address provided.
* 'ulWhere' is temporary and or debugging only.
*/
NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask( uint32_t ulIPAddress,
uint32_t ulWhere );
/*
* Find the best fitting end-point to reach a given IP-address on a given interface
* 'ulWhere' is temporary and or debugging only.
*/
NetworkEndPoint_t * FreeRTOS_InterfaceEndPointOnNetMask( const NetworkInterface_t * pxInterface,
uint32_t ulIPAddress,
uint32_t ulWhere );
#if ( ipconfigUSE_IPv6 != 0 )
NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask_IPv6( const IPv6_Address_t * pxIPv6Address );
#endif /* ipconfigUSE_IPv6 */
#if ( ipconfigUSE_IPv6 != 0 )
/* Get the first end-point belonging to a given interface.
* When pxInterface is NULL, the very first end-point will be returned. */
NetworkEndPoint_t * FreeRTOS_FirstEndPoint_IPv6( const NetworkInterface_t * pxInterface );
#endif /* ipconfigUSE_IPv6 */
/* A ethernet packet has come in on a certain network interface.
* Find the best matching end-point. */
NetworkEndPoint_t * FreeRTOS_MatchingEndpoint( const NetworkInterface_t * pxNetworkInterface,
const uint8_t * pucEthernetBuffer );
/* Find an end-point that has a defined gateway.
* xIPType should equal ipTYPE_IPv4 or ipTYPE_IPv6. */
NetworkEndPoint_t * FreeRTOS_FindGateWay( BaseType_t xIPType );
/* Fill-in the end-point structure. */
void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface,
NetworkEndPoint_t * pxEndPoint,
const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
#if ( ipconfigUSE_IPv6 != 0 )
/* Fill-in the end-point structure. */
void FreeRTOS_FillEndPoint_IPv6( NetworkInterface_t * pxNetworkInterface,
NetworkEndPoint_t * pxEndPoint,
const IPv6_Address_t * pxIPAddress,
const IPv6_Address_t * pxNetPrefix,
size_t uxPrefixLength,
const IPv6_Address_t * pxGatewayAddress,
const IPv6_Address_t * pxDNSServerAddress, /* Not used yet. */
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
#endif
#if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
/** @brief Some simple network statistics. */
typedef struct xRoutingStats
{
UBaseType_t ulOnIp; /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called. */
UBaseType_t ulOnMAC; /**< The number of times 'FreeRTOS_FindEndPointOnMAC()' has been called. */
UBaseType_t ulOnNetMask; /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called. */
UBaseType_t ulMatching; /**< The number of times 'FreeRTOS_MatchingEndpoint()' has been called. */
UBaseType_t ulLocations[ 14 ]; /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called from a particular location. */
UBaseType_t ulLocationsIP[ 8 ]; /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called from a particular location. */
} RoutingStats_t;
extern RoutingStats_t xRoutingStatistics;
#endif /* ( ipconfigHAS_ROUTING_STATISTICS == 1 ) */
NetworkEndPoint_t * pxGetSocketEndpoint( ConstSocket_t xSocket );
void vSetSocketEndpoint( Socket_t xSocket,
NetworkEndPoint_t * pxEndPoint );
const char * pcEndpointName( const NetworkEndPoint_t * pxEndPoint,
char * pcBuffer,
size_t uxSize );
typedef enum
{
eIPv6_Global, /* 001 */
eIPv6_LinkLocal, /* 1111 1110 10 */
eIPv6_SiteLocal, /* 1111 1110 11 */
eIPv6_Multicast, /* 1111 1111 */
eIPv6_Unknown, /* Not implemented. */
}
IPv6_Type_t;
/**
* @brief Check the type of an IPv16 address.
*
* @return A value from enum IPv6_Type_t.
*/
IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FREERTOS_ROUTING_H */